merge m-c to fx-team
authorTim Taubert <tim.taubert@gmx.de>
Mon, 22 Aug 2011 14:06:39 +0200
changeset 75879 f8fbf62f31e8e5b1c63f6c3d19d4bc0dc9f0ec7f
parent 75878 edeed3c6065ced200cc086d9e171411dd49ed308 (current diff)
parent 75640 b7c8af20e4009560b86cb6b84d7025b62ceaaa25 (diff)
child 75880 18288bc1b3a16a6a8e3c14a3033caf1c5a403d15
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
milestone9.0a1
merge m-c to fx-team
browser/components/migration/src/nsNetscapeProfileMigratorBase.cpp
browser/components/migration/src/nsNetscapeProfileMigratorBase.h
browser/components/migration/src/nsSeamonkeyProfileMigrator.cpp
browser/components/migration/src/nsSeamonkeyProfileMigrator.h
config/gtscc.c
db/Makefile.in
dom/interfaces/css/nsIDOMDocumentCSS.idl
layout/reftests/svg/dynamic-filter-contents-01.svg
modules/plugin/test/unit/xpcshell.ini
security/nss/cmd/lib/NSPRerrs.h
security/nss/cmd/lib/SECerrs.h
security/nss/cmd/lib/SSLerrs.h
security/nss/lib/zlib/gzio.c
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -172,16 +172,17 @@ endif
                  browser_bug599325.js \
                  browser_bug609700.js \
                  browser_bug616836.js \
                  browser_bug623893.js \
                  browser_bug624734.js \
                  browser_bug647886.js \
                  browser_bug655584.js \
                  browser_bug664672.js \
+                 browser_canonizeURL.js \
                  browser_findbarClose.js \
                  browser_keywordBookmarklets.js \
                  browser_contextSearchTabPosition.js \
                  browser_ctrlTab.js \
                  browser_customize_popupNotification.js \
                  browser_disablechrome.js \
                  browser_discovery.js \
                  browser_duplicateIDs.js \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_canonizeURL.js
@@ -0,0 +1,54 @@
+function test() {
+  waitForExplicitFinish();
+  testNext();
+}
+
+var pairs = [
+  ["example", "http://www.example.net/"],
+  ["ex-ample", "http://www.ex-ample.net/"],
+  ["  example ", "http://www.example.net/"],
+  [" example/foo ", "http://www.example.net/foo"],
+  [" example/foo bar ", "http://www.example.net/foo%20bar"],
+  ["example.net", "http://example.net/"],
+  ["http://example", "http://example/"],
+  ["example:8080", "http://example:8080/"],
+  ["ex-ample.foo", "http://ex-ample.foo/"],
+  ["example.foo/bar ", "http://example.foo/bar"],
+  ["1.1.1.1", "http://1.1.1.1/"],
+  ["ftp://example", "ftp://example/"],
+  ["ftp.example.bar", "ftp://ftp.example.bar/"],
+  ["ex ample", Services.search.originalDefaultEngine.getSubmission("ex ample").uri.spec],
+];
+
+function testNext() {
+  if (!pairs.length) {
+    finish();
+    return;
+  }
+
+  let [inputValue, expectedURL] = pairs.shift();
+
+  gBrowser.addProgressListener({
+    onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
+      if (aStateFlags & Ci.nsIWebProgressListener.STATE_START &&
+          aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) {
+        is(aRequest.originalURI.spec, expectedURL,
+           "entering '" + inputValue + "' loads expected URL");
+
+        gBrowser.removeProgressListener(this);
+        gBrowser.stop();
+
+        executeSoon(testNext);
+      }
+    }
+  });
+
+  gURLBar.addEventListener("focus", function onFocus() {
+    gURLBar.removeEventListener("focus", onFocus);
+    EventUtils.synthesizeKey("VK_RETURN", { shiftKey: true });
+  });
+
+  gBrowser.selectedBrowser.focus();
+  gURLBar.inputField.value = inputValue;
+  gURLBar.focus();
+}
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -362,17 +362,17 @@
         <parameter name="aTriggeringEvent"/>
         <body><![CDATA[
           var url = this.value;
           if (!url)
             return ["", null, false];
 
           // Only add the suffix when the URL bar value isn't already "URL-like",
           // and only if we get a keyboard event, to match user expectations.
-          if (!/^\s*(www|https?)\b|\/\s*$/i.test(url) &&
+          if (/^\s*[^.:\/\s]+(?:\/.*|\s*)$/i.test(url) &&
               (aTriggeringEvent instanceof KeyEvent)) {
 #ifdef XP_MACOSX
             let accel = aTriggeringEvent.metaKey;
 #else
             let accel = aTriggeringEvent.ctrlKey;
 #endif
             let shift = aTriggeringEvent.shiftKey;
 
@@ -397,34 +397,25 @@
             }
 
             if (suffix) {
               // trim leading/trailing spaces (bug 233205)
               url = url.trim();
 
               // Tack www. and suffix on.  If user has appended directories, insert
               // suffix before them (bug 279035).  Be careful not to get two slashes.
-              // Also, don't add the suffix if it's in the original url (bug 233853).
 
               let firstSlash = url.indexOf("/");
-              let existingSuffix = url.indexOf(suffix.substring(0, suffix.length - 1));
-
-              // * Logic for slash and existing suffix (example)
-              // No slash, no suffix: Add suffix (mozilla)
-              // No slash, yes suffix: Add slash (mozilla.com)
-              // Yes slash, no suffix: Insert suffix (mozilla/stuff)
-              // Yes slash, suffix before slash: Do nothing (mozilla.com/stuff)
-              // Yes slash, suffix after slash: Insert suffix (mozilla/?stuff=.com)
 
               if (firstSlash >= 0) {
-                if (existingSuffix == -1 || existingSuffix > firstSlash)
-                  url = url.substring(0, firstSlash) + suffix +
-                        url.substring(firstSlash + 1);
-              } else
-                url = url + (existingSuffix == -1 ? suffix : "/");
+                url = url.substring(0, firstSlash) + suffix +
+                      url.substring(firstSlash + 1);
+              } else {
+                url = url + suffix;
+              }
 
               url = "http://www." + url;
             }
           }
 
           var postData = {};
           var mayInheritPrincipal = { value: false };
           url = getShortcutOrURI(url, postData, mayInheritPrincipal);
--- a/browser/components/build/nsModule.cpp
+++ b/browser/components/build/nsModule.cpp
@@ -48,17 +48,16 @@
 #elif defined(MOZ_WIDGET_GTK2)
 #include "nsGNOMEShellService.h"
 #endif
 
 #include "nsProfileMigrator.h"
 #if !defined(XP_OS2)
 #include "nsOperaProfileMigrator.h"
 #endif
-#include "nsSeamonkeyProfileMigrator.h"
 #if defined(XP_WIN) && !defined(__MINGW32__)
 #include "nsIEProfileMigrator.h"
 #elif defined(XP_MACOSX)
 #include "nsSafariProfileMigrator.h"
 #endif
 
 #include "rdf.h"
 #include "nsFeedSniffer.h"
@@ -80,17 +79,16 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacShel
 #elif defined(MOZ_WIDGET_GTK2)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init)
 #endif
 
 #if !defined(XP_OS2)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsOperaProfileMigrator)
 #endif
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsProfileMigrator)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsSeamonkeyProfileMigrator)
 #if defined(XP_WIN) && !defined(__MINGW32__)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEProfileMigrator)
 #elif defined(XP_MACOSX)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSafariProfileMigrator)
 #endif
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer)
 
@@ -109,17 +107,16 @@ NS_DEFINE_NAMED_CID(NS_FIREFOX_PROFILEMI
 NS_DEFINE_NAMED_CID(NS_WINIEPROFILEMIGRATOR_CID);
 #elif defined(XP_MACOSX)
 NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_SAFARIPROFILEMIGRATOR_CID);
 #endif
 #if !defined(XP_OS2)
 NS_DEFINE_NAMED_CID(NS_OPERAPROFILEMIGRATOR_CID);
 #endif
-NS_DEFINE_NAMED_CID(NS_SEAMONKEYPROFILEMIGRATOR_CID);
 NS_DEFINE_NAMED_CID(NS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID);
 
 static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
     { &kNS_BROWSERDIRECTORYPROVIDER_CID, false, NULL, DirectoryProviderConstructor },
 #if defined(XP_WIN)
     { &kNS_SHELLSERVICE_CID, false, NULL, nsWindowsShellServiceConstructor },
 #elif defined(MOZ_WIDGET_GTK2)
     { &kNS_SHELLSERVICE_CID, false, NULL, nsGNOMEShellServiceConstructor },
@@ -131,17 +128,16 @@ static const mozilla::Module::CIDEntry k
     { &kNS_WINIEPROFILEMIGRATOR_CID, false, NULL, nsIEProfileMigratorConstructor },
 #elif defined(XP_MACOSX)
     { &kNS_SHELLSERVICE_CID, false, NULL, nsMacShellServiceConstructor },
     { &kNS_SAFARIPROFILEMIGRATOR_CID, false, NULL, nsSafariProfileMigratorConstructor },
 #endif
 #if !defined(XP_OS2)
     { &kNS_OPERAPROFILEMIGRATOR_CID, false, NULL, nsOperaProfileMigratorConstructor },
 #endif
-    { &kNS_SEAMONKEYPROFILEMIGRATOR_CID, false, NULL, nsSeamonkeyProfileMigratorConstructor },
     { &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID, false, NULL, nsPrivateBrowsingServiceWrapperConstructor },
     { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
     { NS_BROWSERDIRECTORYPROVIDER_CONTRACTID, &kNS_BROWSERDIRECTORYPROVIDER_CID },
 #if defined(XP_WIN)
     { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
@@ -168,17 +164,16 @@ static const mozilla::Module::ContractID
     { NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "ie", &kNS_WINIEPROFILEMIGRATOR_CID },
 #elif defined(XP_MACOSX)
     { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
     { NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "safari", &kNS_SAFARIPROFILEMIGRATOR_CID },
 #endif
 #if !defined(XP_OS2)
     { NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "opera", &kNS_OPERAPROFILEMIGRATOR_CID },
 #endif
-    { NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "seamonkey", &kNS_SEAMONKEYPROFILEMIGRATOR_CID },
     { NS_PRIVATE_BROWSING_SERVICE_CONTRACTID, &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID },
     { NULL }
 };
 
 static const mozilla::Module::CategoryEntry kBrowserCategories[] = {
     { XPCOM_DIRECTORY_PROVIDER_CATEGORY, "browser-directory-provider", NS_BROWSERDIRECTORYPROVIDER_CONTRACTID },
     { NS_CONTENT_SNIFFER_CATEGORY, "Feed Sniffer", NS_FEEDSNIFFER_CONTRACTID },
     { NULL }
--- a/browser/components/feeds/src/FeedWriter.js
+++ b/browser/components/feeds/src/FeedWriter.js
@@ -251,17 +251,18 @@ FeedWriter.prototype = {
 
   /**
    * Use this sandbox to run any dom manipulation code on nodes which
    * are already inserted into the content document.
    */
   __contentSandbox: null,
   get _contentSandbox() {
     if (!this.__contentSandbox)
-      this.__contentSandbox = new Cu.Sandbox(this._window);
+      this.__contentSandbox = new Cu.Sandbox(this._window, 
+                                             {sandboxName: 'FeedWriter'});
 
     return this.__contentSandbox;
   },
 
   /**
    * Calls doCommand for a given XUL element within the context of the
    * content document.
    *
--- a/browser/components/migration/content/migration.js
+++ b/browser/components/migration/content/migration.js
@@ -335,19 +335,16 @@ var MigrationWizard = {
         source = "sourceNameIE";
         break;
       case "opera":
         source = "sourceNameOpera";
         break;
       case "safari":
         source = "sourceNameSafari";
         break;
-      case "seamonkey":
-        source = "sourceNameSeamonkey";
-        break;
     }
 
     // semi-wallpaper for crash when multiple profiles exist, since we haven't initialized mSourceProfile in places
     this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate);
 
     var oldHomePageURL = this._migrator.sourceHomePageURL;
 
     if (oldHomePageURL && source) {
--- a/browser/components/migration/content/migration.xul
+++ b/browser/components/migration/content/migration.xul
@@ -65,29 +65,24 @@
     <description id="importBookmarks" control="importSourceGroup" hidden="true">&importFromBookmarks.label;</description>
 
     <radiogroup id="importSourceGroup" align="start">
       <!-- If you are adding a migrator, please add the appropriate
            hooks to GetDefaultBrowserMigratorKey in
            browser/components/migration/src/nsProfileMigrator.cpp -->
 #ifdef XP_MACOSX
       <radio id="safari"    label="&importFromSafari.label;"    accesskey="&importFromSafari.accesskey;"/>
-      <radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
       <radio id="opera"     label="&importFromOpera.label;"     accesskey="&importFromOpera.accesskey;"/>
 #elifdef XP_UNIX
-      <radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
       <radio id="opera"     label="&importFromOpera.label;"     accesskey="&importFromOpera.accesskey;"/>
 #elifdef XP_WIN
 #ifndef NO_IE_MIGRATOR
       <radio id="ie"        label="&importFromIE.label;"        accesskey="&importFromIE.accesskey;"/>
 #endif
-      <radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
       <radio id="opera"     label="&importFromOpera.label;"     accesskey="&importFromOpera.accesskey;"/>
-#else
-      <radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
 #endif
       <radio id="fromfile"  label="&importFromHTMLFile.label;"  accesskey="&importFromHTMLFile.accesskey;" hidden="true"/>
       <radio id="nothing"   label="&importFromNothing.label;"   accesskey="&importFromNothing.accesskey;" hidden="true"/>
     </radiogroup>
     <label id="noSources" hidden="true">&noMigrationSources.label;</label>
   </wizardpage>
 
   <wizardpage id="selectProfile" pageid="selectProfile" label="&selectProfile.title;"
--- a/browser/components/migration/src/Makefile.in
+++ b/browser/components/migration/src/Makefile.in
@@ -47,18 +47,16 @@ FORCE_STATIC_LIB = 1
 FORCE_USE_PIC = 1
 ifndef MOZ_MEMORY
 USE_STATIC_LIBS = 1
 endif
 
 
 CPPSRCS  = nsProfileMigrator.cpp \
            nsBrowserProfileMigratorUtils.cpp \
-           nsNetscapeProfileMigratorBase.cpp \
-           nsSeamonkeyProfileMigrator.cpp \
            $(NULL)
 
 ifneq ($(OS_ARCH),OS2)
 CPPSRCS += nsOperaProfileMigrator.cpp
 endif
 
 ifeq ($(OS_ARCH)_$(GNU_CXX),WINNT_)
 CPPSRCS += nsIEProfileMigrator.cpp \
deleted file mode 100644
--- a/browser/components/migration/src/nsNetscapeProfileMigratorBase.cpp
+++ /dev/null
@@ -1,469 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is The Browser Profile Migrator.
- *
- * The Initial Developer of the Original Code is Ben Goodger.
- * Portions created by the Initial Developer are Copyright (C) 2004
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Ben Goodger <ben@bengoodger.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsAppDirectoryServiceDefs.h"
-#include "nsBrowserProfileMigratorUtils.h"
-#include "nsICookieManager2.h"
-#include "nsIFile.h"
-#include "nsILineInputStream.h"
-#include "nsIOutputStream.h"
-#include "nsIPrefBranch.h"
-#include "nsIPrefLocalizedString.h"
-#include "nsIPrefService.h"
-#include "NSReg.h"
-#include "nsIServiceManager.h"
-#include "nsISupportsPrimitives.h"
-#include "nsIURL.h"
-#include "nsNetscapeProfileMigratorBase.h"
-#include "nsNetUtil.h"
-#include "prtime.h"
-#include "prprf.h"
-
-#ifdef XP_MACOSX
-#define NEED_TO_FIX_4X_COOKIES 1
-#define SECONDS_BETWEEN_1900_AND_1970 2208988800UL
-#endif /* XP_MACOSX */
-
-#define FILE_NAME_PREFS_5X NS_LITERAL_STRING("prefs.js")
-
-///////////////////////////////////////////////////////////////////////////////
-// nsNetscapeProfileMigratorBase
-nsNetscapeProfileMigratorBase::nsNetscapeProfileMigratorBase()
-{
-}
-
-static nsresult
-regerr2nsresult(REGERR errCode)
-{
-  switch (errCode) {
-    case REGERR_PARAM:
-    case REGERR_BADTYPE:
-    case REGERR_BADNAME:
-      return NS_ERROR_INVALID_ARG;
-
-    case REGERR_MEMORY:
-      return NS_ERROR_OUT_OF_MEMORY;
-  }
-  return NS_ERROR_FAILURE;
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::GetProfileDataFromRegistry(nsILocalFile* aRegistryFile,
-                                                          nsISupportsArray* aProfileNames,
-                                                          nsISupportsArray* aProfileLocations)
-{
-  nsresult rv;
-  REGERR errCode;
-
-  // Ensure aRegistryFile exists before open it
-  PRBool regFileExists = PR_FALSE;
-  rv = aRegistryFile->Exists(&regFileExists);
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (!regFileExists)
-    return NS_ERROR_FILE_NOT_FOUND;
-
-  // Open It
-  nsCAutoString regPath;
-  rv = aRegistryFile->GetNativePath(regPath);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if ((errCode = NR_StartupRegistry()))
-    return regerr2nsresult(errCode);
-
-  HREG reg;
-  if ((errCode = NR_RegOpen(regPath.get(), &reg))) {
-    NR_ShutdownRegistry();
-
-    return regerr2nsresult(errCode);
-  }
-
-  RKEY profilesTree;
-  if ((errCode = NR_RegGetKey(reg, ROOTKEY_COMMON, "Profiles", &profilesTree))) {
-    NR_RegClose(reg);
-    NR_ShutdownRegistry();
-
-    return regerr2nsresult(errCode);
-  }
-
-  char profileStr[MAXREGPATHLEN];
-  REGENUM enumState = nsnull;
-
-  while (!NR_RegEnumSubkeys(reg, profilesTree, &enumState, profileStr,
-                            sizeof(profileStr), REGENUM_CHILDREN))
-  {
-    RKEY profileKey;
-    if (NR_RegGetKey(reg, profilesTree, profileStr, &profileKey))
-      continue;
-
-    // "migrated" is "yes" for all valid Seamonkey profiles. It is only "no"
-    // for 4.x profiles. 
-    char migratedStr[3];
-    errCode = NR_RegGetEntryString(reg, profileKey, (char *)"migrated",
-                                   migratedStr, sizeof(migratedStr));
-    if ((errCode != REGERR_OK && errCode != REGERR_BUFTOOSMALL) ||
-        strcmp(migratedStr, "no") == 0)
-      continue;
-
-    // Get the profile location and add it to the locations array
-    REGINFO regInfo;
-    regInfo.size = sizeof(REGINFO);
-
-    if (NR_RegGetEntryInfo(reg, profileKey, (char *)"directory", &regInfo))
-      continue;
-
-    nsCAutoString dirStr;
-    dirStr.SetLength(regInfo.entryLength);
-
-    errCode = NR_RegGetEntryString(reg, profileKey, (char *)"directory",
-                                   dirStr.BeginWriting(), regInfo.entryLength);
-    // Remove trailing \0
-    dirStr.SetLength(regInfo.entryLength-1);
-
-    nsCOMPtr<nsILocalFile> dir;
-#ifdef XP_MACOSX
-    rv = NS_NewNativeLocalFile(EmptyCString(), PR_TRUE, getter_AddRefs(dir));
-    if (NS_FAILED(rv)) break;
-    dir->SetPersistentDescriptor(dirStr);
-#else
-    rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(dirStr), PR_TRUE,
-                         getter_AddRefs(dir));
-    if (NS_FAILED(rv)) break;
-#endif
-
-    PRBool exists;
-    dir->Exists(&exists);
-
-    if (exists) {
-      aProfileLocations->AppendElement(dir);
-
-      // Get the profile name and add it to the names array
-      nsString profileName;
-      CopyUTF8toUTF16(nsDependentCString(profileStr), profileName);
-
-      nsCOMPtr<nsISupportsString> profileNameString(
-        do_CreateInstance("@mozilla.org/supports-string;1"));
-
-      profileNameString->SetData(profileName);
-      aProfileNames->AppendElement(profileNameString);
-    }
-  }
-  NR_RegClose(reg);
-  NR_ShutdownRegistry();
-
-  return rv;
-}
-
-#define GETPREF(xform, method, value) \
-  nsresult rv = aBranch->method(xform->sourcePrefName, value); \
-  if (NS_SUCCEEDED(rv)) \
-    xform->prefHasValue = PR_TRUE; \
-  return rv;
-
-#define SETPREF(xform, method, value) \
-  if (xform->prefHasValue) { \
-    return aBranch->method(xform->targetPrefName ? xform->targetPrefName : xform->sourcePrefName, value); \
-  } \
-  return NS_OK;
-
-nsresult 
-nsNetscapeProfileMigratorBase::GetString(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  GETPREF(xform, GetCharPref, &xform->stringValue);
-}
-
-nsresult 
-nsNetscapeProfileMigratorBase::SetString(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  SETPREF(xform, SetCharPref, xform->stringValue);
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::GetWString(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  nsCOMPtr<nsIPrefLocalizedString> prefValue;
-  nsresult rv = aBranch->GetComplexValue(xform->sourcePrefName, 
-                                         NS_GET_IID(nsIPrefLocalizedString),
-                                         getter_AddRefs(prefValue));
-
-  if (NS_SUCCEEDED(rv) && prefValue) {
-    nsString data;
-    prefValue->ToString(getter_Copies(data));
-
-    xform->stringValue = ToNewCString(NS_ConvertUTF16toUTF8(data));
-    xform->prefHasValue = PR_TRUE;
-  }
-  return rv;
-}
-
-nsresult 
-nsNetscapeProfileMigratorBase::SetWStringFromASCII(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  if (xform->prefHasValue) {
-    nsCOMPtr<nsIPrefLocalizedString> pls(do_CreateInstance("@mozilla.org/pref-localizedstring;1"));
-    NS_ConvertUTF8toUTF16 data(xform->stringValue);
-    pls->SetData(data.get());
-    return aBranch->SetComplexValue(xform->targetPrefName ? xform->targetPrefName : xform->sourcePrefName, NS_GET_IID(nsIPrefLocalizedString), pls);
-  }
-  return NS_OK;
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::SetWString(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  if (xform->prefHasValue) {
-    nsCOMPtr<nsIPrefLocalizedString> pls(do_CreateInstance("@mozilla.org/pref-localizedstring;1"));
-    nsAutoString data = NS_ConvertUTF8toUTF16(xform->stringValue);
-    pls->SetData(data.get());
-    return aBranch->SetComplexValue(xform->targetPrefName ? xform->targetPrefName : xform->sourcePrefName, NS_GET_IID(nsIPrefLocalizedString), pls);
-  }
-  return NS_OK;
-}
-
-
-nsresult 
-nsNetscapeProfileMigratorBase::GetBool(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  GETPREF(xform, GetBoolPref, &xform->boolValue);
-}
-
-nsresult 
-nsNetscapeProfileMigratorBase::SetBool(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  SETPREF(xform, SetBoolPref, xform->boolValue);
-}
-
-nsresult 
-nsNetscapeProfileMigratorBase::GetInt(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  GETPREF(xform, GetIntPref, &xform->intValue);
-}
-
-nsresult 
-nsNetscapeProfileMigratorBase::SetInt(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  SETPREF(xform, SetIntPref, xform->intValue);
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::CopyFile(const nsAString& aSourceFileName, const nsAString& aTargetFileName)
-{
-  nsCOMPtr<nsIFile> sourceFile;
-  mSourceProfile->Clone(getter_AddRefs(sourceFile));
-
-  sourceFile->Append(aSourceFileName);
-  PRBool exists = PR_FALSE;
-  sourceFile->Exists(&exists);
-  if (!exists)
-    return NS_OK;
-
-  nsCOMPtr<nsIFile> targetFile;
-  mTargetProfile->Clone(getter_AddRefs(targetFile));
-  
-  targetFile->Append(aTargetFileName);
-  targetFile->Exists(&exists);
-  if (exists)
-    targetFile->Remove(PR_FALSE);
-
-  return sourceFile->CopyTo(mTargetProfile, aTargetFileName);
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::ImportNetscapeBookmarks(const nsAString& aBookmarksFileName,
-                                                       const PRUnichar* aImportSourceNameKey)
-{
-  nsCOMPtr<nsIFile> bookmarksFile;
-  mSourceProfile->Clone(getter_AddRefs(bookmarksFile));
-  bookmarksFile->Append(aBookmarksFileName);
-  
-  return ImportBookmarksHTML(bookmarksFile, PR_FALSE, PR_FALSE, aImportSourceNameKey);
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::ImportNetscapeCookies(nsIFile* aCookiesFile)
-{
-  nsresult rv;
-  nsCOMPtr<nsIInputStream> cookiesStream;
-  rv = NS_NewLocalFileInputStream(getter_AddRefs(cookiesStream), aCookiesFile);
-  if (NS_FAILED(rv)) return rv;
-
-  nsCOMPtr<nsILineInputStream> lineInputStream(do_QueryInterface(cookiesStream));
-
-  // This code is copied from mozilla/netwerk/cookie/src/nsCookieManager.cpp
-  static NS_NAMED_LITERAL_CSTRING(kTrue, "TRUE");
-
-  nsCAutoString buffer;
-  PRBool isMore = PR_TRUE;
-  PRInt32 hostIndex = 0, isDomainIndex, pathIndex, secureIndex, expiresIndex, nameIndex, cookieIndex;
-  PRInt32 numInts;
-  PRInt64 expires;
-  PRBool isDomain;
-  PRInt64 currentTime = PR_Now() / PR_USEC_PER_SEC;
-
-  nsCOMPtr<nsICookieManager2> cookieManager(do_GetService(NS_COOKIEMANAGER_CONTRACTID, &rv));
-  if (NS_FAILED(rv)) return rv;
-
-  /* file format is:
-   *
-   * host \t isDomain \t path \t secure \t expires \t name \t cookie
-   *
-   * if this format isn't respected we move onto the next line in the file.
-   * isDomain is "TRUE" or "FALSE" (default to "FALSE")
-   * isSecure is "TRUE" or "FALSE" (default to "TRUE")
-   * expires is a PRInt64 integer
-   * note 1: cookie can contain tabs.
-   * note 2: cookies are written in order of lastAccessed time:
-   *         most-recently used come first; least-recently-used come last.
-   */
-
-  while (isMore && NS_SUCCEEDED(lineInputStream->ReadLine(buffer, &isMore))) {
-    if (buffer.IsEmpty() || buffer.First() == '#')
-      continue;
-
-    // this is a cheap, cheesy way of parsing a tab-delimited line into
-    // string indexes, which can be lopped off into substrings. just for
-    // purposes of obfuscation, it also checks that each token was found.
-    // todo: use iterators?
-    if ((isDomainIndex = buffer.FindChar('\t', hostIndex)     + 1) == 0 ||
-        (pathIndex     = buffer.FindChar('\t', isDomainIndex) + 1) == 0 ||
-        (secureIndex   = buffer.FindChar('\t', pathIndex)     + 1) == 0 ||
-        (expiresIndex  = buffer.FindChar('\t', secureIndex)   + 1) == 0 ||
-        (nameIndex     = buffer.FindChar('\t', expiresIndex)  + 1) == 0 ||
-        (cookieIndex   = buffer.FindChar('\t', nameIndex)     + 1) == 0)
-      continue;
-
-    // check the expirytime first - if it's expired, ignore
-    // nullstomp the trailing tab, to avoid copying the string
-    char *iter = buffer.BeginWriting();
-    *(iter += nameIndex - 1) = char(0);
-    numInts = PR_sscanf(buffer.get() + expiresIndex, "%lld", &expires);
-    if (numInts != 1 || expires < currentTime)
-      continue;
-
-    isDomain = Substring(buffer, isDomainIndex, pathIndex - isDomainIndex - 1).Equals(kTrue);
-    const nsDependentCSubstring host =
-      Substring(buffer, hostIndex, isDomainIndex - hostIndex - 1);
-    // check for bad legacy cookies (domain not starting with a dot, or containing a port),
-    // and discard
-    if (isDomain && !host.IsEmpty() && host.First() != '.' ||
-        host.FindChar(':') != -1)
-      continue;
-
-    // create a new nsCookie and assign the data.
-    rv = cookieManager->Add(host,
-                            Substring(buffer, pathIndex, secureIndex - pathIndex - 1),
-                            Substring(buffer, nameIndex, cookieIndex - nameIndex - 1),
-                            Substring(buffer, cookieIndex, buffer.Length() - cookieIndex),
-                            Substring(buffer, secureIndex, expiresIndex - secureIndex - 1).Equals(kTrue),
-                            PR_FALSE, // isHttpOnly
-                            PR_FALSE, // isSession
-                            expires);
-  }
-
-  return rv;
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::GetSignonFileName(PRBool aReplace, char** aFileName)
-{
-  nsresult rv;
-  if (aReplace) {
-    // Find out what the signons file was called, this is stored in a pref
-    // in Seamonkey.
-    nsCOMPtr<nsIPrefService> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
-    psvc->ResetPrefs();
-
-    nsCOMPtr<nsIFile> sourcePrefsName;
-    mSourceProfile->Clone(getter_AddRefs(sourcePrefsName));
-    sourcePrefsName->Append(FILE_NAME_PREFS_5X);
-    psvc->ReadUserPrefs(sourcePrefsName);
-
-    nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(psvc));
-    rv = branch->GetCharPref("signon.SignonFileName", aFileName);
-  }
-  else 
-    rv = LocateSignonsFile(aFileName);
-  return rv;
-}
-
-nsresult
-nsNetscapeProfileMigratorBase::LocateSignonsFile(char** aResult)
-{
-  nsCOMPtr<nsISimpleEnumerator> entries;
-  nsresult rv = mSourceProfile->GetDirectoryEntries(getter_AddRefs(entries));
-  if (NS_FAILED(rv)) return rv;
-
-  nsCAutoString fileName;
-  do {
-    PRBool hasMore = PR_FALSE;
-    rv = entries->HasMoreElements(&hasMore);
-    if (NS_FAILED(rv) || !hasMore) break;
-
-    nsCOMPtr<nsISupports> supp;
-    rv = entries->GetNext(getter_AddRefs(supp));
-    if (NS_FAILED(rv)) break;
-
-    nsCOMPtr<nsIFile> currFile(do_QueryInterface(supp));
-
-    nsCOMPtr<nsIURI> uri;
-    rv = NS_NewFileURI(getter_AddRefs(uri), currFile);
-    if (NS_FAILED(rv)) break;
-    nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
-
-    nsCAutoString extn;
-    url->GetFileExtension(extn);
-
-    if (extn.Equals("s", CaseInsensitiveCompare)) {
-      url->GetFileName(fileName);
-      break;
-    }
-  }
-  while (1);
-
-  *aResult = ToNewCString(fileName);
-
-  return NS_OK;
-}
-
deleted file mode 100644
--- a/browser/components/migration/src/nsNetscapeProfileMigratorBase.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is The Browser Profile Migrator.
- *
- * The Initial Developer of the Original Code is Ben Goodger.
- * Portions created by the Initial Developer are Copyright (C) 2004
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Ben Goodger <ben@bengoodger.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef netscapeprofilemigratorbase___h___
-#define netscapeprofilemigratorbase___h___
-
-#include "nsILocalFile.h"
-#include "nsIStringBundle.h"
-#include "nsISupportsArray.h"
-#include "nsStringAPI.h"
-
-class nsIFile;
-class nsIPrefBranch;
-
-class nsNetscapeProfileMigratorBase
-{
-public:
-  nsNetscapeProfileMigratorBase();
-  virtual ~nsNetscapeProfileMigratorBase() { }
-
-public:
-  typedef nsresult(*prefConverter)(void*, nsIPrefBranch*);
-
-  struct PrefTransform {
-    const char*   sourcePrefName;
-    const char*   targetPrefName;
-    prefConverter prefGetterFunc;
-    prefConverter prefSetterFunc;
-    PRBool        prefHasValue;
-    union {
-      PRInt32     intValue;
-      PRBool      boolValue;
-      char*       stringValue;
-    };
-  };
-
-  static nsresult GetString(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult SetString(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult GetWString(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult SetWString(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult SetWStringFromASCII(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult GetBool(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult SetBool(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult GetInt(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult SetInt(void* aTransform, nsIPrefBranch* aBranch);
-
-protected:
-  nsresult GetProfileDataFromRegistry(nsILocalFile* aRegistryFile,
-                                      nsISupportsArray* aProfileNames,
-                                      nsISupportsArray* aProfileLocations);
-
-  nsresult CopyFile(const nsAString& aSourceFileName, const nsAString& aTargetFileName);
-
-  nsresult ImportNetscapeBookmarks(const nsAString& aBookmarksFileName,
-                                   const PRUnichar* aImportSourceNameKey);
-
-  nsresult ImportNetscapeCookies(nsIFile* aCookiesFile);
-
-  nsresult GetSignonFileName(PRBool aReplace, char** aFileName);
-  nsresult LocateSignonsFile(char** aResult);
-
-protected:
-  nsCOMPtr<nsILocalFile> mSourceProfile;
-  nsCOMPtr<nsIFile> mTargetProfile;
-};
- 
-#endif
--- a/browser/components/migration/src/nsProfileMigrator.cpp
+++ b/browser/components/migration/src/nsProfileMigrator.cpp
@@ -157,17 +157,16 @@ nsProfileMigrator::Import()
 // nsProfileMigrator
 
 NS_IMPL_ISUPPORTS1(nsProfileMigrator, nsIProfileMigrator)
 
 #ifdef XP_WIN
 
 #define INTERNAL_NAME_IEXPLORE        "iexplore"
 #define INTERNAL_NAME_MOZILLA_SUITE   "apprunner"
-#define INTERNAL_NAME_SEAMONKEY       "seamonkey"
 #define INTERNAL_NAME_OPERA           "opera"
 #endif
 
 nsresult
 nsProfileMigrator::GetDefaultBrowserMigratorKey(nsACString& aKey,
                                                 nsCOMPtr<nsIBrowserProfileMigrator>& bpm)
 {
 #if XP_WIN
@@ -238,22 +237,17 @@ nsProfileMigrator::GetDefaultBrowserMigr
   nsAutoString internalName;
   if (NS_FAILED(lfw->GetVersionInfoField("InternalName", internalName)))
     return NS_ERROR_FAILURE;
 
   if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_IEXPLORE)) {
     aKey = "ie";
     return NS_OK;
   }
-  if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_MOZILLA_SUITE) ||
-      internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_SEAMONKEY)) {
-    aKey = "seamonkey";
-    return NS_OK;
-  }
-  if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_OPERA)) {
+  else if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_OPERA)) {
     aKey = "opera";
     return NS_OK;
   }
 
 #else
   PRBool exists = PR_FALSE;
 #define CHECK_MIGRATOR(browser) do {\
   bpm = do_CreateInstance(NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX browser);\
@@ -262,17 +256,16 @@ nsProfileMigrator::GetDefaultBrowserMigr
   if (exists) {\
     aKey = browser;\
     return NS_OK;\
   }} while(0)
 
 #if defined(XP_MACOSX)
   CHECK_MIGRATOR("safari");
 #endif
-  CHECK_MIGRATOR("seamonkey");
   CHECK_MIGRATOR("opera");
 
 #undef CHECK_MIGRATOR
 #endif
   return NS_ERROR_FAILURE;
 }
 
 PRBool
deleted file mode 100644
--- a/browser/components/migration/src/nsSeamonkeyProfileMigrator.cpp
+++ /dev/null
@@ -1,721 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is The Browser Profile Migrator.
- *
- * The Initial Developer of the Original Code is Ben Goodger.
- * Portions created by the Initial Developer are Copyright (C) 2004
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Ben Goodger <ben@bengoodger.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsBrowserProfileMigratorUtils.h"
-#include "nsDirectoryServiceDefs.h"
-#include "nsIObserverService.h"
-#include "nsILoginInfo.h"
-#include "nsILoginManager.h"
-#include "nsILoginManagerStorage.h"
-#include "nsIPrefLocalizedString.h"
-#include "nsIPrefService.h"
-#include "nsIServiceManager.h"
-#include "nsISupportsArray.h"
-#include "nsISupportsPrimitives.h"
-#include "nsNetCID.h"
-#include "nsNetUtil.h"
-#include "nsSeamonkeyProfileMigrator.h"
-#include "nsIProfileMigrator.h"
-
-///////////////////////////////////////////////////////////////////////////////
-// nsSeamonkeyProfileMigrator
-
-#define FILE_NAME_BOOKMARKS       NS_LITERAL_STRING("bookmarks.html")
-#define FILE_NAME_COOKIES         NS_LITERAL_STRING("cookies.txt")
-#define FILE_NAME_SITEPERM_OLD    NS_LITERAL_STRING("cookperm.txt")
-#define FILE_NAME_SITEPERM_NEW    NS_LITERAL_STRING("hostperm.1")
-#define FILE_NAME_CERT8DB         NS_LITERAL_STRING("cert8.db")
-#define FILE_NAME_KEY3DB          NS_LITERAL_STRING("key3.db")
-#define FILE_NAME_SECMODDB        NS_LITERAL_STRING("secmod.db")
-#define FILE_NAME_MIMETYPES       NS_LITERAL_STRING("mimeTypes.rdf")
-#define FILE_NAME_DOWNLOADS       NS_LITERAL_STRING("downloads.rdf")
-#define FILE_NAME_PREFS           NS_LITERAL_STRING("prefs.js")
-#define FILE_NAME_USER_PREFS      NS_LITERAL_STRING("user.js")
-#define FILE_NAME_USERCONTENT     NS_LITERAL_STRING("userContent.css")
-#define DIR_NAME_CHROME           NS_LITERAL_STRING("chrome")
-
-NS_IMPL_ISUPPORTS1(nsSeamonkeyProfileMigrator, nsIBrowserProfileMigrator)
-
-nsSeamonkeyProfileMigrator::nsSeamonkeyProfileMigrator()
-{
-  mObserverService = do_GetService("@mozilla.org/observer-service;1");
-}
-
-nsSeamonkeyProfileMigrator::~nsSeamonkeyProfileMigrator()
-{
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// nsIBrowserProfileMigrator
-
-NS_IMETHODIMP
-nsSeamonkeyProfileMigrator::Migrate(PRUint16 aItems, nsIProfileStartup* aStartup, const PRUnichar* aProfile)
-{
-  nsresult rv = NS_OK;
-  PRBool aReplace = aStartup ? PR_TRUE : PR_FALSE;
-
-  if (!mTargetProfile) {
-    GetProfilePath(aStartup, mTargetProfile);
-    if (!mTargetProfile) return NS_ERROR_FAILURE;
-  }
-  if (!mSourceProfile)
-    GetSourceProfile(aProfile);
-
-  NOTIFY_OBSERVERS(MIGRATION_STARTED, nsnull);
-
-  COPY_DATA(CopyPreferences,  aReplace, nsIBrowserProfileMigrator::SETTINGS);
-  COPY_DATA(CopyCookies,      aReplace, nsIBrowserProfileMigrator::COOKIES);
-  COPY_DATA(CopyPasswords,    aReplace, nsIBrowserProfileMigrator::PASSWORDS);
-  COPY_DATA(CopyOtherData,    aReplace, nsIBrowserProfileMigrator::OTHERDATA);
-
-  // Need to do startup before trying to copy bookmarks, since bookmarks
-  // import requires a profile. Can't do it earlier because services might
-  // end up creating the files we try to copy above.
-  if (aStartup) {
-    rv = aStartup->DoStartup();
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  COPY_DATA(CopyBookmarks,    aReplace, nsIBrowserProfileMigrator::BOOKMARKS);
-
-  if (aReplace && 
-      (aItems & nsIBrowserProfileMigrator::SETTINGS || 
-       aItems & nsIBrowserProfileMigrator::COOKIES || 
-       aItems & nsIBrowserProfileMigrator::PASSWORDS ||
-       !aItems)) {
-    // Permissions (Images, Cookies, Popups)
-    rv |= CopyFile(FILE_NAME_SITEPERM_NEW, FILE_NAME_SITEPERM_NEW);
-    rv |= CopyFile(FILE_NAME_SITEPERM_OLD, FILE_NAME_SITEPERM_OLD);
-  }
-
-  NOTIFY_OBSERVERS(MIGRATION_ENDED, nsnull);
-
-  return rv;
-}
-
-NS_IMETHODIMP
-nsSeamonkeyProfileMigrator::GetMigrateData(const PRUnichar* aProfile, 
-                                           PRBool aReplace, 
-                                           PRUint16* aResult)
-{
-  *aResult = 0;
-
-  if (!mSourceProfile) {
-    GetSourceProfile(aProfile);
-    if (!mSourceProfile)
-      return NS_ERROR_FILE_NOT_FOUND;
-  }
-
-  MigrationData data[] = { { ToNewUnicode(FILE_NAME_PREFS),
-                             nsIBrowserProfileMigrator::SETTINGS,
-                             PR_TRUE },
-                           { ToNewUnicode(FILE_NAME_USER_PREFS),
-                             nsIBrowserProfileMigrator::SETTINGS,
-                             PR_TRUE },
-                           { ToNewUnicode(FILE_NAME_COOKIES),
-                             nsIBrowserProfileMigrator::COOKIES,
-                             PR_FALSE },
-                           { ToNewUnicode(FILE_NAME_BOOKMARKS),
-                             nsIBrowserProfileMigrator::BOOKMARKS,
-                             PR_FALSE },
-                           { ToNewUnicode(FILE_NAME_DOWNLOADS),
-                             nsIBrowserProfileMigrator::OTHERDATA,
-                             PR_TRUE },
-                           { ToNewUnicode(FILE_NAME_MIMETYPES),
-                             nsIBrowserProfileMigrator::OTHERDATA,
-                             PR_TRUE } };
-                                                                  
-  // Frees file name strings allocated above.
-  GetMigrateDataFromArray(data, sizeof(data)/sizeof(MigrationData), 
-                          aReplace, mSourceProfile, aResult);
-
-  // Now locate passwords
-  nsCString signonsFileName;
-  GetSignonFileName(aReplace, getter_Copies(signonsFileName));
-
-  if (!signonsFileName.IsEmpty()) {
-    NS_ConvertASCIItoUTF16 fileName(signonsFileName);
-    nsCOMPtr<nsIFile> sourcePasswordsFile;
-    mSourceProfile->Clone(getter_AddRefs(sourcePasswordsFile));
-    sourcePasswordsFile->Append(fileName);
-    
-    PRBool exists;
-    sourcePasswordsFile->Exists(&exists);
-    if (exists)
-      *aResult |= nsIBrowserProfileMigrator::PASSWORDS;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSeamonkeyProfileMigrator::GetSourceExists(PRBool* aResult)
-{
-  nsCOMPtr<nsISupportsArray> profiles;
-  GetSourceProfiles(getter_AddRefs(profiles));
-
-  if (profiles) { 
-    PRUint32 count;
-    profiles->Count(&count);
-    *aResult = count > 0;
-  }
-  else
-    *aResult = PR_FALSE;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSeamonkeyProfileMigrator::GetSourceHasMultipleProfiles(PRBool* aResult)
-{
-  nsCOMPtr<nsISupportsArray> profiles;
-  GetSourceProfiles(getter_AddRefs(profiles));
-
-  if (profiles) {
-    PRUint32 count;
-    profiles->Count(&count);
-    *aResult = count > 1;
-  }
-  else
-    *aResult = PR_FALSE;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSeamonkeyProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
-{
-  if (!mProfileNames && !mProfileLocations) {
-    mProfileNames = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
-    mProfileLocations = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
-    NS_ENSURE_TRUE(mProfileNames && mProfileLocations, NS_ERROR_UNEXPECTED);
-
-    // Fills mProfileNames and mProfileLocations
-    FillProfileDataFromSeamonkeyRegistry();
-  }
-  
-  NS_IF_ADDREF(*aResult = mProfileNames);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSeamonkeyProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
-{
-  // Load the source pref file
-  nsCOMPtr<nsIPrefService> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
-  psvc->ResetPrefs();
-
-  nsCOMPtr<nsIFile> sourcePrefsFile;
-  
-  mSourceProfile->Clone(getter_AddRefs(sourcePrefsFile));
-  sourcePrefsFile->Append(FILE_NAME_PREFS);
-
-  psvc->ReadUserPrefs(sourcePrefsFile);
-
-  nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(psvc));
-
-  PRBool hasUserValue;
-  nsCOMPtr<nsIPrefLocalizedString> prefValue;
-  nsresult rv = branch->PrefHasUserValue("browser.startup.homepage", &hasUserValue);
-  if (NS_SUCCEEDED(rv) && hasUserValue) {
-    rv = branch->GetComplexValue("browser.startup.homepage", 
-                                 NS_GET_IID(nsIPrefLocalizedString),
-                                 getter_AddRefs(prefValue));
-    if (NS_SUCCEEDED(rv) && prefValue) {
-      nsString data;
-      prefValue->ToString(getter_Copies(data));
-
-      nsCAutoString val;
-      val = ToNewCString(NS_ConvertUTF16toUTF8(data));
-
-      aResult.Assign(val);
-    }
-  }
-
-  psvc->ResetPrefs();
-  psvc->ReadUserPrefs(nsnull);
-
-  return NS_OK;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// nsSeamonkeyProfileMigrator
-
-nsresult
-nsSeamonkeyProfileMigrator::GetSourceProfile(const PRUnichar* aProfile)
-{
-  PRUint32 count;
-  mProfileNames->Count(&count);
-  for (PRUint32 i = 0; i < count; ++i) {
-    nsCOMPtr<nsISupportsString> str;
-    mProfileNames->QueryElementAt(i, NS_GET_IID(nsISupportsString),
-                                  getter_AddRefs(str));
-    nsString profileName;
-    str->GetData(profileName);
-    if (profileName.Equals(aProfile)) {
-      mProfileLocations->QueryElementAt(i, NS_GET_IID(nsILocalFile),
-                                        getter_AddRefs(mSourceProfile));
-      break;
-    }
-  }
-
-  return NS_OK;
-}
-
-nsresult
-nsSeamonkeyProfileMigrator::FillProfileDataFromSeamonkeyRegistry()
-{
-  // Find the Seamonkey Registry
-  nsCOMPtr<nsIProperties> fileLocator(do_GetService("@mozilla.org/file/directory_service;1"));
-  nsCOMPtr<nsILocalFile> seamonkeyRegistry;
-#ifdef XP_WIN
-  fileLocator->Get(NS_WIN_APPDATA_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(seamonkeyRegistry));
-
-  seamonkeyRegistry->Append(NS_LITERAL_STRING("Mozilla"));
-  seamonkeyRegistry->Append(NS_LITERAL_STRING("registry.dat"));
-#elif defined(XP_MACOSX)
-  fileLocator->Get(NS_MAC_USER_LIB_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(seamonkeyRegistry));
-  
-  seamonkeyRegistry->Append(NS_LITERAL_STRING("Mozilla"));
-  seamonkeyRegistry->Append(NS_LITERAL_STRING("Application Registry"));
-#elif defined(XP_UNIX)
-  fileLocator->Get(NS_UNIX_HOME_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(seamonkeyRegistry));
-  
-  seamonkeyRegistry->Append(NS_LITERAL_STRING(".mozilla"));
-  seamonkeyRegistry->Append(NS_LITERAL_STRING("appreg"));
-#elif defined(XP_OS2)
-  fileLocator->Get(NS_OS2_HOME_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(seamonkeyRegistry));
-  
-  seamonkeyRegistry->Append(NS_LITERAL_STRING("Mozilla"));
-  seamonkeyRegistry->Append(NS_LITERAL_STRING("registry.dat"));
-#endif
-
-  return GetProfileDataFromRegistry(seamonkeyRegistry, mProfileNames, mProfileLocations);
-}
-
-#define F(a) nsSeamonkeyProfileMigrator::a
-
-#define MAKEPREFTRANSFORM(pref, newpref, getmethod, setmethod) \
-  { pref, newpref, F(Get##getmethod), F(Set##setmethod), PR_FALSE, { -1 } }
-
-#define MAKESAMETYPEPREFTRANSFORM(pref, method) \
-  { pref, 0, F(Get##method), F(Set##method), PR_FALSE, { -1 } }
-
-
-static 
-nsSeamonkeyProfileMigrator::PrefTransform gTransforms[] = {
-  MAKESAMETYPEPREFTRANSFORM("signon.SignonFileName",                    String),
-  MAKESAMETYPEPREFTRANSFORM("browser.tabs.autoHide",                    Bool),
-  MAKESAMETYPEPREFTRANSFORM("browser.tabs.loadInBackground",            Bool),
-  MAKESAMETYPEPREFTRANSFORM("browser.enable_automatic_image_resizing",  Bool),
-  MAKESAMETYPEPREFTRANSFORM("network.cookie.warnAboutCookies",          Bool),
-  MAKESAMETYPEPREFTRANSFORM("network.cookie.lifetime.enabled",          Bool),
-  MAKESAMETYPEPREFTRANSFORM("network.cookie.lifetime.behavior",         Int),
-  MAKESAMETYPEPREFTRANSFORM("dom.disable_open_during_load",             Bool),
-  MAKESAMETYPEPREFTRANSFORM("signon.rememberSignons",                   Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.enable_ssl3",                     Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.enable_tls",                      Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.warn_entering_secure",            Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.warn_entering_weak",              Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.warn_leaving_secure",             Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.warn_submit_insecure",            Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.warn_viewing_mixed",              Bool),
-  MAKESAMETYPEPREFTRANSFORM("security.default_personal_cert",           String),
-  MAKESAMETYPEPREFTRANSFORM("security.OSCP.enabled",                    Int),
-  MAKESAMETYPEPREFTRANSFORM("security.OSCP.signingCA",                  String),
-  MAKESAMETYPEPREFTRANSFORM("security.OSCP.URL",                        String),
-  MAKESAMETYPEPREFTRANSFORM("javascript.enabled",                       Bool),
-  MAKESAMETYPEPREFTRANSFORM("dom.disable_window_move_resize",           Bool),
-  MAKESAMETYPEPREFTRANSFORM("dom.disable_window_flip",                  Bool),
-  MAKESAMETYPEPREFTRANSFORM("dom.disable_window_open_feature.status",   Bool),
-  MAKESAMETYPEPREFTRANSFORM("dom.disable_window_status_change",         Bool),
-  MAKESAMETYPEPREFTRANSFORM("dom.disable_image_src_set",                Bool),
-  MAKESAMETYPEPREFTRANSFORM("accessibility.typeaheadfind.autostart",    Bool),
-  MAKESAMETYPEPREFTRANSFORM("accessibility.typeaheadfind.linksonly",    Bool),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.type",                       Int),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.http",                       String),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.http_port",                  Int),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.ftp",                        String),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.ftp_port",                   Int),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.ssl",                        String),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.ssl_port",                   Int),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.socks",                      String),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.socks_port",                 Int),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.no_proxies_on",              String),
-  MAKESAMETYPEPREFTRANSFORM("network.proxy.autoconfig_url",             String),
-  MAKESAMETYPEPREFTRANSFORM("browser.display.foreground_color",         String),
-  MAKESAMETYPEPREFTRANSFORM("browser.display.background_color",         String),
-  MAKESAMETYPEPREFTRANSFORM("browser.anchor_color",                     String),
-  MAKESAMETYPEPREFTRANSFORM("browser.visited_color",                    String),
-  MAKESAMETYPEPREFTRANSFORM("browser.underline_anchors",                Bool),
-  MAKESAMETYPEPREFTRANSFORM("browser.display.use_system_colors",        Bool),
-  MAKESAMETYPEPREFTRANSFORM("browser.display.use_document_colors",      Bool),
-  MAKESAMETYPEPREFTRANSFORM("browser.display.use_document_fonts",       Bool),
-  MAKESAMETYPEPREFTRANSFORM("intl.charset.default",                     String),
-  MAKESAMETYPEPREFTRANSFORM("intl.accept_languages",                    String),
-
-  MAKEPREFTRANSFORM("network.image.imageBehavior",      0, Int, Image),
-  MAKEPREFTRANSFORM("network.cookie.cookieBehavior",    0, Int, Cookie),
-  MAKEPREFTRANSFORM("browser.downloadmanager.behavior", 0, Int, DownloadManager),
-
-  MAKEPREFTRANSFORM("wallet.captureForms", "formfill.enabled", Bool, Bool)
-};
-
-nsresult 
-nsSeamonkeyProfileMigrator::SetImage(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  nsresult rv = NS_OK;
-
-  if (xform->prefHasValue)
-    rv = aBranch->SetIntPref("network.image.imageBehavior", xform->intValue == 1 ? 0 : xform->intValue);
-
-  return rv;
-}
-
-nsresult 
-nsSeamonkeyProfileMigrator::SetCookie(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  nsresult rv = NS_OK;
-
-  if (xform->prefHasValue)
-    rv = aBranch->SetIntPref("network.cookie.cookieBehavior", xform->intValue == 3 ? 0 : xform->intValue);
-
-  return rv;
-}
-
-nsresult 
-nsSeamonkeyProfileMigrator::SetDownloadManager(void* aTransform, nsIPrefBranch* aBranch)
-{
-  PrefTransform* xform = (PrefTransform*)aTransform;
-  nsresult rv = NS_OK;
-  
-  if (xform->prefHasValue) {
-    // Seamonkey's download manager uses a single pref to control behavior:
-    // 0 - show download manager window
-    // 1 - show individual progress dialogs
-    // 2 - show nothing
-    //
-    // Firefox has only a download manager window, but it can behave like a progress dialog, thus:
-    // 0 || 1  -> show downloads window when a download starts
-    // 2       -> don't show anything when a download starts
-    // 1       -> close the downloads window as if it were a progress window when downloads complete.
-    //
-    rv |= aBranch->SetBoolPref("browser.download.manager.showWhenStarting", xform->intValue != 2);
-    rv |= aBranch->SetBoolPref("browser.download.manager.closeWhenDone", xform->intValue == 1);
-  }
-  return NS_OK;
-}
-
-nsresult
-nsSeamonkeyProfileMigrator::TransformPreferences(const nsAString& aSourcePrefFileName,
-                                                 const nsAString& aTargetPrefFileName)
-{
-  PrefTransform* transform;
-  PrefTransform* end = gTransforms + sizeof(gTransforms)/sizeof(PrefTransform);
-
-  // Load the source pref file
-  nsCOMPtr<nsIPrefService> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
-  psvc->ResetPrefs();
-
-  nsCOMPtr<nsIFile> sourcePrefsFile;
-  mSourceProfile->Clone(getter_AddRefs(sourcePrefsFile));
-  sourcePrefsFile->Append(aSourcePrefFileName);
-  psvc->ReadUserPrefs(sourcePrefsFile);
-
-  nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(psvc));
-  for (transform = gTransforms; transform < end; ++transform)
-    transform->prefGetterFunc(transform, branch);
-
-  nsTArray<FontPref> fontPrefs;
-  ReadFontsBranch(psvc, &fontPrefs);
-
-  // Now that we have all the pref data in memory, load the target pref file,
-  // and write it back out
-  psvc->ResetPrefs();
-  for (transform = gTransforms; transform < end; ++transform)
-    transform->prefSetterFunc(transform, branch);
-
-  WriteFontsBranch(psvc, &fontPrefs);
-
-  nsCOMPtr<nsIFile> targetPrefsFile;
-  mTargetProfile->Clone(getter_AddRefs(targetPrefsFile));
-  targetPrefsFile->Append(aTargetPrefFileName);
-  psvc->SavePrefFile(targetPrefsFile);
-
-  psvc->ResetPrefs();
-  psvc->ReadUserPrefs(nsnull);
-
-  return NS_OK;
-}
-
-void
-nsSeamonkeyProfileMigrator::ReadFontsBranch(nsIPrefService* aPrefService, 
-                                            nsTArray<FontPref>* aPrefs)
-{
-  // Enumerate the branch
-  nsCOMPtr<nsIPrefBranch> branch;
-  aPrefService->GetBranch("font.", getter_AddRefs(branch));
-
-  PRUint32 count;
-  char** prefs = nsnull;
-  nsresult rv = branch->GetChildList("", &count, &prefs);
-  if (NS_FAILED(rv)) return;
-
-  for (PRUint32 i = 0; i < count; ++i) {
-    // Save each pref's value into an array
-    char* currPref = prefs[i];
-    PRInt32 type;
-    branch->GetPrefType(currPref, &type);
-    FontPref* pref = aPrefs->AppendElement();
-    pref->prefName = currPref;
-    pref->type = type;
-    switch (type) {
-    case nsIPrefBranch::PREF_STRING:
-      rv = branch->GetCharPref(currPref, &pref->stringValue);
-      break;
-    case nsIPrefBranch::PREF_BOOL:
-      rv = branch->GetBoolPref(currPref, &pref->boolValue);
-      break;
-    case nsIPrefBranch::PREF_INT:
-      rv = branch->GetIntPref(currPref, &pref->intValue);
-      break;
-    case nsIPrefBranch::PREF_INVALID:
-      {
-        nsCOMPtr<nsIPrefLocalizedString> str;
-        rv = branch->GetComplexValue(currPref, 
-                                    NS_GET_IID(nsIPrefLocalizedString), 
-                                    getter_AddRefs(str));
-        if (NS_SUCCEEDED(rv) && str)
-          str->ToString(&pref->wstringValue);
-      }
-      break;
-    }
-
-    if (NS_FAILED(rv))
-      aPrefs->RemoveElementAt(aPrefs->Length()-1);
-  }
-}
-
-void
-nsSeamonkeyProfileMigrator::WriteFontsBranch(nsIPrefService* aPrefService,
-                                             nsTArray<FontPref>* aPrefs)
-{
-  nsresult rv;
-
-  // Enumerate the branch
-  nsCOMPtr<nsIPrefBranch> branch;
-  aPrefService->GetBranch("font.", getter_AddRefs(branch));
-
-  PRUint32 count = aPrefs->Length();
-  for (PRUint32 i = 0; i < count; ++i) {
-    FontPref &pref = aPrefs->ElementAt(i);
-    switch (pref.type) {
-    case nsIPrefBranch::PREF_STRING:
-      rv = branch->SetCharPref(pref.prefName, pref.stringValue);
-      NS_Free(pref.stringValue);
-      pref.stringValue = nsnull;
-      break;
-    case nsIPrefBranch::PREF_BOOL:
-      rv = branch->SetBoolPref(pref.prefName, pref.boolValue);
-      break;
-    case nsIPrefBranch::PREF_INT:
-      rv = branch->SetIntPref(pref.prefName, pref.intValue);
-      break;
-    case nsIPrefBranch::PREF_INVALID:
-      nsCOMPtr<nsIPrefLocalizedString> pls(do_CreateInstance("@mozilla.org/pref-localizedstring;1"));
-      pls->SetData(pref.wstringValue);
-      rv = branch->SetComplexValue(pref.prefName, 
-                                   NS_GET_IID(nsIPrefLocalizedString),
-                                   pls);
-      NS_Free(pref.wstringValue);
-      pref.wstringValue = nsnull;
-      break;
-    }
-    NS_Free(pref.prefName);
-  }
-  aPrefs->Clear();
-}
-
-nsresult
-nsSeamonkeyProfileMigrator::CopyPreferences(PRBool aReplace)
-{
-  nsresult rv = NS_OK;
-  if (!aReplace)
-    return rv;
-
-  rv |= TransformPreferences(FILE_NAME_PREFS, FILE_NAME_PREFS);
-  rv |= CopyFile(FILE_NAME_USER_PREFS, FILE_NAME_USER_PREFS);
-
-  // Security Stuff
-  rv |= CopyFile(FILE_NAME_CERT8DB, FILE_NAME_CERT8DB);
-  rv |= CopyFile(FILE_NAME_KEY3DB, FILE_NAME_KEY3DB);
-  rv |= CopyFile(FILE_NAME_SECMODDB, FILE_NAME_SECMODDB);
-
-  // User MIME Type overrides
-  rv |= CopyFile(FILE_NAME_MIMETYPES, FILE_NAME_MIMETYPES);
-
-  rv |= CopyUserContentSheet();
-  return rv;
-}
-
-nsresult 
-nsSeamonkeyProfileMigrator::CopyUserContentSheet()
-{
-  nsCOMPtr<nsIFile> sourceUserContent;
-  mSourceProfile->Clone(getter_AddRefs(sourceUserContent));
-  sourceUserContent->Append(DIR_NAME_CHROME);
-  sourceUserContent->Append(FILE_NAME_USERCONTENT);
-
-  PRBool exists = PR_FALSE;
-  sourceUserContent->Exists(&exists);
-  if (!exists)
-    return NS_OK;
-
-  nsCOMPtr<nsIFile> targetUserContent;
-  mTargetProfile->Clone(getter_AddRefs(targetUserContent));
-  targetUserContent->Append(DIR_NAME_CHROME);
-  nsCOMPtr<nsIFile> targetChromeDir;
-  targetUserContent->Clone(getter_AddRefs(targetChromeDir));
-  targetUserContent->Append(FILE_NAME_USERCONTENT);
-
-  targetUserContent->Exists(&exists);
-  if (exists)
-    targetUserContent->Remove(PR_FALSE);
-
-  return sourceUserContent->CopyTo(targetChromeDir, FILE_NAME_USERCONTENT);
-}
-
-nsresult
-nsSeamonkeyProfileMigrator::CopyCookies(PRBool aReplace)
-{
-  nsresult rv;
-  if (aReplace)
-    rv = CopyFile(FILE_NAME_COOKIES, FILE_NAME_COOKIES);
-  else {
-    nsCOMPtr<nsIFile> seamonkeyCookiesFile;
-    mSourceProfile->Clone(getter_AddRefs(seamonkeyCookiesFile));
-    seamonkeyCookiesFile->Append(FILE_NAME_COOKIES);
-
-    rv = ImportNetscapeCookies(seamonkeyCookiesFile);
-  }
-  return rv;
-}
-
-nsresult
-nsSeamonkeyProfileMigrator::CopyPasswords(PRBool aReplace)
-{
-  nsresult rv;
-
-  nsCString signonsFileName;
-  GetSignonFileName(aReplace, getter_Copies(signonsFileName));
-
-  if (signonsFileName.IsEmpty())
-    return NS_ERROR_FILE_NOT_FOUND;
-
-  NS_ConvertASCIItoUTF16 fileName(signonsFileName);
-  if (aReplace)
-    rv = CopyFile(fileName, fileName);
-  else {
-    // Get the password manager, which is the destination for the passwords
-    // being migrated. Also create a new instance of the legacy password
-    // storage component, which we'll use to slurp in the signons from
-    // Seamonkey's signons.txt.
-    nsCOMPtr<nsILoginManager> pwmgr(
-        do_GetService("@mozilla.org/login-manager;1"));
-    nsCOMPtr<nsILoginManagerStorage> importer(
-        do_CreateInstance("@mozilla.org/login-manager/storage/legacy;1"));
-
-    nsCOMPtr<nsIFile> signonsFile;
-    mSourceProfile->Clone(getter_AddRefs(signonsFile));
-    signonsFile->Append(fileName);
-
-    importer->InitWithFile(signonsFile, nsnull);
-
-    PRUint32 count;
-    nsILoginInfo **logins;
-
-    rv = importer->GetAllLogins(&count, &logins);
-    NS_ENSURE_SUCCESS(rv, rv);
-    for (PRUint32 i = 0; i < count; i++) {
-        pwmgr->AddLogin(logins[i]);
-    }
-    NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
-
-    PRUnichar **hostnames;
-    rv = importer->GetAllDisabledHosts(&count, &hostnames);
-    NS_ENSURE_SUCCESS(rv, rv);
-    for (PRUint32 i = 0; i < count; i++) {
-        pwmgr->SetLoginSavingEnabled(nsDependentString(hostnames[i]),
-                                     PR_FALSE);
-    }
-    NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, hostnames);
-  }
-  return rv;
-}
-
-nsresult
-nsSeamonkeyProfileMigrator::CopyBookmarks(PRBool aReplace)
-{
-  nsresult rv;
-  if (aReplace) {
-    // Initialize the default bookmarks
-    rv = InitializeBookmarks(mTargetProfile);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // Merge in the bookmarks from the source profile
-    nsCOMPtr<nsIFile> sourceFile;
-    mSourceProfile->Clone(getter_AddRefs(sourceFile));
-    sourceFile->Append(FILE_NAME_BOOKMARKS);
-    rv = ImportBookmarksHTML(sourceFile, PR_TRUE, PR_FALSE, EmptyString().get());
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-  else {
-    rv = ImportNetscapeBookmarks(FILE_NAME_BOOKMARKS, 
-                                 NS_LITERAL_STRING("sourceNameSeamonkey").get());
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-  return NS_OK;
-}
-
-nsresult
-nsSeamonkeyProfileMigrator::CopyOtherData(PRBool aReplace)
-{
-  return aReplace ? CopyFile(FILE_NAME_DOWNLOADS, FILE_NAME_DOWNLOADS) : NS_OK;
-}
-
deleted file mode 100644
--- a/browser/components/migration/src/nsSeamonkeyProfileMigrator.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is The Browser Profile Migrator.
- *
- * The Initial Developer of the Original Code is Ben Goodger.
- * Portions created by the Initial Developer are Copyright (C) 2004
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Ben Goodger <ben@bengoodger.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef seamonkeyprofilemigrator___h___
-#define seamonkeyprofilemigrator___h___
-
-#include "nsIBrowserProfileMigrator.h"
-#include "nsILocalFile.h"
-#include "nsIObserverService.h"
-#include "nsISupportsArray.h"
-#include "nsNetscapeProfileMigratorBase.h"
-#include "nsStringAPI.h"
-#include "nsTArray.h"
-
-class nsIFile;
-class nsIPrefBranch;
-class nsIPrefService;
-
-struct FontPref {
-  char*         prefName;
-  PRInt32       type;
-  union {
-    char*       stringValue;
-    PRInt32     intValue;
-    PRBool      boolValue;
-    PRUnichar*  wstringValue;
-  };
-};
-
-class nsSeamonkeyProfileMigrator : public nsNetscapeProfileMigratorBase, 
-                                   public nsIBrowserProfileMigrator
-{
-public:
-  NS_DECL_NSIBROWSERPROFILEMIGRATOR
-  NS_DECL_ISUPPORTS
-
-  nsSeamonkeyProfileMigrator();
-  virtual ~nsSeamonkeyProfileMigrator();
-
-public:
-  static nsresult SetImage(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult SetCookie(void* aTransform, nsIPrefBranch* aBranch);
-  static nsresult SetDownloadManager(void* aTransform, nsIPrefBranch* aBranch);
-
-protected:
-  nsresult FillProfileDataFromSeamonkeyRegistry();
-  nsresult GetSourceProfile(const PRUnichar* aProfile);
-
-  nsresult CopyPreferences(PRBool aReplace);
-  nsresult TransformPreferences(const nsAString& aSourcePrefFileName,
-                                const nsAString& aTargetPrefFileName);
-  void     ReadFontsBranch(nsIPrefService* aPrefService,
-                           nsTArray<FontPref>* aPrefs);
-  void     WriteFontsBranch(nsIPrefService* aPrefService,
-                            nsTArray<FontPref>* aPrefs);
-
-  nsresult CopyUserContentSheet();
-
-  nsresult CopyCookies(PRBool aReplace);
-  nsresult CopyPasswords(PRBool aReplace);
-  nsresult LocateSignonsFile(char** aResult);
-  nsresult CopyBookmarks(PRBool aReplace);
-  nsresult CopyOtherData(PRBool aReplace);
-
-private:
-  nsCOMPtr<nsISupportsArray> mProfileNames;
-  nsCOMPtr<nsISupportsArray> mProfileLocations;
-  nsCOMPtr<nsIObserverService> mObserverService;
-};
- 
-#endif
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -272,27 +272,40 @@ var PlacesOrganizer = {
   },
 
   /**
    * Sets the search scope based on aNode's properties.
    * @param   aNode
    *          the node to set up scope from
    */
   _setSearchScopeForNode: function PO__setScopeForNode(aNode) {
-    var itemId = aNode.itemId;
+    let itemId = aNode.itemId;
+
+    // Set default buttons status.
+    let bookmarksButton = document.getElementById("scopeBarAll");
+    bookmarksButton.hidden = false;
+    let downloadsButton = document.getElementById("scopeBarDownloads");
+    downloadsButton.hidden = true;
+
     if (PlacesUtils.nodeIsHistoryContainer(aNode) ||
         itemId == PlacesUIUtils.leftPaneQueries["History"]) {
       PlacesQueryBuilder.setScope("history");
     }
-    // Default to All Bookmarks for all other nodes, per bug 469437.
-    else
+    else if (itemId == PlacesUIUtils.leftPaneQueries["Downloads"]) {
+      downloadsButton.hidden = false;
+      bookmarksButton.hidden = true;
+      PlacesQueryBuilder.setScope("downloads");
+    }
+    else {
+      // Default to All Bookmarks for all other nodes, per bug 469437.
       PlacesQueryBuilder.setScope("bookmarks");
+    }
 
     // Enable or disable the folder scope button.
-    var folderButton = document.getElementById("scopeBarFolder");
+    let folderButton = document.getElementById("scopeBarFolder");
     folderButton.hidden = !PlacesUtils.nodeIsFolder(aNode) ||
                           itemId == PlacesUIUtils.allBookmarksFolderId;
   },
 
   /**
    * Handle clicks on the tree.
    * Single Left click, right click or modified click do not result in any
    * special action, since they're related to selection.
@@ -896,19 +909,31 @@ var PlacesSearchBox = {
         var query = PlacesUtils.history.getNewQuery();
         query.searchTerms = filterString;
         var options = currentOptions.clone();
         // Make sure we're getting uri results.
         options.resultType = currentOptions.RESULT_TYPE_URI;
         options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
         content.load([query], options);
       }
-      else
+      else {
         content.applyFilter(filterString);
+      }
       break;
+    case "downloads": {
+        let query = PlacesUtils.history.getNewQuery();
+        query.searchTerms = filterString;
+        query.setTransitions([Ci.nsINavHistoryService.TRANSITION_DOWNLOAD], 1);
+        let options = currentOptions.clone();
+        // Make sure we're getting uri results.
+        options.resultType = currentOptions.RESULT_TYPE_URI;
+        options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
+        content.load([query], options);
+      break;
+    }
     default:
       throw "Invalid filterCollection on search";
       break;
     }
 
     PlacesSearchBox.showSearchUI();
 
     // Update the details panel
@@ -928,27 +953,38 @@ var PlacesSearchBox = {
    */
   findCurrent: function PSB_findCurrent() {
     PlacesQueryBuilder.setScope("collection");
     this.focus();
   },
 
   /**
    * Updates the display with the title of the current collection.
-   * @param   title
+   * @param   aTitle
    *          The title of the current collection.
    */
-  updateCollectionTitle: function PSB_updateCollectionTitle(title) {
-    if (title)
-      this.searchFilter.placeholder =
-        PlacesUIUtils.getFormattedString("searchCurrentDefault", [title]);
-    else
-      this.searchFilter.placeholder = this.filterCollection == "history" ?
-                                      PlacesUIUtils.getString("searchHistory") :
-                                      PlacesUIUtils.getString("searchBookmarks");
+  updateCollectionTitle: function PSB_updateCollectionTitle(aTitle) {
+    let title = "";
+    if (aTitle) {
+      title = PlacesUIUtils.getFormattedString("searchCurrentDefault",
+                                               [aTitle]);
+    }
+    else {
+      switch(this.filterCollection) {
+        case "history":
+          title = PlacesUIUtils.getString("searchHistory");
+          break;
+        case "downloads":
+          title = PlacesUIUtils.getString("searchDownloads");
+          break;
+        default:
+          title = PlacesUIUtils.getString("searchBookmarks");                                    
+      }
+    }
+    this.searchFilter.placeholder = title;
   },
 
   /**
    * Gets/sets the active collection from the dropdown menu.
    */
   get filterCollection() {
     return this.searchFilter.getAttribute("collection");
   },
@@ -1020,32 +1056,36 @@ var PlacesQueryBuilder = {
   onScopeSelected: function PQB_onScopeSelected(aButton) {
     switch (aButton.id) {
     case "scopeBarHistory":
       this.setScope("history");
       break;
     case "scopeBarFolder":
       this.setScope("collection");
       break;
+    case "scopeBarDownloads":
+      this.setScope("downloads");
+      break;
     case "scopeBarAll":
       this.setScope("bookmarks");
       break;
     default:
       throw "Invalid search scope button ID";
       break;
     }
   },
 
   /**
    * Sets the search scope.  This can be called when no search is active, and
    * in that case, when the user does begin a search aScope will be used (see
    * PSB_search()).  If there is an active search, it's performed again to
    * update the content tree.
    * @param   aScope
-   *          the search scope, "bookmarks", "collection", or "history"
+   *          The search scope: "bookmarks", "collection", "downloads" or
+   *          "history".
    */
   setScope: function PQB_setScope(aScope) {
     // Determine filterCollection, folders, and scopeButtonId based on aScope.
     var filterCollection;
     var folders = [];
     var scopeButtonId;
     switch (aScope) {
     case "history":
@@ -1067,16 +1107,20 @@ var PlacesQueryBuilder = {
       // selected node, choose bookmarks scope.
     case "bookmarks":
       filterCollection = "bookmarks";
       scopeButtonId = "scopeBarAll";
       folders.push(PlacesUtils.bookmarksMenuFolderId,
                    PlacesUtils.toolbarFolderId,
                    PlacesUtils.unfiledBookmarksFolderId);
       break;
+    case "downloads":
+      filterCollection = "downloads";
+      scopeButtonId = "scopeBarDownloads";
+      break;
     default:
       throw "Invalid search scope";
       break;
     }
 
     // Check the appropriate scope button in the scope bar.
     document.getElementById(scopeButtonId).checked = true;
 
--- a/browser/components/places/content/places.xul
+++ b/browser/components/places/content/places.xul
@@ -407,28 +407,26 @@
       <toolbox id="searchModifiers" hidden="true">
         <toolbar id="organizerScopeBar" class="chromeclass-toolbar" align="center">
           <label id="scopeBarTitle" value="&search.in.label;"/>
           <toolbarbutton id="scopeBarAll" class="small-margin"
                          type="radio" group="scopeBar"
                          oncommand="PlacesQueryBuilder.onScopeSelected(this);"
                          label="&search.scopeBookmarks.label;"
                          accesskey="&search.scopeBookmarks.accesskey;"/>
-          <!--
+          <toolbarbutton id="scopeBarHistory" class="small-margin"
+                         type="radio" group="scopeBar"
+                         oncommand="PlacesQueryBuilder.onScopeSelected(this);"
+                         label="&search.scopeHistory.label;"
+                         accesskey="&search.scopeHistory.accesskey;"/>
           <toolbarbutton id="scopeBarDownloads" class="small-margin"
                          type="radio" group="scopeBar"
                          oncommand="PlacesQueryBuilder.onScopeSelected(this);"
                          label="&search.scopeDownloads.label;"
                          accesskey="&search.scopeDownloads.accesskey;"/>
-          -->
-          <toolbarbutton id="scopeBarHistory" class="small-margin"
-                         type="radio" group="scopeBar"
-                         oncommand="PlacesQueryBuilder.onScopeSelected(this);"
-                         label="&search.scopeHistory.label;"
-                         accesskey="&search.scopeHistory.accesskey;"/>
           <toolbarbutton id="scopeBarFolder" class="small-margin"
                          type="radio" group="scopeBar"
                          oncommand="PlacesQueryBuilder.onScopeSelected(this);"
                          accesskey="&search.scopeFolder.accesskey;"
                          emptytitle="&search.scopeFolder.label;" flex="1"/>
           <!-- The folder scope button should flex but not take up more room
                 than its label needs.  The only simple way to do that is to
                 set a really big flex on the spacer, e.g., 2^31 - 1. -->
--- a/browser/components/places/tests/browser/browser_library_search.js
+++ b/browser/components/places/tests/browser/browser_library_search.js
@@ -56,115 +56,127 @@
  *   4. if the folder scope button is enabled clicks it,
  *   5. resets the search and ensures that the content tree is correct and that
  *      the search UI is hidden, and
  *   6. if folder scope was clicked, searches again and ensures folder scope
  *      remains selected.
  */
 
 const TEST_URL = "http://dummy.mozilla.org/";
+const TEST_DOWNLOAD_URL = "http://dummy.mozilla.org/dummy.pdf";
 
-// Add your tests here.  Each is a function that's called by testHelper().
-var testCases = [
+let gLibrary;
+
+let testCases = [
+  function allBookmarksScope() {
+    let defScope = getDefaultScope(PlacesUIUtils.allBookmarksFolderId);
+    search(PlacesUIUtils.allBookmarksFolderId, "dummy", defScope);
+    ok(!selectScope("scopeBarFolder"),
+       "Folder scope should be disabled for All Bookmarks");
+    ok(selectScope("scopeBarAll"),
+       "Bookmarks scope should be enabled for All Bookmarks");
+    resetSearch("scopeBarAll");
+  },
 
-  // All Bookmarks
-  function () {
-    var defScope = getDefaultScope(PlacesUIUtils.allBookmarksFolderId);
-    search(PlacesUIUtils.allBookmarksFolderId, "dummy", defScope);
-    is(selectScope("scopeBarFolder"), false,
-       "Folder scope should be disabled for All Bookmarks");
+  function historyScope() {
+    let defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries["History"]);
+    search(PlacesUIUtils.leftPaneQueries["History"], "dummy", defScope);
+    ok(!selectScope("scopeBarFolder"),
+       "Folder scope should be disabled for History");
+    ok(selectScope("scopeBarAll"),
+       "Bookmarks scope should be enabled for History");
+    resetSearch("scopeBarAll");
+  },
+
+  function downloadsScope() {
+    let defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries["Downloads"]);
+    search(PlacesUIUtils.leftPaneQueries["Downloads"], "dummy", defScope);
+    ok(!selectScope("scopeBarFolder"),
+       "Folder scope should be disabled for Downloads");
+    ok(!selectScope("scopeBarAll"),
+       "Bookmarks scope should be disabled for Downloads");
     resetSearch(defScope);
   },
 
-  // History
-  function () {
-    var defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries["History"]);
-    search(PlacesUIUtils.leftPaneQueries["History"], "dummy", defScope);
-    is(selectScope("scopeBarFolder"), false,
-       "Folder scope should be disabled for History");
-    resetSearch(defScope);
-  },
-
-  // Toolbar folder
-  function () {
-    var defScope = getDefaultScope(bmsvc.toolbarFolder);
-    search(bmsvc.toolbarFolder, "dummy", defScope);
-    is(selectScope("scopeBarFolder"), true,
+  function toolbarFolderScope() {
+    let defScope = getDefaultScope(PlacesUtils.toolbarFolderId);
+    search(PlacesUtils.toolbarFolderId, "dummy", defScope);
+    ok(selectScope("scopeBarAll"),
+       "Bookmarks scope should be enabled for toolbar folder");
+    ok(selectScope("scopeBarFolder"),
        "Folder scope should be enabled for toolbar folder");
     // Ensure that folder scope is still selected after resetting and searching
     // again.
     resetSearch("scopeBarFolder");
-    search(bmsvc.toolbarFolder, "dummy", "scopeBarFolder");
+    search(PlacesUtils.toolbarFolderId, "dummy", "scopeBarFolder");
   },
 
-  // A regular non-root subfolder
-  function () {
-    var folderId = bmsvc.createFolder(bmsvc.toolbarFolder,
-                                      "dummy folder",
-                                      bmsvc.DEFAULT_INDEX);
-    var defScope = getDefaultScope(folderId);
+  function subFolderScope() {
+    let folderId = PlacesUtils.bookmarks.createFolder(PlacesUtils.toolbarFolderId,
+                                                      "dummy folder",
+                                                      PlacesUtils.bookmarks.DEFAULT_INDEX);
+    let defScope = getDefaultScope(folderId);
     search(folderId, "dummy", defScope);
-    is(selectScope("scopeBarFolder"), true,
+    ok(selectScope("scopeBarAll"),
+       "Bookmarks scope should be enabled for regularfolder");
+    ok(selectScope("scopeBarFolder"),
        "Folder scope should be enabled for regular subfolder");
     // Ensure that folder scope is still selected after resetting and searching
     // again.
     resetSearch("scopeBarFolder");
     search(folderId, "dummy", "scopeBarFolder");
-    bmsvc.removeItem(folderId);
+    PlacesUtils.bookmarks.removeItem(folderId);
   },
 ];
 
 ///////////////////////////////////////////////////////////////////////////////
 
-var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-              getService(Ci.nsINavBookmarksService);
-var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
-                getService(Ci.nsINavHistoryService);
-var libraryWin;
-
-///////////////////////////////////////////////////////////////////////////////
-
 /**
  * Returns the default search scope for a given folder.
  *
  * @param  aFolderId
  *         the item ID of a node in the left pane's tree
  * @return the default scope when the folder is newly selected
  */
 function getDefaultScope(aFolderId) {
-  return aFolderId === PlacesUIUtils.leftPaneQueries["History"] ?
-         "scopeBarHistory" :
-         "scopeBarAll";
+  switch (aFolderId) {
+    case PlacesUIUtils.leftPaneQueries["History"]:
+      return "scopeBarHistory"
+    case PlacesUIUtils.leftPaneQueries["Downloads"]:
+      return "scopeBarDownloads";
+    default:
+      return "scopeBarAll";
+  }
 }
 
 /**
  * Returns the ID of the search scope button that is currently checked.
  *
  * @return the ID of the selected scope folder button
  */
 function getSelectedScopeButtonId() {
-  var doc = libraryWin.document;
-  var scopeButtons = doc.getElementById("organizerScopeBar").childNodes;
+  let doc = gLibrary.document;
+  let scopeButtons = doc.getElementById("organizerScopeBar").childNodes;
   for (let i = 0; i < scopeButtons.length; i++) {
     if (scopeButtons[i].checked)
       return scopeButtons[i].id;
   }
   return null;
 }
 
 /**
  * Returns the single nsINavHistoryQuery represented by a given place URI.
  *
  * @param  aPlaceURI
  *         a URI that represents a single query
  * @return an nsINavHistoryQuery object
  */
 function queryStringToQuery(aPlaceURI) {
-  var queries = {};
-  histsvc.queryStringToQueries(aPlaceURI, queries, {}, {});
+  let queries = {};
+  PlacesUtils.history.queryStringToQueries(aPlaceURI, queries, {}, {});
   return queries.value[0];
 }
 
 /**
  * Resets the search by clearing the search box's text and ensures that the
  * search scope remains as expected.
  *
  * @param  aExpectedScopeButtonId
@@ -183,61 +195,76 @@ function resetSearch(aExpectedScopeButto
  * @param  aFolderId
  *         the item ID of a node in the left pane's tree
  * @param  aSearchStr
  *         the search text; may be empty to reset the search
  * @param  aExpectedScopeButtonId
  *         after searching the selected scope button should be this
  */
 function search(aFolderId, aSearchStr, aExpectedScopeButtonId) {
-  var doc = libraryWin.document;
-  var folderTree = doc.getElementById("placesList");
-  var contentTree = doc.getElementById("placeContent");
+  let doc = gLibrary.document;
+  let folderTree = doc.getElementById("placesList");
+  let contentTree = doc.getElementById("placeContent");
 
   // First, ensure that selecting the folder in the left pane updates the
   // content tree properly.
   if (aFolderId) {
     folderTree.selectItems([aFolderId]);
     isnot(folderTree.selectedNode, null,
        "Sanity check: left pane tree should have selection after selecting!");
 
     // getFolders() on a History query returns an empty array, so no use
     // comparing against aFolderId in that case.
-    if (aFolderId !== PlacesUIUtils.leftPaneQueries["History"]) {
+    if (aFolderId !== PlacesUIUtils.leftPaneQueries["History"] &&
+        aFolderId !== PlacesUIUtils.leftPaneQueries["Downloads"]) {
       // contentTree.place should be equal to contentTree.result.root.uri,
       // but it's not until bug 476952 is fixed.
-      var query = queryStringToQuery(contentTree.result.root.uri);
+      let query = queryStringToQuery(contentTree.result.root.uri);
       is(query.getFolders()[0], aFolderId,
          "Content tree's folder should be what was selected in the left pane");
     }
   }
 
   // Second, ensure that searching updates the content tree and search UI
   // properly.
-  var searchBox = doc.getElementById("searchFilter");
+  let searchBox = doc.getElementById("searchFilter");
   searchBox.value = aSearchStr;
-  libraryWin.PlacesSearchBox.search(searchBox.value);
-  query = queryStringToQuery(contentTree.result.root.uri);
+  gLibrary.PlacesSearchBox.search(searchBox.value);
+  let query = queryStringToQuery(contentTree.result.root.uri);
   if (aSearchStr) {
     is(query.searchTerms, aSearchStr,
        "Content tree's searchTerms should be text in search box");
     is(doc.getElementById("searchModifiers").hidden, false,
        "Scope bar should not be hidden after searching");
-    if (getSelectedScopeButtonId() == "scopeBarHistory" ||
-        getSelectedScopeButtonId() == "scopeBarAll" ||
-        aFolderId == PlacesUtils.bookmarks.unfiledBookmarksFolder) {
+
+    let scopeButtonId = getSelectedScopeButtonId();
+    if (scopeButtonId == "scopeBarDownloads" ||
+        scopeButtonId == "scopeBarHistory" ||
+        scopeButtonId == "scopeBarAll" ||
+        aFolderId == PlacesUtils.unfiledBookmarksFolderId) {
       // Check that the target node exists in the tree's search results.
-      var node = null;
-      for (var i = 0; i < contentTree.view.rowCount; i++) {
+      let url, count;
+      if (scopeButtonId == "scopeBarDownloads") {
+        url = TEST_DOWNLOAD_URL;
+        count = 1;
+      }
+      else {
+        url = TEST_URL;
+        count = scopeButtonId == "scopeBarHistory" ? 2 : 1;
+      }
+      is(contentTree.view.rowCount, count, "Found correct number of results");
+
+      let node = null;
+      for (let i = 0; i < contentTree.view.rowCount; i++) {
         node = contentTree.view.nodeForTreeIndex(i);
-        if (node.uri === TEST_URL)
+        if (node.uri === url)
           break;
       }
       isnot(node, null, "At least the target node should be in the tree");
-      is(node.uri, TEST_URL, "URI of node should match target URL");
+      is(node.uri, url, "URI of node should match target URL");
     }
   }
   else {
     is(query.hasSearchTerms, false,
        "Content tree's searchTerms should not exist after search reset");
     ok(doc.getElementById("searchModifiers").hidden,
        "Scope bar should be hidden after search reset");
   }
@@ -248,58 +275,58 @@ function search(aFolderId, aSearchStr, a
 /**
  * Clicks the given search scope button if it is enabled.
  *
  * @param  aScopeButtonId
  *         the button with this ID will be clicked
  * @return true if the button is enabled, false otherwise
  */
 function selectScope(aScopeButtonId) {
-  var doc = libraryWin.document;
-  var button = doc.getElementById(aScopeButtonId);
+  let doc = gLibrary.document;
+  let button = doc.getElementById(aScopeButtonId);
   isnot(button, null,
-     "Sanity check: scope button with ID " + aScopeButtonId + "should exist");
+     "Sanity check: scope button with ID " + aScopeButtonId + " should exist");
   // Bug 469436 may hide an inappropriate scope button instead of disabling it.
   if (button.disabled || button.hidden)
     return false;
   button.click();
   return true;
 }
 
 /**
  * test() contains window-launching boilerplate that calls this to really kick
  * things off.  Add functions to the testCases array, and this will call them.
- *
- * @param  aLibraryWin
- *         the Places Library window
  */
-function testHelper(aLibraryWin) {
-  libraryWin = aLibraryWin;
+function onLibraryAvailable() {
   testCases.forEach(function (aTest) aTest());
-  aLibraryWin.close();
+
+  gLibrary.close();
+  gLibrary = null;
 
   // Cleanup.
   PlacesUtils.tagging.untagURI(PlacesUtils._uri(TEST_URL), ["dummyTag"]);
-  PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.bookmarks.unfiledBookmarksFolder);
-  PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
-
-  finish();
+  PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
+  waitForClearHistory(finish);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 function test() {
   waitForExplicitFinish();
 
   // Sanity:
   ok(PlacesUtils, "PlacesUtils in context");
-  // Add a visit, a bookmark and a tag.
+
+  // Add visits, a bookmark and a tag.
   PlacesUtils.history.addVisit(PlacesUtils._uri(TEST_URL),
                                Date.now() * 1000, null,
                                PlacesUtils.history.TRANSITION_TYPED, false, 0);
-  PlacesUtils.bookmarks.insertBookmark(PlacesUtils.bookmarks.unfiledBookmarksFolder,
+  PlacesUtils.history.addVisit(PlacesUtils._uri(TEST_DOWNLOAD_URL),
+                               Date.now() * 1000, null,
+                               PlacesUtils.history.TRANSITION_DOWNLOAD, false, 0);
+  PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
                                        PlacesUtils._uri(TEST_URL),
                                        PlacesUtils.bookmarks.DEFAULT_INDEX,
                                        "dummy");
   PlacesUtils.tagging.tagURI(PlacesUtils._uri(TEST_URL), ["dummyTag"]);
 
-  openLibrary(testHelper);
+  gLibrary = openLibrary(onLibraryAvailable);
 }
--- a/browser/components/sessionstore/content/aboutSessionRestore.js
+++ b/browser/components/sessionstore/content/aboutSessionRestore.js
@@ -54,17 +54,17 @@ window.onload = function() {
 
   // remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
   if (sessionData.value.charAt(0) == '(')
     sessionData.value = sessionData.value.slice(1, -1);
   try {
     gStateObject = JSON.parse(sessionData.value);
   }
   catch (exJSON) {
-    var s = new Cu.Sandbox("about:blank");
+    var s = new Cu.Sandbox("about:blank", {sandboxName: 'aboutSessionRestore'});
     gStateObject = Cu.evalInSandbox("(" + sessionData.value + ")", s);
     // If we couldn't parse the string with JSON.parse originally, make sure
     // that the value in the textbox will be parsable.
     sessionData.value = JSON.stringify(gStateObject);
   }
 
   // make sure the data is tracked to be restored in case of a subsequent crash
   var event = document.createEvent("UIEvents");
--- a/browser/components/sessionstore/src/nsSessionStartup.js
+++ b/browser/components/sessionstore/src/nsSessionStartup.js
@@ -130,17 +130,17 @@ SessionStartup.prototype = {
     try {
       // remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
       if (iniString.charAt(0) == '(')
         iniString = iniString.slice(1, -1);
       try {
         this._initialState = JSON.parse(iniString);
       }
       catch (exJSON) {
-        var s = new Cu.Sandbox("about:blank");
+        var s = new Cu.Sandbox("about:blank", {sandboxName: 'nsSessionStartup'});
         this._initialState = Cu.evalInSandbox("(" + iniString + ")", s);
       }
 
       // If this is a normal restore then throw away any previous session
       if (!doResumeSessionOnce)
         delete this._initialState.lastSessionState;
     }
     catch (ex) { debug("The session file is invalid: " + ex); }
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -173,17 +173,18 @@ var Scratchpad = {
     }
 
     if (!this._contentSandbox ||
         this.browserWindow != this._previousBrowserWindow ||
         this._previousBrowser != this.gBrowser.selectedBrowser ||
         this._previousLocation != this.gBrowser.contentWindow.location.href) {
       let contentWindow = this.gBrowser.selectedBrowser.contentWindow;
       this._contentSandbox = new Cu.Sandbox(contentWindow,
-        { sandboxPrototype: contentWindow, wantXrays: false });
+        { sandboxPrototype: contentWindow, wantXrays: false, 
+          sandboxName: 'scratchpad-content'});
 
       this._previousBrowserWindow = this.browserWindow;
       this._previousBrowser = this.gBrowser.selectedBrowser;
       this._previousLocation = contentWindow.location.href;
     }
 
     return this._contentSandbox;
   },
@@ -206,17 +207,18 @@ var Scratchpad = {
       Cu.reportError(this.strings.
                      GetStringFromName("browserWindow.unavailable"));
       return;
     }
 
     if (!this._chromeSandbox ||
         this.browserWindow != this._previousBrowserWindow) {
       this._chromeSandbox = new Cu.Sandbox(this.browserWindow,
-        { sandboxPrototype: this.browserWindow, wantXrays: false });
+        { sandboxPrototype: this.browserWindow, wantXrays: false, 
+          sandboxName: 'scratchpad-chrome'});
 
       this._previousBrowserWindow = this.browserWindow;
     }
 
     return this._chromeSandbox;
   },
 
   /**
--- a/browser/locales/en-US/chrome/browser/places/places.properties
+++ b/browser/locales/en-US/chrome/browser/places/places.properties
@@ -37,16 +37,17 @@ view.sortBy.dateAdded.label=Sort by Adde
 view.sortBy.dateAdded.accesskey=e
 view.sortBy.lastModified.label=Sort by Last Modified
 view.sortBy.lastModified.accesskey=M
 view.sortBy.tags.label=Sort by Tags
 view.sortBy.tags.accesskey=T
 
 searchBookmarks=Search Bookmarks
 searchHistory=Search History
+searchDownloads=Search Downloads
 searchCurrentDefault=Search in '%S'
 findInPrefix=Find in '%S'…
 
 tabs.openWarningTitle=Confirm open
 tabs.openWarningMultipleBranded=You are about to open %S tabs.  This might slow down %S while the pages are loading.  Are you sure you want to continue?
 tabs.openButtonMultiple=Open tabs
 tabs.openWarningPromptMeBranded=Warn me when opening multiple tabs might slow down %S
 
--- a/build/mobile/devicemanagerADB.py
+++ b/build/mobile/devicemanagerADB.py
@@ -1,38 +1,47 @@
 import subprocess
 from devicemanager import DeviceManager, DMError
 import re
 import os
 
 class DeviceManagerADB(DeviceManager):
 
-  def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = "org.mozilla.fennec_unofficial"):
+  def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = None):
     self.host = host
     self.port = port
     self.retrylimit = retrylimit
     self.retries = 0
     self._sock = None
+    if packageName == None:
+      if os.getenv('USER'):
+        packageName = 'org.mozilla.fennec_' + os.getenv('USER')
+      else:
+        packageName = 'org.mozilla.fennec_'
     self.Init(packageName)
 
   def Init(self, packageName):
     # Initialization code that may fail: Catch exceptions here to allow
     # successful initialization even if, for example, adb is not installed.
     try:
       root = self.getDeviceRoot()
       self.verifyPackage(packageName)
       self.tmpDir = root + "/tmp"
       if (not self.dirExists(self.tmpDir)):
         self.mkDir(self.tmpDir)
     except:
       self.packageName = None
       self.tmpDir = None
     try:
       # a test to see if we have root privs
-      self.checkCmd(["shell", "ls", "/sbin"])
+      files = self.listFiles("/data/data")
+      if (len(files) == 1):
+        if (files[0].find("Permission denied") != -1):
+          print "NOT running as root"
+          raise Exception("not running as root")
     except:
       try:
         self.checkCmd(["root"])
       except:
         print "restarting as root failed"
 
   # external function
   # returns:
@@ -93,17 +102,17 @@ class DeviceManagerADB(DeviceManager):
   #  failure: None
   def pushDir(self, localDir, remoteDir):
     # adb "push" accepts a directory as an argument, but if the directory
     # contains symbolic links, the links are pushed, rather than the linked
     # files; we push file-by-file to get around this limitation
     try:
       if (not self.dirExists(remoteDir)):
         self.mkDirs(remoteDir+"/x")
-      for root, dirs, files in os.walk(localDir):
+      for root, dirs, files in os.walk(localDir, followlinks='true'):
         relRoot = os.path.relpath(root, localDir)
         for file in files:
           localFile = os.path.join(root, file)
           remoteFile = remoteDir + "/"
           if (relRoot!="."):
             remoteFile = remoteFile + relRoot + "/"
           remoteFile = remoteFile + file
           self.pushFile(localFile, remoteFile)
@@ -129,18 +138,22 @@ class DeviceManagerADB(DeviceManager):
 
   # Because we always have / style paths we make this a lot easier with some
   # assumptions
   # external function
   # returns:
   #  success: True
   #  failure: False
   def fileExists(self, filepath):
-    self.checkCmd(["shell", "ls", filepath])
-    return True
+    p = self.runCmd(["shell", "ls", "-a", filepath])
+    data = p.stdout.readlines()
+    if (len(data) == 1):
+      if (data[0].rstrip() == filepath):
+        return True
+    return False
 
   def removeFile(self, filename):
     return self.runCmd(["shell", "rm", filename]).stdout.read()
 
   # does a recursive delete of directory on the device: rm -Rf remoteDir
   # external function
   # returns:
   #  success: output of telnet, i.e. "removing file: /mnt/sdcard/tests/test.txt"
@@ -376,28 +389,21 @@ class DeviceManagerADB(DeviceManager):
     devroot = self.getDeviceRoot()
     if (devroot == None):
       return None
 
     if (self.dirExists(devroot + '/fennec')):
       return devroot + '/fennec'
     elif (self.dirExists(devroot + '/firefox')):
       return devroot + '/firefox'
-    elif (self.dirExists('/data/data/org.mozilla.fennec')):
-      return '/data/data/org.mozilla.fennec'
-    elif (self.dirExists('/data/data/org.mozilla.firefox')):
-      return '/data/data/org.mozilla.firefox'
-    elif (self.dirExists('/data/data/org.mozilla.fennec_unofficial')):
-      return '/data/data/org.mozilla.fennec_unofficial'
-    elif (self.dirExists('/data/data/org.mozilla.fennec_aurora')):
-      return '/data/data/org.mozilla.fennec_aurora'
-    elif (self.dirExists('/data/data/org.mozilla.firefox_beta')):
-      return '/data/data/org.mozilla.firefox_beta'
+    elif (self.packageName and self.dirExists('/data/data/' + self.packageName)):
+      return '/data/data/' + self.packageName
 
     # Failure (either not installed or not a recognized platform)
+    print "devicemanagerADB: getAppRoot failed"
     return None
 
   # Gets the directory location on the device for a specific test type
   # Type is one of: xpcshell|reftest|mochitest
   # external function
   # returns:
   #  success: path for test root
   #  failure: None
deleted file mode 100644
--- a/config/gtscc.c
+++ /dev/null
@@ -1,2809 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-/* */
-/*
- *--------------------------------------------------------------------------
- *
- *    
- *
- *--------------------------------------------------------------------------
- *
- *    gtscc - Global To Static C/C++ compiler driver.
- *
- *    Syntax:
- *
- *    gtscc [options] -c file.cpp ...
- *    gtscc [options] file.o ... libxx.a ...
- *
- *    gtscc is a compiler and linker driver/wrapper for Irix only.
- *    gtscc takes all compiler options and passes them onto the Irix
- *    cc/CC compiler/linker.
- *    Typically, gtscc is used in two phases. Phase one is during compilation.
- *    gtscc, the compiler, converts all inline globals to statics, and records
- *    the existence of other globals and how to compile the file in the gtscc
- *    database file.
- *    During linking, globals dependencies are analyzed, and a list of
- *    "convertable" globals is determined. Globals that are not referenced
- *    globally, but are referenced locally are considered convertable.
- *    The linker then recompiles the files that those symbols are in, and
- *    converts them to statics. It also calls the archiver to install
- *    the converted objects into libraries.
- *    Finally the linker is called.
- *
- *    Created: David Williams, djw@netscape.com, 13-Feb-1997
- *
- *--------------------------------------------------------------------------
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <ctype.h>
-
-#if defined(LINUX) && defined(__GLIBC__)
-#include <libelf/libelf.h>
-#else
-#include <libelf.h>
-#endif
-
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/time.h>
-
-#define DEFAULT_MAX_GLOBALS 15500
-
-#define ELFSYM_IS_DEFINED(x)   ((x).st_shndx != SHN_UNDEF)
-#define ELFSYM_IS_UNDEFINED(x) ((x).st_shndx == SHN_UNDEF)
-
-#ifdef IRIX
-#define CC_COMMAND  "cc"
-#define CCC_COMMAND "CC"
-#define AS_COMMAND  "cc"
-#define LD_COMMAND  "CC"
-#define AR_COMMAND  "ar"
-#define AR_OPTIONS  "cr"
-#else
-#define HANDLES_DASHSO
-#define CC_COMMAND  "gcc"
-#define CCC_COMMAND "g++"
-#define AS_COMMAND  "gcc"
-#define LD_COMMAND  "g++"
-#define AR_COMMAND  "ar"
-#define AR_OPTIONS  "cr"
-#endif
-
-#define EH_NEW(type) (type*)malloc(sizeof(type))
-
-#define TRUE 1
-#define FALSE 0
-
-#define EH_TAG_FILE   'F'
-#define EH_TAG_GLOBAL 'G'
-#define EH_TAG_ZAPPED 'Z'
-#define EH_TAG_INLINE 'I'
-#define EH_TAG_UNDEFINED 'U'
-
-#define VERBOSITY_USER(x)  ((x) > 0)
-#define VERBOSITY_DEBUG(x) ((x) > 1)
-#define VERBOSITY_MAJOR(x) ((x) > 2)
-
-static char eh_unnamed_object[] = "<name not known>";
-
-typedef struct {
-	char*    name;       /* archive */
-} EhArchive;
-
-typedef struct {
-	char*      name;     /* name of C/C++ file, relative to rootdir */
-	char*      directory;/* must compile in this directory */
-	char**     cc_args;  /* cc -I ..... */
-	char*      as_savefile;
-	time_t     compile_time;
-	char*      target_object;
-} EhSource;
-
-typedef struct EhObject {
-	struct EhObject* _recompile; /* used for recompilation link list */
-	unsigned   _needs_unzap;
-	char*      name;     /* name of .o */
-	EhArchive* archive;  /* it is stored in */
-	EhSource*  source;
-	char*      pathname;
-	unsigned   nusers;
-} EhObject;
-
-typedef enum {
-	EH_SYM_UNDEFINED,
-	EH_SYM_DEFINED,
-	EH_SYM_ZAPPED,
-	EH_SYM_INLINE /* are treated special - they belong to no file */
-} EhSymState;
-
-typedef struct EhSym {
-	struct EhSym* _next; /* used for link list */
-	char*      name;     /* name of symbol */
-	EhObject*  object;   /* if symbol is undefined == NULL */
-	unsigned   ngusers;   /* number of global users */
-	unsigned   nlusers;   /* number of local file users */
-
-#if 0
-	unsigned   section;  /* section in elf file */
-	unsigned   index;    /* index into symbol table */
-	unsigned char info;
-	unsigned   dirty;
-#endif
-	EhSymState state;
-} EhSym;
-
-#define EHSYM_ISDEFINED(x)   ((x)->object!=NULL && (x)->state==EH_SYM_DEFINED)
-#define EHSYM_ISZAPPED(x)    ((x)->object!=NULL && (x)->state==EH_SYM_ZAPPED)
-#define EHSYM_ISUNDEFINED(x) ((x)->object == NULL)
-#define EHSYM_ISUSED(x)      ((x)->nusers != 0)
-#define EHSYM_ISINLINE(x)    ((x)->state == EH_SYM_INLINE)
-
-#define EH_OBJECT_CANBUILD(x) \
-((x)->source != NULL && (x)->name != eh_unnamed_object)
-
-#define USE_HASHING
-
-typedef struct {
-#ifdef USE_HASHING
-	EhSym** heads;
-	unsigned size;
-#else
-	EhSym* head;
-#endif
-	unsigned nentries;
-} EhSymTable;
-
-static char*
-make_relative_pathname(char* buf, char* filename, char* rootdir)
-{
-	char  buf1[MAXPATHLEN];
-	char  buf2[MAXPATHLEN];
-	char* p;
-	char* q;
-
-	if (rootdir == NULL) {
-		strcpy(buf, filename);
-		return filename;
-	}
-
-	if (filename[0] != '/') {
-		if (getcwd(buf2, sizeof(buf2)) == NULL) {
-			fprintf(stderr, "cannot get pwd\n");
-			return NULL;
-		}
-
-		strcat(buf2, "/");
-		strcat(buf2, filename);
-
-		filename = buf2;
-	}
-
-	if (realpath(filename, buf1) == NULL) {
-		fprintf(stderr, "realpath(%s,..) failed\n", filename);
-		return NULL;
-	}
-	
-	if (realpath(rootdir, buf2) == NULL) {
-		fprintf(stderr, "realpath(%s,..) failed\n", rootdir);
-		return NULL;
-	}
-
-	strcat(buf2, "/");
-
-	for (p = buf1, q = buf2; *p == *q; p++, q++)
-		;
-
-	strcpy(buf, p);
-
-	return buf;
-}
-
-static EhArchive*
-EhArchiveNew(char* name, char* rootdir)
-{
-	EhArchive* archive = EH_NEW(EhArchive);
-	char pathbuf[MAXPATHLEN];
-
-	make_relative_pathname(pathbuf, name, rootdir);
-
-	archive->name = strdup(pathbuf);
-
-	return archive;
-}
-
-#if 0
-/*
- *    This is evil, we should never free anything, because it messes up
- *    interning.
- */
-static void
-EhSourceDelete(EhSource* source)
-{
-	unsigned n;
-	if (source->name != NULL)
-		free(source->name);
-	if (source->directory != NULL)
-		free(source->directory);
-	if (source->cc_args != NULL) {
-		for (n = 0; source->cc_args[n] != NULL; n++)
-			free(source->cc_args[n]);
-		free(source->cc_args);
-	}
-	if (source->as_savefile != NULL)
-		free(source->as_savefile);
-}
-#endif
-
-static EhSource*
-EhSourceNew(char* name, char** cc_args, char* directory)
-{
-	EhSource* source = EH_NEW(EhSource);
-	unsigned n;
-	unsigned m;
-
-	source->name = strdup(name);
-	source->directory = (directory != NULL)? strdup(directory): NULL;
-	source->as_savefile = NULL;
-	source->compile_time = 0;
-	source->target_object = NULL;
-	source->cc_args = NULL;
-
-	if (cc_args != NULL) {
-
-		for (n = 0; cc_args[n] != NULL; n++)
-			;
-
-		source->cc_args = (char**)malloc(sizeof(char*) * (n+1));
-
-		for (m = 0, n = 0; cc_args[n] != NULL;) {
-			if (strcmp(cc_args[n], "-o") == 0 && cc_args[n+1] != NULL) {
-				source->target_object = strdup(cc_args[n+1]);
-				n += 2;
-			} else {
-				source->cc_args[m++] =  strdup(cc_args[n++]);
-			}
-		}
-
-		source->cc_args[m] = NULL;
-	}
-
-	return source;
-}
-
-static EhObject*
-EhObjectNewArchiveObject(EhArchive* archive, char* name)
-{
-	EhObject* object = EH_NEW(EhObject);
-
-	if (name == eh_unnamed_object)
-		object->name = name;
-	else
-		object->name = strdup(name);
-	object->archive = archive;
-	object->source = NULL;
-	object->_recompile = NULL;
-	object->_needs_unzap = 0;
-	object->pathname = NULL;
-	object->nusers = 0;
-
-	return object;
-}
-
-static EhObject*
-EhObjectNew(char* name, char* rootdir)
-{
-	EhObject* object = EhObjectNewArchiveObject(NULL, name);
-	char pathname[MAXPATHLEN];
-
-	make_relative_pathname(pathname, name, rootdir);
-	object->pathname = strdup(pathname);
-
-	return object;
-}
-
-static EhObject*
-EhObjectNewFromSource(EhSource* source)
-{
-	EhObject* object = EhObjectNewArchiveObject(NULL, eh_unnamed_object);
-
-	object->source = source;
-
-	return object;
-}
-
-static char*
-EhObjectGetFilename(EhObject* object, char* buf)
-{
-	if (object->archive) {
-		strcpy(buf, object->archive->name);
-		strcat(buf, ":");
-		strcat(buf, object->name);
-		return buf;
-	} else {
-		return object->name;
-	}
-}
-
-static EhSym*
-EhSymNewDefined(char* name, EhObject* object)
-{
-	EhSym* sym = EH_NEW(EhSym);
-
-	sym->name = strdup(name);
-	sym->object = object;
-	sym->state = EH_SYM_DEFINED;
-	sym->ngusers = 0;
-	sym->nlusers = 0;
-
-	return sym;
-}
-
-static EhSym*
-EhSymNewInline(char* name)
-{
-	EhSym* sym = EhSymNewDefined(name, NULL);
-	sym->state = EH_SYM_INLINE;
-
-	return sym;
-}
-
-static EhSym*
-EhSymNewUndefined(char* name)
-{
-	EhSym* sym = EhSymNewDefined(name, NULL);
-	sym->state = EH_SYM_UNDEFINED;
-
-	return sym;
-}
-
-static EhSym*
-EhSymNewZapped(char* name, EhObject* object)
-{
-	EhSym* sym = EhSymNewDefined(name, object);
-	sym->state = EH_SYM_ZAPPED;
-
-	return sym;
-}
-
-static EhSym*
-EhSymNewRandomZap(char* name)
-{
-	EhSym* sym = EhSymNewZapped(name, NULL);
-
-	return sym;
-}
-
-EhSymTable*
-EhSymTableNew(unsigned p_size)
-{
-	EhSymTable* table = EH_NEW(EhSymTable);
-
-#ifdef USE_HASHING
-	unsigned size;
-	for (size = 0x1; size < (16*1024); size <<= 1) {
-		if (size >= p_size)
-			break;
-	}
-	table->size = size;
-	table->heads = (EhSym**)calloc(size, sizeof(EhSym*));
-#else
-	table->head = NULL;
-#endif
-	table->nentries = 0;
-
-	return table;
-}
-
-EhSym*
-EhSymTableInsert(EhSymTable* table, EhSym* sym)
-{
-#ifdef USE_HASHING
-	unsigned long hash = elf_hash(sym->name);
-	unsigned long mask = table->size - 1;
-	unsigned index = (hash & mask);
-
-	sym->_next = table->heads[index];
-	table->heads[index] = sym;
-#else
-	sym->_next = table->head;
-	table->head = sym;
-#endif
-	table->nentries++;
-
-	return sym;
-}
-
-EhSym*
-EhSymTableFind(EhSymTable* table, char* name)
-{
-	EhSym* sym;
-	EhSym* head;
-
-#ifdef USE_HASHING
-	unsigned long hash = elf_hash(name);
-	unsigned long mask = table->size - 1;
-	unsigned index = (hash & mask);
-	head = table->heads[index];
-#else
-	head = table->head;
-#endif
-
-	for (sym = head; sym != NULL; sym = sym->_next) {
-		if (strcmp(name, sym->name) == 0)
-			break;
-	}
-
-	return sym;
-}
-
-typedef int (*eh_dump_mappee_t)(EhSym* sym, void* arg);
-
-static int
-EhSymTableMap(EhSymTable* table, eh_dump_mappee_t func, void* arg)
-{
-	EhSym* sym;
-	EhSym* head;
-
-#ifdef USE_HASHING
-	unsigned n;
-	for (n = 0; n < table->size; n++) {
-		head = table->heads[n];
-#else
-		head = table->head; {
-#endif
-		for (sym = head; sym != NULL; sym = sym->_next) {
-			if ((func)(sym, arg) == -1)
-				return -1;
-		}
-	}
-
-	return 0;
-}
-
-typedef struct {
-	EhObject* o_old;
-	EhObject* o_new;
-} fixup_info;
-
-static int
-fixup_mappee(EhSym* sym, void* arg)
-{
-	fixup_info* info = (fixup_info*)arg;
-
-	if (sym->object == info->o_old)
-		sym->object = info->o_new;
-
-	return 0;
-}
-
-static EhObject*
-EhSymTableObjectFixup(EhSymTable* table, EhObject* o_old, EhObject* o_new)
-{
-	fixup_info info;
-
-	/*
-	 *    Now visit every sym that pointed to tmp, and point it
-	 *    at object.
-	 */
-	info.o_old = o_old;
-	info.o_new = o_new;
-	EhSymTableMap(table, fixup_mappee, &info);
-	
-	return o_new;
-}
-
-
-
-static char*
-safe_fgets(char* buf, unsigned size, FILE* fp)
-{
-	unsigned nread = 0;
-
-	if (buf == NULL)
-		buf = (char*)malloc(size);
-
-	for (;;) {
-
-		if (fgets(&buf[nread], size - nread, fp) == NULL) {
-			free(buf);
-			return NULL;
-		}
-
-		if (strchr(buf, '\n') != NULL)
-			return buf;
-
-		/*
-		 *    fgets returns n-1 characters and \0
-		 */
-		nread += (size - nread) - 1;
-		size += 1024;
-		buf = (char*)realloc(buf, size);
-	}
-}
-
-static int
-EhSymTableSetSymbolState(EhSymTable* table, char* name, EhSymState new_state)
-{
-	EhSym* sym = EhSymTableFind(table, name);
-
-	if (sym == NULL) {
-		sym = EhSymNewDefined(name, NULL);
-
-		EhSymTableInsert(table, sym);
-	}
-
-	/* new_state must be EH_SYM_DEFINED || EH_SYM_ZAPPED */
-	if (sym->state == EH_SYM_DEFINED || sym->state == EH_SYM_ZAPPED) {
-		sym->state = new_state;
-	} else if (sym->state == EH_SYM_INLINE) {
-		char* state_name;
-		if (new_state == EH_SYM_DEFINED)
-			state_name = "global";
-		else
-			state_name = "static";
-		fprintf(stderr,
-				"WARNING: Symbol %s is an inline.\n"
-				"         Forcing the symbol %s will be ignored.\n",
-				name,
-				state_name);
-	} else { /* EH_SYM_UNDEFINED */
-		/*
-		 *    This call is being made after objects have started being
-		 *    read. This is too late. I'm not sure I care though.
-		 */
-		return -1;
-	}
-
-	return 0;
-}
-
-static int
-EhSymTableFpLoad(EhSymTable* table, FILE* fp)
-{
-	char* buf = NULL; /* I hope this is big enough */
-	char* p;
-	char* name;
-	char* state;
-	EhSym* sym;
-	EhSource* source = NULL;
-	EhObject* object = NULL;
-	char* cc_args[512];
-	unsigned n;
-	unsigned line_n = 0;
-	char* ctime = NULL;
-	char* directory;
-	char* savefile;
-
-	while ((buf = safe_fgets(buf, 1024, fp)) != NULL) {
-
-		if ((p = strchr(buf, '\n')) == NULL) {
-			fprintf(stderr, "line to long: %d\n", line_n);
-			return -1;
-		}
-		*p = '\0';
-
-		line_n++;
-
-		if (buf[0] == '!') /* comment */
-			continue;
-
-		for (p = buf; isspace(*p); p++)
-			;
-
-		name = p;
-		for (; !isspace(*p); p++)
-			;
-		*p++ = '\0';
-
-		if (name[0] == '\0')
-			continue;
-		
-		for (; isspace(*p); p++)
-			;
-
-		state = p;
-		for (; !isspace(*p) && *p != '\0'; p++)
-			;
-		*p++ = '\0';
-
-		if (state[0] == EH_TAG_GLOBAL
-			||
-			state[0] == EH_TAG_ZAPPED
-			||
-			state[0] == EH_TAG_INLINE) {
-			sym = EhSymTableFind(table, name);
-			if (sym == NULL) { /* install a new one */
-				
-				if (source == NULL && state[0] != EH_TAG_INLINE) {
-					fprintf(stderr,
-							"[%d] found new style symbol (%s) but no source\n",
-							line_n, name);
-				}
-
-				if (state[0] == EH_TAG_GLOBAL)
-					sym = EhSymNewDefined(name, object);
-				else if (state[0] == EH_TAG_INLINE)
-					sym = EhSymNewInline(name);
-				else
-					sym = EhSymNewZapped(name, object);
-				
-				EhSymTableInsert(table, sym);
-			} else {
-				if (state[0] == EH_TAG_GLOBAL) {
-					if (sym->state != EH_SYM_DEFINED) {
-						fprintf(stderr,
-								"out of sync defined symbol: %s, fixing\n",
-								sym->name);
-						sym->state = EH_SYM_DEFINED;
-					}
-				} else if (state[0] == EH_TAG_INLINE) {
-					if (sym->state != EH_SYM_INLINE) {
-						fprintf(stderr,
-								"out of sync inlined symbol: %s, fixing\n",
-								sym->name);
-						sym->state = EH_SYM_INLINE;
-					}
-				} else {
-					if (sym->state != EH_SYM_ZAPPED) {
-						fprintf(stderr,
-								"out of sync zapped symbol: %s, fixing\n",
-								sym->name);
-						sym->state = EH_SYM_ZAPPED;
-					}
-				}
-
-#if 0
-				/* these are probably "special" symbols like .div */
-				if (sym->object != object) {
-					fprintf(stderr,
-							"out of sync object for symbol: %s, ignoring\n",
-							sym->name);
-				}
-#endif
-			}
-
-			continue; /* no more fields we care about */
-		} else if (state[0] == EH_TAG_FILE) {
-
-			directory = p;
-			for (; !isspace(*p) && *p != '\0'; p++)
-				;
-			*p++ = '\0';
-
-			savefile = p;
-			for (; !isspace(*p) && *p != '\0'; p++)
-				;
-			*p++ = '\0';
-
-			ctime = p;
-			for (; !isspace(*p) && *p != '\0'; p++)
-				;
-			*p++ = '\0';
-
-			for (n = 0; *p != '\0';) {
-
-				for (; isspace(*p); p++)
-					;
-			
-				cc_args[n++] = p++;
-				
-				for (; !isspace(*p) && *p != '\0'; p++)
-					;
-				
-				if (*p == '\0')
-					break;
-
-				*p++ = '\0';
-			}
-			cc_args[n] = NULL;
-
-			if (strcmp(directory, ".") == 0)
-				directory = NULL;
-			source = EhSourceNew(name, cc_args, directory);
-			if (ctime != NULL)
-				source->compile_time = (time_t)atoi(ctime);
-			object = EhObjectNewFromSource(source);
-
-		} else { /* old style symbol list */
-			sym = EhSymTableFind(table, name);
-			if (sym != NULL) {
-				if (sym->state != EH_SYM_ZAPPED) {
-					fprintf(stderr,
-							"out of sync random zapped symbol: %s, fixing\n",
-							sym->name);
-					sym->state = EH_SYM_ZAPPED;
-				}
-			} else {
-				sym = EhSymNewRandomZap(name);
-			}
-		}
-	}
-
-	return line_n;
-}
-
-typedef struct {
-	EhSym**  vector;
-	unsigned index;
-} flush_info;
-
-static int
-flush_mappee(EhSym* sym, void* arg)
-{
-	flush_info* info = (flush_info*)arg;
-
-	if (sym->state == EH_SYM_INLINE
-		||
-		(sym->object != NULL && sym->state == EH_SYM_DEFINED)
-		||
-		(sym->object != NULL && sym->state == EH_SYM_ZAPPED)) {
-		if (info->vector != NULL)
-			info->vector[info->index] = sym;
-		info->index++;
-	}
-
-	return 0;
-}
-
-static  int
-flush_compare(const void* ap, const void* bp)
-{
-	EhSym** ax = (EhSym**)ap;
-	EhSym** bx = (EhSym**)bp;
-	EhSym* a = *ax;
-	EhSym* b = *bx;
-	EhObject* oa = a->object;
-	EhObject* ob = b->object;
-	int foo;
-
-	if (oa == NULL && ob != NULL)
-		return -1;
-	if (oa != NULL && ob == NULL)
-		return 1;
-	if (oa == NULL && ob == NULL) {
-		foo = strcmp(a->name, b->name);
-		if (foo < 0)
-			return -1;
-		else if (foo > 0)
-			return 1;
-		return 0;
-	}
-
-	if (oa->source == NULL && ob->source != NULL)
-		return -1;
-	if (oa->source != NULL && ob->source == NULL)
-		return 1;
-	if (oa->source == ob->source)
-		return 0;
-	if (oa->source < ob->source)
-		return -1;
-	if (oa->source > ob->source)
-		return 1;
-	foo = strcmp(a->name, b->name);
-	if (foo < 0)
-		return -1;
-	else if (foo > 0)
-		return 1;
-	return 0;
-}
-
-static void
-EhSourceFpWrite(EhSource* source, FILE* fp)
-{
-	unsigned n = 0;
-
-	fputs(source->name, fp);
-	fputc(' ', fp);
-	fputc(EH_TAG_FILE, fp);
-
-	fputc(' ', fp);
-	if (source->directory != NULL)
-		fprintf(fp, "%s", source->directory);
-	else
-		fputc('.', fp);
-	
-	fputc(' ', fp);
-	if (source->as_savefile != NULL)
-		fprintf(fp, "%s", source->as_savefile);
-	else
-		fputc('.', fp);
-	
-	fputc(' ', fp);
-	fprintf(fp, "%d", source->compile_time);
-
-	if (source->target_object != NULL) {
-		fputs(" -o ", fp);
-		fputs(source->target_object, fp);
-	}
-	
-	if (source->cc_args != NULL) {
-		for (n = 0; source->cc_args[n] != NULL; n++) {
-			fputc(' ', fp);
-			fputs(source->cc_args[n], fp);
-		}
-	}
-
-	if (n < 1)
-		fprintf(stderr, "WARNING: %s has no args\n", source->name);
-
-	fputc('\n', fp);
-}
-
-static int
-EhSymTableFpDump(EhSymTable* table, FILE* fp)
-{
-	flush_info info;
-	unsigned n;
-	EhObject* object = NULL;
-	EhSym**   syms;
-	EhSym*    sym;
-	unsigned size;
-
-	info.index = 0;
-	info.vector = NULL;
-	EhSymTableMap(table, flush_mappee, (void*)&info);
-	size = info.index;
-
-	syms = (EhSym**)malloc(sizeof(EhSym*) * size);
-	info.index = 0;
-	info.vector = syms;
-	EhSymTableMap(table, flush_mappee, (void*)&info);
-
-	/* sort */
-	qsort(syms, size, sizeof(EhSym*), flush_compare);
-
-	/* dump */
-	for (n = 0; n < size; n++) {
-		sym = syms[n];
-
-		if (sym->object != object) {
-			object = sym->object;
-
-			if (object->source != NULL) {
-				EhSourceFpWrite(object->source, fp);
-			}
-		}
-
-		if (sym->state == EH_SYM_INLINE) {
-			fprintf(fp, "%s %c\n", sym->name, EH_TAG_INLINE);
-		} else if (object->source != NULL && sym->state == EH_SYM_ZAPPED) {
-			fprintf(fp, "%s %c\n", sym->name, EH_TAG_ZAPPED);
-		} else if (object->source != NULL && sym->state == EH_SYM_DEFINED) {
-			fprintf(fp, "%s %c\n", sym->name, EH_TAG_GLOBAL);
-		}
-	}
-
-	free(syms);
-
-	return n;
-}
-
-int djw_debug;
-char* djw_test_name;
-
-int
-eh_process_object(Elf* elf, EhObject* object, EhSymTable* table)
-{
-	Elf32_Shdr *   shdr;
-	Elf32_Ehdr *   ehdr;
-	Elf_Scn * scn;
-	Elf_Data *     shstr_data;
-	Elf_Data*      sym_data = NULL;
-	Elf_Data*      str_data = NULL;
-	Elf_Data*      rel_data[4];
-	int            nrel_data = 0;
-	Elf32_Rel*     rel_entries;
-	Elf_Data*      rela_data[10];
-	int            nrela_data = 0;
-	Elf32_Rela*    rela_entries;
-	unsigned int   cnt;
-	Elf32_Sym* elf_sym;
-	int i;
-	int j;
-	int k;
-	char*  name;
-	EhSym* sym;
-	char buf[MAXPATHLEN];
-
-	/* Obtain the .shstrtab data buffer */
-	if (((ehdr = elf32_getehdr(elf)) == NULL) ||
-		((scn = elf_getscn(elf, ehdr->e_shstrndx)) == NULL) ||
-		((shstr_data = elf_getdata(scn, NULL)) == NULL)) {
-		fprintf(stderr, "problems on %s\n", EhObjectGetFilename(object, buf));
-		return -1;
-	}
-
-	/* get the string table */
-	for (cnt = 1, scn = NULL; (scn = elf_nextscn(elf, scn)); cnt++) {
-		if ((shdr = elf32_getshdr(scn)) == NULL) {
-			fprintf(stderr, "problems on %s, section %d\n",
-					EhObjectGetFilename(object, buf), cnt);
-			return -1;
-		}
-
-#if 0
-		fprintf(stderr, "%s: section %d type %d name %s\n",
-				EhObjectGetFilename(object, buf),
-				cnt,
-				shdr->sh_type,
-				(char*)shstr_data->d_buf + shdr->sh_name);
-#endif
-
-		/*
-		 *    Get the string table.
-		 */
-		if (shdr->sh_type == SHT_STRTAB &&
-#ifdef sun
-			strcmp((char*)shstr_data->d_buf + shdr->sh_name, ".strtab") == 0 &&
-#endif
-			cnt != ehdr->e_shstrndx) {
-			if (str_data != NULL) {
-				fprintf(stderr, "multiple string tables for %s - bailing\n",
-						EhObjectGetFilename(object, buf));
-				return -1;
-			}
-			str_data = elf_getdata(scn, NULL);
-		} else if (shdr->sh_type == SHT_SYMTAB) { /* look into sym table */
-			if (sym_data != NULL) {
-				fprintf(stderr, "multiple symbol tables for %s - bailing\n",
-						EhObjectGetFilename(object, buf));
-				return -1;
-			}
-			sym_data = elf_getdata(scn, NULL);
-		} else if (shdr->sh_type == SHT_REL) { /* look into rel table */
-			if (nrel_data >= 4) {
-				fprintf(stderr, "too many relocation tables for %s bailing\n",
-						EhObjectGetFilename(object, buf));
-				return -1;
-			}
-			rel_data[nrel_data++] = elf_getdata(scn, NULL);
-		} else if (shdr->sh_type == SHT_RELA) { /* look into rela table */
-			if (nrela_data >= 10) {
-				fprintf(stderr, "too many RELA tables for %s bailing\n",
-						EhObjectGetFilename(object, buf));
-				return -1;
-			}
-			rela_data[nrela_data++] = elf_getdata(scn, NULL);
-		}
-	}
-
-	if (sym_data == NULL) {
-		fprintf(stderr, "could not load sym table for %s\n",
-				EhObjectGetFilename(object, buf));
-		return -1;
-	}
-
-	if (str_data == NULL) {
-		fprintf(stderr, "could not load string table for %s\n",
-				EhObjectGetFilename(object, buf));
-		return -1;
-	}
-
-	elf_sym = (Elf32_Sym*)sym_data->d_buf;
-
-	for (i = 0; i < (sym_data->d_size/sizeof(Elf32_Sym)); i++) {
-
-		/*
-		 *    We are only interested in globals.
-		 */
-		if (ELF32_ST_BIND(elf_sym[i].st_info) != STB_GLOBAL)
-			continue;
-		
-		name = (char *)str_data->d_buf + elf_sym[i].st_name;
-		
-		if (djw_test_name != NULL
-			&& strcmp(djw_test_name, name) == 0) {
-			printf("found %s\n", name);
-		}
-		
-		sym = EhSymTableFind(table, name);
-		
-		/*
-		 *    Treat inlines as non-globals
-		 */
-		if (sym != NULL && sym->state == EH_SYM_INLINE)
-			continue;
-		
-#if 0
-		printf("name = %s value = %d type = %d, info = %d,"
-			   " other = %d, size = %d\n",
-			   name,
-			   elf_sym[i].st_value,
-			   ELF32_ST_TYPE(elf_sym[i].st_info),
-			   elf_sym[i].st_info,
-			   elf_sym[i].st_other,
-			   elf_sym[i].st_size);
-#endif
-		
-		/* defined */
-		if (ELFSYM_IS_DEFINED(elf_sym[i])) {
-			
-			if (sym != NULL) {
-				
-				if (sym->object == NULL) { /* object undefined */
-					sym->object = object;
-				} else if (sym->object->name==eh_unnamed_object) {
-					
-					if (object->source != NULL
-						&&
-						object->source != sym->object->source) {
-						
-						fprintf(stderr,
-								"warning: symbol %s defined in more than one source file\n"
-								"last time: %s\n"
-								"this time: %s (ignored)\n",
-								sym->name,
-								object->source->name,
-								sym->object->source->name);
-					} else {
-						object->source = sym->object->source;
-						/*
-						 *    Do a global: sym->object = object;
-						 */
-						EhSymTableObjectFixup(table,
-											  sym->object, /*old*/
-											  object); /*new*/
-						
-					}
-					
-				} else if (sym->object != object) {
-					fprintf(stderr,
-							"warning: symbol %s define in multiple object files\n"
-							"last time: %s\n"
-							"this time: %s (ignored)\n",
-							sym->name,
-							object->name,
-							sym->object->name);
-				}
-				
-				sym->state = EH_SYM_DEFINED;
-
-			} else {
-				sym = EhSymNewDefined(name, object);
-				EhSymTableInsert(table, sym);
-			}				
-
-	        for (k = 0; k < nrel_data; k++) {
-				int nentries = rel_data[k]->d_size/sizeof(Elf32_Rel);
-
-				rel_entries = (Elf32_Rel*)rel_data[k]->d_buf;
-				
-				for (j = 0; j < nentries; j++) {
-					if (ELF32_R_SYM(rel_entries[j].r_info) == i) {
-						/* locally referenced */
-						sym->nlusers++;
-					}
-				}
-			}
-	        for (k = 0; k < nrela_data; k++) {
-				int nentries = rela_data[k]->d_size/sizeof(Elf32_Rela);
-
-				rela_entries = (Elf32_Rela*)rela_data[k]->d_buf;
-				
-				for (j = 0; j < nentries; j++) {
-					if (ELF32_R_SYM(rela_entries[j].r_info) == i) {
-						/* locally referenced */
-						sym->nlusers++;
-					}
-				}
-			}
-		}  
-		
-		/* Undefined. */
-		else if (ELFSYM_IS_UNDEFINED(elf_sym[i])) {
-			
-			if (sym == NULL) {
-				sym = EhSymNewUndefined(name);
-				EhSymTableInsert(table, sym);
-			}
-			sym->ngusers++;
-		} else {
-			
-#if 1
-			printf("what is this: "
-				   "name = %s value = %d type = %d, "
-				   "info = %d, other = %d, size = %d\n",
-				   name,
-				   elf_sym[i].st_value,
-				   ELF32_ST_TYPE(elf_sym[i].st_info),
-				   elf_sym[i].st_info,
-				   elf_sym[i].st_other,
-				   elf_sym[i].st_size);
-#endif
-			;
-		}/* type ==... */
-	} /* for each symbol */
-
-	return 0;
-}
-
-int
-eh_process_file(char* filename, EhSymTable* table, char* rootdir)
-{
-	Elf* elf;
-	Elf* arf;
-	int  fd;
-	Elf_Cmd cmd;
-	Elf_Kind e_kind;
-	EhObject* object;
-	EhArchive* archive;
-	Elf_Arhdr* arhdr;
-	char* name;
-	int   rv = 0;
-
-	if ((fd = open(filename, O_RDONLY)) == -1) {
-		fprintf(stderr, "error opening %s\n", filename);
-		return -1;
-	}
-
-	elf_version(EV_CURRENT);
-	if ((arf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
-		return -1;
-	}
-
-	e_kind = elf_kind(arf);
-	if (e_kind == ELF_K_ELF) {
-		object = EhObjectNew(filename, rootdir);
-		rv = eh_process_object(arf, object, table);
-		
-	} else if (e_kind == ELF_K_AR) {
-
-		archive = EhArchiveNew(filename, rootdir);
-		cmd = ELF_C_READ;
-
-#if 0
-		arsyms = elf_getarsym(arf, &narsyms);
-
-		for (i = 0; i < narsyms && arsyms[i].as_name != NULL; i++) {
-			printf("%s - %d\n", arsyms[i].as_name, arsyms[i].as_off);
-		}
-
-		arhdr = elf_getarhdr(arf);
-		for (i = 0; arhdr[i].ar_rawname != NULL; i++) {
-
-			if (arhdr[i].ar_name != NULL)
-				printf("%s\n", arhdr[i].ar_name);
-			else
-				printf("[%s]\n", arhdr[i].ar_rawname);
-		}
-#endif
-
-		rv = 0;
-
-		while ((elf = elf_begin(fd, cmd, arf)) != 0) {
-
-			e_kind = elf_kind(elf);
-
-			if (e_kind != ELF_K_ELF)
-				continue;
-
-			arhdr = elf_getarhdr(elf);
-
-			if (arhdr != NULL) {
-				if (arhdr->ar_name != NULL)
-					name = arhdr->ar_name;
-				else
-					name = arhdr->ar_rawname;
-			} else {
-				name = eh_unnamed_object;
-			}
-
-			object = EhObjectNewArchiveObject(archive, name);
-			rv = eh_process_object(elf, object, table);
-
-			if (rv == -1)
-				break;
-
-			cmd = elf_next(elf);
-			elf_end(elf);
-		}
-	}
-
-	elf_end(arf);
-
-	close(fd);
-
-	return rv;
-}
-
-static int
-eh_dump_unused(EhSym* sym, void* arg)
-{
-	char buf[MAXPATHLEN];
-
-	printf(/*"0x%x "*/ "%s %d %d ", /*sym,*/
-		   sym->name, sym->ngusers, sym->nlusers);
-
-	if (EHSYM_ISINLINE(sym))
-		printf("%c ", EH_TAG_INLINE);
-	else if (EHSYM_ISZAPPED(sym))
-		printf("%c ", EH_TAG_ZAPPED);
-	else if (EHSYM_ISDEFINED(sym))
-		printf("%c ", EH_TAG_GLOBAL);
-	else
-		printf("%c ", EH_TAG_UNDEFINED);
-
-	if (sym->object != NULL) {
-		printf("%s ", EhObjectGetFilename(sym->object, buf));
-		if (sym->object->source != NULL) {
-			printf("%s recompilable\n", sym->object->source->name);
-		} else {
-			printf("nosource notrecompilable\n");
-		}
-	} else {
-		printf("noobject nosource notrecompilable\n");
-	}
-	
-	return 0;
-}
-
-static void
-print_dump(EhSymTable* table)
-{
-	printf("everything\n");
-	EhSymTableMap(table, eh_dump_unused, NULL);
-}
-
-typedef struct {
-	unsigned ndefined;
-	unsigned nused; /* globally */
-	unsigned nundefined;
-	unsigned nzapped;
-	unsigned nzapped_nowused;
-	unsigned ninlined;
-	unsigned nunlinked;
-	unsigned ndeadcode;
-} SummaryInfo;
-
-static int
-eh_summary_mappee(EhSym* sym, void* arg) {
-	SummaryInfo* info = (SummaryInfo*)arg;
-
-	if (EHSYM_ISDEFINED(sym)) {
-		if (sym->ngusers != 0)
-			info->nused++;
-		else if (sym->object != NULL && sym->object->nusers == 0)
-			info->nunlinked++;
-		else if (sym->nlusers != 0)
-			info->ndefined++;
-		else
-			info->ndeadcode++;
-			
-	} else if (EHSYM_ISZAPPED(sym)) { /* one of ours */
-		if (sym->ngusers != 0)
-			info->nzapped_nowused++;
-		else
-			info->nzapped++;
-	} else if (EHSYM_ISINLINE(sym)) { /* one of ours */
-		info->ninlined++;
-	} else {
-		info->nundefined++;
-	}
-
-	return 0;
-}
-
-static void
-get_summary(EhSymTable* table, SummaryInfo* info)
-{
-	info->ndefined = 0;
-	info->nused = 0;
-	info->nundefined = 0;
-	info->nzapped = 0;
-	info->nzapped_nowused = 0;
-	info->ninlined = 0;
-	info->nunlinked = 0;
-	info->ndeadcode = 0;
-	
-	EhSymTableMap(table, eh_summary_mappee, info);
-} 
-
-static void
-print_summary(EhSymTable* table)
-{
-	SummaryInfo info;
-
-	get_summary(table, &info);
-	
-	printf("summary:\n"
-		   "defined and used:             %d\n"
-		   "defined but unused globally:  %d\n"
-		   "total globals in target:      %d\n"
-		   "--------------------------------\n"
-		   "global to statics *:          %d\n"
-		   "global to statics (now used): %d\n"
-		   "inlined to statics *:         %d\n"
-		   "defined in unlinked objects:  %d\n"
-		   "defined but unused (deadcode):%d\n"
-		   "undefined but used:           %d\n",
-		   info.nused,
-		   info.ndefined,
-		   (info.nused + info.ndefined),
-		   info.nzapped,
-		   info.nzapped_nowused,
-		   info.ninlined,
-		   info.nunlinked,			   
-		   info.ndeadcode,			   
-		   info.nundefined);
-}
-
-typedef struct EhDirMapEntree {
-	char* dirname;
-	struct EhDirMapEntree* _next;
-} EhDirMapEntree;
-
-typedef struct EhDirMap {
-	EhDirMapEntree* head;
-} EhDirMap;
-
-static EhDirMap*
-EhDirMapNew(void)
-{
-	EhDirMap* dm = EH_NEW(EhDirMap);
-	dm->head = NULL;
-	return dm;
-}
-
-static void
-EhDirMapAddDirectory(EhDirMap* map, char* dirname)
-{
-	EhDirMapEntree* entree = EH_NEW(EhDirMapEntree);
-	EhDirMapEntree* foo;
-
-	entree->dirname = strdup(dirname);
-	entree->_next = NULL;
-
-	if (map->head == NULL) {
-		map->head = entree;
-	} else {
-		for (foo = map->head; foo->_next != NULL; foo = foo->_next)
-			;
-
-		foo->_next = entree;
-	}
-}
-
-static char*
-EhDirMapGetLibName(EhDirMap* map, char* name, char* libbuf)
-{
-	EhDirMapEntree* foo;
-	struct stat     buf;
-
-	for (foo = map->head; foo != NULL; foo = foo->_next) {
-		sprintf(libbuf, "%s/lib%s.a", foo->dirname, name);
-
-		if (stat(libbuf, &buf) != -1)
-			return libbuf;
-	}
-
-	return NULL;
-}
-
-static char*
-test_for_global(char* buf)
-{
-#ifdef IRIX
-	if (strncmp(buf, "\t.globl\t", 8) == 0)
-		return &buf[8];
-#else
-	if (strncmp(buf, "\t.global ", 9) == 0)
-		return &buf[9];
-#endif
-	return NULL;
-}
-
-static char*
-test_for_file(char* foo, char* buf)
-{
-#ifdef IRIX
-	char* p;
-	char* q;
-	if (strncmp(buf, "\t.file\t", 6) == 0) {
-		for (p = &buf[6]; *p != '"' && *p != '\0'; p++)
-			;
-		if (*p == '\0')
-			return NULL;
-		p++; /* quote */
-		q = strchr(p, '"');
-		if (q == NULL)
-			return NULL;
-		memcpy(foo, p, q - p);
-		foo[q - p] = '\0';
-		return foo;
-	}
-#else
-	printf("test_for_file() not implemented\n");
-#endif
-	return NULL;
-}
-
-static int
-EhSourceZapFp(EhSource* source, EhSymTable* table, FILE* fpi, FILE* fpo,
-			  unsigned verbosity, unsigned cplusplus)
-{
-	char*     buf = NULL;
-	char*     p;
-	int       nzap = 0;
-	char*     name;
-	EhSym*    sym;
-	int       i_zapped;
-	EhObject* object = EhObjectNewFromSource(source);
-	char*     filename = source->name;
-	char*     tmp_name;
-	char      foo[256];
-	unsigned  line_n = 0;
-
-	if (VERBOSITY_DEBUG(verbosity))
-		fputs("gts: ", stderr);
-
-	while ((buf = safe_fgets(buf, 4192, fpi)) != NULL) {
-
-		i_zapped = 0;
-		for (p = buf; *p != '\0' && *p != '\n'; p++)
-			;
-		*p = '\0';
-
-		if ((tmp_name = test_for_file(foo, buf)) != NULL) {
-			if (strcmp(tmp_name, filename) != 0) /* not the same file */
-				filename = "non local file";
-			else
-				filename = source->name;
-		}
-
-		else if ((name = test_for_global(buf)) != NULL) {
-
-			sym = EhSymTableFind(table, name);
-
-			/* an inline, we have to treat specially */
-			if ((filename != source->name && cplusplus != 0) /* inline now */
-				||
-				(sym != NULL && sym->state == EH_SYM_INLINE)) {/* was inline */
-
-				if (!sym) { 
-
-					sym = EhSymNewInline(name);
-					
-					EhSymTableInsert(table, sym);
-				}
-				sym->state = EH_SYM_INLINE; /* just make sure */
-
-				if (fpo != NULL) /* always zap inlines we see */
-					fputs(" # gts", fpo);
-
-			} else { /* a real global */
-
-				if (fpo != NULL && sym != NULL && EHSYM_ISZAPPED(sym)) {
-					if (VERBOSITY_DEBUG(verbosity)) {
-						fprintf(stderr, "%s ", &buf[8]);
-					}
-					nzap++;
-
-					if (fpo != NULL)
-						fputs(" # gts", fpo);
-				}
-
-				if (sym != NULL) {
-					if (sym->object == NULL) {
-						sym->object = object;
-					} else if (sym->object != object) {
-						sym->object->source = source;
-						EhSymTableObjectFixup(table, object, sym->object);
-						object = sym->object;
-					}
-				} else { /* install a new one */
-					
-					sym = EhSymNewDefined(name, object);
-					
-					EhSymTableInsert(table, sym);
-				}
-
-			}
-		}
-
-		if (fpo != NULL) {
-			fputs(buf, fpo);
-			fputc('\n', fpo);
-		}
-		line_n++;
-	}
-	
-	if (VERBOSITY_DEBUG(verbosity))
-		fputc('\n', stderr);
-
-	return nzap;
-}
-
-static void
-print_command(char* command, char** args, unsigned verbosity)
-{
-	int i;
-	FILE* fp = stderr;
-	if (!VERBOSITY_USER(verbosity))
-		return;
-
-	fprintf(fp, "%s: ", command);
-	for (i = 0; args[i]; i++) {
-		fprintf(fp, "%s ", args[i]);
-	}
-	fprintf(fp, "\n");
-}
-
-static int
-do_command(char* label, char** args, unsigned verbosity)
-{
-	int status;
-	pid_t child_pid;
-	char* file = args[0];
-
-	print_command(label, args, verbosity);
-
-	if ((child_pid = fork()) == -1) {
-		fprintf(stderr, "could not fork: ");
-		perror(NULL);
-		return -1;
-	}
-
-	if (child_pid == 0) { /* i am the child */
-		if (execvp(file, args) == -1) {
-			fprintf(stderr, "could not exec %s: ", file);
-			perror(NULL);
-			exit(3);
-		}
-		/*NOTREACHED*/
-	}
-
-	if (waitpid(child_pid, &status, 0) == -1) {
-		fprintf(stderr, "wait on %s failed: ", file);
-		perror(NULL);
-		return -1;
-	}
-
-	return WEXITSTATUS(status);
-}
-
-static char*
-suffix_name(char* s)
-{
-	char* p;
-
-	if ((p = strrchr(s, '.')) != NULL)
-		return p;
-	else
-		return "";
-}
-
-static char base_name_buf[MAXPATHLEN];
-
-static char*
-base_name(char* s)
-{
-	char* p;
-
-	if ((p = strrchr(s, '.')) != NULL) {
-		memcpy(base_name_buf, s, p - s);
-		base_name_buf[p - s] = '\0';
-		s = base_name_buf;
-	}
-	return s;
-}
-
-static char*
-file_base_name(char *s)
-{
-	char* p;
-
-	s = base_name(s);
-
-	if ((p = strrchr(s, '/')) != NULL)
-		s = &p[1];
-	
-	return s;
-}
-static int
-EhSourceCompile(EhSource*   source,
-				EhSymTable* table,
-				unsigned    verbosity,
-				unsigned    do_compile,
-				unsigned    do_zap,
-				unsigned    do_assem)
-{
-	char* filename = source->name;
-	char** opts = source->cc_args;
-	char asname[MAXPATHLEN];
-	char o_asname[MAXPATHLEN];
-	char* cc_opts[256];
-	unsigned i = 0;
-	unsigned j = 0;
-	FILE* in_fp;
-	FILE* out_fp;
-	int   status;
-	int nzap = 0;
-	char* save_prefix = NULL;
-	unsigned do_dash_s = (do_zap != 0 || save_prefix != NULL);
-	char* cc_command;
-	char* use_savefile = NULL;
-	struct timeval start_time;
-	struct timeval end_time;
-#ifdef DEBUG_djw
-	char savebuf[1024];
-#endif
-	unsigned is_cplusplus = 0;
-
-#ifdef LINUX
-	gettimeofday(&start_time,NULL);
-#else
-	gettimeofday(&start_time);
-#endif
-
-	/* munge file */
-#ifdef HANDLES_DASHSO
-	if (source->target_object != NULL)
-		strcpy(asname, base_name(source->target_object));
-	else
-#endif
-		strcpy(asname, file_base_name(filename));
-	strcat(asname, ".s");
-
-	strcpy(o_asname, asname);
-	strcat(o_asname, ".gts_tmp");
-
-	if (strcmp(suffix_name(filename), ".cpp") == 0) {
-		cc_command = CCC_COMMAND;
-		is_cplusplus = 1;
-	} else if (strcmp(suffix_name(filename), ".s") == 0) {
-		do_compile = FALSE;
-		cc_command = CC_COMMAND;
-	} else {
-		cc_command = CC_COMMAND;
-	}
-
-	if (do_compile) {
-
-		j = 0;
-		cc_opts[j++] = cc_command;
-		cc_opts[j++] = "-c";
-
-		if (do_dash_s) {
-			cc_opts[j++] = "-S";
-#ifdef HANDLES_DASHSO
-			if (source->target_object != NULL) {
-				cc_opts[j++] = "-o";
-				cc_opts[j++] = asname;
-			}
-#endif
-		} else if (source->target_object != NULL) {
-			cc_opts[j++] = "-o";
-			cc_opts[j++] = source->target_object;
-		}
-		
-		i = 0;
-		while (opts[i] != NULL)
-			cc_opts[j++] = opts[i++];
-		
-		cc_opts[j++] = filename;
-		cc_opts[j] = NULL;
-		
-		if ((status = do_command("compile", cc_opts, verbosity)) != 0) {
-			fprintf(stderr, "compile failed (returned %d)\n", status);
-			return -1;
-		}
-
-		if (!do_dash_s)
-			return 0;
-	}
-
-	/*
-	 *    Now we have a foo.s file, what do we do with it?
-	 */
-	if (do_zap > 1) {
-
-		if (use_savefile == NULL)
-			use_savefile = asname;
-
-		if ((in_fp = fopen(use_savefile, "r")) == NULL) {
-			fprintf(stderr, "could not open %s for reading\n", asname);
-			return -1;
-		}
-	
-		if ((out_fp = fopen(o_asname, "w")) == NULL) {
-			fprintf(stderr, "could not open %s for writing\n", o_asname);
-			return -1;
-		}
-	
-		j = 0;
-		cc_opts[j++] = "gts";
-		cc_opts[j++] = asname;
-		cc_opts[j++] = o_asname;
-		cc_opts[j++] = NULL;
-		print_command("gts", cc_opts, verbosity);
-
-		nzap = EhSourceZapFp(source, table, in_fp, out_fp, verbosity, is_cplusplus);
-
-		fclose(in_fp);
-		fclose(out_fp);
-
-		j = 0;
-		cc_opts[j++] = "rename";
-		cc_opts[j++] = o_asname;
-		cc_opts[j++] = asname;
-		cc_opts[j++] = NULL;
-		print_command("rename", cc_opts, verbosity);
-
-#ifdef DEBUG_djw
-		strcpy(savebuf, "gts_pre_");
-		strcat(savebuf, asname);
-		rename(asname, savebuf);
-#endif
-
-		if (rename(o_asname, asname) == -1) {
-			fprintf(stderr, "could not rename %s\n", o_asname);
-			return -1;
-		}
-
-	} else if (do_zap > 0) { /* audit only */
-
-		if ((in_fp = fopen(asname, "r")) == NULL) {
-			fprintf(stderr, "could not open %s for reading\n", asname);
-			return -1;
-		}
-	
-		j = 0;
-		cc_opts[j++] = "audit";
-		cc_opts[j++] = asname;
-		cc_opts[j++] = NULL;
-		print_command("audit", cc_opts, verbosity);
-
-		nzap = EhSourceZapFp(source, table, in_fp, NULL, verbosity, is_cplusplus);
-
-		fclose(in_fp);
-	}
-
-	if (do_assem) {
-		i = 0;
-		j = 0;
-		cc_opts[j++] = AS_COMMAND;
-		cc_opts[j++] = "-c";
-
-		if (source->target_object != NULL) {
-			cc_opts[j++] = "-o";
-			cc_opts[j++] = source->target_object;
-		}
-
-		while (opts[i] != NULL)
-			cc_opts[j++] = opts[i++];
-
-		cc_opts[j++] = asname;
-		cc_opts[j] = NULL;
-
-		if ((status = do_command("assemble", cc_opts, verbosity)) != 0) {
-
-			unlink(asname);
-
-			fprintf(stderr,
-				"gtscc of %s failed (exit status = %d), reverting to %s:\n",
-					filename,
-					status,
-					cc_command);
-			
-			i = 0;
-			j = 0;
-			cc_opts[j++] = cc_command;
-			cc_opts[j++] = "-c";
-
-			if (source->target_object != NULL) {
-				cc_opts[j++] = "-o";
-				cc_opts[j++] = source->target_object;
-			}
-
-			for (; opts[i]; i++, j++)
-				cc_opts[j] = opts[i];
-			
-			cc_opts[j++] = filename;
-			cc_opts[j] = NULL;
-			
-			if ((status = do_command("fix-compile", cc_opts, verbosity)) != 0)
-				return -1;
-
-			return 0;
-		}
-	}
-
-	if (save_prefix != NULL && save_prefix[0] != '\0') {
-
-		sprintf(o_asname, save_prefix, file_base_name(filename));
-
-		j = 0;
-		cc_opts[j++] = "rename";
-		cc_opts[j++] = asname;
-		cc_opts[j++] = o_asname;
-		cc_opts[j++] = NULL;
-		print_command("savefile", cc_opts, verbosity);
-
-		if (rename(asname, o_asname) == -1) {
-			fprintf(stderr, "could not rename %s to %s - sorry\n",
-					asname, o_asname);
-			return -1;
-		}
-
-		if (source->as_savefile != NULL)
-			free(source->as_savefile);
-		source->as_savefile = strdup(o_asname);
-	} else {
-
-		j = 0;
-		cc_opts[j++] = "unlink";
-		cc_opts[j++] = asname;
-		cc_opts[j++] = NULL;
-		print_command("unlink", cc_opts, verbosity);
-
-#ifdef DEBUG_djw
-		strcpy(savebuf, "gts_post_");
-		strcat(savebuf, asname);
-		rename(asname, savebuf);
-#else
-		unlink(asname);
-#endif
-	}
-
-#ifdef LINUX
-	gettimeofday(&end_time,NULL);
-#else
-	gettimeofday(&end_time);
-#endif
-
-	source->compile_time = ((end_time.tv_sec - start_time.tv_sec) * 1000) +
-                           ((end_time.tv_usec - start_time.tv_usec) / 1000);
-
-	return nzap;
-}
-
-static char target_buf[MAXPATHLEN]; /* this will go away with rel source */
-
-static char*
-EhSourceGetTarget(EhSource* source)
-{
-	if (source->target_object != NULL)
-		return source->target_object;
-
-	strcpy(target_buf, base_name(source->name));
-	strcat(target_buf, ".o");
-
-	return target_buf;
-}
-
-static int
-EhArchiveUpdate(EhArchive* archive, char* target, char* rootdir,
-				unsigned verbosity)
-{
-	char* args[8];
-	unsigned nargs;
-	int status;
-	char pathname[MAXPATHLEN];
-
-	pathname[0] = '\0';
-	if (rootdir != NULL) {
-		strcat(pathname, rootdir);
-		strcat(pathname, "/");
-	}
-	strcat(pathname, archive->name);
-
-#if 0
-	nargs = 0;
-	args[nargs++] = AR_COMMAND;
-	args[nargs++] = "dc";
-	args[nargs++] = pathname;
-	args[nargs++] = target;
-	args[nargs++] = NULL;
-	
-	if ((status = do_command("delete from archive", args, verbosity)) != 0) {
-		fprintf(stderr, "archive: %s delete %s failed (status = %d)\n",
-				pathname,
-				target);
-		return -1;
-	}
-#endif
-
-	nargs = 0;
-	args[nargs++] = AR_COMMAND;
-	args[nargs++] = AR_OPTIONS;
-	args[nargs++] = pathname;
-	args[nargs++] = target;
-	args[nargs++] = NULL;
-	
-	if ((status = do_command("archive", args, verbosity)) != 0) {
-		fprintf(stderr, "archive: %s <- %s failed (status = %d)\n",
-				pathname,
-				target);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int
-EhObjectRebuild(EhObject*   object,
-				EhSymTable* table,
-				unsigned    verbosity,
-				char*       rootdir)
-{
-	EhSource* source = object->source;
-	char  cwd[MAXPATHLEN];
-	char  fullpath[MAXPATHLEN];
-	int   rv = 0;
-	int   do_chdir = 0;
-
-	if (!source) {
-		fprintf(stderr,
-				"wanted to recompile %s, but I don't how\n",
-				object->name);
-		return -1;
-	}
-	
-#if 0
-	if (VERBOSITY_USER(verbosity))
-#endif
-		fprintf(stderr, "recompiling %s\n", source->name);
-	
-	/*
-	 *    Check to see if we need to chdir
-	 */
-	if (source->directory != NULL) {
-		if (getcwd(cwd, sizeof(cwd)) == NULL) {
-			fprintf(stderr, "cannot get pwd: cannot compile\n");
-			return -1;
-		}
-		
-		make_relative_pathname(fullpath, cwd, rootdir);
-		
-		if (strcmp(fullpath, source->directory) != 0) {
-			fullpath[0] = '\0';
-			if (rootdir != NULL) {
-				strcat(fullpath, rootdir);
-				strcat(fullpath, "/");
-			}
-			strcat(fullpath, source->directory);
-
-			if (chdir(fullpath) == -1) {
-				fprintf(stderr, "cannot chdir - can't compile\n");
-				return -1;
-			}
-			do_chdir++;
-		}
-	}
-
-	rv = EhSourceCompile(source,
-						 table,
-						 verbosity,
-						 TRUE,  /* compile  */
-						 2,     /* do zap   */
-						 TRUE); /* do assem */
-
-	if (do_chdir) {
-		if (chdir(cwd) == -1) {
-			fprintf(stderr, "cannot chdir - this will be very confused\n");
-			return -1;
-		}
-	}
-
-	if (rv == -1) {
-		fprintf(stderr, "recompiling %s failed\n",  source->name);
-		return -1;
-	}
-	
-	/* do archive */
-	fullpath[0] = '\0';
-	if (rootdir != NULL) {
-		strcat(fullpath, rootdir);
-		strcat(fullpath, "/");
-	}
-
-	if (source->directory != NULL)
-		strcat(fullpath, source->directory);
-
-	strcat(fullpath, "/");
-	strcat(fullpath, EhSourceGetTarget(source));
-	
-	if (object->archive != NULL) {
-		if (EhArchiveUpdate(object->archive, fullpath, rootdir,
-							verbosity) == -1)
-			return -1;
-	}
-
-	/* do install */
-#if 0
-	if (rv != -1) {
-	}
-#endif
-
-	return rv;
-}
-
-static int
-object_nusers_mappee(EhSym* sym, void* arg)
-{
-	if (sym->object != NULL)
-		sym->object->nusers += sym->ngusers;
-	return 0;
-}
-
-typedef struct {
-	EhObject* recompile_list;
-	unsigned  recompile_count;
-	unsigned  recompile_wish_count;
-	unsigned  unzap_count;
-	unsigned  zap_count;
-} RecompileInfo;
-
-static int
-recompile_init_mappee(EhSym* sym, void* arg)
-{
-	RecompileInfo* info = (RecompileInfo*)arg;
-
-	if (EHSYM_ISZAPPED(sym) && sym->ngusers != 0) {
-		if (EH_OBJECT_CANBUILD(sym->object)) {
-			sym->state = EH_SYM_DEFINED;
-			if (sym->object->_recompile == NULL) {
-				sym->object->_recompile = info->recompile_list;
-				info->recompile_list = sym->object;
-				info->recompile_count++;
-			}
-			info->unzap_count++;
-			sym->object->_needs_unzap++;
-		}
-		info->recompile_wish_count++;
-	}
-	else if (EHSYM_ISDEFINED(sym) /* it's defined */
-			 && sym->ngusers == 0 /* there are no global users */
-			 && sym->nlusers != 0 /* BUT, ther are local users */
-			 && sym->object->nusers != 0) { /* object is linked */
-
-		if (EH_OBJECT_CANBUILD(sym->object)) {
-			sym->state = EH_SYM_ZAPPED;
-			if (sym->object->_recompile == NULL) {
-				sym->object->_recompile = info->recompile_list;
-				info->recompile_list = sym->object;
-				info->recompile_count++;
-			}
-			info->zap_count++;
-		}
-		info->recompile_wish_count++;
-	}
-
-	return 0;
-}
-
-static char**    recompile_compare_prefs;
-static char**    recompile_compare_unprefs;
-
-static unsigned
-match_prefs(char* candidate, char** prefs)
-{
-	unsigned n;
-
-	for (n = 0; prefs[n] != NULL; n++) {
-		char*    pref = prefs[n];
-		unsigned len = strlen(pref);
-		if (strncmp(pref, candidate, len) == 0)
-			return n; /* cool */
-	}
-	return (unsigned)-1; /* big! */
-}
-
-static  int
-recompile_compare(const void* ap, const void* bp)
-{
-	EhObject** ax = (EhObject**)ap;
-	EhObject** bx = (EhObject**)bp;
-	EhObject*  obj_a = *ax;
-	EhObject*  obj_b = *bx;
-	EhSource*  src_a = obj_a->source;
-	EhSource*  src_b = obj_b->source;
-	unsigned   matcha;
-	unsigned   matchb;
-	int        foo;
-
-	if (obj_a->_needs_unzap == 0 && obj_b->_needs_unzap != 0)
-		return -1;
-	if (obj_a->_needs_unzap != 0 && obj_b->_needs_unzap == 0)
-		return 1;
-
-	if (src_a == NULL && src_b != NULL)
-		return 1;
-	if (src_a != NULL && src_b == NULL)
-		return -1;
-	if (src_a == src_b)
-		return 0;
-
-	if (recompile_compare_unprefs != NULL
-		&& src_a->directory != NULL && src_b->directory != NULL) {
-
-		matcha = match_prefs(src_a->directory, recompile_compare_unprefs);
-		matchb = match_prefs(src_b->directory, recompile_compare_unprefs);
-
-		if (matcha > matchb) /* greater is good */
-			return -1;
-		if (matcha < matchb)
-			return 1;
-	}
-
-	if (recompile_compare_prefs != NULL
-		&& src_a->directory != NULL && src_b->directory != NULL) {
-
-		matcha = match_prefs(src_a->directory, recompile_compare_prefs);
-		matchb = match_prefs(src_b->directory, recompile_compare_prefs);
-
-		if (matcha > matchb) /* greater is bad */
-			return 1;
-		if (matcha < matchb)
-			return -1;
-	}
-
-	/* else same directory probably */
-	foo = strcmp(src_a->name, src_b->name);
-
-	if (foo < 0)
-		return -1;
-	if (foo > 0)
-		return 1;
-
-	return 0;
-}
-
-static int
-do_recompilation(EhSymTable* table, char* gts_file, unsigned max_globals,
-				 char** prefs, char** unprefs,
-				 char* rootdir, unsigned verbosity)
-{
-	SummaryInfo s_info;
-	RecompileInfo info;
-	unsigned    size;
-	unsigned n;
-	EhObject* object;
-	EhObject** recompiles;
-	unsigned delta;
-	int rv;
-	unsigned nzaps;
-	EhObject dummy; /* just marks the end of the recomp list */
-	time_t  eta;
-
-	get_summary(table, &s_info);
-
-	if ((s_info.nused + s_info.ndefined) <= max_globals) {
-		if (VERBOSITY_USER(verbosity))
-			fprintf(stderr,
-			"number of globals <= requested max, skipping recompilation\n");
-		return 0;
-	}
-
-	/* Init recompilation. */
-	info.recompile_list = &dummy; /* cannot use NULL, because syms test that */
-	info.recompile_count = 0;
-	info.recompile_wish_count = 0;
-	info.unzap_count = 0;
-	info.zap_count = 0;
-	EhSymTableMap(table, recompile_init_mappee, (void*)&info);
-	size = info.recompile_count;
-
-	recompiles = (EhObject**)malloc(sizeof(EhObject*) * size);
-
-	/* install */
-	n = 0;
-	for (object = info.recompile_list;
-		 object != &dummy;
-		 object = object->_recompile) {
-		recompiles[n++] = object;
-	}
-
-	/* sort */
-	recompile_compare_prefs = prefs;
-	recompile_compare_unprefs = unprefs;
-	qsort(recompiles, size, sizeof(EhObject*), recompile_compare);
-
-	/*
-	 *    sorted !
-	 *    less recompile the first n, n = ndefined - max
-	 */
-	delta = (s_info.nused + s_info.ndefined) - max_globals;
-
-	if (delta > info.zap_count) {
-		fprintf(stderr,
-				"WARNING: there too many globals (%d/%d fixables).\n"
-				"         I don't think I can fix this, but I'll try.\n"
-				"         You might get lucky.\n",
-				info.zap_count,
-				delta);
-	}
-
-	if (VERBOSITY_USER(verbosity))
-		fprintf(stderr, "scheduling recompilation targets:\n");
-
-	eta = 0;
-	for (n = 0; n < size; n++) {
-		char* cname = "unknown";
-		object = recompiles[n];
-		if (object->source != NULL) {
-			cname = object->source->name;
-			eta += object->source->compile_time;
-		}
-		
-		if (VERBOSITY_DEBUG(verbosity))
-			fprintf(stderr, "object %s from source %s\n", object->name, cname);
-	}
-
-#if 0
-	if (VERBOSITY_USER(verbosity))
-#endif
-		fprintf(stderr, "gts-ing %d symbols, eta = %d minutes\n", delta,
-				eta/(60*1000));
-
-	if (gts_file != NULL) {
-		FILE* zap_fp;
-		if ((zap_fp = fopen(gts_file, "w")) == NULL) {
-			perror(0);
-			fprintf(stderr,
-					"WARNING: could not open the gtscc db file %s.\n"
-					"         I will continue with the recompilation, but\n"
-					"         if you recompile any of the files I touched\n"
-					"         I'll have to recompile them after you!\n",
-					gts_file);
-		} else {
-		
-			EhSymTableFpDump(table, zap_fp);
-			
-			fclose(zap_fp);
-		}
-	}
-
-	for (n = 0, nzaps = 0; n < size && nzaps < delta; n++) {
-
-		object = recompiles[n];
-		rv = EhObjectRebuild(object, table, verbosity, rootdir);
-
-		if (rv == -1)
-			return -1;
-
-		nzaps += rv;
-
-		object->_recompile = NULL; /* clean up now */
-	}
-
-	if (nzaps < delta) {
-		fprintf(stderr,
-				"WARNING: I wanted to gts %d symbols, but only managed\n"
-				"         to get %d of them.\n"
-				"         Your link may fail with GOT errors.\n",
-				delta,
-				nzaps);
-	}
-	
-	free(recompiles);
-
-	return n;
-}
-
-typedef struct FileList
-{
-	char*            name;
-	struct FileList* next;
-} FileList;
-
-static FileList*
-fileListFind(FileList* list, char* name)
-{
-	FileList* foo;
-
-	for (foo = list; foo != NULL; foo = foo->next) {
-		if (strcmp(name, foo->name) == 0)
-			return foo;
-	}
-	return NULL;
-}
-
-static FileList*
-fileListAppend(FileList** list_a, char* name)
-{
-	FileList* list = *list_a;
-	FileList* foo;
-	FileList* last;
-
-	for (foo = list, last = NULL; foo != NULL; last = foo, foo = foo->next)
-		;
-
-	if (last == NULL) {
-		foo = EH_NEW(FileList);
-		foo->next = NULL;
-		foo->name = strdup(name);
-		*list_a = foo;
-	} else {
-		foo = EH_NEW(FileList);
-		foo->next = NULL;
-		foo->name = strdup(name);
-		last->next = foo;
-	}
-
-	return *list_a;
-}
-
-#if 0
-static FileList* c_list;
-#endif
-static FileList* o_list;
-
-#if 0
-static char*
-EhSourceAdjustPathname(EhSource* source, char* rootdir)
-{
-	char buf[MAXPATHLEN];
-	char buf2[MAXPATHLEN];
-	char* p;
-	char* q;
-	char* filename = source->name;
-
-	if (getcwd(buf, sizeof(buf)) == NULL) {
-		fprintf(stderr, "cannot get pwd\n");
-		return NULL;
-	}
-
-	strcat(buf, "/");
-	strcat(buf, filename);
-
-	if (rootdir == NULL) {
-		filename = buf;
-	} else {
-		if (realpath(buf, buf2) == NULL) {
-			fprintf(stderr, "realpath() failed: %s\n", buf2);
-			return NULL;
-		}
-
-		if (realpath(rootdir, buf) == NULL) {
-			fprintf(stderr, "realpath() failed: %s\n", buf);
-			return NULL;
-		}
-		strcat(buf, "/"); 
-		
-		for (p = buf, q = buf2; *p == *q; p++, q++)
-			;
-
-		filename = q;
-	}
-
-	free(source->name);
-	source->name = strdup(filename);
-
-	return source->name;
-}
-#endif
-
-static unsigned
-katoi(char *buf)
-{
-	unsigned base = 1;
-	char* s;
-	
-	for (s = buf; isdigit(*s); s++)
-		;
-
-	if (*s == 'k' || *s == 'K')
-		base = 1024;
-
-	*s = '\0';
-
-	return base * atoi(buf);
-}
-
-static void
-usage(void)
-{
-	fprintf(stderr,
-			"Usage:\n"
-			"as a compiler:\n"
-			"gtscc [gtscc_options] [compiler_options] -c file.c file.cpp ...\n"
-			"gtscc_options:\n"
-			"-gtsfile <db.gts>       the gts database file (use this)\n"
-			"-gtszapsymbol <name>    convert symbol <name>\n"
-			"-gtsnozapsymbol <name>  don't convert symbol <name>\n"
-			"-gtsrootdir <directory> the root for the tree (use this)\n"
-			"-gtsverbose             be more verbose (3 levels)\n"
-			"-gtsnozap               don't convert globals to statics\n"
-			"-gtsnoupdate            don't update the database file\n"
-			"as a linker:\n"
-			"gtscc [gtscc_options] [linker_options] file.o ... libxx.a ...\n"
-			"gtscc_options:\n"
-			"-gtsfile <db.gts>       the gts database file (use this)\n"
-			"-gtszapsymbol <name>    convert symbol <name>\n"
-			"-gtsnozapsymbol <name>  don't convert symbol <name>\n"
-			"-gtsrootdir <directory> the root for the tree (use this)\n"
-			"-gtspref <directory>    please recompile these paths first\n"
-			"-gtsunpref <directory>  please try to avoid recompiling these\n"
-			"-gtsverbose             be more verbose (3 levels)\n"
-			"-gtssummary             print a summary of global usage\n"
-			"-gtsdump                print a detailed listing of all symbols\n"
-			"-gtsmaxglobals <number>[k] maximum globals allowed in target\n"
-			"-gtsnorecompile         don't do the normal recompilation\n"
-			"-gtsnolink              don't call linker after recompilation\n"
-			"-gtsnoupdate            don't update the database file\n"
-			"-help                   print this\n"
-	);
-}
-
-int
-main(int argc, char** argv)
-{
-	EhSymTable* table = EhSymTableNew(1000);
-	EhSym* sym;
-	FILE* zap_fp;
-	unsigned n = 0;
-	unsigned verbosity = 0;
-	char* arg_buf[256];
-	unsigned nargs = 0;
-	EhDirMap*   dmap = EhDirMapNew();
-	unsigned do_dump = 0;
-	unsigned do_summary = 0;
-	unsigned do_link = 1;
-	unsigned in_link = 1;
-	unsigned do_audit = 1;
-	unsigned do_zap = 1;
-	unsigned do_assem = 1;
-	unsigned do_recompile = 1;
-	unsigned do_collect = 1;
-	char* name;
-	char* saveprefix = NULL;
-	char* rootdir = NULL;
-	int rv;
-	EhSource* source = NULL;
-	char* gts_file = NULL;
-	char* path_prefs[32];
-	unsigned npath_prefs = 0;
-	char* path_un_prefs[32];
-	unsigned npath_un_prefs = 0;
-	char* suffix;
-	unsigned max_globals = DEFAULT_MAX_GLOBALS;
-	FileList* list;
-
-	if (elf_version(EV_CURRENT) == EV_NONE) {
-		fprintf(stderr, "something losing about your elf lib - sorry!\n");
-		return 3;
-		/* library out of date */
-		/* recover from error */
-	}
-
-	arg_buf[nargs] = NULL;
-
-	for (n = 1; n < argc; n++) {
-
-		if (strcmp(argv[n], "-help") == 0) {
-			usage();
-			return 0;
-		} else if (strcmp(argv[n], "-gtssummary") == 0) {
-			do_summary = 1;
-		} else if (strcmp(argv[n], "-gtsdump") == 0) {
-			do_dump = 1;
-		} else if (strcmp(argv[n], "-gtsnorecompile") == 0) {
-			do_recompile = 0;
-		} else if (strcmp(argv[n], "-gtsnolink") == 0) {
-			do_link = 0;
-		} else if (strcmp(argv[n], "-gtsverbose") == 0) {
-			verbosity++;
-		} else if (strcmp(argv[n], "-gtsnoupdate") == 0) {
-			do_collect = 0;
-		} else if (strcmp(argv[n], "-gtsnoaudit") == 0) {
-			do_audit = 0;
-		} else if (strcmp(argv[n], "-gtsnozap") == 0) {
-			do_zap = 0;
-		} else if (strcmp(argv[n], "-gtsrootdir") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtsrootdir requires an argument\n");
-				usage();
-				return 2;
-			}
-			rootdir = argv[n+1];
-			n++;
-		} else if (strcmp(argv[n], "-gtsdebugsym") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtsdebugsym requires an argument\n");
-				usage();
-				return 2;
-			}
-			djw_test_name = argv[n+1];
-			n++;
-		} else if (strcmp(argv[n], "-gtsmaxglobals") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtsmaxglobals requires an argument\n");
-				usage();
-				return 2;
-			}
-			max_globals = katoi(argv[n+1]);
-			n++;
-
-		} else if (strcmp(argv[n], "-gtspref") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtspref requires an argument\n");
-				usage();
-				return 2;
-			}
-			path_prefs[npath_prefs++] = argv[n+1];
-			path_prefs[npath_prefs] = NULL;
-			n++;
-
-		} else if (strcmp(argv[n], "-gtsunpref") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtsunpref requires an argument\n");
-				usage();
-				return 2;
-			}
-			path_un_prefs[npath_un_prefs++] = argv[n+1];
-			path_un_prefs[npath_un_prefs] = NULL;
-			n++;
-
-		} else if (strcmp(argv[n], "-gtssaveprefix") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtssaveprefix requires an argument\n");
-				usage();
-				return 2;
-			}
-			saveprefix = argv[n+1];
-			n++;
-
-		} else if (strcmp(argv[n], "-gtsfile") == 0) {
-
-			struct stat sbuf;
-
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtsfile requires an argument\n");
-				usage();
-				return 2;
-			}
-
-			gts_file = argv[n+1];
-				
-			if (stat(gts_file, &sbuf) == -1) {
-				fprintf(stderr,
-						"warning: %s does not exist, will be created\n",
-						gts_file);
-			} else {
-				
-				if ((zap_fp = fopen(gts_file, "r")) == NULL) {
-					fprintf(stderr,	"you lose cannot open %s\n", gts_file);
-					usage();
-					return 2;
-				}
-
-				if (EhSymTableFpLoad(table, zap_fp) == -1) {
-					fprintf(stderr,
-							"error: failed reading symbols from gtsfile %s\n",
-							argv[n+1]);
-					usage();
-					return 2;
-				}
-				
-				fclose(zap_fp);
-			}
-
-			n++;
-
-		} else if (strcmp(argv[n], "-gtszapsymbol") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtszapsymbol requires an argument\n");
-				usage();
-				return 2;
-			}
-
-			EhSymTableSetSymbolState(table, argv[n+1], EH_SYM_ZAPPED);
-			n++;
-
-		} else if (strcmp(argv[n], "-gtsnozapsymbol") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtsnozapsymbol requires an argument\n");
-				usage();
-				return 2;
-			}
-
-			EhSymTableSetSymbolState(table, argv[n+1], EH_SYM_DEFINED);
-			n++;
-
-		} else if (strcmp(argv[n], "-gtsname") == 0) {
-			if (argc < n+2) {
-				fprintf(stderr,	"-gtsname requires an argument\n");
-				usage();
-				return 2;
-			}
-
-			sym = EhSymTableFind(table, argv[n+1]);
-			if (!sym)
-				sym = EhSymNewRandomZap(argv[n+1]);
-			n++;
-			do_audit = 1;
-
-		} else if (strcmp(argv[n], "-c") == 0) { /* do not link */
-			in_link = 0;
-			do_link = 0;
-		} else if (strcmp(argv[n], "-S") == 0) { /* do not assem */
-			do_assem = 0;
-		} else if (strcmp(argv[n], "-o") == 0) { /* parse through */
-			arg_buf[nargs++] = argv[n++];
-			arg_buf[nargs++] = argv[n];
-			arg_buf[nargs] = NULL;
-		} else if (strcmp((suffix = suffix_name(argv[n])), ".cpp") == 0
-				   ||
-				   strcmp(suffix, ".c") == 0
-				   ||
-				   strcmp(suffix, ".s") == 0) {
-			char pathname[MAXPATHLEN];
-
-			make_relative_pathname(pathname, ".", rootdir);
-
-			source = EhSourceNew(argv[n], arg_buf, pathname);
-
-			rv = EhSourceCompile(source,
-								 table,
-								 verbosity,
-								 TRUE, /* compile, .s files ignore anyway */
-								 (do_audit + do_zap),
-								 do_assem);
-			if (rv == -1)
-				return 1;
-
-#if 0
-			EhSourceAdjustPathname(source, rootdir);
-#endif
-
-		} else if (strcmp(suffix, ".o") == 0 || strcmp(suffix, ".a") == 0) {
-
-			if (fileListFind(o_list, argv[n]) == NULL) {
-				fileListAppend(&o_list, argv[n]);
-			} else {
-				fprintf(stderr,
-						"%s repeated on command line - ignored\n",
-						argv[n]);
-			}
-			arg_buf[nargs++] = argv[n];
-			arg_buf[nargs] = NULL;
-
-		} else if (strncmp(argv[n], "-L", 2) == 0) {
-			EhDirMapAddDirectory(dmap, &argv[n][2]);
-		} else if (strncmp(argv[n], "-l", 2) == 0) {
-			char pathbuf[MAXPATHLEN];
-			name = EhDirMapGetLibName(dmap, &argv[n][2], pathbuf);
-			if (name != NULL) {
-				if (fileListFind(o_list, name) == NULL) {
-					fileListAppend(&o_list, name);
-				} else {
-					fprintf(stderr,
-							"%s repeated on command line - ignored\n",
-							name);
-				}
-			} else {
-				fprintf(stderr, 
-						"unable to resolve library reference %s - ignoring\n",
-						argv[n]);
-			}
-			arg_buf[nargs++] = argv[n];
-			arg_buf[nargs] = NULL;
-		} else {
-			arg_buf[nargs++] = argv[n];
-			arg_buf[nargs] = NULL;
-		}
-	}
-
-	/*
-	 *    Analyse objects.
-	 */
-	if (o_list != NULL) {
-		for (list = o_list; list != NULL; list = list->next) {
-
-			if (eh_process_file(list->name, table, rootdir)) {
-				fprintf(stderr, "oops we died around %s\n", list->name);
-				return 1;
-			}
-		}
-		
-		/* look for unused objects */
-		EhSymTableMap(table, object_nusers_mappee, 0);
-	}
-
-	if (do_summary) {
-		print_summary(table);
-	}
-
-	if (do_dump) {
-		print_dump(table);
-	}
-
-	if (!in_link && gts_file != NULL) {
-		FILE* zap_fp;
-		if ((zap_fp = fopen(gts_file, "w")) == NULL) {
-			perror(0);
-			usage();
-			return 2;
-		}
-
-		EhSymTableFpDump(table, zap_fp);
-		fclose(zap_fp);
-		return 0;
-	}
-
-	/*
-	 *    Now the fun really starts.
-	 */
-	if (do_recompile) {
-		char** pp = NULL;
-		char** up = NULL;
-		
-		if (npath_prefs > 0)
-			pp = path_prefs;
-		
-		if (npath_un_prefs > 0)
-			up = path_un_prefs;
-
-		if (!do_collect)
-			gts_file = NULL;
-		
-		rv = do_recompilation(table, gts_file, max_globals, pp, up, rootdir,
-							  verbosity);
-		if (rv == -1)
-			return 1;
-	}
-
-	/*
-	 *    Finally.
-	 */
-	if (do_link) {
-
-		int status;
-
-		arg_buf[nargs+1] = NULL;
-		for (n = nargs; n > 0; n--)
-			arg_buf[n] = arg_buf[n-1];
-		arg_buf[0] = LD_COMMAND;
-		
-		status = do_command("link", arg_buf, verbosity);
-
-		if (status == -1)
-			return 3;
-		else
-			return status;
-	}
-	
-	return 0;
-}
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -148,16 +148,30 @@ xpcshell-tests:
 	  -I$(topsrcdir)/build \
 	  $(testxpcsrcdir)/runxpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  $(EXTRA_TEST_ARGS) \
 	  $(LIBXUL_DIST)/bin/xpcshell \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 
+xpcshell-tests-remote: DM_TRANS?=adb
+xpcshell-tests-remote:
+	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+	  -I$(topsrcdir)/build \
+	  -I$(topsrcdir)/build/mobile \
+	  $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
+	  --symbols-path=$(DIST)/crashreporter-symbols \
+	  --build-info-json=$(DEPTH)/mozinfo.json \
+	  $(EXTRA_TEST_ARGS) \
+	  --dm_trans=$(DM_TRANS) \
+	  --deviceIP=${TEST_DEVICE} \
+	  --objdir=$(DEPTH) \
+	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
+
 # Execute a single test, specified in $(SOLO_FILE), but don't automatically
 # start the test. Instead, present the xpcshell prompt so the user can
 # attach a debugger and then start the test.
 check-interactive:
 	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/build \
 	  $(testxpcsrcdir)/runxpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
@@ -177,16 +191,33 @@ check-one:
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  --test-path=$(SOLO_FILE) \
 	  --profile-name=$(MOZ_APP_NAME) \
 	  --verbose \
 	  $(EXTRA_TEST_ARGS) \
 	  $(LIBXUL_DIST)/bin/xpcshell \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 
+check-one-remote: DM_TRANS?=adb
+check-one-remote:
+	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+	  -I$(topsrcdir)/build \
+	  -I$(topsrcdir)/build/mobile \
+	  $(testxpcsrcdir)/remotexpcshelltests.py \
+	  --symbols-path=$(DIST)/crashreporter-symbols \
+	  --build-info-json=$(DEPTH)/mozinfo.json \
+	  --test-path=$(SOLO_FILE) \
+	  --profile-name=$(MOZ_APP_NAME) \
+	  --verbose \
+	  $(EXTRA_TEST_ARGS) \
+	  --dm_trans=$(DM_TRANS) \
+	  --deviceIP=${TEST_DEVICE} \
+	  --objdir=$(DEPTH) \
+          --noSetup \
+	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 endif # XPCSHELL_TESTS
 
 ifdef CPP_UNIT_TESTS
 
 # Compile the tests to $(DIST)/bin.  Make lots of niceties available by default
 # through TestHarness.h, by modifying the list of includes and the libs against
 # which stuff links.
 CPPSRCS += $(CPP_UNIT_TESTS)
--- a/configure.in
+++ b/configure.in
@@ -965,16 +965,17 @@ if test -n "$_WIN32_MSVC"; then
     SKIP_COMPILER_CHECKS=1
     SKIP_LIBRARY_CHECKS=1
 
     # Since we're skipping compiler and library checks, hard-code
     # some facts here.
     AC_DEFINE(HAVE_IO_H)
     AC_DEFINE(HAVE_SETBUF)
     AC_DEFINE(HAVE_ISATTY)
+    AC_DEFINE(HAVE_STDCALL)
 fi
 
 fi # COMPILE_ENVIRONMENT
 
 AC_SUBST(MIDL_FLAGS)
 AC_SUBST(_MSC_VER)
 
 AC_SUBST(GNU_AS)
--- a/content/events/src/nsDOMMessageEvent.cpp
+++ b/content/events/src/nsDOMMessageEvent.cpp
@@ -98,19 +98,21 @@ nsDOMMessageEvent::UnrootData()
 {
   NS_ASSERTION(mDataRooted, "...");
   NS_DROP_JS_OBJECTS(this, nsDOMMessageEvent);
   mDataRooted = false;
   mData = JSVAL_VOID;
 }
 
 NS_IMETHODIMP
-nsDOMMessageEvent::GetData(jsval* aData)
+nsDOMMessageEvent::GetData(JSContext* aCx, jsval* aData)
 {
   *aData = mData;
+  if (!JS_WrapValue(aCx, aData))
+    return NS_ERROR_FAILURE;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMMessageEvent::GetOrigin(nsAString& aOrigin)
 {
   aOrigin = mOrigin;
   return NS_OK;
--- a/content/events/test/Makefile.in
+++ b/content/events/test/Makefile.in
@@ -132,15 +132,17 @@ endif
 		test_bug586961.xul \
 		test_bug415498.xul \
 		bug415498-doc1.html \
 		bug415498-doc2.html \
 		bug602962.xul \
 		test_bug602962.xul \
 		test_bug617528.xul \
 		window_bug617528.xul \
+		test_bug679494.xul \
+		file_bug679494.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 libs:: $(_CHROME_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/events/test/file_bug679494.html
@@ -0,0 +1,8 @@
+<html>
+<head>
+  <title>Test for Bug 679494</title>
+</head>
+<body>
+  There and back again.
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/events/test/test_bug679494.xul
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=67949
+-->
+<window title="Mozilla Bug 67949" onload="doTest();"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <title>Test for Bug 67949</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+<body  xmlns="http://www.w3.org/1999/xhtml">
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=67949">Mozilla Bug 67949</a>
+  <p id="display"></p>
+<div id="content" style="display: none">
+  <iframe id="contentframe" src="http://mochi.test:8888/tests/content/event/test/file_679494.html"></iframe>
+</div>
+</body>
+
+<script class="testbody" type="application/javascript;version=1.8"><![CDATA[
+
+/* Test for bug 679494 */
+function doTest() {
+  SimpleTest.waitForExplicitFinish();
+
+  var w = document.getElementById("contentframe").contentWindow;
+  w.addEventListener("message", function(e) {
+    is("test", e.data, "We got the data without a compartment mismatch assertion!");
+    SimpleTest.finish();
+    }, false);
+  w.postMessage("test", "*");
+}
+
+]]></script>
+
+</window>
--- a/content/html/content/src/nsHTMLTableCellElement.cpp
+++ b/content/html/content/src/nsHTMLTableCellElement.cpp
@@ -31,24 +31,26 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #include "nsIDOMHTMLTableCellElement.h"
 #include "nsIDOMHTMLTableRowElement.h"
+#include "nsHTMLTableElement.h"
 #include "nsIDOMHTMLCollection.h"
 #include "nsIDOMEventTarget.h"
 #include "nsMappedAttributes.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsRuleData.h"
+#include "nsRuleWalker.h"
 #include "nsIDocument.h"
 #include "celldata.h"
 
 class nsHTMLTableCellElement : public nsGenericHTMLElement,
                                public nsIDOMHTMLTableCellElement
 {
 public:
   nsHTMLTableCellElement(already_AddRefed<nsINodeInfo> aNodeInfo);
@@ -198,29 +200,25 @@ nsHTMLTableCellElement::GetCellIndex(PRI
 
 
 NS_IMETHODIMP
 nsHTMLTableCellElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
 {
   nsresult rv = nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Add style information from the mapped attributes of the table
-  // element.  This depends on the strange behavior of the
-  // |MapAttributesIntoRule| in nsHTMLTableElement.cpp, which is
-  // technically incorrect since it's violating the nsIStyleRule
-  // contract.  However, things are OK (except for the incorrect
-  // dependence on display type rather than tag) since tables and cells
-  // match different, less specific, rules.
-  nsIContent* table = GetTable();
-  if (table) {
-    rv = table->WalkContentStyleRules(aRuleWalker);
+  nsIContent* node = GetTable();
+  if (node && node->IsHTML() && node->NodeInfo()->Equals(nsGkAtoms::table)) {
+    nsHTMLTableElement* table = static_cast<nsHTMLTableElement*>(node);
+    nsMappedAttributes* tableInheritedAttributes =
+      table->GetAttributesMappedForCell();
+    if (tableInheritedAttributes)
+      aRuleWalker->Forward(tableInheritedAttributes);
   }
-
-  return rv;
+  return NS_OK;
 }
 
 
 NS_IMPL_STRING_ATTR(nsHTMLTableCellElement, Abbr, abbr)
 NS_IMPL_STRING_ATTR(nsHTMLTableCellElement, Axis, axis)
 NS_IMPL_STRING_ATTR(nsHTMLTableCellElement, BgColor, bgcolor)
 NS_IMPL_STRING_ATTR(nsHTMLTableCellElement, Ch, _char)
 NS_IMPL_STRING_ATTR(nsHTMLTableCellElement, ChOff, charoff)
--- a/content/html/content/src/nsHTMLTableElement.cpp
+++ b/content/html/content/src/nsHTMLTableElement.cpp
@@ -29,91 +29,38 @@
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
-#include "nsIDOMHTMLTableElement.h"
+#include "nsHTMLTableElement.h"
 #include "nsIDOMHTMLTableCaptionElem.h"
 #include "nsIDOMHTMLTableSectionElem.h"
 #include "nsCOMPtr.h"
 #include "nsIDOMEventTarget.h"
 #include "nsDOMError.h"
 #include "nsContentList.h"
-#include "nsMappedAttributes.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsHTMLParts.h"
 #include "nsRuleData.h"
 #include "nsStyleContext.h"
 #include "nsIDocument.h"
 #include "nsContentUtils.h"
 /* for collections */
 #include "nsIDOMElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIHTMLCollection.h"
 /* end for collections */
-
-class TableRowsCollection;
-
-class nsHTMLTableElement :  public nsGenericHTMLElement,
-                            public nsIDOMHTMLTableElement
-{
-public:
-  nsHTMLTableElement(already_AddRefed<nsINodeInfo> aNodeInfo);
-  virtual ~nsHTMLTableElement();
-
-  // nsISupports
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
-
-  // nsIDOMElement
-  NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
-
-  // nsIDOMHTMLElement
-  NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
-
-  // nsIDOMHTMLTableElement
-  NS_DECL_NSIDOMHTMLTABLEELEMENT
-
-  virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
-                                nsIAtom* aAttribute,
-                                const nsAString& aValue,
-                                nsAttrValue& aResult);
-  virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
-  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
-
-  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-
-  virtual nsXPCClassInfo* GetClassInfo();
-
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLTableElement,
-                                                     nsGenericHTMLElement)
-
-  already_AddRefed<nsIDOMHTMLTableSectionElement> GetTHead() {
-    return GetSection(nsGkAtoms::thead);
-  }
-  already_AddRefed<nsIDOMHTMLTableSectionElement> GetTFoot() {
-    return GetSection(nsGkAtoms::tfoot);
-  }
-  nsContentList* TBodies();
-protected:
-  already_AddRefed<nsIDOMHTMLTableSectionElement> GetSection(nsIAtom *aTag);
-
-  nsRefPtr<nsContentList> mTBodies;
-  nsRefPtr<TableRowsCollection> mRows;
-};
-
+#include "nsHTMLStyleSheet.h"
 
 /* ------------------------------ TableRowsCollection -------------------------------- */
 /**
  * This class provides a late-bound collection of rows in a table.
  * mParent is NOT ref-counted to avoid circular references
  */
 class TableRowsCollection : public nsIHTMLCollection 
 {
@@ -362,25 +309,27 @@ TableRowsCollection::ParentDestroyed()
 /* -------------------------- nsHTMLTableElement --------------------------- */
 // the class declaration is at the top of this file
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Table)
 
 
 nsHTMLTableElement::nsHTMLTableElement(already_AddRefed<nsINodeInfo> aNodeInfo)
-  : nsGenericHTMLElement(aNodeInfo)
+  : nsGenericHTMLElement(aNodeInfo),
+    mTableInheritedAttributes(TABLE_ATTRS_DIRTY)
 {
 }
 
 nsHTMLTableElement::~nsHTMLTableElement()
 {
   if (mRows) {
     mRows->ParentDestroyed();
   }
+  ReleaseInheritedAttributes();
 }
 
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLTableElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLTableElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mTBodies,
                                                        nsIDOMNodeList)
@@ -1025,229 +974,165 @@ MapAttributesIntoRule(const nsMappedAttr
   // testing the display type of the style context rather than checking
   // which *element* it's matching (style rules should not stop matching
   // when the display type is changed).
 
   nsPresContext* presContext = aData->mPresContext;
   nsCompatibility mode = presContext->CompatibilityMode();
 
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(TableBorder)) {
-    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
-    if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
-      // cellspacing
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellspacing);
-      nsCSSValue* borderSpacing = aData->ValueForBorderSpacing();
-      if (value && value->Type() == nsAttrValue::eInteger) {
-        if (borderSpacing->GetUnit() == eCSSUnit_Null)
-          borderSpacing->
-            SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
+    // cellspacing
+    const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellspacing);
+    nsCSSValue* borderSpacing = aData->ValueForBorderSpacing();
+    if (value && value->Type() == nsAttrValue::eInteger) {
+      if (borderSpacing->GetUnit() == eCSSUnit_Null) {
+        borderSpacing->
+          SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
       }
-      else if (value && value->Type() == nsAttrValue::ePercent &&
-               eCompatibility_NavQuirks == mode) {
-        // in quirks mode, treat a % cellspacing value a pixel value.
-        if (borderSpacing->GetUnit() == eCSSUnit_Null)
-          borderSpacing->
-            SetFloatValue(100.0f * value->GetPercentValue(), eCSSUnit_Pixel);
+    }
+    else if (value && value->Type() == nsAttrValue::ePercent &&
+             eCompatibility_NavQuirks == mode) {
+      // in quirks mode, treat a % cellspacing value a pixel value.
+      if (borderSpacing->GetUnit() == eCSSUnit_Null) {
+        borderSpacing->
+         SetFloatValue(100.0f * value->GetPercentValue(), eCSSUnit_Pixel);
       }
     }
   }
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Table)) {
-    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
-    if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
-      const nsAttrValue* value;
-      // layout
-      nsCSSValue* tableLayout = aData->ValueForTableLayout();
-      if (tableLayout->GetUnit() == eCSSUnit_Null) {
-        value = aAttributes->GetAttr(nsGkAtoms::layout);
-        if (value && value->Type() == nsAttrValue::eEnum)
-          tableLayout->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
-      }
-      
-      // cols
-      value = aAttributes->GetAttr(nsGkAtoms::cols);
-      if (value) {
-        nsCSSValue* cols = aData->ValueForCols();
-        if (value->Type() == nsAttrValue::eInteger) 
-          cols->SetIntValue(value->GetIntegerValue(), eCSSUnit_Integer);
-        else // COLS had no value, so it refers to all columns
-          cols->SetIntValue(NS_STYLE_TABLE_COLS_ALL, eCSSUnit_Enumerated);
-      }
+    const nsAttrValue* value;
+    // layout
+    nsCSSValue* tableLayout = aData->ValueForTableLayout();
+    if (tableLayout->GetUnit() == eCSSUnit_Null) {
+      value = aAttributes->GetAttr(nsGkAtoms::layout);
+      if (value && value->Type() == nsAttrValue::eEnum)
+        tableLayout->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
+    }
+    // cols
+    value = aAttributes->GetAttr(nsGkAtoms::cols);
+    if (value) {
+      nsCSSValue* cols = aData->ValueForCols();
+      if (value->Type() == nsAttrValue::eInteger)
+        cols->SetIntValue(value->GetIntegerValue(), eCSSUnit_Integer);
+      else // COLS had no value, so it refers to all columns
+        cols->SetIntValue(NS_STYLE_TABLE_COLS_ALL, eCSSUnit_Enumerated);
     }
   }
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Margin)) {
     const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
-  
-    if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
-      // align; Check for enumerated type (it may be another type if
-      // illegal)
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
+    // align; Check for enumerated type (it may be another type if
+    // illegal)
+    const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
 
-      if (value && value->Type() == nsAttrValue::eEnum) {
-        if (value->GetEnumValue() == NS_STYLE_TEXT_ALIGN_CENTER ||
-            value->GetEnumValue() == NS_STYLE_TEXT_ALIGN_MOZ_CENTER) {
-          nsCSSValue* marginLeft = aData->ValueForMarginLeftValue();
-          if (marginLeft->GetUnit() == eCSSUnit_Null)
-            marginLeft->SetAutoValue();
-          nsCSSValue* marginRight = aData->ValueForMarginRightValue();
-          if (marginRight->GetUnit() == eCSSUnit_Null)
-            marginRight->SetAutoValue();
-        }
+    if (value && value->Type() == nsAttrValue::eEnum) {
+      if (value->GetEnumValue() == NS_STYLE_TEXT_ALIGN_CENTER ||
+          value->GetEnumValue() == NS_STYLE_TEXT_ALIGN_MOZ_CENTER) {
+        nsCSSValue* marginLeft = aData->ValueForMarginLeftValue();
+        if (marginLeft->GetUnit() == eCSSUnit_Null)
+          marginLeft->SetAutoValue();
+        nsCSSValue* marginRight = aData->ValueForMarginRightValue();
+        if (marginRight->GetUnit() == eCSSUnit_Null)
+          marginRight->SetAutoValue();
+      }
+    }
+
+    // hspace is mapped into left and right margin,
+    // vspace is mapped into top and bottom margins
+    // - *** Quirks Mode only ***
+    if (eCompatibility_NavQuirks == mode) {
+      value = aAttributes->GetAttr(nsGkAtoms::hspace);
+
+      if (value && value->Type() == nsAttrValue::eInteger) {
+        nsCSSValue* marginLeft = aData->ValueForMarginLeftValue();
+        if (marginLeft->GetUnit() == eCSSUnit_Null)
+          marginLeft->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); 
+        nsCSSValue* marginRight = aData->ValueForMarginRightValue();
+        if (marginRight->GetUnit() == eCSSUnit_Null)
+          marginRight->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
       }
 
-      // hspace is mapped into left and right margin, 
-      // vspace is mapped into top and bottom margins
-      // - *** Quirks Mode only ***
-      if (eCompatibility_NavQuirks == mode) {
-        value = aAttributes->GetAttr(nsGkAtoms::hspace);
-
-        if (value && value->Type() == nsAttrValue::eInteger) {
-          nsCSSValue* marginLeft = aData->ValueForMarginLeftValue();
-          if (marginLeft->GetUnit() == eCSSUnit_Null)
-            marginLeft->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); 
-          nsCSSValue* marginRight = aData->ValueForMarginRightValue();
-          if (marginRight->GetUnit() == eCSSUnit_Null)
-            marginRight->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
-        }
-
-        value = aAttributes->GetAttr(nsGkAtoms::vspace);
+      value = aAttributes->GetAttr(nsGkAtoms::vspace);
 
-        if (value && value->Type() == nsAttrValue::eInteger) {
-          nsCSSValue* marginTop = aData->ValueForMarginTop();
-          if (marginTop->GetUnit() == eCSSUnit_Null)
-            marginTop->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); 
-          nsCSSValue* marginBottom = aData->ValueForMarginBottom();
-          if (marginBottom->GetUnit() == eCSSUnit_Null)
-            marginBottom->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); 
-        }
-      }
-    }
-  }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Padding)) {
-    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
-    if (readDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL) {
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellpadding);
-      if (value) {
-        nsAttrValue::ValueType valueType = value->Type();
-        if (valueType == nsAttrValue::eInteger || valueType == nsAttrValue::ePercent) {
-          // We have cellpadding.  This will override our padding values if we don't
-          // have any set.
-          nsCSSValue padVal;
-          if (valueType == nsAttrValue::eInteger)
-            padVal.SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
-          else {
-            // when we support % cellpadding in standard mode, uncomment the following
-            float pctVal = value->GetPercentValue();
-            //if (eCompatibility_NavQuirks == mode) {
-              // in quirks mode treat a pct cellpadding value as a pixel value
-              padVal.SetFloatValue(100.0f * pctVal, eCSSUnit_Pixel);
-            //}
-            //else {
-            //  padVal.SetPercentValue(pctVal);
-            //}
-          }
-          nsCSSValue* paddingLeft = aData->ValueForPaddingLeftValue();
-          if (paddingLeft->GetUnit() == eCSSUnit_Null)
-            *paddingLeft = padVal;
-          nsCSSValue* paddingRight = aData->ValueForPaddingRightValue();
-          if (paddingRight->GetUnit() == eCSSUnit_Null)
-            *paddingRight = padVal;
-          nsCSSValue* paddingTop = aData->ValueForPaddingTop();
-          if (paddingTop->GetUnit() == eCSSUnit_Null)
-            *paddingTop = padVal;
-          nsCSSValue* paddingBottom = aData->ValueForPaddingBottom();
-          if (paddingBottom->GetUnit() == eCSSUnit_Null)
-            *paddingBottom = padVal;
-        }
+      if (value && value->Type() == nsAttrValue::eInteger) {
+        nsCSSValue* marginTop = aData->ValueForMarginTop();
+        if (marginTop->GetUnit() == eCSSUnit_Null)
+          marginTop->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); 
+        nsCSSValue* marginBottom = aData->ValueForMarginBottom();
+        if (marginBottom->GetUnit() == eCSSUnit_Null)
+          marginBottom->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); 
       }
     }
   }
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
-    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
-  
-    if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
-      // width: value
-      nsCSSValue* width = aData->ValueForWidth();
-      if (width->GetUnit() == eCSSUnit_Null) {
-        const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
-        if (value && value->Type() == nsAttrValue::eInteger) 
-          width->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
-        else if (value && value->Type() == nsAttrValue::ePercent)
-          width->SetPercentValue(value->GetPercentValue());
-      }
+    // width: value
+    nsCSSValue* width = aData->ValueForWidth();
+    if (width->GetUnit() == eCSSUnit_Null) {
+      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
+      if (value && value->Type() == nsAttrValue::eInteger)
+        width->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
+      else if (value && value->Type() == nsAttrValue::ePercent)
+        width->SetPercentValue(value->GetPercentValue());
+    }
 
-      // height: value
-      nsCSSValue* height = aData->ValueForHeight();
-      if (height->GetUnit() == eCSSUnit_Null) {
-        const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
-        if (value && value->Type() == nsAttrValue::eInteger) 
-          height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
-        else if (value && value->Type() == nsAttrValue::ePercent)
-          height->SetPercentValue(value->GetPercentValue()); 
-      }
+    // height: value
+    nsCSSValue* height = aData->ValueForHeight();
+    if (height->GetUnit() == eCSSUnit_Null) {
+      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
+      if (value && value->Type() == nsAttrValue::eInteger)
+        height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
+      else if (value && value->Type() == nsAttrValue::ePercent)
+        height->SetPercentValue(value->GetPercentValue());
     }
   }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Visibility)) {
-    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
-  
-    if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL)
-      nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
-  }
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Border)) {
-    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
-    if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
-      // bordercolor
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bordercolor);
-      nscolor color;
-      if (value && presContext->UseDocumentColors() &&
-          value->GetColorValue(color)) {
-        nsCSSValue* borderLeftColor = aData->ValueForBorderLeftColorValue();
-        if (borderLeftColor->GetUnit() == eCSSUnit_Null)
-          borderLeftColor->SetColorValue(color);
-        nsCSSValue* borderRightColor = aData->ValueForBorderRightColorValue();
-        if (borderRightColor->GetUnit() == eCSSUnit_Null)
-          borderRightColor->SetColorValue(color);
-        nsCSSValue* borderTopColor = aData->ValueForBorderTopColor();
-        if (borderTopColor->GetUnit() == eCSSUnit_Null)
-          borderTopColor->SetColorValue(color);
-        nsCSSValue* borderBottomColor = aData->ValueForBorderBottomColor();
-        if (borderBottomColor->GetUnit() == eCSSUnit_Null)
-          borderBottomColor->SetColorValue(color);
-      }
+    // bordercolor
+    const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bordercolor);
+    nscolor color;
+    if (value && presContext->UseDocumentColors() &&
+        value->GetColorValue(color)) {
+      nsCSSValue* borderLeftColor = aData->ValueForBorderLeftColorValue();
+      if (borderLeftColor->GetUnit() == eCSSUnit_Null)
+        borderLeftColor->SetColorValue(color);
+      nsCSSValue* borderRightColor = aData->ValueForBorderRightColorValue();
+      if (borderRightColor->GetUnit() == eCSSUnit_Null)
+        borderRightColor->SetColorValue(color);
+      nsCSSValue* borderTopColor = aData->ValueForBorderTopColor();
+      if (borderTopColor->GetUnit() == eCSSUnit_Null)
+        borderTopColor->SetColorValue(color);
+      nsCSSValue* borderBottomColor = aData->ValueForBorderBottomColor();
+      if (borderBottomColor->GetUnit() == eCSSUnit_Null)
+        borderBottomColor->SetColorValue(color);
+    }
 
-      // border
-      const nsAttrValue* borderValue = aAttributes->GetAttr(nsGkAtoms::border);
-      if (borderValue) {
-        // border = 1 pixel default
-        PRInt32 borderThickness = 1;
+    // border
+    const nsAttrValue* borderValue = aAttributes->GetAttr(nsGkAtoms::border);
+    if (borderValue) {
+      // border = 1 pixel default
+      PRInt32 borderThickness = 1;
 
-        if (borderValue->Type() == nsAttrValue::eInteger)
-          borderThickness = borderValue->GetIntegerValue();
+      if (borderValue->Type() == nsAttrValue::eInteger)
+        borderThickness = borderValue->GetIntegerValue();
 
-        // by default, set all border sides to the specified width
-        nsCSSValue* borderLeftWidth = aData->ValueForBorderLeftWidthValue();
-        if (borderLeftWidth->GetUnit() == eCSSUnit_Null)
-          borderLeftWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
-        nsCSSValue* borderRightWidth = aData->ValueForBorderRightWidthValue();
-        if (borderRightWidth->GetUnit() == eCSSUnit_Null)
-          borderRightWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
-        nsCSSValue* borderTopWidth = aData->ValueForBorderTopWidth();
-        if (borderTopWidth->GetUnit() == eCSSUnit_Null)
-          borderTopWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
-        nsCSSValue* borderBottomWidth = aData->ValueForBorderBottomWidth();
-        if (borderBottomWidth->GetUnit() == eCSSUnit_Null)
-          borderBottomWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
-      }
+      // by default, set all border sides to the specified width
+      nsCSSValue* borderLeftWidth = aData->ValueForBorderLeftWidthValue();
+      if (borderLeftWidth->GetUnit() == eCSSUnit_Null)
+        borderLeftWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
+      nsCSSValue* borderRightWidth = aData->ValueForBorderRightWidthValue();
+      if (borderRightWidth->GetUnit() == eCSSUnit_Null)
+        borderRightWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
+      nsCSSValue* borderTopWidth = aData->ValueForBorderTopWidth();
+      if (borderTopWidth->GetUnit() == eCSSUnit_Null)
+        borderTopWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
+      nsCSSValue* borderBottomWidth = aData->ValueForBorderBottomWidth();
+      if (borderBottomWidth->GetUnit() == eCSSUnit_Null)
+        borderBottomWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
     }
   }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Background)) {
-    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
-  
-    if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL)
-      nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
-  }
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(PRBool)
 nsHTMLTableElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::layout },
     { &nsGkAtoms::cellpadding },
@@ -1274,8 +1159,149 @@ nsHTMLTableElement::IsAttributeMapped(co
   return FindAttributeDependence(aAttribute, map, NS_ARRAY_LENGTH(map));
 }
 
 nsMapRuleToAttributesFunc
 nsHTMLTableElement::GetAttributeMappingFunction() const
 {
   return &MapAttributesIntoRule;
 }
+
+static void
+MapInheritedTableAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData)
+{
+  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Padding)) {
+    const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellpadding);
+    if (value) {
+      nsAttrValue::ValueType valueType = value->Type();
+      if (valueType == nsAttrValue::eInteger ||
+          valueType == nsAttrValue::ePercent) {
+        // We have cellpadding.  This will override our padding values if we
+        // don't have any set.
+        nsCSSValue padVal;
+        if (valueType == nsAttrValue::eInteger)
+          padVal.SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
+        else {
+          // when we support % cellpadding in standard mode, uncomment the
+          // following
+          float pctVal = value->GetPercentValue();
+          //if (eCompatibility_NavQuirks == mode) {
+          // in quirks mode treat a pct cellpadding value as a pixel value
+          padVal.SetFloatValue(100.0f * pctVal, eCSSUnit_Pixel);
+          //}
+          //else {
+          //  padVal.SetPercentValue(pctVal);
+          //}
+        }
+        nsCSSValue* paddingLeft = aData->ValueForPaddingLeftValue();
+        if (paddingLeft->GetUnit() == eCSSUnit_Null)
+          *paddingLeft = padVal;
+        nsCSSValue* paddingRight = aData->ValueForPaddingRightValue();
+        if (paddingRight->GetUnit() == eCSSUnit_Null)
+          *paddingRight = padVal;
+        nsCSSValue* paddingTop = aData->ValueForPaddingTop();
+        if (paddingTop->GetUnit() == eCSSUnit_Null)
+          *paddingTop = padVal;
+        nsCSSValue* paddingBottom = aData->ValueForPaddingBottom();
+        if (paddingBottom->GetUnit() == eCSSUnit_Null)
+          *paddingBottom = padVal;
+      }
+    }
+  }
+}
+
+nsMappedAttributes*
+nsHTMLTableElement::GetAttributesMappedForCell()
+{
+  if (mTableInheritedAttributes) {
+    if (mTableInheritedAttributes == TABLE_ATTRS_DIRTY)
+      BuildInheritedAttributes();
+    if (mTableInheritedAttributes != TABLE_ATTRS_DIRTY)
+      return mTableInheritedAttributes;
+  }
+  return nsnull;
+}
+
+void
+nsHTMLTableElement::BuildInheritedAttributes()
+{
+  NS_ASSERTION(mTableInheritedAttributes == TABLE_ATTRS_DIRTY,
+               "potential leak, plus waste of work");
+  nsIDocument *document = GetCurrentDoc();
+  nsHTMLStyleSheet* sheet = document ?
+                              document->GetAttributeStyleSheet() : nsnull;
+  nsRefPtr<nsMappedAttributes> newAttrs;
+  if (sheet) {
+    const nsAttrValue* value = mAttrsAndChildren.GetAttr(nsGkAtoms::cellpadding);
+    if (value) {
+      nsRefPtr<nsMappedAttributes> modifiableMapped = new
+      nsMappedAttributes(sheet, MapInheritedTableAttributesIntoRule);
+
+      if (modifiableMapped) {
+        nsAttrValue val(*value);
+        modifiableMapped->SetAndTakeAttr(nsGkAtoms::cellpadding, val);
+      }
+      newAttrs = sheet->UniqueMappedAttributes(modifiableMapped);
+      NS_ASSERTION(newAttrs, "out of memory, but handling gracefully");
+
+      if (newAttrs != modifiableMapped) {
+        // Reset the stylesheet of modifiableMapped so that it doesn't
+        // spend time trying to remove itself from the hash.  There is no
+        // risk that modifiableMapped is in the hash since we created
+        // it ourselves and it didn't come from the stylesheet (in which
+        // case it would not have been modifiable).
+        modifiableMapped->DropStyleSheetReference();
+      }
+    }
+    mTableInheritedAttributes = newAttrs;
+    NS_IF_ADDREF(mTableInheritedAttributes);
+  }
+}
+
+nsresult
+nsHTMLTableElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                              nsIContent* aBindingParent,
+                              PRBool aCompileEventHandlers)
+{
+  ReleaseInheritedAttributes();
+  return nsGenericHTMLElement::BindToTree(aDocument, aParent,
+                                          aBindingParent,
+                                          aCompileEventHandlers);
+}
+
+void
+nsHTMLTableElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
+{
+  ReleaseInheritedAttributes();
+  nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
+}
+
+nsresult
+nsHTMLTableElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
+                            nsIAtom* aPrefix, const nsAString& aValue,
+                            PRBool aNotify)
+{
+  PRBool isCellPadding = (aAttribute == nsGkAtoms::cellpadding);
+  if (isCellPadding) {
+    ReleaseInheritedAttributes();
+  }
+
+  nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aAttribute,
+                                              aPrefix, aValue, aNotify);
+
+  if (isCellPadding) {
+    BuildInheritedAttributes();
+  }
+  return rv;
+}
+
+nsresult
+nsHTMLTableElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
+                               PRBool aNotify)
+{
+  PRBool isCellPadding = (aAttribute == nsGkAtoms::cellpadding);
+  if (isCellPadding) {
+    ReleaseInheritedAttributes();
+  }
+
+  return nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
+}
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/nsHTMLTableElement.h
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsIDOMHTMLTableElement.h"
+#include "nsGenericHTMLElement.h"
+#include "nsMappedAttributes.h"
+
+#define TABLE_ATTRS_DIRTY ((nsMappedAttributes*)0x1)
+
+
+class TableRowsCollection;
+
+class nsHTMLTableElement :  public nsGenericHTMLElement,
+                            public nsIDOMHTMLTableElement
+{
+public:
+  nsHTMLTableElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  virtual ~nsHTMLTableElement();
+
+  // nsISupports
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // nsIDOMNode
+  NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
+
+  // nsIDOMElement
+  NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
+
+  // nsIDOMHTMLElement
+  NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
+
+  // nsIDOMHTMLTableElement
+  NS_DECL_NSIDOMHTMLTABLEELEMENT
+
+  virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
+                                nsIAtom* aAttribute,
+                                const nsAString& aValue,
+                                nsAttrValue& aResult);
+  virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
+  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
+
+  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+  virtual nsXPCClassInfo* GetClassInfo();
+  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                              nsIContent* aBindingParent,
+                              PRBool aCompileEventHandlers);
+  virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
+                              PRBool aNullParent = PR_TRUE);
+  virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom *aName,
+                           nsIAtom *aPrefix, const nsAString &aValue,
+                           PRBool aNotify);
+  virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
+                             PRBool aNotify);
+
+
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLTableElement,
+                                                     nsGenericHTMLElement)
+  nsMappedAttributes* GetAttributesMappedForCell();
+  already_AddRefed<nsIDOMHTMLTableSectionElement> GetTHead() {
+    return GetSection(nsGkAtoms::thead);
+  }
+  already_AddRefed<nsIDOMHTMLTableSectionElement> GetTFoot() {
+    return GetSection(nsGkAtoms::tfoot);
+  }
+  nsContentList* TBodies();
+protected:
+  already_AddRefed<nsIDOMHTMLTableSectionElement> GetSection(nsIAtom *aTag);
+
+  nsRefPtr<nsContentList> mTBodies;
+  nsRefPtr<TableRowsCollection> mRows;
+  // Sentinel value of TABLE_ATTRS_DIRTY indicates that this is dirty and needs
+  // to be recalculated.
+  nsMappedAttributes *mTableInheritedAttributes;
+  void BuildInheritedAttributes();
+  void ReleaseInheritedAttributes() {
+    if (mTableInheritedAttributes &&
+        mTableInheritedAttributes != TABLE_ATTRS_DIRTY)
+      NS_RELEASE(mTableInheritedAttributes);
+      mTableInheritedAttributes = TABLE_ATTRS_DIRTY;
+  }
+};
+
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -283,16 +283,30 @@ NS_IMETHODIMP nsSVGFE::GetHeight(nsIDOMS
 
 /* readonly attribute nsIDOMSVGAnimatedString result; */
 NS_IMETHODIMP nsSVGFE::GetResult(nsIDOMSVGAnimatedString * *aResult)
 {
   return GetResultImageName().ToDOMAnimatedString(aResult, this);
 }
 
 //----------------------------------------------------------------------
+// nsIContent methods
+
+NS_IMETHODIMP_(PRBool)
+nsSVGFE::IsAttributeMapped(const nsIAtom* name) const
+{
+  static const MappedAttributeEntry* const map[] = {
+    sFiltersMap
+  };
+  
+  return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||
+    nsSVGFEBase::IsAttributeMapped(name);
+}
+
+//----------------------------------------------------------------------
 // nsSVGElement methods
 
 nsSVGElement::LengthAttributesInfo
 nsSVGFE::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               NS_ARRAY_LENGTH(sLengthInfo));
 }
@@ -2746,18 +2760,17 @@ nsSVGFEFloodElement::ComputeTargetBBox(c
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 NS_IMETHODIMP_(PRBool)
 nsSVGFEFloodElement::IsAttributeMapped(const nsIAtom* name) const
 {
   static const MappedAttributeEntry* const map[] = {
-    sFEFloodMap,
-    sFiltersMap
+    sFEFloodMap
   };
   
   return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||
     nsSVGFEFloodElementBase::IsAttributeMapped(name);
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
--- a/content/svg/content/src/nsSVGFilters.h
+++ b/content/svg/content/src/nsSVGFilters.h
@@ -142,16 +142,19 @@ public:
   virtual PRBool SubregionIsUnionOfRegions() { return PR_TRUE; }
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_SVG_FE_CID)
   
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES
 
+  // nsIContent interface
+  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
+
   virtual nsSVGString& GetResultImageName() = 0;
   // Return a list of all image names used as sources. Default is to
   // return no sources.
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
   // Compute the bounding box of the filter output. The default is just the
   // union of the source bounding boxes. The caller is
   // responsible for clipping this to the filter primitive subregion, so
   // if the filter fills its filter primitive subregion, it can just
deleted file mode 100644
--- a/db/Makefile.in
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is mozilla.org code.
-#
-# The Initial Developer of the Original Code is
-# Netscape Communications Corporation.
-# Portions created by the Initial Developer are Copyright (C) 1998
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either of the GNU General Public License Version 2 or later (the "GPL"),
-# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH     = ..
-topsrcdir = @top_srcdir@
-srcdir    = @srcdir@
-VPATH     = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-include $(topsrcdir)/config/rules.mk
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -11122,23 +11122,16 @@ nsNavigator::JavaEnabled(PRBool *aReturn
         break;
       }
     }
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsNavigator::TaintEnabled(PRBool *aReturn)
-{
-  *aReturn = PR_FALSE;
-  return NS_OK;
-}
-
 void
 nsNavigator::LoadingNewDocument()
 {
   // Release these so that they will be recreated for the
   // new document (if requested).  The plugins or mime types
   // arrays may have changed.  See bug 150087.
   if (mMimeTypes) {
     mMimeTypes->Invalidate();
--- a/dom/interfaces/base/nsIDOMNavigator.idl
+++ b/dom/interfaces/base/nsIDOMNavigator.idl
@@ -34,17 +34,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 ***** */
 
 #include "domstubs.idl"
 
-[scriptable, uuid(d7758ece-f088-4701-9ae4-1450192dca38)]
+[scriptable, uuid(5dd9f1f5-3347-4945-a350-4eedeb97d24c)]
 interface nsIDOMNavigator : nsISupports
 {
   readonly attribute DOMString           appCodeName;
   readonly attribute DOMString           appName;
   readonly attribute DOMString           appVersion;
   readonly attribute DOMString           language;
   readonly attribute nsIDOMMimeTypeArray mimeTypes;
   readonly attribute DOMString           platform;
@@ -55,11 +55,10 @@ interface nsIDOMNavigator : nsISupports
   readonly attribute DOMString           productSub;
   readonly attribute nsIDOMPluginArray   plugins;
   readonly attribute DOMString           userAgent;
   readonly attribute boolean             cookieEnabled;
   readonly attribute boolean             onLine;
   readonly attribute DOMString           buildID;
 
   boolean                   javaEnabled();
-  boolean                   taintEnabled();
 };
 
deleted file mode 100644
--- a/dom/interfaces/css/nsIDOMDocumentCSS.idl
+++ /dev/null
@@ -1,46 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Johnny Stenback <jst@netscape.com> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsIDOMDocumentStyle.idl"
-
-[scriptable, uuid(39f76c23-45b2-428a-9240-a981e5abf148)]
-interface nsIDOMDocumentCSS : nsIDOMDocumentStyle
-{
-  nsIDOMCSSStyleDeclaration getOverrideStyle(in nsIDOMElement elt, 
-                                       in DOMString pseudoElt);
-};
--- a/dom/interfaces/events/nsIDOMMessageEvent.idl
+++ b/dom/interfaces/events/nsIDOMMessageEvent.idl
@@ -46,16 +46,17 @@
  * http://www.whatwg.org/specs/web-apps/current-work/#messageevent
  */
 [scriptable, uuid(dc8ec5c6-ebf2-4f95-be99-cd13e3c0d0c6)]
 interface nsIDOMMessageEvent : nsIDOMEvent
 {
   /**
    * Custom string data associated with this event.
    */
+  [implicit_jscontext]
   readonly attribute jsval data;
   
   /**
    * The origin of the site from which this event originated, which is the
    * scheme, ":", and if the URI has a host, "//" followed by the
    * host, and if the port is not the default for the given scheme,
    * ":" followed by that port.  This value does not have a trailing slash.
    */
--- a/dom/interfaces/svg/nsIDOMSVGSVGElement.idl
+++ b/dom/interfaces/svg/nsIDOMSVGSVGElement.idl
@@ -69,17 +69,16 @@ interface nsIDOMSVGSVGElement
     nsIDOMSVGTests,
     nsIDOMSVGLangSpace,
     nsIDOMSVGExternalResourcesRequired,
     nsIDOMSVGStylable,
     nsIDOMSVGLocatable,
     nsIDOMSVGFitToViewBox,
     nsIDOMSVGZoomAndPan,
     events::nsIDOMEventTarget,
-    css::nsIDOMDocumentCSS
 */
 { 
   readonly attribute nsIDOMSVGAnimatedLength x;
   readonly attribute nsIDOMSVGAnimatedLength y;
   readonly attribute nsIDOMSVGAnimatedLength width;
   readonly attribute nsIDOMSVGAnimatedLength height;
   attribute DOMString         contentScriptType;
       // raises DOMException on setting
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -124,16 +124,17 @@ PluginModuleChild::PluginModuleChild()
   , mNestedEventHook(NULL)
   , mGlobalCallWndProcHook(NULL)
 #endif
 {
     NS_ASSERTION(!gInstance, "Something terribly wrong here!");
     memset(&mFunctions, 0, sizeof(mFunctions));
     memset(&mSavedData, 0, sizeof(mSavedData));
     gInstance = this;
+    mUserAgent.SetIsVoid(PR_TRUE);
 #ifdef XP_MACOSX
     mac_plugin_interposing::child::SetUpCocoaInterposing();
 #endif
 }
 
 PluginModuleChild::~PluginModuleChild()
 {
     NS_ASSERTION(gInstance == this, "Something terribly wrong here!");
@@ -724,17 +725,17 @@ PluginModuleChild::ActorDestroy(ActorDes
 void
 PluginModuleChild::CleanUp()
 {
 }
 
 const char*
 PluginModuleChild::GetUserAgent()
 {
-    if (!CallNPN_UserAgent(&mUserAgent))
+    if (mUserAgent.IsVoid() && !CallNPN_UserAgent(&mUserAgent))
         return NULL;
 
     return NullableStringGet(mUserAgent);
 }
 
 bool
 PluginModuleChild::RegisterActorForNPObject(NPObject* aObject,
                                             PluginScriptableObjectChild* aActor)
--- a/dom/plugins/test/unit/xpcshell.ini
+++ b/dom/plugins/test/unit/xpcshell.ini
@@ -1,6 +1,10 @@
 [DEFAULT]
 head = head_plugins.js
 tail = 
 
 [test_bug455213.js]
+# Bug 676953: test fails consistently on Android
+fail-if = os == "android"
 [test_bug471245.js]
+# Bug 676953: test fails consistently on Android
+fail-if = os == "android"
--- a/dom/src/storage/nsDOMStorage.cpp
+++ b/dom/src/storage/nsDOMStorage.cpp
@@ -65,18 +65,18 @@ using mozilla::dom::StorageChild;
 #include "nsIPermission.h"
 #include "nsIPermissionManager.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIOfflineCacheUpdate.h"
 #include "nsIJSContextStack.h"
 #include "nsIPrivateBrowsingService.h"
 #include "nsDOMString.h"
 #include "nsNetCID.h"
-#include "nsIProxyObjectManager.h"
 #include "mozilla/Preferences.h"
+#include "nsThreadUtils.h"
 
 using namespace mozilla;
 
 static const PRUint32 ASK_BEFORE_ACCEPT = 1;
 static const PRUint32 ACCEPT_SESSION = 2;
 static const PRUint32 BEHAVIOR_REJECT = 2;
 
 static const PRUint32 DEFAULT_QUOTA = 5 * 1024;
@@ -1893,16 +1893,44 @@ nsPIDOMStorage::nsDOMStorageType
 nsDOMStorage2::StorageType()
 {
   if (mStorage)
     return mStorage->StorageType();
 
   return nsPIDOMStorage::Unknown;
 }
 
+namespace {
+
+class StorageNotifierRunnable : public nsRunnable
+{
+public:
+  StorageNotifierRunnable(nsISupports* aSubject)
+    : mSubject(aSubject)
+  { }
+
+  NS_DECL_NSIRUNNABLE
+
+private:
+  nsCOMPtr<nsISupports> mSubject;
+};
+
+NS_IMETHODIMP
+StorageNotifierRunnable::Run()
+{
+  nsCOMPtr<nsIObserverService> observerService =
+    mozilla::services::GetObserverService();
+  if (observerService) {
+    observerService->NotifyObservers(mSubject, "dom-storage2-changed", nsnull);
+  }
+  return NS_OK;
+}
+
+} // anonymous namespace
+
 void
 nsDOMStorage2::BroadcastChangeNotification(const nsSubstring &aKey,
                                           const nsSubstring &aOldValue,
                                           const nsSubstring &aNewValue)
 {
   nsresult rv;
   nsCOMPtr<nsIDOMStorageEvent> event = new nsDOMStorageEvent();
   rv = event->InitStorageEvent(NS_LITERAL_STRING("storage"),
@@ -1912,36 +1940,18 @@ nsDOMStorage2::BroadcastChangeNotificati
                                aOldValue,
                                aNewValue,
                                mDocumentURI,
                                static_cast<nsIDOMStorage*>(this));
   if (NS_FAILED(rv)) {
     return;
   }
 
-  nsCOMPtr<nsIObserverService> observerService =
-    mozilla::services::GetObserverService();
-  if (!observerService) {
-    return;
-  }
-
-  nsCOMPtr<nsIObserverService> observerServiceProxy;
-  rv = NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
-                            NS_GET_IID(nsIObserverService),
-                            observerService,
-                            NS_PROXY_ASYNC | NS_PROXY_ALWAYS,
-                            getter_AddRefs(observerServiceProxy));
-  if (NS_FAILED(rv)) {
-    return;
-  }
-
-  // Fire off a notification that a storage object changed.
-  observerServiceProxy->NotifyObservers(event,
-                                        "dom-storage2-changed",
-                                        nsnull);
+  nsRefPtr<StorageNotifierRunnable> r = new StorageNotifierRunnable(event);
+  NS_DispatchToMainThread(r);
 }
 
 NS_IMETHODIMP
 nsDOMStorage2::GetLength(PRUint32 *aLength)
 {
   return mStorage->GetLength(aLength);
 }
 
--- a/dom/system/unix/Makefile.in
+++ b/dom/system/unix/Makefile.in
@@ -48,35 +48,38 @@ LIBRARY_NAME    = domsystemunix_s
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
 EXPORT_LIBRARY = 1
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 
+ifndef MOZ_ENABLE_QTMOBILITY
 CPPSRCS     = \
         nsDeviceMotionSystem.cpp \
         $(NULL)
+endif
 
 ifdef MOZ_MAEMO_LIBLOCATION
         CPPSRCS         += MaemoLocationProvider.cpp
         LOCAL_INCLUDES  += $(MOZ_PLATFORM_MAEMO_CFLAGS) \
                            -I$(topsrcdir)/dom/src/geolocation \
                            $(NULL)
 endif
 
 ifdef MOZ_PLATFORM_MAEMO
 CPPSRCS += nsHapticFeedback.cpp
 LOCAL_INCLUDES  += $(MOZ_DBUS_CFLAGS) \
                    $(NULL)
 ifdef MOZ_ENABLE_QTMOBILITY
-MOCSRCS         += moc_QTMLocationProvider.cpp
+MOCSRCS         += moc_QTMLocationProvider.cpp moc_nsQTMDeviceMotionSystem.cpp
 CPPSRCS         += $(MOCSRCS) \
                    QTMLocationProvider.cpp \
+                   nsQTMDeviceMotionSystem.cpp \
                    $(NULL)
 LOCAL_INCLUDES  += $(MOZ_QT_CFLAGS) \
                    -I$(topsrcdir)/dom/src/geolocation \
                    $(NULL)
 endif
 endif
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/system/unix/nsQTMDeviceMotionSystem.cpp
@@ -0,0 +1,126 @@
+/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Oleg Romashin <romaxa@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
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "mozilla/dom/ContentChild.h"
+#include "nsQTMDeviceMotionSystem.h"
+#include <QObject>
+#include <QtSensors/QAccelerometer>
+#include <QtSensors/QRotationSensor>
+
+#include "nsXULAppAPI.h"
+
+using namespace mozilla;
+using namespace QtMobility;
+
+bool
+MozQAccelerometerSensorFilter::filter(QAccelerometerReading* reading)
+{
+    mSystem.DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION,
+                                -reading->x(),
+                                -reading->y(),
+                                -reading->z());
+    return true;
+}
+
+bool
+MozQRotationSensorFilter::filter(QRotationReading* reading)
+{
+    // QRotationReading class:
+    // - the rotation around z axis (alpha) is given as z in QRotationReading;
+    // - the rotation around x axis (beta) is given as x in QRotationReading;
+    // - the rotation around y axis (gamma) is given as y in QRotationReading;
+    // See: http://doc.qt.nokia.com/qtmobility-1.0/qrotationreading.html
+    mSystem.DeviceMotionChanged(nsIDeviceMotionData::TYPE_ORIENTATION,
+                                reading->z(),
+                                reading->x(),
+                                reading->y());
+    return true;
+}
+
+nsDeviceMotionSystem::nsDeviceMotionSystem()
+{
+    if (XRE_GetProcessType() == GeckoProcessType_Default) {
+        mAccelerometer = new QAccelerometer();
+        mAccelerometerFilter = new MozQAccelerometerSensorFilter(*this);
+        mAccelerometer->addFilter(mAccelerometerFilter);
+        mRotation = new QRotationSensor();
+        mRotationFilter = new MozQRotationSensorFilter(*this);
+        mRotation->addFilter(mRotationFilter);
+    }
+}
+
+nsDeviceMotionSystem::~nsDeviceMotionSystem()
+{
+    if (XRE_GetProcessType() == GeckoProcessType_Default) {
+        mAccelerometer->removeFilter(mAccelerometerFilter);
+        mAccelerometer->stop();
+        mRotation->removeFilter(mRotationFilter);
+        mRotation->stop();
+        delete mAccelerometer;
+        delete mAccelerometerFilter;
+        delete mRotation;
+        delete mRotationFilter;
+    }
+}
+
+void nsDeviceMotionSystem::Startup()
+{
+    if (XRE_GetProcessType() == GeckoProcessType_Default) {
+        mAccelerometer->start();
+        if (!mAccelerometer->isActive()) {
+            NS_WARNING("AccelerometerSensor didn't start!");
+        }
+        mRotation->start();
+        if (!mRotation->isActive()) {
+            NS_WARNING("RotationSensor didn't start!");
+        }
+    }
+    else
+        mozilla::dom::ContentChild::GetSingleton()->
+            SendAddDeviceMotionListener();
+}
+
+void nsDeviceMotionSystem::Shutdown()
+{
+    if (XRE_GetProcessType() == GeckoProcessType_Default) {
+        mAccelerometer->stop();
+        mRotation->stop();
+    }
+    else
+        mozilla::dom::ContentChild::GetSingleton()->
+            SendRemoveDeviceMotionListener();
+}
new file mode 100644
--- /dev/null
+++ b/dom/system/unix/nsQTMDeviceMotionSystem.h
@@ -0,0 +1,100 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Oleg Romashin <romaxa@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
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsDeviceMotionSystem_h
+#define nsDeviceMotionSystem_h
+
+#include <QObject>
+#include <QtSensors/QAccelerometer>
+#include <QtSensors/QRotationSensor>
+#include "nsDeviceMotion.h"
+
+using namespace QtMobility;
+
+
+class MozQAccelerometerSensorFilter;
+class MozQRotationSensorFilter;
+
+class nsDeviceMotionSystem : public nsDeviceMotion
+{
+public:
+  nsDeviceMotionSystem();
+  virtual ~nsDeviceMotionSystem();
+
+private:
+  virtual void Startup();
+  virtual void Shutdown();
+
+  QtMobility::QAccelerometer* mAccelerometer;
+  MozQAccelerometerSensorFilter* mAccelerometerFilter;
+  QtMobility::QRotationSensor* mRotation;
+  MozQRotationSensorFilter* mRotationFilter;
+};
+
+class MozQAccelerometerSensorFilter : public QObject, public QAccelerometerFilter
+{
+    Q_OBJECT
+
+public:
+    MozQAccelerometerSensorFilter(nsDeviceMotionSystem& aSystem) : mSystem(aSystem) {}
+
+    virtual ~MozQAccelerometerSensorFilter(){}
+
+    virtual bool filter(QAccelerometerReading* reading);
+
+private:
+    bool filter(QSensorReading *reading) { return filter(static_cast<QAccelerometerReading*>(reading)); }
+    nsDeviceMotionSystem& mSystem;
+};
+
+class MozQRotationSensorFilter : public QObject, public QRotationFilter
+{
+    Q_OBJECT
+
+public:
+    MozQRotationSensorFilter(nsDeviceMotionSystem& aSystem) : mSystem(aSystem) {}
+
+    virtual ~MozQRotationSensorFilter(){}
+
+    virtual bool filter(QRotationReading* reading);
+
+private:
+    bool filter(QSensorReading *reading) { return filter(static_cast<QRotationReading*>(reading)); }
+    nsDeviceMotionSystem& mSystem;
+};
+
+#endif /* nsDeviceMotionSystem_h */
+
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -6784,33 +6784,35 @@ nsHTMLEditRules::ReturnInListItem(nsISel
 
   // if we are in an empty listitem, then we want to pop up out of the list
   // but only if prefs says it's ok and if the parent isn't the active editing host.
   PRBool isEmpty;
   res = IsEmptyBlock(aListItem, &isEmpty, PR_TRUE, PR_FALSE);
   NS_ENSURE_SUCCESS(res, res);
   if (isEmpty && (rootNode != list) && mReturnInEmptyLIKillsList)
   {
+    // get the list offset now -- before we might eventually split the list
+    nsCOMPtr<nsIDOMNode> listparent;
+    PRInt32 offset;
+    res = nsEditor::GetNodeLocation(list, address_of(listparent), &offset);
+    NS_ENSURE_SUCCESS(res, res);
+
     // are we the last list item in the list?
     PRBool bIsLast;
     res = mHTMLEditor->IsLastEditableChild(aListItem, &bIsLast);
     NS_ENSURE_SUCCESS(res, res);
     if (!bIsLast)
     {
       // we need to split the list!
       nsCOMPtr<nsIDOMNode> tempNode;
       res = mHTMLEditor->SplitNode(list, itemOffset, getter_AddRefs(tempNode));
       NS_ENSURE_SUCCESS(res, res);
     }
 
     // are we in a sublist?
-    nsCOMPtr<nsIDOMNode> listparent;
-    PRInt32 offset;
-    res = nsEditor::GetNodeLocation(list, address_of(listparent), &offset);
-    NS_ENSURE_SUCCESS(res, res);
     if (nsHTMLEditUtils::IsList(listparent))  //in a sublist
     {
       // if so, move this list item out of this list and into the grandparent list
       res = mHTMLEditor->MoveNode(aListItem,listparent,offset+1);
       NS_ENSURE_SUCCESS(res, res);
       res = aSelection->Collapse(aListItem,0);
     }
     else
--- a/editor/libeditor/html/tests/test_bug674861.html
+++ b/editor/libeditor/html/tests/test_bug674861.html
@@ -8,39 +8,67 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/EventUtils.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=674861">Mozilla Bug 674861</a>
 <p id="display"></p>
 <div id="content">
-  <h2> Bullet List </h2>
-  <ul contenteditable>
-    <li> item 1 </li>
-    <li> item 2 </li>
-    <li> item 3 </li>
-  </ul>
+  <section id="test1">
+    <h2> Editable Bullet List </h2>
+    <ul contenteditable>
+      <li> item A </li>
+      <li> item B </li>
+      <li> item C </li>
+    </ul>
+
+    <h2> Editable Ordered List </h2>
+    <ol contenteditable>
+      <li> item A </li>
+      <li> item B </li>
+      <li> item C </li>
+    </ol>
+
+    <h2> Editable Definition List </h2>
+    <dl contenteditable>
+      <dt> term A </dt>
+      <dd> definition A </dd>
+      <dt> term B </dt>
+      <dd> definition B </dd>
+      <dt> term C </dt>
+      <dd> definition C </dd>
+    </dl>
+  </section>
 
-  <h2> Ordered List </h2>
-  <ol contenteditable>
-    <li> item 1 </li>
-    <li> item 2 </li>
-    <li> item 3 </li>
-  </ol>
+  <section id="test2" contenteditable>
+    <h2> Bullet List In Editable Section </h2>
+    <ul>
+      <li> item A </li>
+      <li> item B </li>
+      <li> item C </li>
+    </ul>
 
-  <h2> Definition List </h2>
-  <dl contenteditable>
-    <dt> term 1 </dt>
-    <dd> definition 1 </dd>
-    <dt> term 2 </dt>
-    <dd> definition 2 </dd>
-    <dt> term 3 </dt>
-    <dd> definition 3 </dd>
-  </dl>
+    <h2> Ordered List In Editable Section </h2>
+    <ol>
+      <li> item A </li>
+      <li> item B </li>
+      <li> item C </li>
+    </ol>
+
+    <h2> Definition List In Editable Section </h2>
+    <dl>
+      <dt> term A </dt>
+      <dd> definition A </dd>
+      <dt> term B </dt>
+      <dd> definition B </dd>
+      <dt> term C </dt>
+      <dd> definition C </dd>
+    </dl>
+  </section>
 </div>
 
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 674861 **/
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(runTests);
@@ -77,43 +105,81 @@ function try2split(element, caretPos) {
   sel.addRange(range);
   
   // simulates two [Return] keypresses
   synthesizeKey("VK_RETURN", {});
   synthesizeKey("VK_RETURN", {});
 }
 
 function runTests() {
-  const ul = document.querySelector("#content ul");
-  const ol = document.querySelector("#content ol");
-  const dl = document.querySelector("#content dl");
+  const test1 = document.getElementById("test1");
+  const test2 = document.getElementById("test2");
+
+  // -----------------------------------------------------------------------
+  // #test1: editable lists should NOT be splittable
+  // -----------------------------------------------------------------------
+  const ul = test1.querySelector("ul");
+  const ol = test1.querySelector("ol");
+  const dl = test1.querySelector("dl");
 
   // bullet list
   ul.focus();
   try2split(ul.querySelector("li"), CARET_END);
-  is(document.querySelectorAll("#content ul").length, 1,
-    "The <ul> list should not be splittable.");
+  is(test1.querySelectorAll("ul").length, 1,
+    "The <ul contenteditable> list should not be splittable.");
   is(ul.querySelectorAll("li").length, 5,
     "Two new <li> elements should have been created.");
 
   // ordered list
   ol.focus();
   try2split(ol.querySelector("li"), CARET_END);
-  is(document.querySelectorAll("#content ol").length, 1,
-    "The <ol> list should not be splittable.");
+  is(test1.querySelectorAll("ol").length, 1,
+    "The <ol contenteditable> list should not be splittable.");
   is(ol.querySelectorAll("li").length, 5,
     "Two new <li> elements should have been created.");
 
   // definition list
   dl.focus();
   try2split(dl.querySelector("dd"), CARET_END);
-  is(document.querySelectorAll("#content dl").length, 1,
-    "The <dl> list should not be splittable.");
+  is(test1.querySelectorAll("dl").length, 1,
+    "The <dl contenteditable> list should not be splittable.");
   is(dl.querySelectorAll("dt").length, 5,
     "Two new <dt> elements should have been created.");
 
+  // -----------------------------------------------------------------------
+  // #test2: lists in editable blocks should be splittable
+  // -----------------------------------------------------------------------
+  test2.focus();
+
+  // bullet list
+  try2split(test2.querySelector("ul li"), CARET_END);
+  is(test2.querySelectorAll("ul").length, 2,
+    "The <ul> list should have been splitted.");
+  is(test2.querySelectorAll("ul li").length, 3,
+    "No new <li> element should have been created.");
+  is(test2.querySelectorAll("ul+p").length, 1,
+    "A new paragraph should have been created.");
+
+  // ordered list
+  try2split(test2.querySelector("ol li"), CARET_END);
+  is(test2.querySelectorAll("ol").length, 2,
+    "The <ol> list should have been splitted.");
+  is(test2.querySelectorAll("ol li").length, 3,
+    "No new <li> element should have been created.");
+  is(test2.querySelectorAll("ol+p").length, 1,
+    "A new paragraph should have been created.");
+
+  // definition list
+  try2split(test2.querySelector("dl dd"), CARET_END);
+  is(test2.querySelectorAll("dl").length, 2,
+    "The <dl> list should have been splitted.");
+  is(test2.querySelectorAll("dt").length, 3,
+    "No new <dt> element should have been created.");
+  is(test2.querySelectorAll("dl+p").length, 1,
+    "A new paragraph should have been created.");
+
   // done
   SimpleTest.finish();
 }
 </script>
 </pre>
 </body>
 </html>
--- a/embedding/android/GeckoApp.java
+++ b/embedding/android/GeckoApp.java
@@ -416,16 +416,17 @@ abstract public class GeckoApp
         GeckoAppShell.putChildInForeground();
         super.onRestart();
     }
 
     @Override
     public void onStart()
     {
         Log.i(LOG_FILE_NAME, "start");
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_START));
         super.onStart();
     }
 
     @Override
     public void onDestroy()
     {
         Log.i(LOG_FILE_NAME, "destroy");
         // Tell Gecko to shutting down; we'll end up calling System.exit()
--- a/embedding/android/GeckoEvent.java
+++ b/embedding/android/GeckoEvent.java
@@ -67,16 +67,17 @@ public class GeckoEvent {
     public static final int SIZE_CHANGED = 8;
     public static final int ACTIVITY_STOPPING = 9;
     public static final int ACTIVITY_PAUSING = 10;
     public static final int ACTIVITY_SHUTDOWN = 11;
     public static final int LOAD_URI = 12;
     public static final int SURFACE_CREATED = 13;
     public static final int SURFACE_DESTROYED = 14;
     public static final int GECKO_EVENT_SYNC = 15;
+    public static final int ACTIVITY_START = 17;
 
     public static final int IME_COMPOSITION_END = 0;
     public static final int IME_COMPOSITION_BEGIN = 1;
     public static final int IME_SET_TEXT = 2;
     public static final int IME_GET_TEXT = 3;
     public static final int IME_DELETE_TEXT = 4;
     public static final int IME_SET_SELECTION = 5;
     public static final int IME_GET_SELECTION = 6;
--- a/embedding/tests/unit/xpcshell.ini
+++ b/embedding/tests/unit/xpcshell.ini
@@ -1,6 +1,10 @@
 [DEFAULT]
 head = 
 tail = 
 
 [test_wwauthpromptfactory.js]
+# Bug 676955: test fails consistently on Android
+fail-if = os == "android"
 [test_wwpromptfactory.js]
+# Bug 676955: test fails consistently on Android
+fail-if = os == "android"
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -163,16 +163,17 @@ pattern_get_surface-no-error.patch: Don'
 missing-cairo-clip-init.diff: Missing cairo_clip_init call in cairo_gstate_show_text_glyphs lead to crash
 
 fix-cairo-win32-print-gdi-error.diff: Don't use fwprintf with char* format.  Flush stderr so that all error messages appears before exit.
 
 pixman-image-transform.patch: Reset the transform on pixman images when using them as destinations.
 
 fix-cairo-surface-wrapper-flush-build-warning.patch: Ensures that _cairo_surface_wrapper_flush always returns a status, to silence the build warning
 
+fixup-unbounded.patch: Hack to work around bad assumption.
 ==== pixman patches ====
 
 pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv.
 
 pixman-rename-and-endian.patch: include cairo-platform.h for renaming of external symbols and endian macros
 
 NOTE: we previously supported ARM assembler on MSVC, this has been removed because of the maintenance burden
 
--- a/gfx/cairo/cairo/src/cairo-image-surface.c
+++ b/gfx/cairo/cairo/src/cairo-image-surface.c
@@ -1797,17 +1797,17 @@ static cairo_status_t
 					    cairo_boxes_t *boxes)
 {
     cairo_boxes_t clear;
     cairo_box_t box;
     cairo_status_t status;
     struct _cairo_boxes_chunk *chunk;
     int i;
 
-    if (boxes->num_boxes <= 1 && clip_region == NULL)
+    if (boxes->num_boxes < 1 && clip_region == NULL)
 	return _cairo_image_surface_fixup_unbounded (dst, extents, NULL);
 
     _cairo_boxes_init (&clear);
 
     box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
     box.p1.y = _cairo_fixed_from_int (extents->unbounded.y);
     box.p2.x = _cairo_fixed_from_int (extents->unbounded.x);
     box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height);
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/fixup-unbounded.patch
@@ -0,0 +1,22 @@
+diff --git a/gfx/cairo/cairo/src/cairo-image-surface.c b/gfx/cairo/cairo/src/cairo-image-surface.c
+--- a/gfx/cairo/cairo/src/cairo-image-surface.c
++++ b/gfx/cairo/cairo/src/cairo-image-surface.c
+@@ -1797,17 +1797,17 @@ _cairo_image_surface_fixup_unbounded_box
+ 					    cairo_boxes_t *boxes)
+ {
+     cairo_boxes_t clear;
+     cairo_box_t box;
+     cairo_status_t status;
+     struct _cairo_boxes_chunk *chunk;
+     int i;
+ 
+-    if (boxes->num_boxes <= 1 && clip_region == NULL)
++    if (boxes->num_boxes < 1 && clip_region == NULL)
+ 	return _cairo_image_surface_fixup_unbounded (dst, extents, NULL);
+ 
+     _cairo_boxes_init (&clear);
+ 
+     box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
+     box.p1.y = _cairo_fixed_from_int (extents->unbounded.y);
+     box.p2.x = _cairo_fixed_from_int (extents->unbounded.x);
+     box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height);
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -186,50 +186,106 @@ ThebesLayerBufferOGL::RenderTo(const nsI
       // entire visible region's bounds, and we should draw it all in one quad
       // to avoid unexpected aliasing.
       tmpRegion = visibleRegion.GetBounds();
       renderRegion = &tmpRegion;
     } else {
       renderRegion = &visibleRegion;
     }
 
-    mTexImage->BeginTileIteration();
-    if (mTexImageOnWhite) {
-      mTexImageOnWhite->BeginTileIteration();
-      NS_ASSERTION(mTexImageOnWhite->GetTileRect() == mTexImage->GetTileRect(), "component alpha textures should be the same size.");
-    }
     nsIntRegion region(*renderRegion);
     nsIntPoint origin = GetOriginOffset();
     region.MoveBy(-origin);           // translate into TexImage space, buffer origin might not be at texture (0,0)
 
+    // Figure out the intersecting draw region
+    nsIntSize texSize = mTexImage->GetSize();
+    nsIntRect textureRect = nsIntRect(0, 0, texSize.width, texSize.height);
+    textureRect.MoveBy(region.GetBounds().TopLeft());
+    nsIntRegion subregion;
+    subregion.And(region, textureRect);
+    if (subregion.IsEmpty())  // Region is empty, nothing to draw
+      return;
+
+    nsIntRegion screenRects;
+    nsIntRegion regionRects;
+
+    // Collect texture/screen coordinates for drawing
+    nsIntRegionRectIterator iter(subregion);
+    while (const nsIntRect* iterRect = iter.Next()) {
+        nsIntRect regionRect = *iterRect;
+        nsIntRect screenRect = regionRect;
+        screenRect.MoveBy(origin);
+
+        screenRects.Or(screenRects, screenRect);
+        regionRects.Or(regionRects, regionRect);
+    }
+
+    mTexImage->BeginTileIteration();
+    if (mTexImageOnWhite) {
+      NS_ASSERTION(mTexImage->GetTileCount() == mTexImageOnWhite->GetTileCount(),
+                   "Tile count mismatch on component alpha texture");
+      mTexImageOnWhite->BeginTileIteration();
+    }
+
+    bool usingTiles = (mTexImage->GetTileCount() > 1);
     do {
-      nsIntRect textureRect = mTexImage->GetTileRect();
-      textureRect.MoveBy(region.GetBounds().x, region.GetBounds().y);
-      nsIntRegion subregion(region);
-      subregion.And(region, textureRect); // region this texture is visible in
-      if (subregion.IsEmpty()) {
-        continue;
+      if (mTexImageOnWhite) {
+        NS_ASSERTION(mTexImageOnWhite->GetTileRect() == mTexImage->GetTileRect(), "component alpha textures should be the same size.");
       }
+
+      nsIntRect tileRect = mTexImage->GetTileRect();
+
       // Bind textures.
       TextureImage::ScopedBindTexture texBind(mTexImage, LOCAL_GL_TEXTURE0);
       TextureImage::ScopedBindTexture texOnWhiteBind(mTexImageOnWhite, LOCAL_GL_TEXTURE1);
 
-      nsIntRegionRectIterator iter(subregion);
-      while (const nsIntRect *iterRect = iter.Next()) {
-        nsIntRect regionRect = *iterRect;  // one rectangle of this texture's region
-        // translate into the correct place for this texture sub-region
-        nsIntRect screenRect = regionRect;
-        screenRect.MoveBy(origin);
-        program->SetLayerQuadRect(screenRect);
+      // Draw texture. If we're using tiles, we do repeating manually, as texture
+      // repeat would cause each individual tile to repeat instead of the
+      // compound texture as a whole. This involves drawing at most 4 sections,
+      // 2 for each axis that has texture repeat.
+      for (int y = 0; y < (usingTiles ? 2 : 1); y++) {
+        for (int x = 0; x < (usingTiles ? 2 : 1); x++) {
+          nsIntRect currentTileRect(tileRect);
+          currentTileRect.MoveBy(x * texSize.width, y * texSize.height);
+
+          nsIntRegionRectIterator screenIter(screenRects);
+          nsIntRegionRectIterator regionIter(regionRects);
+
+          const nsIntRect* screenRect;
+          const nsIntRect* regionRect;
+          while ((screenRect = screenIter.Next()) &&
+                 (regionRect = regionIter.Next())) {
+              nsIntRect tileScreenRect(*screenRect);
+              nsIntRect tileRegionRect(*regionRect);
 
-        regionRect.MoveBy(-mTexImage->GetTileRect().TopLeft()); // get region of tile
-        aManager->BindAndDrawQuadWithTextureRect(program, regionRect,
-                                                 textureRect.Size(),
-                                                 mTexImage->GetWrapMode());
+              // When we're using tiles, find the intersection between the tile
+              // rect and this region rect. Tiling is then handled by the
+              // outer for-loops and modifying the tile rect.
+              if (usingTiles) {
+                  tileScreenRect.MoveBy(-origin);
+                  tileScreenRect = tileScreenRect.Intersect(currentTileRect);
+                  tileScreenRect.MoveBy(origin);
+
+                  if (tileScreenRect.IsEmpty())
+                    continue;
+
+                  tileRegionRect = regionRect->Intersect(currentTileRect);
+                  tileRegionRect.MoveBy(-currentTileRect.TopLeft());
+              }
+
+              program->SetLayerQuadRect(tileScreenRect);
+              aManager->BindAndDrawQuadWithTextureRect(program, tileRegionRect,
+                                                       tileRect.Size(),
+                                                       mTexImage->GetWrapMode());
+          }
+        }
       }
+
+      if (mTexImageOnWhite)
+          mTexImageOnWhite->NextTile();
     } while (mTexImage->NextTile());
   }
 
   if (mTexImageOnWhite) {
     // Restore defaults
     gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                              LOCAL_GL_ONE, LOCAL_GL_ONE);
   }
@@ -786,16 +842,28 @@ ShadowBufferOGL::Upload(gfxASurface* aUp
   }
 
   nsIntRegion destRegion(aUpdated);
   // aUpdated is in screen coordinates.  Move it so that the layer's
   // top-left is 0,0
   nsIntPoint visTopLeft = mLayer->GetVisibleRegion().GetBounds().TopLeft();
   destRegion.MoveBy(-visTopLeft);
 
+  // Correct for rotation
+  destRegion.MoveBy(aRotation);
+  nsIntRect destBounds = destRegion.GetBounds();
+  destRegion.MoveBy((destBounds.x >= size.width) ? -size.width : 0,
+                    (destBounds.y >= size.height) ? -size.height : 0);
+
+  // There's code to make sure that updated regions don't cross rotation
+  // boundaries, so assert here that this is the case
+  NS_ASSERTION(((destBounds.x % size.width) + destBounds.width <= size.width) &&
+               ((destBounds.y % size.height) + destBounds.height <= size.height),
+               "Updated region lies across rotation boundaries!");
+
   // NB: this gfxContext must not escape EndUpdate() below
   mTexImage->DirectUpdate(aUpdate, destRegion);
 
   mBufferRect = aRect;
   mBufferRotation = aRotation;
 }
 
 ShadowThebesLayerOGL::ShadowThebesLayerOGL(LayerManagerOGL *aManager)
--- a/gfx/src/nsThebesFontEnumerator.cpp
+++ b/gfx/src/nsThebesFontEnumerator.cpp
@@ -102,18 +102,17 @@ nsThebesFontEnumerator::EnumerateFonts(c
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsThebesFontEnumerator::HaveFontFor(const char *aLangGroup,
                                     PRBool *aResult)
 {
-    NS_ENSURE_ARG_POINTER(*aResult);
-    NS_ENSURE_ARG_POINTER(*aLangGroup);
+    NS_ENSURE_ARG_POINTER(aResult);
 
     *aResult = PR_TRUE;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsThebesFontEnumerator::GetDefaultFont(const char *aLangGroup,
                                        const char *aGeneric,
--- a/gfx/thebes/GLContext.cpp
+++ b/gfx/thebes/GLContext.cpp
@@ -570,51 +570,52 @@ BasicTextureImage::~BasicTextureImage()
 }
 
 gfxASurface*
 BasicTextureImage::BeginUpdate(nsIntRegion& aRegion)
 {
     NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
 
     // determine the region the client will need to repaint
-    ImageFormat format =
-        (GetContentType() == gfxASurface::CONTENT_COLOR) ?
-        gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32;
-    if (mTextureState != Valid)
-    {
-        // if the texture hasn't been initialized yet, or something important
-        // changed, we need to recreate our backing surface and force the
-        // client to paint everything
-        mUpdateRegion = nsIntRect(nsIntPoint(0, 0), mSize);
-    } else {
-        mUpdateRegion = aRegion;
-    }
-
-    aRegion = mUpdateRegion;
+    GetUpdateRegion(aRegion);
+    mUpdateRegion = aRegion;
 
     nsIntRect rgnSize = mUpdateRegion.GetBounds();
     if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(rgnSize)) {
         NS_ERROR("update outside of image");
         return NULL;
     }
 
-    mUpdateSurface = 
+    ImageFormat format =
+        (GetContentType() == gfxASurface::CONTENT_COLOR) ?
+        gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32;
+    mUpdateSurface =
         GetSurfaceForUpdate(gfxIntSize(rgnSize.width, rgnSize.height), format);
 
     if (!mUpdateSurface || mUpdateSurface->CairoStatus()) {
         mUpdateSurface = NULL;
         return NULL;
     }
 
     mUpdateSurface->SetDeviceOffset(gfxPoint(-rgnSize.x, -rgnSize.y));
 
     return mUpdateSurface;
 }
 
 void
+BasicTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
+{
+  // if the texture hasn't been initialized yet, or something important
+  // changed, we need to recreate our backing surface and force the
+  // client to paint everything
+  if (mTextureState != Valid)
+      aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
+}
+
+void
 BasicTextureImage::EndUpdate()
 {
     NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
 
     // FIXME: this is the slow boat.  Make me fast (with GLXPixmap?).
 
     // Undo the device offset that BeginUpdate set; doesn't much matter for us here,
     // but important if we ever do anything directly with the surface.
@@ -724,89 +725,139 @@ TiledTextureImage::TiledTextureImage(GLC
 
 TiledTextureImage::~TiledTextureImage()
 {
 }
 
 bool 
 TiledTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
 {
-    nsIntRect bounds = aRegion.GetBounds();
     nsIntRegion region;
     if (mTextureState != Valid) {
-        bounds = nsIntRect(0, 0, mSize.width, mSize.height);
+        nsIntRect bounds = nsIntRect(0, 0, mSize.width, mSize.height);
         region = nsIntRegion(bounds);
     } else {
         region = aRegion;
     }
 
     PRBool result = PR_TRUE;
     for (unsigned i = 0; i < mImages.Length(); i++) {
-        unsigned int xPos = (i % mColumns) * mTileSize;
-        unsigned int yPos = (i / mColumns) * mTileSize;
+        int xPos = (i % mColumns) * mTileSize;
+        int yPos = (i / mColumns) * mTileSize;
         nsIntRegion tileRegion;
         tileRegion.And(region, nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize())); // intersect with tile
         if (tileRegion.IsEmpty())
             continue;
         tileRegion.MoveBy(-xPos, -yPos); // translate into tile local space
         result &= mImages[i]->DirectUpdate(aSurf,
                                            tileRegion,
                                            aFrom + nsIntPoint(xPos, yPos));
     }
     mShaderType = mImages[0]->GetShaderProgramType();
     mIsRGBFormat = mImages[0]->IsRGB();
     mTextureState = Valid;
     return result;
 }
 
+void
+TiledTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
+{
+    if (mTextureState != Valid) {
+        // if the texture hasn't been initialized yet, or something important
+        // changed, we need to recreate our backing surface and force the
+        // client to paint everything
+        aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
+        return;
+    }
+
+    nsIntRegion newRegion;
+
+    // We need to query each texture with the region it will be drawing and
+    // set aForRegion to be the combination of all of these regions
+    for (unsigned i = 0; i < mImages.Length(); i++) {
+        int xPos = (i % mColumns) * mTileSize;
+        int yPos = (i / mColumns) * mTileSize;
+        nsIntRect imageRect = nsIntRect(nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize()));
+
+        if (aForRegion.Intersects(imageRect)) {
+            // Make a copy of the region
+            nsIntRegion subRegion;
+            subRegion.And(aForRegion, imageRect);
+            // Translate it into tile-space
+            subRegion.MoveBy(-xPos, -yPos);
+            // Query region
+            mImages[i]->GetUpdateRegion(subRegion);
+            // Translate back
+            subRegion.MoveBy(xPos, yPos);
+            // Add to the accumulated region
+            newRegion.Or(newRegion, subRegion);
+        }
+    }
+
+    aForRegion = newRegion;
+}
+
 gfxASurface*
 TiledTextureImage::BeginUpdate(nsIntRegion& aRegion)
 {
     NS_ASSERTION(!mInUpdate, "nested update");
     mInUpdate = PR_TRUE;
 
+    // Note, we don't call GetUpdateRegion here as if the updated region is
+    // fully contained in a single tile, we get to avoid iterating through
+    // the tiles again (and a little copying).
     if (mTextureState != Valid)
     {
         // if the texture hasn't been initialized yet, or something important
         // changed, we need to recreate our backing surface and force the
         // client to paint everything
-        mUpdateRegion = nsIntRect(nsIntPoint(0, 0), mSize);
-    } else {
-        mUpdateRegion = aRegion;
+        aRegion = nsIntRect(nsIntPoint(0, 0), mSize);
     }
 
+    nsIntRect bounds = aRegion.GetBounds();
+
     for (unsigned i = 0; i < mImages.Length(); i++) {
-        unsigned int xPos = (i % mColumns) * mTileSize;
-        unsigned int yPos = (i / mColumns) * mTileSize;
+        int xPos = (i % mColumns) * mTileSize;
+        int yPos = (i / mColumns) * mTileSize;
         nsIntRegion imageRegion = nsIntRegion(nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize()));
 
         // a single Image can handle this update request
         if (imageRegion.Contains(aRegion)) {
             // adjust for tile offset
             aRegion.MoveBy(-xPos, -yPos);
             // forward the actual call
             nsRefPtr<gfxASurface> surface = mImages[i]->BeginUpdate(aRegion);
             // caller expects container space
             aRegion.MoveBy(xPos, yPos);
+            // Correct the device offset
+            gfxPoint offset = surface->GetDeviceOffset();
+            surface->SetDeviceOffset(gfxPoint(offset.x - xPos,
+                                              offset.y - yPos));
             // we don't have a temp surface
             mUpdateSurface = nsnull;
             // remember which image to EndUpdate
             mCurrentImage = i;
             return surface.get();
         }
     }
+
+    // Get the real updated region, taking into account the capabilities of
+    // each TextureImage tile
+    GetUpdateRegion(aRegion);
+    mUpdateRegion = aRegion;
+    bounds = aRegion.GetBounds();
+
     // update covers multiple Images - create a temp surface to paint in
     gfxASurface::gfxImageFormat format =
         (GetContentType() == gfxASurface::CONTENT_COLOR) ?
         gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32;
-
-    nsIntRect bounds = aRegion.GetBounds();
     mUpdateSurface = gfxPlatform::GetPlatform()->
         CreateOffscreenSurface(gfxIntSize(bounds.width, bounds.height), gfxASurface::ContentFromFormat(format));
     mUpdateSurface->SetDeviceOffset(gfxPoint(-bounds.x, -bounds.y));
+
     return mUpdateSurface;
 }
 
 void
 TiledTextureImage::EndUpdate()
 {
     NS_ASSERTION(mInUpdate, "EndUpdate not in update");
     if (!mUpdateSurface) { // update was to a single TextureImage
@@ -815,19 +866,20 @@ TiledTextureImage::EndUpdate()
         mTextureState = Valid;
         mShaderType = mImages[mCurrentImage]->GetShaderProgramType();
         mIsRGBFormat = mImages[mCurrentImage]->IsRGB();
         return;
     }
 
     // upload tiles from temp surface
     for (unsigned i = 0; i < mImages.Length(); i++) {
-        unsigned int xPos = (i % mColumns) * mTileSize;
-        unsigned int yPos = (i / mColumns) * mTileSize;
+        int xPos = (i % mColumns) * mTileSize;
+        int yPos = (i / mColumns) * mTileSize;
         nsIntRect imageRect = nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize());
+
         nsIntRegion subregion;
         subregion.And(mUpdateRegion, imageRect);
         if (subregion.IsEmpty())
             continue;
         subregion.MoveBy(-xPos, -yPos); // Tile-local space
         // copy tile from temp surface
         gfxASurface* surf = mImages[i]->BeginUpdate(subregion);
         nsRefPtr<gfxContext> ctx = new gfxContext(surf);
@@ -837,16 +889,17 @@ TiledTextureImage::EndUpdate()
         ctx->Paint();
         mImages[i]->EndUpdate();
     }
 
     mUpdateSurface = nsnull;
     mInUpdate = PR_FALSE;
     mShaderType = mImages[0]->GetShaderProgramType();
     mIsRGBFormat = mImages[0]->IsRGB();
+    mTextureState = Valid;
 }
 
 void TiledTextureImage::BeginTileIteration()
 {
     mCurrentImage = 0;
 }
 
 PRBool TiledTextureImage::NextTile()
@@ -896,16 +949,21 @@ void TiledTextureImage::Resize(const nsI
           nsRefPtr<TextureImage> teximg =
                   mGL->TileGenFunc(size, mContentType, mUseNearestFilter);
           mImages.AppendElement(teximg.forget());
       }
     }
     mTextureState = Allocated;
 }
 
+PRUint32 TiledTextureImage::GetTileCount()
+{
+    return mImages.Length();
+}
+
 PRBool
 GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
 {
     if (!IsOffscreenSizeAllowed(aSize))
         return PR_FALSE;
 
     MakeCurrent();
 
--- a/gfx/thebes/GLContext.h
+++ b/gfx/thebes/GLContext.h
@@ -189,16 +189,25 @@ public:
      * BeginUpdate() calls cannot be "nested", and each successful
      * BeginUpdate() must be followed by exactly one EndUpdate() (see
      * below).  Failure to do so can leave this in a possibly
      * inconsistent state.  Unsuccessful BeginUpdate()s must not be
      * followed by EndUpdate().
      */
     virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion) = 0;
     /**
+     * Retrieves the region that will require updating, given a
+     * region that needs to be updated. This can be used for
+     * making decisions about updating before calling BeginUpdate().
+     *
+     * |aRegion| is an inout param.
+     */
+    virtual void GetUpdateRegion(nsIntRegion& aForRegion) {
+    };
+    /**
      * Finish the active update and synchronize with the server, if
      * necessary.
      *
      * BeginUpdate() must have been called exactly once before
      * EndUpdate().
      */
     virtual void EndUpdate() = 0;
 
@@ -213,16 +222,21 @@ public:
         return PR_FALSE;
     };
 
     virtual nsIntRect GetTileRect() {
         return nsIntRect(nsIntPoint(0,0), mSize);
     };
 
     virtual GLuint GetTextureID() = 0;
+
+    virtual PRUint32 GetTileCount() {
+        return 1;
+    };
+
     /**
      * Set this TextureImage's size, and ensure a texture has been
      * allocated.  Must not be called between BeginUpdate and EndUpdate.
      * After a resize, the contents are undefined.
      *
      * If this isn't implemented by a subclass, it will just perform
      * a dummy BeginUpdate/EndUpdate pair.
      */
@@ -343,16 +357,17 @@ public:
         , mTextureState(Created)
         , mGLContext(aContext)
         , mUpdateOffset(0, 0)
     {}
 
     virtual void BindTexture(GLenum aTextureUnit);
 
     virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
+    virtual void GetUpdateRegion(nsIntRegion& aForRegion);
     virtual void EndUpdate();
     virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
     virtual GLuint GetTextureID() { return mTexture; };
     // Returns a surface to draw into
     virtual already_AddRefed<gfxASurface>
       GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt);
 
     // Call when drawing into the update surface is complete.
@@ -387,18 +402,20 @@ class TiledTextureImage
     : public TextureImage
 {
 public:
     TiledTextureImage(GLContext* aGL, nsIntSize aSize,
         TextureImage::ContentType, PRBool aUseNearestFilter = PR_FALSE);
     ~TiledTextureImage();
     void DumpDiv();
     virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
+    virtual void GetUpdateRegion(nsIntRegion& aForRegion);
     virtual void EndUpdate();
     virtual void Resize(const nsIntSize& aSize);
+    virtual PRUint32 GetTileCount();
     virtual void BeginTileIteration();
     virtual PRBool NextTile();
     virtual nsIntRect GetTileRect();
     virtual GLuint GetTextureID() {
         return mImages[mCurrentImage]->GetTextureID();
     };
     virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
     virtual PRBool InUpdate() const { return mInUpdate; };
--- a/gfx/thebes/GLContextProviderEGL.cpp
+++ b/gfx/thebes/GLContextProviderEGL.cpp
@@ -1202,37 +1202,38 @@ public:
         if (ctx && !ctx->IsDestroyed()) {
             ctx->MakeCurrent();
             ctx->fDeleteTextures(1, &mTexture);
             ReleaseTexImage();
             DestroyEGLSurface();
         }
     }
 
+    virtual void GetUpdateRegion(nsIntRegion& aForRegion)
+    {
+        if (mTextureState != Valid) {
+            // if the texture hasn't been initialized yet, force the
+            // client to paint everything
+            aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
+        } else if (!mBackingSurface) {
+            // We can only draw a rectangle, not subregions due to
+            // the way that our texture upload functions work.  If
+            // needed, we /could/ do multiple texture uploads if we have
+            // non-overlapping rects, but that's a tradeoff.
+            aForRegion = nsIntRegion(mUpdateRect);
+        }
+    }
+
     virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion)
     {
         NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
 
         // determine the region the client will need to repaint
-        if (mTextureState != Valid) {
-            // if the texture hasn't been initialized yet, force the
-            // client to paint everything
-            mUpdateRect = nsIntRect(nsIntPoint(0, 0), mSize);
-            //printf_stderr("v Forcing full paint\n");
-            aRegion = nsIntRegion(mUpdateRect);
-        } else {
-            mUpdateRect = aRegion.GetBounds();
-            if (!mBackingSurface) {
-                // We can only draw a rectangle, not subregions due to
-                // the way that our texture upload functions work.  If
-                // needed, we /could/ do multiple texture uploads if we have
-                // non-overlapping rects, but that's a tradeoff.
-                aRegion = nsIntRegion(mUpdateRect);
-            }
-        }
+        GetUpdateRegion(aRegion);
+        mUpdateRect = aRegion.GetBounds();
 
         //printf_stderr("BeginUpdate with updateRect [%d %d %d %d]\n", mUpdateRect.x, mUpdateRect.y, mUpdateRect.width, mUpdateRect.height);
         if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(mUpdateRect)) {
             NS_ERROR("update outside of image");
             return NULL;
         }
 
         if (mBackingSurface) {
--- a/intl/uconv/tests/unit/xpcshell.ini
+++ b/intl/uconv/tests/unit/xpcshell.ini
@@ -106,16 +106,18 @@ tail =
 [test_encode_CP1255.js]
 [test_encode_CP1256.js]
 [test_encode_CP1257.js]
 [test_encode_CP1258.js]
 [test_encode_CP850.js]
 [test_encode_CP852.js]
 [test_encode_CP855.js]
 [test_encode_CP857.js]
+# Bug 676958: test consistently hangs on Android
+skip-if = os == "android"
 [test_encode_CP862.js]
 [test_encode_CP864.js]
 [test_encode_CP874.js]
 [test_encode_armscii.js]
 [test_encode_geostd8.js]
 [test_encode_gbk.js]
 [test_encode_tcvn5712.js]
 [test_encode_utf-7_internal.js]
--- a/ipc/testshell/tests/xpcshell.ini
+++ b/ipc/testshell/tests/xpcshell.ini
@@ -1,6 +1,8 @@
 [DEFAULT]
 head = 
 tail = 
 
 [test_ipcshell.js]
+# Bug 676963: test fails consistently on Android
+fail-if = os == "android"
 [test_ipcshell_child.js]
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -72,46 +72,16 @@ endif
 
 MODULE		    = js
 LIBRARY_NAME	    = mozjs
 STATIC_LIBRARY_NAME = js_static
 GRE_MODULE	    = 1
 
 LIBS		= $(NSPR_LIBS) 
 
-ifdef GNU_CXX
-ifdef INTEL_CXX
-# icc gets special optimize flags
-ifdef MOZ_PROFILE_GENERATE
-MODULE_OPTIMIZE_FLAGS = -O0
-else
-MODULE_OPTIMIZE_FLAGS = -O2 -ip
-endif
-else # not INTEL_CXX
-
-MODULE_OPTIMIZE_FLAGS = -O3 -fstrict-aliasing -fno-stack-protector
-
-# We normally want -fomit-frame-pointer, but we want an explicit
-# -fno-omit-frame-pointer if we're using a sampling profiler.
-ifndef MOZ_PROFILING
-MODULE_OPTIMIZE_FLAGS += -fomit-frame-pointer
-else
-MODULE_OPTIMIZE_FLAGS += -fno-omit-frame-pointer
-endif
-
-endif
-else # not GNU_CXX
-ifeq ($(OS_ARCH),SunOS)
-MODULE_OPTIMIZE_FLAGS = -xO4
-endif
-ifeq ($(OS_ARCH),WINNT)
-MODULE_OPTIMIZE_FLAGS = -O2
-endif
-endif
-
 ifeq ($(OS_ARCH),WINNT)
 NO_PROFILE_GUIDED_OPTIMIZE = 1
 endif
 
 # JavaScript must be built shared, even for static builds, as it is used by
 # other modules which are always built shared. Failure to do so results in
 # the js code getting copied into xpinstall and jsd as well as mozilla-bin,
 # and then the static data cells used for locking no longer work.
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -148,16 +148,30 @@ xpcshell-tests:
 	  -I$(topsrcdir)/build \
 	  $(testxpcsrcdir)/runxpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  $(EXTRA_TEST_ARGS) \
 	  $(LIBXUL_DIST)/bin/xpcshell \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 
+xpcshell-tests-remote: DM_TRANS?=adb
+xpcshell-tests-remote:
+	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+	  -I$(topsrcdir)/build \
+	  -I$(topsrcdir)/build/mobile \
+	  $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
+	  --symbols-path=$(DIST)/crashreporter-symbols \
+	  --build-info-json=$(DEPTH)/mozinfo.json \
+	  $(EXTRA_TEST_ARGS) \
+	  --dm_trans=$(DM_TRANS) \
+	  --deviceIP=${TEST_DEVICE} \
+	  --objdir=$(DEPTH) \
+	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
+
 # Execute a single test, specified in $(SOLO_FILE), but don't automatically
 # start the test. Instead, present the xpcshell prompt so the user can
 # attach a debugger and then start the test.
 check-interactive:
 	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/build \
 	  $(testxpcsrcdir)/runxpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
@@ -177,16 +191,33 @@ check-one:
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  --test-path=$(SOLO_FILE) \
 	  --profile-name=$(MOZ_APP_NAME) \
 	  --verbose \
 	  $(EXTRA_TEST_ARGS) \
 	  $(LIBXUL_DIST)/bin/xpcshell \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 
+check-one-remote: DM_TRANS?=adb
+check-one-remote:
+	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+	  -I$(topsrcdir)/build \
+	  -I$(topsrcdir)/build/mobile \
+	  $(testxpcsrcdir)/remotexpcshelltests.py \
+	  --symbols-path=$(DIST)/crashreporter-symbols \
+	  --build-info-json=$(DEPTH)/mozinfo.json \
+	  --test-path=$(SOLO_FILE) \
+	  --profile-name=$(MOZ_APP_NAME) \
+	  --verbose \
+	  $(EXTRA_TEST_ARGS) \
+	  --dm_trans=$(DM_TRANS) \
+	  --deviceIP=${TEST_DEVICE} \
+	  --objdir=$(DEPTH) \
+          --noSetup \
+	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 endif # XPCSHELL_TESTS
 
 ifdef CPP_UNIT_TESTS
 
 # Compile the tests to $(DIST)/bin.  Make lots of niceties available by default
 # through TestHarness.h, by modifying the list of includes and the libs against
 # which stuff links.
 CPPSRCS += $(CPP_UNIT_TESTS)
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -1987,21 +1987,24 @@ case "$target" in
 	    MKSHLIB_UNFORCE_ALL=''
 	;;
     esac
     ;;
 
 *-darwin*) 
     MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
     MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
-    # If we're building with --enable-profiling, we need a frame pointer.
+
+    MOZ_OPTIMIZE_FLAGS="-O3  -fstrict-aliasing -fno-stack-protector"
+    # We normally want -fomit-frame-pointer, but we want an explicit
+    # -fno-omit-frame-pointer if we're using a sampling profiler.
     if test -z "$MOZ_PROFILING"; then
-        MOZ_OPTIMIZE_FLAGS="-O3 -fomit-frame-pointer"
+        MOZ_OPTIMIZE_FLAGS="$MOZ_OPTIMIZE_FLAGS -fomit-frame-pointer"
     else
-        MOZ_OPTIMIZE_FLAGS="-O3 -fno-omit-frame-pointer"
+        MOZ_OPTIMIZE_FLAGS="$MOZ_OPTIMIZE_FLAGS -fno-omit-frame-pointer"
     fi
     _PEDANTIC=
     CFLAGS="$CFLAGS -fpascal-strings -fno-common"
     CXXFLAGS="$CXXFLAGS -fpascal-strings -fno-common"
     DLL_SUFFIX=".dylib"
     DSO_LDOPTS=''
     STRIP="$STRIP -x -S"
     _PLATFORM_DEFAULT_TOOLKIT='cairo-cocoa'
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -2197,17 +2197,17 @@ JS_DumpBytecode(JSContext *cx, JSScript 
 
 #if defined(DEBUG)
     AutoArenaAllocator mark(&cx->tempPool);
     Sprinter sprinter;
     INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
 
     fprintf(stdout, "--- SCRIPT %s:%d ---\n", script->filename, script->lineno);
     js_Disassemble(cx, script, true, &sprinter);
-    fprintf(stdout, "%s\n", sprinter.base);
+    fputs(sprinter.base, stdout);
     fprintf(stdout, "--- END SCRIPT %s:%d ---\n", script->filename, script->lineno);
 #endif
 }
 
 JS_PUBLIC_API(void)
 JS_DumpCompartmentBytecode(JSContext *cx)
 {
     for (JSScript *script = (JSScript *) JS_LIST_HEAD(&cx->compartment->scripts);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -6694,25 +6694,32 @@ MaybeDumpValue(const char *name, const V
 }
 
 JS_FRIEND_API(void)
 js_DumpStackFrame(JSContext *cx, StackFrame *start)
 {
     /* This should only called during live debugging. */
     VOUCH_DOES_NOT_REQUIRE_STACK();
 
-    if (!start)
-        start = cx->maybefp();
-    FrameRegsIter i(cx);
-    while (!i.done() && i.fp() != start)
-        ++i;
-
-    if (i.done()) {
-        fprintf(stderr, "fp = %p not found in cx = %p\n", (void *)start, (void *)cx);
-        return;
+    FrameRegsIter i(cx, StackIter::GO_THROUGH_SAVED);
+    if (!start) {
+        if (i.done()) {
+            fprintf(stderr, "no stack for cx = %p\n", (void*) cx);
+            return;
+        }
+        start = i.fp();
+    } else {
+        while (!i.done() && i.fp() != start)
+            ++i;
+
+        if (i.done()) {
+            fprintf(stderr, "fp = %p not found in cx = %p\n",
+                    (void *)start, (void *)cx);
+            return;
+        }
     }
 
     for (; !i.done(); ++i) {
         StackFrame *const fp = i.fp();
 
         fprintf(stderr, "StackFrame at %p\n", (void *) fp);
         if (fp->isFunctionFrame()) {
             fprintf(stderr, "callee fun: ");
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -453,16 +453,33 @@ js_Disassemble1(JSContext *cx, JSScript 
         Sprint(sp, " x ");
     }
     if (lines)
         Sprint(sp, "%4u", JS_PCToLineNumber(cx, script, pc));
     Sprint(sp, "  %s", js_CodeName[op]);
     type = JOF_TYPE(cs->format);
     switch (type) {
       case JOF_BYTE:
+          // Scan the trynotes to find the associated catch block
+          // and make the try opcode look like a jump instruction
+          // with an offset. This simplifies code coverage analysis
+          // based on this disassembled output.
+          if (op == JSOP_TRY) {
+              JSTryNoteArray *trynotes = script->trynotes();
+              uint32 i;
+              for(i = 0; i < trynotes->length; i++) {
+                  JSTryNote note = trynotes->vector[i];
+                  if (note.kind == JSTRY_CATCH && note.start == loc + 1) {
+                      Sprint(sp, " %u (%+d)",
+                             (unsigned int) (loc+note.length+1),
+                             (int) (note.length+1));
+                      break;
+                  }
+              }
+          }
         break;
 
       case JOF_JUMP:
       case JOF_JUMPX:
         off = GetJumpOffset(pc, pc);
         Sprint(sp, " %u (%+d)", loc + (intN) off, (intN) off);
         break;
 
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -404,21 +404,22 @@ bool
 ForceFrame::enter()
 {
     frame = context->new_<DummyFrameGuard>();
     if (!frame)
        return false;
     LeaveTrace(context);
 
     JS_ASSERT(context->compartment == target->compartment());
+    JSCompartment *destination = context->compartment;
 
     JSObject *scopeChain = target->getGlobal();
     JS_ASSERT(scopeChain->isNative());
 
-    return context->stack.pushDummyFrame(context, REPORT_ERROR, *scopeChain, frame);
+    return context->stack.pushDummyFrame(context, destination, *scopeChain, frame);
 }
 
 AutoCompartment::AutoCompartment(JSContext *cx, JSObject *target)
     : context(cx),
       origin(cx->compartment),
       target(target),
       destination(target->getCompartment()),
       entered(false)
@@ -437,31 +438,18 @@ AutoCompartment::enter()
     JS_ASSERT(!entered);
     if (origin != destination) {
         LeaveTrace(context);
 
         JSObject *scopeChain = target->getGlobal();
         JS_ASSERT(scopeChain->isNative());
 
         frame.construct();
-
-        /*
-         * Set the compartment eagerly so that pushDummyFrame associates the
-         * resource allocation request with 'destination' instead of 'origin'.
-         * (This is important when content has overflowed the stack and chrome
-         * is preparing to run JS to throw up a slow script dialog.) However,
-         * if an exception is thrown, we need it to be in origin's compartment
-         * so be careful to only report after restoring.
-         */
-        context->compartment = destination;
-        if (!context->stack.pushDummyFrame(context, DONT_REPORT_ERROR, *scopeChain, &frame.ref())) {
-            context->compartment = origin;
-            js_ReportOverRecursed(context);
+        if (!context->stack.pushDummyFrame(context, destination, *scopeChain, &frame.ref()))
             return false;
-        }
 
         if (context->isExceptionPending())
             context->wrapPendingException();
     }
     entered = true;
     return true;
 }
 
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -383,25 +383,26 @@ StackSpace::ensureEnoughSpaceToEnterTrac
     ptrdiff_t needed = TraceNativeStorage::MAX_NATIVE_STACK_SLOTS +
                        TraceNativeStorage::MAX_CALL_STACK_ENTRIES * VALUES_PER_STACK_FRAME;
     return ensureSpace(cx, DONT_REPORT_ERROR, firstUnused(), needed);
 }
 #endif
 
 STATIC_POSTCONDITION(!return || ubound(from) >= nvals)
 JS_ALWAYS_INLINE bool
-StackSpace::ensureSpace(JSContext *cx, MaybeReportError report, Value *from, ptrdiff_t nvals) const
+StackSpace::ensureSpace(JSContext *cx, MaybeReportError report, Value *from, ptrdiff_t nvals,
+                        JSCompartment *dest) const
 {
     assertInvariants();
     JS_ASSERT(from >= firstUnused());
 #ifdef XP_WIN
     JS_ASSERT(from <= commitEnd_);
 #endif
     if (JS_UNLIKELY(conservativeEnd_ - from < nvals))
-        return ensureSpaceSlow(cx, report, from, nvals);
+        return ensureSpaceSlow(cx, report, from, nvals, dest);
     return true;
 }
 
 inline Value *
 StackSpace::getStackLimit(JSContext *cx, MaybeReportError report)
 {
     FrameRegs &regs = cx->regs();
     uintN nvals = regs.fp()->numSlots() + VALUES_PER_STACK_FRAME;
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -409,23 +409,26 @@ StackSpace::mark(JSTracer *trc)
             slotsEnd = (Value *)fp;
         }
         MarkStackRangeConservatively(trc, seg->slotsBegin(), slotsEnd);
         nextSegEnd = (Value *)seg;
     }
 }
 
 JS_FRIEND_API(bool)
-StackSpace::ensureSpaceSlow(JSContext *cx, MaybeReportError report,
-                            Value *from, ptrdiff_t nvals) const
+StackSpace::ensureSpaceSlow(JSContext *cx, MaybeReportError report, Value *from, ptrdiff_t nvals,
+                            JSCompartment *dest) const
 {
     assertInvariants();
 
-    bool trusted = !cx->compartment ||
-                   cx->compartment->principals == cx->runtime->trustedPrincipals();
+    /* See CX_COMPARTMENT comment. */
+    if (dest == (JSCompartment *)CX_COMPARTMENT)
+        dest = cx->compartment;
+
+    bool trusted = !dest || dest->principals == cx->runtime->trustedPrincipals();
     Value *end = trusted ? trustedEnd_ : defaultEnd_;
 
     /*
      * conservativeEnd_ must stay below defaultEnd_: if conservativeEnd_ were
      * to be bumped past defaultEnd_, untrusted JS would be able to consume the
      * buffer space at the end of the stack reserved for trusted JS.
      */
 
@@ -543,27 +546,27 @@ ContextStack::containsSlow(const StackFr
  * pushing a StackSegment. The 'pushedSeg' outparam indicates whether such a
  * segment was pushed (and hence whether the caller needs to call popSegment).
  *
  * Additionally, to minimize calls to ensureSpace, ensureOnTop ensures that
  * there is space for nvars slots on top of the stack.
  */
 Value *
 ContextStack::ensureOnTop(JSContext *cx, MaybeReportError report, uintN nvars,
-                          MaybeExtend extend, bool *pushedSeg)
+                          MaybeExtend extend, bool *pushedSeg, JSCompartment *dest)
 {
     Value *firstUnused = space().firstUnused();
 
     if (onTop() && extend) {
-        if (!space().ensureSpace(cx, report, firstUnused, nvars))
+        if (!space().ensureSpace(cx, report, firstUnused, nvars, dest))
             return NULL;
         return firstUnused;
     }
 
-    if (!space().ensureSpace(cx, report, firstUnused, VALUES_PER_STACK_SEGMENT + nvars))
+    if (!space().ensureSpace(cx, report, firstUnused, VALUES_PER_STACK_SEGMENT + nvars, dest))
         return NULL;
 
     FrameRegs *regs;
     CallArgsList *calls;
     if (seg_ && extend) {
         regs = seg_->maybeRegs();
         calls = seg_->maybeCalls();
     } else {
@@ -691,28 +694,30 @@ ContextStack::pushExecuteFrame(JSContext
 
     efg->prevRegs_ = seg_->pushRegs(efg->regs_);
     JS_ASSERT(space().firstUnused() == efg->regs_.sp);
     efg->setPushed(*this);
     return true;
 }
 
 bool
-ContextStack::pushDummyFrame(JSContext *cx, MaybeReportError report, JSObject &scopeChain,
-                             DummyFrameGuard *dfg)
+ContextStack::pushDummyFrame(JSContext *cx, JSCompartment *dest, JSObject &scopeChain, DummyFrameGuard *dfg)
 {
+    JS_ASSERT(dest == scopeChain.compartment());
+
     uintN nvars = VALUES_PER_STACK_FRAME;
-    Value *firstUnused = ensureOnTop(cx, report, nvars, CAN_EXTEND, &dfg->pushedSeg_);
+    Value *firstUnused = ensureOnTop(cx, REPORT_ERROR, nvars, CAN_EXTEND, &dfg->pushedSeg_, dest);
     if (!firstUnused)
         return NULL;
 
     StackFrame *fp = reinterpret_cast<StackFrame *>(firstUnused);
     fp->initDummyFrame(cx, scopeChain);
     dfg->regs_.initDummyFrame(*fp);
 
+    cx->compartment = dest;
     dfg->prevRegs_ = seg_->pushRegs(dfg->regs_);
     JS_ASSERT(space().firstUnused() == dfg->regs_.sp);
     dfg->setPushed(*this);
     return true;
 }
 
 void
 ContextStack::popFrame(const FrameGuard &fg)
@@ -785,34 +790,21 @@ ContextStack::popGeneratorFrame(const Ge
 
     /* ~FrameGuard/popFrame will finish the popping. */
     JS_ASSERT(ImplicitCast<const FrameGuard>(gfg).pushed());
 }
 
 bool
 ContextStack::saveFrameChain()
 {
-    /*
-     * The StackSpace uses the context's current compartment to determine
-     * whether to allow access to the privileged end-of-stack buffer.
-     * However, we always want saveFrameChain to have access to this privileged
-     * buffer since it gets used to prepare calling trusted JS. To force this,
-     * we clear the current compartment (which is interpreted by ensureSpace as
-     * 'trusted') and either restore it on OOM or let resetCompartment()
-     * clobber it.
-     */
-    JSCompartment *original = cx_->compartment;
-    cx_->compartment = NULL;
+    JSCompartment *dest = NULL;
 
     bool pushedSeg;
-    if (!ensureOnTop(cx_, DONT_REPORT_ERROR, 0, CANT_EXTEND, &pushedSeg)) {
-        cx_->compartment = original;
-        js_ReportOverRecursed(cx_);
+    if (!ensureOnTop(cx_, REPORT_ERROR, 0, CANT_EXTEND, &pushedSeg, dest))
         return false;
-    }
 
     JS_ASSERT(pushedSeg);
     JS_ASSERT(!hasfp());
     JS_ASSERT(onTop() && seg_->isEmpty());
 
     cx_->resetCompartment();
     return true;
 }
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -39,16 +39,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef Stack_h__
 #define Stack_h__
 
 #include "jsfun.h"
 
 struct JSContext;
+struct JSCompartment;
 
 namespace js {
 
 class StackFrame;
 class FrameRegs;
 class StackSegment;
 class StackSpace;
 class ContextStack;
@@ -1331,20 +1332,33 @@ class StackSpace
     static void staticAsserts() {
         JS_STATIC_ASSERT(CAPACITY_VALS % COMMIT_VALS == 0);
     }
 
     friend class AllFramesIter;
     friend class ContextStack;
     friend class StackFrame;
 
+    /*
+     * Except when changing compartment (see pushDummyFrame), the 'dest'
+     * parameter of ensureSpace is cx->compartment. Ideally, we'd just pass
+     * this directly (and introduce a helper that supplies cx->compartment when
+     * no 'dest' is given). For some compilers, this really hurts performance,
+     * so, instead, a trivially sinkable magic constant is used to indicate
+     * that dest should be cx->compartment.
+     */
+    static const size_t CX_COMPARTMENT = 0xc;
+
     inline bool ensureSpace(JSContext *cx, MaybeReportError report,
-                            Value *from, ptrdiff_t nvals) const;
+                            Value *from, ptrdiff_t nvals,
+                            JSCompartment *dest = (JSCompartment *)CX_COMPARTMENT) const;
     JS_FRIEND_API(bool) ensureSpaceSlow(JSContext *cx, MaybeReportError report,
-                                        Value *from, ptrdiff_t nvals) const;
+                                        Value *from, ptrdiff_t nvals,
+                                        JSCompartment *dest) const;
+
     StackSegment &findContainingSegment(const StackFrame *target) const;
 
   public:
     StackSpace();
     bool init();
     ~StackSpace();
 
     /*
@@ -1423,17 +1437,18 @@ class ContextStack
 #else
     void assertSpaceInSync() const {}
 #endif
 
     /* Implementation details of push* public interface. */
     StackSegment *pushSegment(JSContext *cx);
     enum MaybeExtend { CAN_EXTEND = true, CANT_EXTEND = false };
     Value *ensureOnTop(JSContext *cx, MaybeReportError report, uintN nvars,
-                       MaybeExtend extend, bool *pushedSeg);
+                       MaybeExtend extend, bool *pushedSeg,
+                       JSCompartment *dest = (JSCompartment *)StackSpace::CX_COMPARTMENT);
 
     inline StackFrame *
     getCallFrame(JSContext *cx, MaybeReportError report, const CallArgs &args,
                  JSFunction *fun, JSScript *script, StackFrame::Flags *pflags) const;
 
     /* Make pop* functions private since only called by guard classes. */
     void popSegment();
     friend class InvokeArgsGuard;
@@ -1504,19 +1519,26 @@ class ContextStack
     /*
      * Called by SendToGenerator to resume a yielded generator. In addition to
      * pushing a frame onto the VM stack, this function copies over the
      * floating frame stored in 'gen'. When 'gfg' is destroyed, the destructor
      * will copy the frame back to the floating frame.
      */
     bool pushGeneratorFrame(JSContext *cx, JSGenerator *gen, GeneratorFrameGuard *gfg);
 
-    /* Pushes a "dummy" frame; should be removed one day. */
-    bool pushDummyFrame(JSContext *cx, MaybeReportError report, JSObject &scopeChain,
-                        DummyFrameGuard *dfg);
+    /*
+     * When changing the compartment of a cx, it is necessary to immediately
+     * change the scope chain to a global in the right compartment since any
+     * amount of general VM code can run before the first scripted frame is
+     * pushed (if at all). This is currently and hackily accomplished by
+     * pushing a "dummy frame" with the correct scope chain. On success, this
+     * function will change the compartment to 'scopeChain.compartment()' and
+     * push a dummy frame for 'scopeChain'. On failure, nothing is changed.
+     */
+    bool pushDummyFrame(JSContext *cx, JSCompartment *dest, JSObject &scopeChain, DummyFrameGuard *dfg);
 
     /*
      * An "inline frame" may only be pushed from within the top, active
      * segment. This is the case for calls made inside mjit code and Interpret.
      * The 'stackLimit' overload updates 'stackLimit' if it changes.
      */
     bool pushInlineFrame(JSContext *cx, FrameRegs &regs, const CallArgs &args,
                          JSObject &callee, JSFunction *fun, JSScript *script,
@@ -1685,17 +1707,18 @@ class FrameRegsIter
     StackIter iter_;
 
     void settle() {
         while (!iter_.done() && !iter_.isScript())
             ++iter_;
     }
 
   public:
-    FrameRegsIter(JSContext *cx) : iter_(cx) { settle(); }
+    FrameRegsIter(JSContext *cx, StackIter::SavedOption opt = StackIter::STOP_AT_SAVED)
+        : iter_(cx, opt) { settle(); }
 
     bool done() const { return iter_.done(); }
     FrameRegsIter &operator++() { ++iter_; settle(); return *this; }
 
     bool operator==(const FrameRegsIter &rhs) const { return iter_ == rhs.iter_; }
     bool operator!=(const FrameRegsIter &rhs) const { return iter_ != rhs.iter_; }
 
     StackFrame *fp() const { return iter_.fp(); }
--- a/js/src/xpconnect/shell/xpcshell.cpp
+++ b/js/src/xpconnect/shell/xpcshell.cpp
@@ -1832,17 +1832,19 @@ main(int argc, char **argv, char **envp)
         if (argc > 1 && !strcmp(argv[1], "--greomni")) {
             nsCOMPtr<nsILocalFile> greOmni;
             nsCOMPtr<nsILocalFile> appOmni;
             XRE_GetFileFromPath(argv[2], getter_AddRefs(greOmni));
             if (argc > 3 && !strcmp(argv[3], "--appomni")) {
                 XRE_GetFileFromPath(argv[4], getter_AddRefs(appOmni));
                 argc-=2;
                 argv+=2;
-            } 
+            } else {
+                appOmni = greOmni;
+            }
             
             XRE_InitOmnijar(greOmni, appOmni);
             argc-=2;
             argv+=2;
         }
 
         nsCOMPtr<nsIServiceManager> servMan;
         rv = NS_InitXPCOM2(getter_AddRefs(servMan), appDir, &dirprovider);
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -2068,17 +2068,18 @@ nsXPConnect::CreateSandbox(JSContext *cx
     if(!ccx.IsValid())
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
     *_retval = nsnull;
 
     jsval rval = JSVAL_VOID;
     AUTO_MARK_JSVAL(ccx, &rval);
 
-    nsresult rv = xpc_CreateSandboxObject(cx, &rval, principal, NULL, false);
+    nsresult rv = xpc_CreateSandboxObject(cx, &rval, principal, NULL, false, 
+                                          EmptyCString());
     NS_ASSERTION(NS_FAILED(rv) || !JSVAL_IS_PRIMITIVE(rval),
                  "Bad return value from xpc_CreateSandboxObject()!");
 
     if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(rval)) {
         *_retval = XPCJSObjectHolder::newHolder(ccx, JSVAL_TO_OBJECT(rval));
         NS_ENSURE_TRUE(*_retval, NS_ERROR_OUT_OF_MEMORY);
 
         NS_ADDREF(*_retval);
--- a/js/src/xpconnect/src/xpccomponents.cpp
+++ b/js/src/xpconnect/src/xpccomponents.cpp
@@ -498,17 +498,17 @@ nsXPCComponents_InterfacesByID::GetContr
     *aContractID = nsnull;
     return NS_ERROR_NOT_AVAILABLE;
 }
 
 /* readonly attribute string classDescription; */
 NS_IMETHODIMP
 nsXPCComponents_InterfacesByID::GetClassDescription(char * *aClassDescription)
 {
-    static const char classDescription[] = "XPCComponents_Interfaces";
+    static const char classDescription[] = "XPCComponents_InterfacesByID";
     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
 /* readonly attribute nsCIDPtr classID; */
 NS_IMETHODIMP
 nsXPCComponents_InterfacesByID::GetClassID(nsCID * *aClassID)
 {
@@ -1070,17 +1070,17 @@ nsXPCComponents_ClassesByID::GetContract
     *aContractID = nsnull;
     return NS_ERROR_NOT_AVAILABLE;
 }
 
 /* readonly attribute string classDescription; */
 NS_IMETHODIMP 
 nsXPCComponents_ClassesByID::GetClassDescription(char * *aClassDescription)
 {
-    static const char classDescription[] = "XPCComponents_Interfaces";
+    static const char classDescription[] = "XPCComponents_ClassesByID";
     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
 /* readonly attribute nsCIDPtr classID; */
 NS_IMETHODIMP 
 nsXPCComponents_ClassesByID::GetClassID(nsCID * *aClassID)
 {
@@ -1341,17 +1341,17 @@ nsXPCComponents_Results::GetContractID(c
     *aContractID = nsnull;
     return NS_ERROR_NOT_AVAILABLE;
 }
 
 /* readonly attribute string classDescription; */
 NS_IMETHODIMP 
 nsXPCComponents_Results::GetClassDescription(char * *aClassDescription)
 {
-    static const char classDescription[] = "XPCComponents_Interfaces";
+    static const char classDescription[] = "XPCComponents_Results";
     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
 /* readonly attribute nsCIDPtr classID; */
 NS_IMETHODIMP 
 nsXPCComponents_Results::GetClassID(nsCID * *aClassID)
 {
@@ -1570,17 +1570,17 @@ nsXPCComponents_ID::GetContractID(char *
     *aContractID = nsnull;
     return NS_ERROR_NOT_AVAILABLE;
 }
 
 /* readonly attribute string classDescription; */
 NS_IMETHODIMP 
 nsXPCComponents_ID::GetClassDescription(char * *aClassDescription)
 {
-    static const char classDescription[] = "XPCComponents_Interfaces";
+    static const char classDescription[] = "XPCComponents_ID";
     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
 /* readonly attribute nsCIDPtr classID; */
 NS_IMETHODIMP 
 nsXPCComponents_ID::GetClassID(nsCID * *aClassID)
 {
@@ -1798,17 +1798,17 @@ nsXPCComponents_Exception::GetContractID
     *aContractID = nsnull;
     return NS_ERROR_NOT_AVAILABLE;
 }
 
 /* readonly attribute string classDescription; */
 NS_IMETHODIMP 
 nsXPCComponents_Exception::GetClassDescription(char * *aClassDescription)
 {
-    static const char classDescription[] = "XPCComponents_Interfaces";
+    static const char classDescription[] = "XPCComponents_Exception";
     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
 /* readonly attribute nsCIDPtr classID; */
 NS_IMETHODIMP 
 nsXPCComponents_Exception::GetClassID(nsCID * *aClassID)
 {
@@ -2093,17 +2093,17 @@ nsXPCConstructor::GetContractID(char * *
     *aContractID = nsnull;
     return NS_ERROR_NOT_AVAILABLE;
 }
 
 /* readonly attribute string classDescription; */
 NS_IMETHODIMP 
 nsXPCConstructor::GetClassDescription(char * *aClassDescription)
 {
-    static const char classDescription[] = "XPCComponents_Interfaces";
+    static const char classDescription[] = "XPCConstructor";
     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
 /* readonly attribute nsCIDPtr classID; */
 NS_IMETHODIMP 
 nsXPCConstructor::GetClassID(nsCID * *aClassID)
 {
@@ -2359,17 +2359,17 @@ nsXPCComponents_Constructor::GetContract
     *aContractID = nsnull;
     return NS_ERROR_NOT_AVAILABLE;
 }
 
 /* readonly attribute string classDescription; */
 NS_IMETHODIMP 
 nsXPCComponents_Constructor::GetClassDescription(char * *aClassDescription)
 {
-    static const char classDescription[] = "XPCComponents_Interfaces";
+    static const char classDescription[] = "XPCComponents_Constructor";
     *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
     return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
 /* readonly attribute nsCIDPtr classID; */
 NS_IMETHODIMP 
 nsXPCComponents_Constructor::GetClassID(nsCID * *aClassID)
 {
@@ -3148,17 +3148,17 @@ class Identity : public nsISupports
 {
     NS_DECL_ISUPPORTS
 };
 
 NS_IMPL_ISUPPORTS0(Identity)
 
 nsresult
 xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop, JSObject *proto,
-                        bool wantXrays)
+                        bool wantXrays, const nsACString &sandboxName)
 {
     // Create the sandbox global object
     nsresult rv;
     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
     if(NS_FAILED(rv))
         return NS_ERROR_XPC_UNEXPECTED;
 
     nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(prinOrSop));
@@ -3235,16 +3235,20 @@ xpc_CreateSandboxObject(JSContext * cx, 
 
     if (vp) {
         *vp = OBJECT_TO_JSVAL(sandbox);
         if (!WrapForSandbox(cx, wantXrays, vp)) {
             return NS_ERROR_UNEXPECTED;
         }
     }
 
+    xpc::CompartmentPrivate *compartmentPrivate =
+        static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(cx, compartment));
+    compartmentPrivate->location = sandboxName;
+
     return NS_OK;
 }
 
 /* PRBool call(in nsIXPConnectWrappedNative wrapper,
                in JSContextPtr cx,
                in JSObjectPtr obj,
                in PRUint32 argc,
                in JSValPtr argv,
@@ -3346,16 +3350,18 @@ nsXPCComponents_utils_Sandbox::CallOrCon
         }
 
         if (!prinOrSop)
             return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
     }
 
     JSObject *proto = nsnull;
     bool wantXrays = true;
+    nsCString sandboxName;
+
     if (argc > 1) {
         if (!JSVAL_IS_OBJECT(argv[1]))
             return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
 
         JSObject *optionsObject = JSVAL_TO_OBJECT(argv[1]);
         jsval option;
 
         JSBool found;
@@ -3377,19 +3383,36 @@ nsXPCComponents_utils_Sandbox::CallOrCon
         if (found) {
             if (!JS_GetProperty(cx, optionsObject, "wantXrays", &option) ||
                 !JSVAL_IS_BOOLEAN(option)) {
                 return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
             }
 
             wantXrays = JSVAL_TO_BOOLEAN(option);
         }
+
+        if (!JS_HasProperty(cx, optionsObject, "sandboxName", &found))
+            return NS_ERROR_INVALID_ARG;
+
+        if (found) {
+            if (!JS_GetProperty(cx, optionsObject, "sandboxName", &option) ||
+                !JSVAL_IS_STRING(option)) {
+                return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
+            }
+
+            char *tmp = JS_EncodeString(cx, JSVAL_TO_STRING(option));
+            if (!tmp) {
+                return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
+            }
+
+            sandboxName.Adopt(tmp, strlen(tmp));
+        }
     }
 
-    rv = xpc_CreateSandboxObject(cx, vp, prinOrSop, proto, wantXrays);
+    rv = xpc_CreateSandboxObject(cx, vp, prinOrSop, proto, wantXrays, sandboxName);
 
     if (NS_FAILED(rv)) {
         return ThrowAndFail(rv, cx, _retval);
     }
 
     *_retval = PR_TRUE;
 
     return rv;
--- a/js/src/xpconnect/src/xpcjsruntime.cpp
+++ b/js/src/xpconnect/src/xpcjsruntime.cpp
@@ -1573,32 +1573,40 @@ CompartmentStats::CompartmentStats(JSCon
     if(c == cx->runtime->atomsCompartment)
     {
         name.AssignLiteral("atoms");
     }
     else if(c->principals)
     {
         if(c->principals->codebase)
         {
-            // A hack: replace forward slashes with '\\' so they aren't
-            // treated as path separators.  Users of the reporters
-            // (such as about:memory) have to undo this change.
             name.Assign(c->principals->codebase);
-            name.ReplaceChar('/', '\\');
 
             // If it's the system compartment, append the address.
             // This means that multiple system compartments (and there
             // can be many) can be distinguished.
             if(c->isSystemCompartment)
             {
+                if (c->data && 
+                    !((xpc::CompartmentPrivate*)c->data)->location.IsEmpty())
+                {
+                    name.AppendLiteral(", ");
+                    name.Append(((xpc::CompartmentPrivate*)c->data)->location);
+                }
+
                 // ample; 64-bit address max is 18 chars
                 static const int maxLength = 31;
                 nsPrintfCString address(maxLength, ", 0x%llx", PRUint64(c));
                 name.Append(address);
             }
+
+            // A hack: replace forward slashes with '\\' so they aren't
+            // treated as path separators.  Users of the reporters
+            // (such as about:memory) have to undo this change.
+            name.ReplaceChar('/', '\\');
         }
         else
         {
             name.AssignLiteral("null-codebase");
         }
     }
     else
     {
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -4310,17 +4310,17 @@ xpc_GetJSPrivate(JSObject *obj)
 // do setup etc on, puts the sandbox object in *vp (which must be
 // rooted by the caller), and uses the principal that's either
 // directly passed in prinOrSop or indirectly as an
 // nsIScriptObjectPrincipal holding the principal. If no principal is
 // reachable through prinOrSop, a new null principal will be created
 // and used.
 nsresult
 xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop,
-                        JSObject *proto, bool preferXray);
+                        JSObject *proto, bool preferXray, const nsACString &sandboxName);
 
 // Helper for evaluating scripts in a sandbox object created with
 // xpc_CreateSandboxObject(). The caller is responsible of ensuring
 // that *rval doesn't get collected during the call or usage after the
 // call. This helper will use filename and lineNo for error reporting,
 // and if no filename is provided it will use the codebase from the
 // principal and line number 1 as a fallback. if returnStringOnly is
 // true, then the result in *rval, or the exception in cx->exception
@@ -4389,16 +4389,17 @@ struct CompartmentPrivate
     // NB: key and ptr are mutually exclusive.
     nsAutoPtr<PtrAndPrincipalHashKey> key;
     nsCOMPtr<nsISupports> ptr;
     bool wantXrays;
     bool cycleCollectionEnabled;
     JSObject2JSObjectMap *waiverWrapperMap;
     // NB: we don't want this map to hold a strong reference to the wrapper.
     nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *> *expandoMap;
+    nsCString location;
 
     bool RegisterExpandoObject(XPCWrappedNative *wn, JSObject *expando) {
         if (!expandoMap) {
             expandoMap = new nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *>();
             if (!expandoMap->Init(8))
                 return false;
         }
         return expandoMap->Put(wn, expando);
new file mode 100644
--- /dev/null
+++ b/js/src/xpconnect/tests/unit/test_bug677864.js
@@ -0,0 +1,12 @@
+function check_cl(iface, desc) {
+    do_check_eq(iface.QueryInterface(Components.interfaces.nsIClassInfo).classDescription, desc);
+}
+
+function run_test() {
+    check_cl(Components, 'XPCComponents');
+    check_cl(Components.interfaces, 'XPCComponents_Interfaces');
+    check_cl(Components.interfacesByID, 'XPCComponents_InterfacesByID');
+    check_cl(Components.classes, 'XPCComponents_Classes');
+    check_cl(Components.classesByID, 'XPCComponents_ClassesByID');
+    check_cl(Components.results, 'XPCComponents_Results');
+}
--- a/js/src/xpconnect/tests/unit/xpcshell.ini
+++ b/js/src/xpconnect/tests/unit/xpcshell.ini
@@ -4,16 +4,19 @@ tail =
 
 [test_bogus_files.js]
 [test_bug408412.js]
 [test_bug451678.js]
 [test_bug596580.js]
 [test_bug604362.js]
 [test_bug608142.js]
 [test_bug641378.js]
+[test_bug677864.js]
 [test_bug_442086.js]
 [test_file.js]
 [test_import.js]
 [test_js_weak_references.js]
 [test_localeCompare.js]
+# Bug 676965: test fails consistently on Android
+fail-if = os == "android"
 [test_recursive_import.js]
 [test_xpcomutils.js]
 [test_unload.js]
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -638,17 +638,18 @@ void nsCaret::InvalidateTextOverflowBloc
   // invalidate it.
   if (mLastContent) {
     nsIFrame* caretFrame = mLastContent->GetPrimaryFrame();
     if (caretFrame) {
       nsIFrame* block = nsLayoutUtils::GetAsBlock(caretFrame) ? caretFrame :
         nsLayoutUtils::FindNearestBlockAncestor(caretFrame);
       if (block) {
         const nsStyleTextReset* style = block->GetStyleTextReset();
-        if (style->mTextOverflow.mType != NS_STYLE_TEXT_OVERFLOW_CLIP) {
+        if (style->mTextOverflow.mLeft.mType != NS_STYLE_TEXT_OVERFLOW_CLIP ||
+            style->mTextOverflow.mRight.mType != NS_STYLE_TEXT_OVERFLOW_CLIP) {
           block->InvalidateOverflowRect();
         }
       }
     }
   }
 }
 
 //-----------------------------------------------------------------------------
--- a/layout/base/nsPresArena.cpp
+++ b/layout/base/nsPresArena.cpp
@@ -78,21 +78,17 @@
 #   define MAP_ANON MAP_ANONYMOUS
 #  else
 #   error "Don't know how to get anonymous memory"
 #  endif
 # endif
 #endif
 
 // Size to use for PLArena block allocations.
-// XXX: This should be 8192;  the subtracted elements are a hack that's
-// required to ensure the allocation requests are power-of-two-sized and thus
-// avoid lots of wasted memory caused by the heap allocator rounding up request
-// sizes.  Bug 676457 will fix it properly.
-static const size_t ARENA_PAGE_SIZE = 8192 - sizeof(PLArena) - PL_ARENA_CONST_ALIGN_MASK;
+static const size_t ARENA_PAGE_SIZE = 8192;
 
 // Freed memory is filled with a poison value, which we arrange to
 // form a pointer either to an always-unmapped region of the address
 // space, or to a page that has been reserved and rendered
 // inaccessible via OS primitives.  See tests/TestPoisonArea.cpp for
 // extensive discussion of the requirements for this page.  The code
 // from here to 'class FreeList' needs to be kept in sync with that
 // file.
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -275,18 +275,18 @@ TextOverflow::WillProcessLines(nsDisplay
   if (scroll) {
     textOverflow->mCanHaveHorizontalScrollbar =
       scroll->GetScrollbarStyles().mHorizontal != NS_STYLE_OVERFLOW_HIDDEN;
     textOverflow->mContentArea.MoveBy(scroll->GetScrollPosition());
   }
   textOverflow->mBlockIsRTL =
     aBlockFrame->GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL;
   const nsStyleTextReset* style = aBlockFrame->GetStyleTextReset();
-  textOverflow->mLeft.Init(style->mTextOverflow);
-  textOverflow->mRight.Init(style->mTextOverflow);
+  textOverflow->mLeft.Init(style->mTextOverflow.mLeft);
+  textOverflow->mRight.Init(style->mTextOverflow.mRight);
   // The left/right marker string is setup in ExamineLineFrames when a line
   // has overflow on that side.
 
   return textOverflow.forget();
 }
 
 void
 TextOverflow::DidProcessLines()
@@ -424,21 +424,21 @@ TextOverflow::ExamineLineFrames(nsLineBo
 
   PRUint32 pass = 0;
   bool guessLeft =
     mLeft.mStyle->mType != NS_STYLE_TEXT_OVERFLOW_CLIP && leftOverflow;
   bool guessRight =
     mRight.mStyle->mType != NS_STYLE_TEXT_OVERFLOW_CLIP && rightOverflow;
   do {
     // Setup marker strings as needed.
-    if (guessLeft || guessRight) {
+    if (guessLeft) {
       mLeft.SetupString(mBlock);
-      mRight.mMarkerString = mLeft.mMarkerString;
-      mRight.mWidth = mLeft.mWidth;
-      mRight.mInitialized = mLeft.mInitialized;
+    }
+    if (guessRight) {
+      mRight.SetupString(mBlock);
     }
     
     // If there is insufficient space for both markers then keep the one on the
     // end side per the block's 'direction'.
     nscoord rightMarkerWidth = mRight.mWidth;
     nscoord leftMarkerWidth = mLeft.mWidth;
     if (leftOverflow && rightOverflow &&
         leftMarkerWidth + rightMarkerWidth > contentArea.width) {
@@ -583,17 +583,18 @@ TextOverflow::PruneDisplayListContents(n
 
 /* static */ bool
 TextOverflow::CanHaveTextOverflow(nsDisplayListBuilder* aBuilder,
                                   nsIFrame*             aBlockFrame)
 {
   const nsStyleTextReset* style = aBlockFrame->GetStyleTextReset();
   // Nothing to do for text-overflow:clip or if 'overflow-x:visible'
   // or if we're just building items for event processing.
-  if ((style->mTextOverflow.mType == NS_STYLE_TEXT_OVERFLOW_CLIP) ||
+  if ((style->mTextOverflow.mLeft.mType == NS_STYLE_TEXT_OVERFLOW_CLIP &&
+       style->mTextOverflow.mRight.mType == NS_STYLE_TEXT_OVERFLOW_CLIP) ||
       IsHorizontalOverflowVisible(aBlockFrame) ||
       aBuilder->IsForEventDelivery()) {
     return false;
   }
 
   // Inhibit the markers if a descendant content owns the caret.
   nsRefPtr<nsCaret> caret = aBlockFrame->PresContext()->PresShell()->GetCaret();
   PRBool visible = PR_FALSE;
--- a/layout/generic/TextOverflow.h
+++ b/layout/generic/TextOverflow.h
@@ -183,17 +183,17 @@ class TextOverflow {
   nsDisplayListBuilder*  mBuilder;
   nsIFrame*              mBlock;
   nsDisplayList*         mMarkerList;
   bool                   mBlockIsRTL;
   bool                   mCanHaveHorizontalScrollbar;
 
   class Marker {
   public:
-    void Init(const nsStyleTextOverflow& aStyle) {
+    void Init(const nsStyleTextOverflowSide& aStyle) {
       mInitialized = false;
       mWidth = 0;
       mStyle = &aStyle;
     }
 
     /**
      * Setup the marker string and calculate its size, if not done already.
      */
@@ -206,17 +206,17 @@ class TextOverflow {
       mHasOverflow = false;
     }
 
     // The intrinsic width of the marker string.
     nscoord                        mWidth;
     // The marker text.
     nsString                       mMarkerString;
     // The style for this side.
-    const nsStyleTextOverflow*     mStyle;
+    const nsStyleTextOverflowSide* mStyle;
     // True if there is visible overflowing inline content on this side.
     bool                           mHasOverflow;
     // True if mMarkerString and mWidth have been setup from style.
     bool                           mInitialized;
   };
 
   Marker mLeft;  // the horizontal left marker
   Marker mRight; // the horizontal right marker
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1487,28 +1487,19 @@ nsBlockFrame::ComputeOverflowAreas(const
 {
   // Compute the overflow areas of our children
   // XXX_perf: This can be done incrementally.  It is currently one of
   // the things that makes incremental reflow O(N^2).
   nsRect bounds(0, 0, aMetrics.width, aMetrics.height);
   nsOverflowAreas areas(bounds, bounds);
 
   if (!IsClippingChildren(this, aReflowState)) {
-    PRBool inQuirks = (PresContext()->CompatibilityMode() == eCompatibility_NavQuirks);
     for (line_iterator line = begin_lines(), line_end = end_lines();
          line != line_end;
          ++line) {
-
-      // Text-shadow overflows
-      if (!inQuirks && line->IsInline()) {
-        nsRect shadowRect = nsLayoutUtils::GetTextShadowRectsUnion(
-                              line->GetVisualOverflowArea(), this);
-        areas.VisualOverflow().UnionRect(areas.VisualOverflow(), shadowRect);
-      }
-
       areas.UnionWith(line->GetOverflowAreas());
     }
 
     // Factor the bullet in; normally the bullet will be factored into
     // the line-box's overflow areas. However, if the line is a block
     // line then it won't; if there are no lines, it won't. So just
     // factor it in anyway (it can't hurt if it was already done).
     // XXXldb Can we just fix GetOverflowArea instead?
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -2555,25 +2555,16 @@ nsLineLayout::RelativePositionFrames(Per
     // below.
     // At this point psd->mFrame->mBounds might be out of date since
     // bidi reordering can move and resize the frames. So use the frame's
     // rect instead of mBounds.
     nsRect adjustedBounds(nsPoint(0, 0), psd->mFrame->mFrame->GetSize());
 
     overflowAreas.ScrollableOverflow().UnionRect(
       psd->mFrame->mOverflowAreas.ScrollableOverflow(), adjustedBounds);
-
-    // Text-shadow overflow
-    if (mPresContext->CompatibilityMode() != eCompatibility_NavQuirks) {
-      nsRect shadowRect = nsLayoutUtils::GetTextShadowRectsUnion(adjustedBounds,
-                                                                 psd->mFrame->mFrame);
-      adjustedBounds.UnionRect(adjustedBounds, shadowRect);
-    }
-
-    // Text shadow is only part of visual overflow and not scrollable overflow.
     overflowAreas.VisualOverflow().UnionRect(
       psd->mFrame->mOverflowAreas.VisualOverflow(), adjustedBounds);
   }
   else {
     // The minimum combined area for the frames that are direct
     // children of the block starts at the upper left corner of the
     // line and is sized to match the size of the line's bounding box
     // (the same size as the values returned from VerticalAlignFrames)
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -6623,18 +6623,17 @@ RoundOut(const gfxRect& aRect)
   r.width = NSToCoordCeil(aRect.XMost()) - r.x;
   r.height = NSToCoordCeil(aRect.YMost()) - r.y;
   return r;
 }
 
 nsRect
 nsTextFrame::ComputeTightBounds(gfxContext* aContext) const
 {
-  if ((GetStyleContext()->HasTextDecorationLines() &&
-       eCompatibility_NavQuirks == PresContext()->CompatibilityMode()) ||
+  if (GetStyleContext()->HasTextDecorationLines() ||
       (GetStateBits() & TEXT_HYPHEN_BREAK)) {
     // This is conservative, but OK.
     return GetVisualOverflowRect();
   }
 
   gfxSkipCharsIterator iter = const_cast<nsTextFrame*>(this)->EnsureTextRun();
   if (!mTextRun)
     return nsRect(0, 0, 0, 0);
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -845,25 +845,16 @@ nsMathMLContainerFrame::AttributeChanged
 
 void
 nsMathMLContainerFrame::GatherAndStoreOverflow(nsHTMLReflowMetrics* aMetrics)
 {
   // nsIFrame::FinishAndStoreOverflow likes the overflow area to include the
   // frame rectangle.
   aMetrics->SetOverflowAreasToDesiredBounds();
 
-  // Text-shadow overflows.
-  if (PresContext()->CompatibilityMode() != eCompatibility_NavQuirks) {
-    nsRect frameRect(0, 0, aMetrics->width, aMetrics->height);
-    nsRect shadowRect = nsLayoutUtils::GetTextShadowRectsUnion(frameRect, this);
-    // shadows contribute only to visual overflow
-    nsRect& visOverflow = aMetrics->VisualOverflow();
-    visOverflow.UnionRect(visOverflow, shadowRect);
-  }
-
   // All non-child-frame content such as nsMathMLChars (and most child-frame
   // content) is included in mBoundingMetrics.
   nsRect boundingBox(mBoundingMetrics.leftBearing,
                      aMetrics->ascent - mBoundingMetrics.ascent,
                      mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing,
                      mBoundingMetrics.ascent + mBoundingMetrics.descent);
 
   // REVIEW: Maybe this should contribute only to visual overflow
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/175190-1-ref.html
@@ -0,0 +1,40 @@
+<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+<title>Test Page</title>
+<style type="text/css">
+<!--
+td{
+  background-color: rgb(140,140,140);
+}
+-->
+</style>
+</head>
+<body>
+<table cellpadding=0 cellspacing=0 border=0 width=150>
+<tr><td><img  width="16" height="16"
+             src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC"
+             border=0></td></tr>
+<tr><td><img  width="16" height="16"
+             src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC"
+             border=0></td></tr>
+</table>
+<table cellpadding=0 cellspacing=0 border=0 width=150>
+<tr><td><img  width="16" height="16"
+             src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC"
+             border=0></td></tr>
+<tr><td><img  width="16" height="16"
+             src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC"
+             border=0></td></tr>
+</table>
+<table cellpadding=0 cellspacing=0 border=0>
+<tr><td><img  width="16" height="16"
+             src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC"
+             border=0></td></tr>
+<tr><td><img  width="16" height="16"
+             src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC"
+             border=0></td></tr>
+</table>
+<hr>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/175190-1.html
@@ -0,0 +1,41 @@
+<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+<title>Test Page</title>
+<style type="text/css">
+<!--
+.nav {
+  display:block;
+  background-color: rgb(140,140,140);
+}
+-->
+</style>
+</head>
+<body>
+<table cellpadding=0 cellspacing=0 border=0 width=150>
+<tr><td class="nav"><a href="a.htm"><img  width="16" height="16"
+             src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC"
+             border=0></a></td></tr>
+<tr><td class="nav"><a href="a.htm"><img  width="16" height="16"
+             src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC"
+             border=0></a></td></tr>
+</table>
+<table cellpadding=0 cellspacing=0 border=0 width=150>
+<tr><td><a href="a.htm" class="nav"><img  width="16" height="16"
+             src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC"
+             border=0></a></td></tr>
+<tr><td><a href="a.htm" class="nav"><img  width="16" height="16"
+             src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC"
+             border=0></a></td></tr>
+</table>
+<table cellpadding=0 cellspacing=0 border=0 width=150>
+<tr><td><a href="a.htm"><img class="nav" width="16" height="16"
+             src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC"
+             border=0></a></td></tr>
+<tr><td><a href="a.htm"><img class="nav" width="16" height="16"
+             src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC"
+             border=0></a></td></tr>
+</table>
+<hr>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/186317-1-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+            "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>border crosstalk</title>
+</head>
+<style>
+table.t1 td {border: 1px solid black}
+</style>
+<body >
+
+
+<TABLE style="border-collapse:collapse" class="t1">
+<TR><TD>1</td> <TD>2</td> <TD>3</td></tr>
+</TABLE>
+
+<table border="1">
+<tr><td>1</td><td>2</td></tr>
+<tr><td >3</td><td>4</td></tr>
+</table>
+
+
+</body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/186317-1.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+            "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>border crosstalk</title>
+</head>
+
+<body >
+
+
+<TABLE border="1" style="border-collapse:collapse">
+<TR><TD>1</td> <TD>2</td> <TD>3</td></tr>
+</TABLE>
+
+<table border="1">
+<tr><td>1</td><td>2</td></tr>
+<tr><td >3</td><td>4</td></tr>
+</table>
+
+
+</body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/260406-1-ref.html
@@ -0,0 +1,20 @@
+<html>
+<head>
+<style type="text/css">
+ .forms {display:inline;}
+ .nn2{background-image: url("260406.gif");width:20px;height:18px;}
+</style>
+</head>
+<body>
+    <table border="0" cellpadding="0" cellspacing="0">
+        <tr>
+            <td>P</td>
+        </tr>
+    </table>
+    <table border="0" cellpadding="0" cellspacing="0">
+        <tr>
+            <td class="nn2"></td>
+        </tr>
+    </table>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/260406-1.html
@@ -0,0 +1,20 @@
+<html>
+<head>
+<style type="text/css">
+ .forms {display:inline;}
+ .nn2{background-image: url("260406.gif");width:20px;height:18px;}
+</style>
+</head>
+<body>
+    <table border="0" cellpadding="0" cellspacing="0">
+        <tr>
+            <td class="forms">P</td>
+        </tr>
+    </table>
+    <table border="0" cellpadding="0" cellspacing="0">
+        <tr>
+            <td class="nn2"></td>
+        </tr>
+    </table>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5d0a77dc555a5e9f78b27cc2f48643603883a2fe
GIT binary patch
literal 954
zc${<hbhEHb6k!lz_|Cvk-I9Io+_7`l&Rx5A?H&l-yZ8Lwz4t)${Q2{HK>Ymuz31<r
zzkmP!I|%&$55l8h6buuf!vF-JyuiRQpF!55<AXxe!Dc}j4TB968X1{+7)%6a2qdzw
zvI{AAFa#<yFmS0!wG>Q9Jl4y@Tf-8N@W`Q=Pew1}Mxm<rbOXg#AsZMLot@3cb<AYK
z#l*w&9faT6G!!ZZE#OTtyE@~+%d>3!hOfS4Y(3z_9Acig<yT=tL%Wo<oWgIz12@}w
pwrtA%9rpazPKG;nCKrVD@9yRLvrRVO!NLdowfLXgN((Sp0|2$1I%NO=
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -133,24 +133,26 @@ random == 99850-1b.html 99850-1-ref.html
 != 144004-3.html 144004-3-ref.html
 == 163504-1a.html 163504-1-ref.html
 == 163504-1b.html 163504-1-ref.html
 == 163504-2a.html 163504-2-ref.html
 == 163504-2b.html 163504-2-ref.html
 == 167496-1.html 167496-1-ref.html
 == 169749-1.html 169749-1-ref.html
 == 172073-1.html 172073-1-ref.html
+== 175190-1.html 175190-1-ref.html
 == 179596-1a.html 179596-1a-ref.html
 == 179596-1b.html 179596-1b-ref.html
 == 179596-2.html 179596-2-ref.html
 == 179596-2.html 179596-2-ref2.html
 == 179596-2.html 179596-2-ref3.html
 == 180085-1.html 180085-1-ref.html
 == 180085-2.html 180085-2-ref.html
 == 185388-1.html 185388-1-ref.html
+== 186317-1.html 186317-1-ref.html
 == 192902-1.html 192902-ref.html
 == 192767-01.xul 192767-11.xul
 == 192767-02.xul 192767-12.xul
 == 192767-03.xul 192767-13.xul
 == 192767-04.xul 192767-14.xul
 == 192767-05.xul 192767-15.xul
 == 192767-06.xul 192767-16.xul
 == 192767-07.xul 192767-17.xul
@@ -263,16 +265,17 @@ fails-if(Android) != 192767-17.xul 19276
 == 244135-2.html 244135-2-ref.html
 == 244932-1.html 244932-1-ref.html
 == 249141.xul 249141-ref.xul
 == 249982-1.html 249982-1-ref.html
 == 246669-1.html 246669-1-ref.html
 == 252920-1.html 252920-1-ref.html
 == 253701-1.html 253701-1-ref.html
 == 255820-1.html 255820-1-ref.html
+== 260406-1.html 260406-1-ref.html
 == 261826-1.xul 261826-1-ref.xul
 == 262151-1.html 262151-1-ref.html
 == 262998-1.html 262998-1-ref.html
 == 267353-1.html 267353-1-ref.html
 == 269908-1.html 269908-1-ref.html
 == 269908-2.html 269908-2-ref.html
 == 269908-3.html 269908-3-ref.html
 == 269908-4.html 269908-4-ref.html
--- a/layout/reftests/reftest.list
+++ b/layout/reftests/reftest.list
@@ -283,16 +283,19 @@ include ../../widget/reftests/reftest.li
 include ../../content/test/reftest/xml-stylesheet/reftest.list
 
 # xul-document-load/
 include xul-document-load/reftest.list
 
 # xul/
 include xul/reftest.list
 
+# xul
+include ../xul/base/reftest/reftest.list
+
 # xul grid
 include ../xul/base/src/grid/reftests/reftest.list
 
 # z-index/
 include z-index/reftest.list
 
 # reftest(s) to verify content bugfixes
 include ../../content/html/document/reftests/reftests.list
rename from layout/reftests/svg/dynamic-filter-contents-01.svg
rename to layout/reftests/svg/dynamic-filter-contents-01a.svg
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/dynamic-filter-contents-01b.svg
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg class="reftest-wait" xmlns="http://www.w3.org/2000/svg" onload="startTest()">
+  <defs>
+    <filter id="f" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox" 
+            x="0" y="0" width="1" height="1">
+      <feFlood flood-color="#ff0000" flood-opacity="0.5" result="flood"/>
+      <feComposite id="comp" width="1" height="1" in="flood" operator="over" in2="SourceGraphic"/>
+    </filter>
+  </defs>
+
+  <rect width="100" height="100" fill="lime" filter="url(#f)"/>
+
+  <script>
+  function startTest() {
+    document.addEventListener("MozReftestInvalidate", doTest, false);
+    // in case we're not gecko
+    setTimeout(doTest, 5000);
+  }
+
+  function doTest() {
+    document.getElementById("comp").setAttribute("color-interpolation-filters", "sRGB");
+    document.documentElement.removeAttribute('class');
+  }
+  </script>
+</svg>
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -59,17 +59,18 @@ fails-if(Android) == dynamic-conditions-
 == dynamic-conditions-09.svg about:blank
 == dynamic-conditions-10.svg about:blank
 == dynamic-conditions-11.svg pass.svg
 == dynamic-conditions-12.svg pass.svg
 == dynamic-conditions-13.svg about:blank
 == dynamic-clipPath-01.svg pass.svg
 == dynamic-feFlood-01.svg pass.svg
 == dynamic-feImage-01.svg pass.svg
-== dynamic-filter-contents-01.svg dynamic-filter-contents-01-ref.svg
+== dynamic-filter-contents-01a.svg dynamic-filter-contents-01-ref.svg
+== dynamic-filter-contents-01b.svg dynamic-filter-contents-01-ref.svg
 == dynamic-gradient-contents-01.svg pass.svg
 == dynamic-gradient-contents-02.svg pass.svg
 == dynamic-inner-svg-01.svg pass.svg
 == dynamic-link-style-01.svg pass.svg
 == dynamic-marker-01.svg pass.svg
 == dynamic-marker-02.svg dynamic-marker-02-ref.svg
 == dynamic-mask-contents-01.svg pass.svg
 == dynamic-pattern-01.svg pass.svg
--- a/layout/reftests/table-anonymous-boxes/reftest.list
+++ b/layout/reftests/table-anonymous-boxes/reftest.list
@@ -1,12 +1,12 @@
 == 121142-1a.html 121142-1-ref.html
 == 121142-1b.html 121142-1-ref.html
 == 121142-2.html 121142-2-ref.html
-fails == 156888-1.html 156888-1-ref.html # bug 484825
+== 156888-1.html 156888-1-ref.html
 == 156888-2.html 156888-2-ref.html
 == 162063-1.xhtml about:blank
 == 203923-1.html white-space-ref.html
 == 203923-2.html white-space-ref.html
 == 208305-1.html 208305-1-ref.html
 == 208305-2.html white-space-ref.html
 == 208305-3.html white-space-ref.html
 == 208305-4.html white-space-ref.html
--- a/layout/reftests/text-decoration/decoration-color-override-quirks-ref.html
+++ b/layout/reftests/text-decoration/decoration-color-override-quirks-ref.html
@@ -1,5 +1,5 @@
 <html>
 	<body>
-		<u>hello</u><img src="http://www.mozilla.org/images/livemarks16.png"><font color="purple"><u>hello</u></font>
+		<u>hello</u><img src="../backgrounds/red-128-alpha-32x32.png"><font color="purple"><u>hello</u></font>
 	</body>
 </html>
--- a/layout/reftests/text-decoration/decoration-color-override-quirks.html
+++ b/layout/reftests/text-decoration/decoration-color-override-quirks.html
@@ -1,5 +1,5 @@
 <html>
 	<body>
-		<u>hello<img src="http://www.mozilla.org/images/livemarks16.png"><font color="purple">hello</font></u>
+		<u>hello<img src="../backgrounds/red-128-alpha-32x32.png"><font color="purple">hello</font></u>
 	</body>
 </html>
--- a/layout/reftests/text-decoration/decoration-color-override-standards-ref.html
+++ b/layout/reftests/text-decoration/decoration-color-override-standards-ref.html
@@ -1,6 +1,6 @@
 <!DOCTYPE HTML>
 <html>
 	<body>
-		<u>hello<img src="http://www.mozilla.org/images/livemarks16.png"><span style="color: purple;">hello</span></u>
+		<u>hello<img src="../backgrounds/red-128-alpha-32x32.png"><span style="color: purple;">hello</span></u>
 	</body>
 </html>
--- a/layout/reftests/text-decoration/decoration-color-override-standards.html
+++ b/layout/reftests/text-decoration/decoration-color-override-standards.html
@@ -1,6 +1,6 @@
 <!DOCTYPE HTML>
 <html>
 	<body>
-		<u>hello<img src="http://www.mozilla.org/images/livemarks16.png"><font color="purple">hello</font></u>
+		<u>hello<img src="../backgrounds/red-128-alpha-32x32.png"><font color="purple">hello</font></u>
 	</body>
 </html>
--- a/layout/reftests/text-overflow/reftest.list
+++ b/layout/reftests/text-overflow/reftest.list
@@ -13,8 +13,9 @@ HTTP(..) == quirks-line-height.html quir
 HTTP(..) == standards-decorations.html standards-decorations-ref.html
 HTTP(..) == standards-line-height.html standards-line-height-ref.html
 HTTP(..) == selection.html selection-ref.html
 HTTP(..) == marker-shadow.html marker-shadow-ref.html
 == aligned-baseline.html aligned-baseline-ref.html
 skip-if(Android) == clipped-elements.html clipped-elements-ref.html
 == theme-overflow.html theme-overflow-ref.html
 HTTP(..) == table-cell.html table-cell-ref.html
+HTTP(..) == two-value-syntax.html two-value-syntax-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-overflow/two-value-syntax-ref.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<!--
+    Any copyright is dedicated to the Public Domain.
+    http://creativecommons.org/licenses/publicdomain/
+
+    Test: text-overflow:<left> <right>
+-->
+<html><head>
+<title>text-overflow: text-overflow:&lt;left&gt; &lt;right&gt;</title>
+<style type="text/css">
+@font-face {
+  font-family: DejaVuSansMono;
+  src: url(../fonts/DejaVuSansMono.woff);
+}
+html,body {
+    color:black; background-color:white; font-size:16px; padding:0; margin:0; font-family:DejaVuSansMono;
+}
+
+.test {
+  overflow:hidden;
+  width:100%;
+  white-space:nowrap;
+}
+span {
+  margin: 0 -2px;
+}
+.rlo {
+  unicode-bidi: bidi-override; direction:rtl;
+}
+.lro {
+  unicode-bidi: bidi-override;
+}
+.rtl {
+  direction:rtl;
+}
+.ltr {
+  direction:ltr;
+}
+
+</style>
+
+</head><body>
+
+<div style="float:left;">
+|||||
+<div class="test t1"><span>&nbsp;&#x2026;||&#x2026;</span></div>
+<div class="test rtl t1"><span>&nbsp;&#x2026;||&#x2026;</span></div>
+<div class="test t2"><span>&nbsp;&#x2026;||||</span></div>
+<div class="test rtl t2"><span>||||&#x2026;</span></div>
+<div class="test t3"><span>||||&#x2026;</span></div>
+<div class="test rtl t3"><span>&nbsp;&#x2026;||||</span></div>
+<div class="test t4"><span>||||.</span></div>
+<div class="test rtl t4"><span>&nbsp;.||||</span></div>
+<div class="test t5"><span>&nbsp;.||||</span></div>
+<div class="test rtl t5"><span>||||.</span></div>
+<div class="test t6"><span>&nbsp;.||,</span></div>
+<div class="test rtl t6"><span>&nbsp;,||.</span></div>
+<div class="test t7"><span>&nbsp;&#x2026;||,</span></div>
+<div class="test rtl t7"><span>&nbsp;,||&#x2026;</span></div>
+<div class="test t8"><span>&nbsp;.||&#x2026;</span></div>
+<div class="test rtl t8"><span>&nbsp;&#x2026;||.</span></div>
+</div>
+
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-overflow/two-value-syntax.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<!--
+    Any copyright is dedicated to the Public Domain.
+    http://creativecommons.org/licenses/publicdomain/
+
+    Test: text-overflow:<left> <right>
+-->
+<html><head>
+<title>text-overflow: text-overflow:&lt;left&gt; &lt;right&gt;</title>
+<style type="text/css">
+@font-face {
+  font-family: DejaVuSansMono;
+  src: url(../fonts/DejaVuSansMono.woff);
+}
+html,body {
+    color:black; background-color:white; font-size:16px; padding:0; margin:0; font-family:DejaVuSansMono;
+}
+
+.test {
+  overflow:hidden;
+  width:100%;
+  white-space:nowrap;
+}
+span {
+  margin: 0 -2px;
+}
+.rlo {
+  unicode-bidi: bidi-override; direction:rtl;
+}
+.lro {
+  unicode-bidi: bidi-override;
+}
+.rtl {
+  direction:rtl;
+}
+.ltr {
+  direction:ltr;
+}
+
+.t1 { text-overflow:ellipsis ellipsis; }
+.t2 { text-overflow:ellipsis clip; }
+.t3 { text-overflow:clip ellipsis; }
+.t4 { text-overflow:clip "."; }
+.t5 { text-overflow:"." clip; }
+.t6 { text-overflow:"." ","; }
+.t7 { text-overflow:ellipsis ","; }
+.t8 { text-overflow:"." ellipsis; }
+
+</style>
+
+</head><body>
+
+<div style="float:left;">
+|||||
+<div class="test t1"><span>||||||</span></div>
+<div class="test rtl t1"><span>||||||</span></div>
+<div class="test t2"><span>||||||</span></div>
+<div class="test rtl t2"><span>||||||</span></div>
+<div class="test t3"><span>||||||</span></div>
+<div class="test rtl t3"><span>||||||</span></div>
+<div class="test t4"><span>||||||</span></div>
+<div class="test rtl t4"><span>||||||</span></div>
+<div class="test t5"><span>||||||</span></div>
+<div class="test rtl t5"><span>||||||</span></div>
+<div class="test t6"><span>||||||</span></div>
+<div class="test rtl t6"><span>||||||</span></div>
+<div class="test t7"><span>||||||</span></div>
+<div class="test rtl t7"><span>||||||</span></div>
+<div class="test t8"><span>||||||</span></div>
+<div class="test rtl t8"><span>||||||</span></div>
+</div>
+
+
+</body>
+</html>
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -508,16 +508,17 @@ protected:
   PRBool ParseMozTransform();
   PRBool ParseOutline();
   PRBool ParseOverflow();
   PRBool ParsePadding();
   PRBool ParseQuotes();
   PRBool ParseSize();
   PRBool ParseTextDecoration();
   PRBool ParseTextDecorationLine(nsCSSValue& aValue);
+  PRBool ParseTextOverflow(nsCSSValue& aValue);
 
   PRBool ParseShadowItem(nsCSSValue& aValue, PRBool aIsBoxShadow);
   PRBool ParseShadowList(nsCSSProperty aProperty);
   PRBool ParseTransitionProperty();
   PRBool ParseTransitionTimingFunctionValues(nsCSSValue& aValue);
   PRBool ParseTransitionTimingFunctionValueComponent(float& aComponent,
                                                      char aStop,
                                                      PRBool aCheckRange);
@@ -5596,16 +5597,18 @@ CSSParserImpl::ParseSingleValueProperty(
       case eCSSProperty_font_family:
         return ParseFamily(aValue);
       case eCSSProperty_font_weight:
         return ParseFontWeight(aValue);
       case eCSSProperty_marks:
         return ParseMarks(aValue);
       case eCSSProperty_text_decoration_line:
         return ParseTextDecorationLine(aValue);
+      case eCSSProperty_text_overflow:
+        return ParseTextOverflow(aValue);
       default:
         NS_ABORT_IF_FALSE(PR_FALSE, "should not reach here");
         return PR_FALSE;
     }
   }
 
   PRUint32 variant = nsCSSProps::ParserVariant(aPropID);
   if (variant == 0) {
@@ -8113,16 +8116,37 @@ CSSParserImpl::ParseTextDecorationLine(n
         aValue.SetIntValue(intValue, eCSSUnit_Enumerated);
       }
     }
     return PR_TRUE;
   }
   return PR_FALSE;
 }
 
+PRBool
+CSSParserImpl::ParseTextOverflow(nsCSSValue& aValue)
+{
+  if (ParseVariant(aValue, VARIANT_INHERIT, nsnull)) {
+    // 'inherit' and 'initial' must be alone
+    return PR_TRUE;
+  }
+
+  nsCSSValue left;
+  if (!ParseVariant(left, VARIANT_KEYWORD | VARIANT_STRING,
+                    nsCSSProps::kTextOverflowKTable))
+    return PR_FALSE;
+
+  nsCSSValue right;
+  if (ParseVariant(right, VARIANT_KEYWORD | VARIANT_STRING,
+                    nsCSSProps::kTextOverflowKTable))
+    aValue.SetPairValue(left, right);
+  else
+    aValue.SetPairValue(left, left);
+  return PR_TRUE;
+}
 
 PRBool
 CSSParserImpl::ParseTransitionProperty()
 {
   nsCSSValue value;
   if (ParseVariant(value, VARIANT_INHERIT | VARIANT_NONE | VARIANT_ALL,
                    nsnull)) {
     // 'inherit', 'initial', 'none', and 'all' must be alone
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -2206,18 +2206,19 @@ CSS_PROP_TEXT(
     VARIANT_HLP | VARIANT_CALC,
     nsnull,
     offsetof(nsStyleText, mTextIndent),
     eStyleAnimType_Coord)
 CSS_PROP_TEXTRESET(
     text-overflow,
     text_overflow,
     TextOverflow,
-    CSS_PROPERTY_PARSE_VALUE,
-    VARIANT_HK | VARIANT_STRING,
+    CSS_PROPERTY_PARSE_VALUE |
+        CSS_PROPERTY_VALUE_PARSER_FUNCTION,
+    0,
     kTextOverflowKTable,
     offsetof(nsStyleTextReset, mTextOverflow),
     eStyleAnimType_None)
 CSS_PROP_TEXT(
     text-shadow,
     text_shadow,
     TextShadow,
     CSS_PROPERTY_PARSE_FUNCTION |
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -2444,29 +2444,45 @@ nsComputedDOMStyle::DoGetTextIndent()
   SetValueToCoord(val, GetStyleText()->mTextIndent, PR_FALSE,
                   &nsComputedDOMStyle::GetCBContentWidth);
   return val;
 }
 
 nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetTextOverflow()
 {
-  nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
   const nsStyleTextReset *style = GetStyleTextReset();
-
-  if (style->mTextOverflow.mType == NS_STYLE_TEXT_OVERFLOW_STRING) {
+  nsROCSSPrimitiveValue *left = GetROCSSPrimitiveValue();
+  if (style->mTextOverflow.mLeft.mType == NS_STYLE_TEXT_OVERFLOW_STRING) {
     nsString str;
-    nsStyleUtil::AppendEscapedCSSString(style->mTextOverflow.mString, str);
-    val->SetString(str);
+    nsStyleUtil::AppendEscapedCSSString(style->mTextOverflow.mLeft.mString, str);
+    left->SetString(str);
   } else {
-    val->SetIdent(
-      nsCSSProps::ValueToKeywordEnum(style->mTextOverflow.mType,
+    left->SetIdent(
+      nsCSSProps::ValueToKeywordEnum(style->mTextOverflow.mLeft.mType,
                                      nsCSSProps::kTextOverflowKTable));
   }
-  return val;
+  if (style->mTextOverflow.mLeft == style->mTextOverflow.mRight) {
+    return left;
+  }
+  nsROCSSPrimitiveValue *right = GetROCSSPrimitiveValue();
+  if (style->mTextOverflow.mRight.mType == NS_STYLE_TEXT_OVERFLOW_STRING) {
+    nsString str;
+    nsStyleUtil::AppendEscapedCSSString(style->mTextOverflow.mRight.mString, str);
+    right->SetString(str);
+  } else {
+    right->SetIdent(
+      nsCSSProps::ValueToKeywordEnum(style->mTextOverflow.mRight.mType,
+                                     nsCSSProps::kTextOverflowKTable));
+  }
+
+  nsDOMCSSValueList *valueList = GetROCSSValueList(PR_FALSE);
+  valueList->AppendCSSValue(left);
+  valueList->AppendCSSValue(right);
+  return valueList;
 }
 
 nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetTextShadow()
 {
   return GetCSSShadowArray(GetStyleText()->mTextShadow,
                            GetStyleColor()->mColor,
                            PR_FALSE);
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -3490,32 +3490,51 @@ nsRuleNode::ComputeTextResetData(void* a
     text->SetDecorationStyle(decorationStyleValue->GetIntValue());
   } else if (eCSSUnit_Inherit == decorationStyleValue->GetUnit()) {
     text->SetDecorationStyle(parentText->GetDecorationStyle());
     canStoreInRuleTree = PR_FALSE;
   } else if (eCSSUnit_Initial == decorationStyleValue->GetUnit()) {
     text->SetDecorationStyle(NS_STYLE_TEXT_DECORATION_STYLE_SOLID);
   }
 
-  // text-overflow: enum, string, inherit, initial
+  // text-overflow: pair(enum|string), inherit, initial
   const nsCSSValue* textOverflowValue =
     aRuleData->ValueForTextOverflow();
-  if (eCSSUnit_Enumerated == textOverflowValue->GetUnit() ||
-      eCSSUnit_Initial    == textOverflowValue->GetUnit()) {
-    SetDiscrete(*textOverflowValue, text->mTextOverflow.mType,
-                canStoreInRuleTree,
-                SETDSC_ENUMERATED, parentText->mTextOverflow.mType,
-                NS_STYLE_TEXT_OVERFLOW_CLIP, 0, 0, 0, 0);
-    text->mTextOverflow.mString.Truncate();
+  if (eCSSUnit_Initial == textOverflowValue->GetUnit()) {
+    text->mTextOverflow = nsStyleTextOverflow();
   } else if (eCSSUnit_Inherit == textOverflowValue->GetUnit()) {
     canStoreInRuleTree = PR_FALSE;
     text->mTextOverflow = parentText->mTextOverflow;
-  } else if (eCSSUnit_String == textOverflowValue->GetUnit()) {
-    textOverflowValue->GetStringValue(text->mTextOverflow.mString);
-    text->mTextOverflow.mType = NS_STYLE_TEXT_OVERFLOW_STRING;
+  } else if (eCSSUnit_Pair == textOverflowValue->GetUnit()) {
+    const nsCSSValuePair& textOverflowValue =
+      aRuleData->ValueForTextOverflow()->GetPairValue();
+
+    const nsCSSValue *textOverflowLeftValue = &textOverflowValue.mXValue;
+    if (eCSSUnit_Enumerated == textOverflowLeftValue->GetUnit()) {
+      SetDiscrete(*textOverflowLeftValue, text->mTextOverflow.mLeft.mType,
+                  canStoreInRuleTree,
+                  SETDSC_ENUMERATED, parentText->mTextOverflow.mLeft.mType,
+                  NS_STYLE_TEXT_OVERFLOW_CLIP, 0, 0, 0, 0);
+      text->mTextOverflow.mLeft.mString.Truncate();
+    } else if (eCSSUnit_String == textOverflowLeftValue->GetUnit()) {
+      textOverflowLeftValue->GetStringValue(text->mTextOverflow.mLeft.mString);
+      text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_STRING;
+    }
+
+    const nsCSSValue *textOverflowRightValue = &textOverflowValue.mYValue;
+    if (eCSSUnit_Enumerated == textOverflowRightValue->GetUnit()) {
+      SetDiscrete(*textOverflowRightValue, text->mTextOverflow.mRight.mType,
+                  canStoreInRuleTree,
+                  SETDSC_ENUMERATED, parentText->mTextOverflow.mRight.mType,
+                  NS_STYLE_TEXT_OVERFLOW_CLIP, 0, 0, 0, 0);
+      text->mTextOverflow.mRight.mString.Truncate();
+    } else if (eCSSUnit_String == textOverflowRightValue->GetUnit()) {
+      textOverflowRightValue->GetStringValue(text->mTextOverflow.mRight.mString);
+      text->mTextOverflow.mRight.mType = NS_STYLE_TEXT_OVERFLOW_STRING;
+    }
   }
 
   // unicode-bidi: enum, inherit, initial
   SetDiscrete(*aRuleData->ValueForUnicodeBidi(), text->mUnicodeBidi, canStoreInRuleTree,
               SETDSC_ENUMERATED, parentText->mUnicodeBidi,
               NS_STYLE_UNICODE_BIDI_NORMAL, 0, 0, 0, 0);
 
   COMPUTE_END_RESET(TextReset, text)
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1126,30 +1126,42 @@ private:
   static PRBool WidthCoordDependsOnContainer(const nsStyleCoord &aCoord);
   static PRBool HeightCoordDependsOnContainer(const nsStyleCoord &aCoord)
   {
     return aCoord.GetUnit() == eStyleUnit_Auto || // CSS 2.1, 10.6.4, item (5)
            aCoord.HasPercent();
   }
 };
 
-struct nsStyleTextOverflow {
-  nsStyleTextOverflow() : mType(NS_STYLE_TEXT_OVERFLOW_CLIP) {}
+struct nsStyleTextOverflowSide {
+  nsStyleTextOverflowSide() : mType(NS_STYLE_TEXT_OVERFLOW_CLIP) {}
 
-  bool operator==(const nsStyleTextOverflow& aOther) const {
+  bool operator==(const nsStyleTextOverflowSide& aOther) const {
     return mType == aOther.mType &&
            (mType != NS_STYLE_TEXT_OVERFLOW_STRING ||
             mString == aOther.mString);
   }
+  bool operator!=(const nsStyleTextOverflowSide& aOther) const {
+    return !(*this == aOther);
+  }
+
+  nsString mString;
+  PRUint8  mType;
+};
+
+struct nsStyleTextOverflow {
+  bool operator==(const nsStyleTextOverflow& aOther) const {
+    return mLeft == aOther.mLeft && mRight == aOther.mRight;
+  }
   bool operator!=(const nsStyleTextOverflow& aOther) const {
     return !(*this == aOther);
   }
 
-  nsString mString;
-  PRUint8  mType;
+  nsStyleTextOverflowSide mLeft;
+  nsStyleTextOverflowSide mRight;
 };
 
 struct nsStyleTextReset {
   nsStyleTextReset(void);
   nsStyleTextReset(const nsStyleTextReset& aOther);
   ~nsStyleTextReset(void);
 
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -2541,19 +2541,19 @@ var gCSSProperties = {
 			"-moz-calc(3*25px + 50%)",
 		],
 		invalid_values: []
 	},
 	"text-overflow": {
 		domProp: "textOverflow",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
-		initial_values: [ "clip" ],
-		other_values: [ "ellipsis", '""', "''", '"hello"' ],
-		invalid_values: [ "none", "auto" ]
+		initial_values: [ "clip", "clip clip" ],
+		other_values: [ "ellipsis", '""', "''", '"hello"', 'clip ellipsis', 'clip ""', '"hello" ""', '"" ellipsis' ],
+		invalid_values: [ "none", "auto", '"hello" inherit', 'inherit "hello"', 'clip initial', 'initial clip', 'initial inherit', 'inherit initial', 'inherit none']
 	},
 	"text-shadow": {
 		domProp: "textShadow",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		prerequisites: { "color": "blue" },
 		initial_values: [ "none" ],
 		other_values: [ "2px 2px", "2px 2px 1px", "2px 2px green", "2px 2px 1px green", "green 2px 2px", "green 2px 2px 1px", "green 2px 2px, blue 1px 3px 4px", "currentColor 3px 3px", "blue 2px 2px, currentColor 1px 2px",
new file mode 100644
--- /dev/null
+++ b/layout/xul/base/reftest/image-scaling-min-height-1-ref.xul
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        xmlns:html="http://www.w3.org/1999/xhtml">
+<html:style><![CDATA[
+
+window { -moz-box-align: start; -moz-box-pack: start }
+hbox { background: yellow }
+vbox { background: blue; width: 15px; height: 15px }
+
+]]></html:style>
+
+<hbox><vbox /><label value="a b c d e f" /></hbox>
+
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/xul/base/reftest/image-scaling-min-height-1.xul
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        xmlns:html="http://www.w3.org/1999/xhtml">
+<html:style><![CDATA[
+
+window { -moz-box-align: start; -moz-box-pack: start }
+hbox { background: yellow }
+image { background: blue; min-width: 15px; min-height: 15px }
+
+]]></html:style>
+
+<hbox><image /><label value="a b c d e f" /></hbox>
+
+</window>
--- a/layout/xul/base/reftest/reftest.list
+++ b/layout/xul/base/reftest/reftest.list
@@ -1,4 +1,5 @@
-== textbox-multiline-noresize.xul textbox-multiline-ref.xul 
+fails-if(Android) == textbox-multiline-noresize.xul textbox-multiline-ref.xul # reference is blank on Android (due to no native theme support?)
 != textbox-multiline-resize.xul textbox-multiline-ref.xul 
 == popup-explicit-size.xul popup-explicit-size-ref.xul
 == image-size.xul image-size-ref.xul
+== image-scaling-min-height-1.xul image-scaling-min-height-1-ref.xul
--- a/mobile/chrome/content/ContentPopupHelper.js
+++ b/mobile/chrome/content/ContentPopupHelper.js
@@ -88,20 +88,20 @@ var ContentPopupHelper = {
       event.initEvent("contentpopuphidden", true, false);
       this._popup.dispatchEvent(event);
     }
 
     this._popup = aPopup;
   },
 
   /**
-   * This method positioned an arrowbox on the screen using a 'virtual'
+   * This method positions an arrowbox on the screen using a 'virtual'
    * element as referrer that match the real content element
-   * This method called element.getBoundingClientRect() many times and can be
-   * expensive, do not called it too many times.
+   * This method calls element.getBoundingClientRect() many times and can be
+   * expensive, do not call it too many times.
    */
   anchorTo: function(aAnchorRect) {
     let popup = this._popup;
     if (!popup)
       return;
 
     // Use the old rect until we get a new one
     this._anchorRect = aAnchorRect ? aAnchorRect : this._anchorRect;
@@ -205,28 +205,31 @@ var ContentPopupHelper = {
     switch(aEvent.type) {
       case "TabSelect":
       case "TabClose":
         this.popup = null;
         break;
 
       case "PanBegin":
       case "AnimatedZoomBegin":
-        popup.left = 0;
         popup.style.visibility = "hidden";
         break;
 
       case "PanFinished":
       case "AnimatedZoomEnd":
-        popup.style.visibility = "visible";
         this.anchorTo();
         break;
 
       case "MozBeforeResize":
-        popup.left = 0;
+        popup.style.visibility = "hidden";
+
+        // When screen orientation changes, we have to ensure that
+        // the popup width doesn't overflow the content's visible
+        // area.
+        popup.firstChild.style.maxWidth = "0px";
         break;
 
       case "resize":
         window.setTimeout(function(self) {
           self.anchorTo();
         }, 0, this);
         break;
     }
--- a/mobile/chrome/content/ContextCommands.js
+++ b/mobile/chrome/content/ContextCommands.js
@@ -48,21 +48,16 @@ var ContextCommands = {
       target.focus();
     }
   },
 
   openInNewTab: function cc_openInNewTab() {
     Browser.addTab(ContextHelper.popupState.linkURL, false, Browser.selectedTab);
   },
 
-  saveLink: function cc_saveLink() {
-    let browse