Merge of 3.1a2 release branch back to default, with version bumps to 3.1b1pre
authorBen Hearsum <bhearsum@mozilla.com>
Fri, 29 Aug 2008 09:31:25 -0400
changeset 18524 1ac4ead1f4fc7557082a5f59b52b278dbdfa0c58
parent 18523 9eea398698242da00fe7f562d9cc62e920e9cb02 (current diff)
parent 18520 69d14bce003f620cd2b01dd8477366ee3ce22617 (diff)
child 18525 d14db8996980288f833516bdea775bf2cab3ec45
push idunknown
push userunknown
push dateunknown
milestone1.9.1b1pre
Merge of 3.1a2 release branch back to default, with version bumps to 3.1b1pre
.hgtags
browser/app/module.ver
browser/components/sessionstore/test/chrome/Makefile.in
browser/components/sessionstore/test/chrome/test_bug350525.xul
browser/components/sessionstore/test/chrome/test_bug393716.xul
browser/config/version.txt
config/milestone.txt
embedding/minimo/README
embedding/minimo/chromelite/Makefile.in
embedding/minimo/chromelite/nsSimpleChromeHandler.cpp
embedding/minimo/chromelite/nsSimpleChromeHandler.h
embedding/minimo/chromelite/nsSimpleChromeRegistry.cpp
embedding/minimo/chromelite/nsSimpleChromeRegistry.h
gfx/thebes/public/gfxQtFonts.h
gfx/thebes/src/gfxQtFonts.cpp
netwerk/cache/public/nsIOfflineCacheSession.idl
rdf/chrome/Makefile.in
rdf/chrome/build/Makefile.in
rdf/chrome/build/chrome.pkg
rdf/chrome/build/chrome.xml
rdf/chrome/build/chromeIDL.xml
rdf/chrome/build/nsChromeFactory.cpp
rdf/chrome/public/Makefile.in
rdf/chrome/public/nsIChromeRegistrySea.idl
rdf/chrome/src/Makefile.in
rdf/chrome/src/nsChromeProtocolHandler.cpp
rdf/chrome/src/nsChromeProtocolHandler.h
rdf/chrome/src/nsChromeRegistry.cpp
rdf/chrome/src/nsChromeRegistry.h
rdf/chrome/src/nsChromeUIDataSource.cpp
rdf/chrome/src/nsChromeUIDataSource.h
rdf/chrome/tools/Makefile.in
rdf/chrome/tools/chromereg/Makefile.in
rdf/chrome/tools/chromereg/regchrome.cpp
toolkit/components/startup/src/nsUserInfoMac.cpp
toolkit/mozapps/update/test/unit/test_bug312661.js
toolkit/xre/MacLaunchHelper.m
widget/public/nsIMouseListener.h
xpfe/communicator/Makefile.in
xpfe/communicator/jar.mn
xpfe/communicator/resources/content/aboutPopups.xul
xpfe/communicator/resources/content/askViewZoom.js
xpfe/communicator/resources/content/askViewZoom.xul
xpfe/communicator/resources/content/browserBindings.xul
xpfe/communicator/resources/content/builtinURLs.js
xpfe/communicator/resources/content/communicator.css
xpfe/communicator/resources/content/contentAreaClick.js
xpfe/communicator/resources/content/contentAreaContextOverlay.xul
xpfe/communicator/resources/content/contentAreaDD.js
xpfe/communicator/resources/content/contentAreaUtils.js
xpfe/communicator/resources/content/contents-platform.rdf
xpfe/communicator/resources/content/contents-region.rdf
xpfe/communicator/resources/content/contents.rdf
xpfe/communicator/resources/content/editorBindings.xul
xpfe/communicator/resources/content/findUtils.js
xpfe/communicator/resources/content/mac/platformBrowserBindings.xul
xpfe/communicator/resources/content/mac/platformCommunicatorOverlay.xul
xpfe/communicator/resources/content/mac/platformEditorBindings.xul
xpfe/communicator/resources/content/manifest.rdf
xpfe/communicator/resources/content/nsContextMenu.js
xpfe/communicator/resources/content/openLocation.js
xpfe/communicator/resources/content/openLocation.xul
xpfe/communicator/resources/content/printPreviewBindings.xml
xpfe/communicator/resources/content/printing.js
xpfe/communicator/resources/content/tasksOverlay.js
xpfe/communicator/resources/content/tasksOverlay.xul
xpfe/communicator/resources/content/unix/platformBrowserBindings.xul
xpfe/communicator/resources/content/unix/platformCommunicatorOverlay.xul
xpfe/communicator/resources/content/unix/platformEditorBindings.xul
xpfe/communicator/resources/content/utilityOverlay.js
xpfe/communicator/resources/content/utilityOverlay.xul
xpfe/communicator/resources/content/viewZoomOverlay.js
xpfe/communicator/resources/content/viewZoomOverlay.xul
xpfe/communicator/resources/content/win/platformBrowserBindings.xul
xpfe/communicator/resources/content/win/platformCommunicatorOverlay.xul
xpfe/communicator/resources/content/win/platformEditorBindings.xul
xpfe/communicator/resources/locale/en-US/manifest.rdf
xpfe/components/startup/Makefile.in
xpfe/components/startup/public/Makefile.in
xpfe/components/startup/public/nsIAppStartup.idl
xpfe/components/startup/public/nsICloseAllWindows.idl
xpfe/components/startup/public/nsICmdLineHandler.idl
xpfe/components/startup/public/nsICmdLineService.idl
xpfe/components/startup/public/nsINativeAppSupport.idl
xpfe/components/startup/public/nsINativeAppSupportWin.idl
xpfe/components/startup/public/nsISplashScreen.h
xpfe/components/startup/public/nsIUserInfo.idl
xpfe/components/startup/src/Makefile.in
xpfe/components/startup/src/nsAppStartup.cpp
xpfe/components/startup/src/nsAppStartup.h
xpfe/components/startup/src/nsCloseAllWindows.js
xpfe/components/startup/src/nsCommandLineService.cpp
xpfe/components/startup/src/nsCommandLineService.h
xpfe/components/startup/src/nsCommandLineServiceMac.cpp
xpfe/components/startup/src/nsCommandLineServiceMac.h
xpfe/components/startup/src/nsUserInfo.h
xpfe/components/startup/src/nsUserInfoMac.cpp
xpfe/components/startup/src/nsUserInfoMac.h
xpfe/components/startup/src/nsUserInfoOS2.cpp
xpfe/components/startup/src/nsUserInfoUnix.cpp
xpfe/components/startup/src/nsUserInfoWin.cpp
xpfe/components/xremote/Makefile.in
xpfe/components/xremote/public/Makefile.in
xpfe/components/xremote/public/nsISuiteRemoteService.idl
xpfe/components/xremote/src/Makefile.in
xpfe/components/xremote/src/XRemoteContentListener.cpp
xpfe/components/xremote/src/XRemoteContentListener.h
xpfe/components/xremote/src/XRemoteService.cpp
xpfe/components/xremote/src/XRemoteService.h
xpfe/components/xremote/src/xremote.pkg
xpfe/global/Makefile.in
xpfe/global/buildconfig.html.in
xpfe/global/jar.mn
xpfe/global/resources/Makefile.in
xpfe/global/resources/content/Makefile.in
xpfe/global/resources/content/XPCNativeWrapper.js
xpfe/global/resources/content/about.xhtml
xpfe/global/resources/content/about.xul
xpfe/global/resources/content/aboutAbout.html
xpfe/global/resources/content/bindings/browser.xml
xpfe/global/resources/content/bindings/button.xml
xpfe/global/resources/content/bindings/checkbox.xml
xpfe/global/resources/content/bindings/colorpicker.xml
xpfe/global/resources/content/bindings/dialog.xml
xpfe/global/resources/content/bindings/editor.xml
xpfe/global/resources/content/bindings/general.xml
xpfe/global/resources/content/bindings/groupbox.xml
xpfe/global/resources/content/bindings/listbox.xml
xpfe/global/resources/content/bindings/menu.xml
xpfe/global/resources/content/bindings/menulist.xml
xpfe/global/resources/content/bindings/popup.xml
xpfe/global/resources/content/bindings/progressmeter.xml
xpfe/global/resources/content/bindings/radio.xml
xpfe/global/resources/content/bindings/scale.xml
xpfe/global/resources/content/bindings/scrollbar.xml
xpfe/global/resources/content/bindings/scrollbox.xml
xpfe/global/resources/content/bindings/splitter.xml
xpfe/global/resources/content/bindings/stringbundle.xml
xpfe/global/resources/content/bindings/tabbox.xml
xpfe/global/resources/content/bindings/tabbrowser.xml
xpfe/global/resources/content/bindings/text.xml
xpfe/global/resources/content/bindings/textbox.xml
xpfe/global/resources/content/bindings/toolbarbutton.xml
xpfe/global/resources/content/bindings/tree.xml
xpfe/global/resources/content/bindings/wizard.xml
xpfe/global/resources/content/charsetOverlay.js
xpfe/global/resources/content/charsetOverlay.xul
xpfe/global/resources/content/commonDialog.js
xpfe/global/resources/content/commonDialog.xul
xpfe/global/resources/content/config.js
xpfe/global/resources/content/config.xul
xpfe/global/resources/content/contents-platform.rdf
xpfe/global/resources/content/contents-region.rdf
xpfe/global/resources/content/contents.rdf
xpfe/global/resources/content/dialogOverlay.js
xpfe/global/resources/content/dialogOverlay.xul
xpfe/global/resources/content/fullScreen.js
xpfe/global/resources/content/globalOverlay.js
xpfe/global/resources/content/globalOverlay.xul
xpfe/global/resources/content/hiddenWindow.xul
xpfe/global/resources/content/license.html
xpfe/global/resources/content/logo.gif
xpfe/global/resources/content/mac/Makefile.in
xpfe/global/resources/content/mac/jar.mn
xpfe/global/resources/content/mac/platformDialog.xml
xpfe/global/resources/content/mac/platformDialogOverlay.xul
xpfe/global/resources/content/mac/platformXUL.css
xpfe/global/resources/content/manifest.rdf
xpfe/global/resources/content/mozilla.xhtml
xpfe/global/resources/content/nsClipboard.js
xpfe/global/resources/content/nsDragAndDrop.js
xpfe/global/resources/content/nsTreeController.js
xpfe/global/resources/content/nsTreeSorting.js
xpfe/global/resources/content/nsUserSettings.js
xpfe/global/resources/content/os2/Makefile.in
xpfe/global/resources/content/os2/jar.mn
xpfe/global/resources/content/os2/platformDialogOverlay.xul
xpfe/global/resources/content/os2/platformXUL.css
xpfe/global/resources/content/printPageSetup.js
xpfe/global/resources/content/printPageSetup.xul
xpfe/global/resources/content/printPreviewProgress.js
xpfe/global/resources/content/printPreviewProgress.xul
xpfe/global/resources/content/printProgress.js
xpfe/global/resources/content/printProgress.xul
xpfe/global/resources/content/printdialog.js
xpfe/global/resources/content/printdialog.xul
xpfe/global/resources/content/selectDialog.js
xpfe/global/resources/content/selectDialog.xul
xpfe/global/resources/content/strres.js
xpfe/global/resources/content/unix/Makefile.in
xpfe/global/resources/content/unix/jar.mn
xpfe/global/resources/content/unix/platformDialogOverlay.xul
xpfe/global/resources/content/unix/platformXUL.css
xpfe/global/resources/content/unix/printjoboptions.js
xpfe/global/resources/content/unix/printjoboptions.xul
xpfe/global/resources/content/win/Makefile.in
xpfe/global/resources/content/win/jar.mn
xpfe/global/resources/content/win/platformDialogOverlay.xul
xpfe/global/resources/content/win/platformXUL.css
xpfe/global/resources/content/wizardHandlerSet.js
xpfe/global/resources/content/wizardManager.js
xpfe/global/resources/content/wizardOverlay.js
xpfe/global/resources/content/wizardOverlay.xul
xpfe/global/resources/content/xul.css
xpfe/global/resources/locale/Makefile.in
xpfe/global/resources/locale/en-US/Makefile.in
xpfe/global/resources/locale/en-US/about.dtd
xpfe/global/resources/locale/en-US/brand.dtd
xpfe/global/resources/locale/en-US/charsetOverlay.dtd
xpfe/global/resources/locale/en-US/commonDialog.dtd
xpfe/global/resources/locale/en-US/commonDialogs.properties
xpfe/global/resources/locale/en-US/config.dtd
xpfe/global/resources/locale/en-US/config.properties
xpfe/global/resources/locale/en-US/contents-region.rdf
xpfe/global/resources/locale/en-US/contents.rdf
xpfe/global/resources/locale/en-US/dialog.properties
xpfe/global/resources/locale/en-US/dialogOverlay.dtd
xpfe/global/resources/locale/en-US/intl.css
xpfe/global/resources/locale/en-US/keys.properties
xpfe/global/resources/locale/en-US/languageNames.properties
xpfe/global/resources/locale/en-US/mac/Makefile.in
xpfe/global/resources/locale/en-US/mac/contents-platform.rdf
xpfe/global/resources/locale/en-US/mac/jar.mn
xpfe/global/resources/locale/en-US/mac/platformDialogOverlay.dtd
xpfe/global/resources/locale/en-US/mac/platformKeys.properties
xpfe/global/resources/locale/en-US/mac/wizard.properties
xpfe/global/resources/locale/en-US/nsTreeSorting.properties
xpfe/global/resources/locale/en-US/os2/Makefile.in
xpfe/global/resources/locale/en-US/os2/contents-platform.rdf
xpfe/global/resources/locale/en-US/os2/jar.mn
xpfe/global/resources/locale/en-US/printPageSetup.dtd
xpfe/global/resources/locale/en-US/printPageSetup.properties
xpfe/global/resources/locale/en-US/printPreviewProgress.dtd
xpfe/global/resources/locale/en-US/printProgress.dtd
xpfe/global/resources/locale/en-US/printdialog.dtd
xpfe/global/resources/locale/en-US/region.dtd
xpfe/global/resources/locale/en-US/region.properties
xpfe/global/resources/locale/en-US/regionNames.properties
xpfe/global/resources/locale/en-US/tabbrowser.dtd
xpfe/global/resources/locale/en-US/tabbrowser.properties
xpfe/global/resources/locale/en-US/textcontext.dtd
xpfe/global/resources/locale/en-US/tree.dtd
xpfe/global/resources/locale/en-US/unix/Makefile.in
xpfe/global/resources/locale/en-US/unix/contents-platform.rdf
xpfe/global/resources/locale/en-US/unix/jar.mn
xpfe/global/resources/locale/en-US/unix/platformDialogOverlay.dtd
xpfe/global/resources/locale/en-US/unix/platformKeys.properties
xpfe/global/resources/locale/en-US/unix/printjoboptions.dtd
xpfe/global/resources/locale/en-US/unix/wizard.properties
xpfe/global/resources/locale/en-US/win/Makefile.in
xpfe/global/resources/locale/en-US/win/contents-platform.rdf
xpfe/global/resources/locale/en-US/win/jar.mn
xpfe/global/resources/locale/en-US/win/platformDialogOverlay.dtd
xpfe/global/resources/locale/en-US/win/platformKeys.properties
xpfe/global/resources/locale/en-US/win/wizard.properties
xpfe/global/resources/locale/en-US/wizardManager.properties
xpfe/global/resources/locale/en-US/wizardOverlay.dtd
--- a/.hgignore
+++ b/.hgignore
@@ -1,14 +1,15 @@
 # .hgignore - List of filenames hg should ignore
 
 # Filenames that should be ignored wherever they appear
 ~$
 \.pyc$
 (^|/)TAGS$
+\.DS_Store$
 
 # User files that may appear at the root
 ^\.mozconfig$
 ^mozconfig$
 ^\.mozconfig\.mk$
 ^\.mozconfig\.out$
 ^configure$
 ^config\.cache$
--- a/accessible/src/base/nsAccessibilityAtomList.h
+++ b/accessible/src/base/nsAccessibilityAtomList.h
@@ -165,16 +165,17 @@ ACCESSIBILITY_ATOM(data, "data")
 ACCESSIBILITY_ATOM(droppable, "droppable")   // XUL combo box
 ACCESSIBILITY_ATOM(editable, "editable")
 ACCESSIBILITY_ATOM(_for, "for")
 ACCESSIBILITY_ATOM(hidden, "hidden")   // XUL tree columns
 ACCESSIBILITY_ATOM(href, "href") // XUL, XLink
 ACCESSIBILITY_ATOM(increment, "increment") // XUL
 ACCESSIBILITY_ATOM(lang, "lang")
 ACCESSIBILITY_ATOM(linkedPanel, "linkedpanel") // XUL
+ACCESSIBILITY_ATOM(longDesc, "longdesc")
 ACCESSIBILITY_ATOM(maxpos, "maxpos") // XUL
 ACCESSIBILITY_ATOM(minpos, "minpos") // XUL
 ACCESSIBILITY_ATOM(multiline, "multiline") // XUL
 ACCESSIBILITY_ATOM(name, "name")
 ACCESSIBILITY_ATOM(onclick, "onclick")
 ACCESSIBILITY_ATOM(readonly, "readonly")
 ACCESSIBILITY_ATOM(simple, "simple") // XLink
 ACCESSIBILITY_ATOM(src, "src")
@@ -182,16 +183,17 @@ ACCESSIBILITY_ATOM(selected, "selected")
 ACCESSIBILITY_ATOM(summary, "summary")
 ACCESSIBILITY_ATOM(tabindex, "tabindex")
 ACCESSIBILITY_ATOM(title, "title")
 ACCESSIBILITY_ATOM(tooltiptext, "tooltiptext")
 ACCESSIBILITY_ATOM(type, "type")
 ACCESSIBILITY_ATOM(value, "value")
 
   // Alphabetical list of text attributes (AT API)
+ACCESSIBILITY_ATOM(backgroundColor, "background-color")
 ACCESSIBILITY_ATOM(invalid, "invalid")
 ACCESSIBILITY_ATOM(language, "language")
 
   // ARIA (DHTML accessibility) attributes
   // Also add to nsARIAMap.cpp and nsARIAMap.h
   // ARIA role attribute
 ACCESSIBILITY_ATOM(role, "role")
 ACCESSIBILITY_ATOM(aria_activedescendant, "aria-activedescendant")
--- a/accessible/src/base/nsAccessibilityUtils.cpp
+++ b/accessible/src/base/nsAccessibilityUtils.cpp
@@ -796,16 +796,30 @@ nsAccUtils::GetDocShellTreeItemFor(nsIDO
   nsCOMPtr<nsISupports> container = doc->GetContainer();
   nsIDocShellTreeItem *docShellTreeItem = nsnull;
   if (container)
     CallQueryInterface(container, &docShellTreeItem);
 
   return docShellTreeItem;
 }
 
+nsIFrame*
+nsAccUtils::GetFrameFor(nsIDOMElement *aElm)
+{
+  nsCOMPtr<nsIPresShell> shell = nsAccessNode::GetPresShellFor(aElm);
+  if (!shell)
+    return nsnull;
+  
+  nsCOMPtr<nsIContent> content(do_QueryInterface(aElm));
+  if (!content)
+    return nsnull;
+  
+  return shell->GetPrimaryFrameFor(content);
+}
+
 PRBool
 nsAccUtils::GetID(nsIContent *aContent, nsAString& aID)
 {
   nsIAtom *idAttribute = aContent->GetIDAttributeName();
   return idAttribute ? aContent->GetAttr(kNameSpaceID_None, idAttribute, aID) : PR_FALSE;
 }
 
 PRBool
--- a/accessible/src/base/nsAccessibilityUtils.h
+++ b/accessible/src/base/nsAccessibilityUtils.h
@@ -303,16 +303,21 @@ public:
 
   /**
    * Return document shell tree item for the given DOM node.
    */
   static already_AddRefed<nsIDocShellTreeItem>
     GetDocShellTreeItemFor(nsIDOMNode *aNode);
 
   /**
+   * Retrun frame for the given DOM element.
+   */
+  static nsIFrame* GetFrameFor(nsIDOMElement *aElm);
+
+  /**
    * Get the ID for an element, in some types of XML this may not be the ID attribute
    * @param aContent  Node to get the ID for
    * @param aID       Where to put ID string
    * @return          PR_TRUE if there is an ID set for this node
    */
   static PRBool GetID(nsIContent *aContent, nsAString& aID);
 
   /**
--- a/accessible/src/base/nsApplicationAccessible.cpp
+++ b/accessible/src/base/nsApplicationAccessible.cpp
@@ -100,16 +100,18 @@ nsApplicationAccessible::Init()
   return rv;
 }
 
 // nsIAccessible
 
 NS_IMETHODIMP
 nsApplicationAccessible::GetName(nsAString& aName)
 {
+  aName.Truncate();
+
   nsCOMPtr<nsIStringBundleService> bundleService =
     do_GetService(NS_STRINGBUNDLE_CONTRACTID);
 
   NS_ASSERTION(bundleService, "String bundle service must be present!");
   NS_ENSURE_STATE(bundleService);
 
   nsCOMPtr<nsIStringBundle> bundle;
   bundleService->CreateBundle("chrome://branding/locale/brand.properties",
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -113,18 +113,21 @@ nsRootAccessible::nsRootAccessible(nsIDO
 // destruction
 //-----------------------------------------------------
 nsRootAccessible::~nsRootAccessible()
 {
 }
 
 // helpers
 /* readonly attribute AString name; */
-NS_IMETHODIMP nsRootAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsRootAccessible::GetName(nsAString& aName)
 {
+  aName.Truncate();
+
   if (!mDocument) {
     return NS_ERROR_FAILURE;
   }
 
   if (mRoleMapEntry) {
     nsAccessible::GetName(aName);
     if (!aName.IsEmpty()) {
       return NS_OK;
--- a/accessible/src/base/nsTextUtils.cpp
+++ b/accessible/src/base/nsTextUtils.cpp
@@ -34,22 +34,23 @@
  * 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 "nsTextUtils.h"
 
 #include "nsAccessNode.h"
+#include "nsAccessibilityUtils.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsLangTextAttr
 
 PRBool
-nsLangTextAttr::equal(nsIDOMElement *aElm)
+nsLangTextAttr::Equal(nsIDOMElement *aElm)
 {
   nsCOMPtr<nsIContent> content(do_QueryInterface(aElm));
   if (!content)
     return PR_FALSE;
 
   nsAutoString lang;
   nsAccUtils::GetLanguageFor(content, mRootContent, lang);
 
@@ -75,17 +76,16 @@ struct nsCSSTextAttrMapItem
  */
 
 const char* const kAnyValue = nsnull;
 const char* const kCopyName = nsnull;
 const char* const kCopyValue = nsnull;
 
 static nsCSSTextAttrMapItem gCSSTextAttrsMap[] = {
   // CSS name            CSS value        Attribute name              Attribute name
-  { "background-color",  kAnyValue,       kCopyName,                  kCopyValue },
   { "color",             kAnyValue,       kCopyName,                  kCopyValue },
   { "font-family",       kAnyValue,       kCopyName,                  kCopyValue },
   { "font-size",         kAnyValue,       kCopyName,                  kCopyValue },
   { "font-style",        kAnyValue,       kCopyName,                  kCopyValue },
   { "font-weight",       kAnyValue,       kCopyName,                  kCopyValue },
   { "text-decoration",   "line-through",  "text-line-through-style",  "solid" },
   { "text-decoration",   "underline",     "text-underline-style",     "solid" },
   { "text-align",        kAnyValue,       kCopyName,                  kCopyValue },
@@ -101,17 +101,17 @@ nsCSSTextAttr::nsCSSTextAttr(PRBool aInc
                                             getter_AddRefs(mStyleDecl));
 
   if (!mIncludeDefAttrValue)
     nsAccessNode::GetComputedStyleDeclaration(EmptyString(), aRootElm,
                                               getter_AddRefs(mDefStyleDecl));
 }
 
 PRBool
-nsCSSTextAttr::equal(nsIDOMElement *aElm)
+nsCSSTextAttr::Equal(nsIDOMElement *aElm)
 {
   if (!aElm || !mStyleDecl)
     return PR_FALSE;
 
   nsCOMPtr<nsIDOMCSSStyleDeclaration> currStyleDecl;
   nsAccessNode::GetComputedStyleDeclaration(EmptyString(), aElm,
                                             getter_AddRefs(currStyleDecl));
   if (!currStyleDecl)
@@ -125,23 +125,23 @@ nsCSSTextAttr::equal(nsIDOMElement *aElm
     return PR_FALSE;
 
   nsAutoString value;
   rv = mStyleDecl->GetPropertyValue(cssName, value);
   return NS_SUCCEEDED(rv) && value == currValue;
 }
 
 PRBool
-nsCSSTextAttr::iterate()
+nsCSSTextAttr::Iterate()
 {
   return ++mIndex < static_cast<PRInt32>(NS_ARRAY_LENGTH(gCSSTextAttrsMap));
 }
 
 PRBool
-nsCSSTextAttr::get(nsACString& aName, nsAString& aValue)
+nsCSSTextAttr::Get(nsACString& aName, nsAString& aValue)
 {
   if (!mStyleDecl)
     return PR_FALSE;
 
   NS_ConvertASCIItoUTF16 cssName(gCSSTextAttrsMap[mIndex].mCSSName);
   nsresult rv = mStyleDecl->GetPropertyValue(cssName, aValue);
   if (NS_FAILED(rv))
     return PR_FALSE;
@@ -174,8 +174,70 @@ nsCSSTextAttr::get(nsACString& aName, ns
   // Get the value of text attribute.
   const char *attrValue = gCSSTextAttrsMap[mIndex].mAttrValue;
   if (attrValue != kCopyValue)
     AppendASCIItoUTF16(attrValue, aValue);
 
   return PR_TRUE;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// nsBackgroundTextAttr
+
+nsBackgroundTextAttr::nsBackgroundTextAttr(nsIFrame *aFrame,
+                                           nsIFrame *aRootFrame) :
+  mFrame(aFrame), mRootFrame(aRootFrame)
+{
+}
+
+PRBool
+nsBackgroundTextAttr::Equal(nsIDOMElement *aElm)
+{
+  nsIFrame *frame = nsAccUtils::GetFrameFor(aElm);
+  if (!frame)
+    return PR_FALSE;
+
+  return GetColor(mFrame) == GetColor(frame);    
+}
+
+PRBool
+nsBackgroundTextAttr::Get(nsAString& aValue)
+{
+  // Do not expose "background-color" text attribute if its value is matched
+  // with the default value.
+  nscolor color = GetColor(mFrame);
+  if (mRootFrame && color == GetColor(mRootFrame))
+    return PR_FALSE;
+
+  // Combine the string like rgb(R, G, B) from nscolor.
+  nsAutoString value;
+  value.AppendLiteral("rgb(");
+  value.AppendInt(NS_GET_R(color));
+  value.AppendLiteral(", ");
+  value.AppendInt(NS_GET_G(color));
+  value.AppendLiteral(", ");
+  value.AppendInt(NS_GET_B(color));
+  value.Append(')');
+
+  aValue = value;
+  return PR_TRUE;
+}
+
+nscolor
+nsBackgroundTextAttr::GetColor(nsIFrame *aFrame)
+{
+  const nsStyleBackground *styleBackground = aFrame->GetStyleBackground();
+
+  if (!styleBackground->IsTransparent())
+    return styleBackground->mBackgroundColor;
+
+  nsIFrame *parentFrame = aFrame->GetParent();
+  if (!parentFrame)
+    return styleBackground->mBackgroundColor;
+
+  // Each frame of parents chain for the initially passed 'aFrame' has
+  // transparent background color. So background color isn't changed from
+  // 'mRootFrame' to initially passed 'aFrame'.
+  if (parentFrame == mRootFrame)
+    return GetColor(mRootFrame);
+
+  return GetColor(parentFrame);
+}
--- a/accessible/src/base/nsTextUtils.h
+++ b/accessible/src/base/nsTextUtils.h
@@ -38,44 +38,45 @@
 
 #ifndef nsTextUtils_h_
 #define nsTextUtils_h_
 
 #include "nsIDOMElement.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 
 #include "nsIContent.h"
+#include "nsIFrame.h"
 
 #include "nsCOMPtr.h"
 #include "nsString.h"
 
 /**
  * Base class to work with text attributes. See derived classes below.
  */
 class nsTextAttr
 {
 public:
   /**
    * Return true if the text attribute for the given element equals with
    * predefined attribute.
    */
-  virtual PRBool equal(nsIDOMElement *aElm) = 0;
+  virtual PRBool Equal(nsIDOMElement *aElm) = 0;
 };
 
 /**
  * Class is used for the work with 'lang' text attributes. Used in
  * nsHyperTextAccessible.
  */
 class nsLangTextAttr : public nsTextAttr
 {
 public:
   nsLangTextAttr(nsAString& aLang, nsIContent *aRootContent) :
     mLang(aLang), mRootContent(aRootContent) { }
 
-  virtual PRBool equal(nsIDOMElement *aElm);
+  virtual PRBool Equal(nsIDOMElement *aElm);
 
 private:
   nsString mLang;
   nsCOMPtr<nsIContent> mRootContent;
 };
 
 /**
  * Class is used for the work with CSS based text attributes. Used in
@@ -83,30 +84,66 @@ private:
  */
 class nsCSSTextAttr : public nsTextAttr
 {
 public:
   nsCSSTextAttr(PRBool aIncludeDefAttrValue, nsIDOMElement *aElm,
                 nsIDOMElement *aRootElm);
 
   // nsTextAttr
-  virtual PRBool equal(nsIDOMElement *aElm);
+  virtual PRBool Equal(nsIDOMElement *aElm);
 
   // nsCSSTextAttr
   /**
    * Interates through attributes.
    */
-  PRBool iterate();
+  PRBool Iterate();
 
   /**
    * Get name and value of attribute.
    */
-  PRBool get(nsACString& aName, nsAString& aValue);
+  PRBool Get(nsACString& aName, nsAString& aValue);
 
 private:
   PRInt32 mIndex;
   PRBool mIncludeDefAttrValue;
 
   nsCOMPtr<nsIDOMCSSStyleDeclaration> mStyleDecl;
   nsCOMPtr<nsIDOMCSSStyleDeclaration> mDefStyleDecl;
 };
 
+/**
+ * Class is used for the work with "background-color" text attribute. It is
+ * used in nsHyperTextAccessible.
+ */
+class nsBackgroundTextAttr : public nsTextAttr
+{
+public:
+  nsBackgroundTextAttr(nsIFrame *aFrame, nsIFrame *aRootFrame);
+  
+  // nsTextAttr
+  virtual PRBool Equal(nsIDOMElement *aElm);
+
+  /**
+   * Returns true and background color value if "background-color" text
+   * attribute should be exposed.
+   */
+  virtual PRBool Get(nsAString& aValue);
+
+private:
+  /**
+   * Return background color for the given frame.
+   *
+   * @note  If background color for the given frame is transparent then walk
+   *        trhough the frame parents chain until we'll got either a frame with
+   *        not transparent background color or the given root frame. In the
+   *        last case return background color for the root frame.
+   *
+   * @param aFrame      [in] the given frame to calculate background-color
+   * @return            background color
+   */
+  nscolor GetColor(nsIFrame *aFrame);
+
+  nsIFrame *mFrame;
+  nsIFrame *mRootFrame;
+};
+
 #endif
--- a/accessible/src/html/nsHTMLFormControlAccessible.cpp
+++ b/accessible/src/html/nsHTMLFormControlAccessible.cpp
@@ -270,18 +270,21 @@ nsHTMLButtonAccessible::GetState(PRUint3
 }
 
 NS_IMETHODIMP nsHTMLButtonAccessible::GetRole(PRUint32 *_retval)
 {
   *_retval = nsIAccessibleRole::ROLE_PUSHBUTTON;
   return NS_OK;
 }
 
-NS_IMETHODIMP nsHTMLButtonAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsHTMLButtonAccessible::GetName(nsAString& aName)
 {
+  aName.Truncate();
+
   nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
   if (!content) {
     return NS_ERROR_FAILURE; // Node shut down
   }
 
   nsAutoString name;
   // Prefer aria-labelledby attribute for name
   if (content->HasAttr(kNameSpaceID_None,
@@ -393,18 +396,21 @@ NS_IMETHODIMP nsHTMLTextFieldAccessible:
   if (content &&
       content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::type,
                            nsAccessibilityAtoms::password, eIgnoreCase)) {
     *aRole = nsIAccessibleRole::ROLE_PASSWORD_TEXT;
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP nsHTMLTextFieldAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsHTMLTextFieldAccessible::GetName(nsAString& aName)
 {
+  aName.Truncate();
+
   nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
   if (!content) {
     return NS_ERROR_FAILURE;
   }
   nsresult rv = GetHTMLName(aName, PR_FALSE);
   if (NS_FAILED(rv) || !aName.IsEmpty() || !content->GetBindingParent()) {
     return rv;
   }
@@ -601,22 +607,24 @@ nsIContent* nsHTMLGroupboxAccessible::Ge
       // Either XHTML namespace or no namespace
       return testLegendContent;
     }
   }
 
   return nsnull;
 }
 
-NS_IMETHODIMP nsHTMLGroupboxAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsHTMLGroupboxAccessible::GetName(nsAString& aName)
 {
+  aName.Truncate();
+
   if (!mDOMNode) {
     return NS_ERROR_FAILURE;
   }
-  aName.Truncate();
   if (mRoleMapEntry) {
     nsAccessible::GetName(aName);
     if (!aName.IsEmpty()) {
       return NS_OK;
     }
   }
 
   nsIContent *legendContent = GetLegend();
--- a/accessible/src/html/nsHTMLImageAccessible.cpp
+++ b/accessible/src/html/nsHTMLImageAccessible.cpp
@@ -205,19 +205,56 @@ void nsHTMLImageAccessible::CacheChildre
 
     privatePrevAccessible = do_QueryInterface(areaAccessible);
     NS_ASSERTION(privatePrevAccessible, "nsIAccessible impl's should always support nsPIAccessible as well");
     privatePrevAccessible->SetParent(this);
   }
   mAccChildCount = childCount;
 }
 
-NS_IMETHODIMP nsHTMLImageAccessible::DoAction(PRUint8 index)
+NS_IMETHODIMP
+nsHTMLImageAccessible::GetNumActions(PRUint8 *aNumActions)
 {
-  if (index == eAction_ShowLongDescription) {
+  NS_ENSURE_ARG_POINTER(aNumActions);
+  *aNumActions = 0;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  nsresult rv= nsLinkableAccessible::GetNumActions(aNumActions);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (HasLongDesc())
+    (*aNumActions)++;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLImageAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
+{
+  aName.Truncate();
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  if (IsValidLongDescIndex(aIndex)) {
+    aName.AssignLiteral("showlongdesc"); 
+    return NS_OK;
+  }
+  return nsLinkableAccessible::GetActionName(aIndex, aName);
+}
+
+NS_IMETHODIMP
+nsHTMLImageAccessible::DoAction(PRUint8 aIndex)
+{
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  if (IsValidLongDescIndex(aIndex)) {
     //get the long description uri and open in a new window
     nsCOMPtr<nsIDOMHTMLImageElement> element(do_QueryInterface(mDOMNode));
     NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
     nsAutoString longDesc;
     nsresult rv = element->GetLongDesc(longDesc);
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIDOMDocument> domDocument;
     rv = mDOMNode->GetOwnerDocument(getter_AddRefs(domDocument));
@@ -225,17 +262,17 @@ NS_IMETHODIMP nsHTMLImageAccessible::DoA
     nsCOMPtr<nsIDocument> document(do_QueryInterface(domDocument));
     nsCOMPtr<nsPIDOMWindow> piWindow = document->GetWindow();
     nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(piWindow));
     NS_ENSURE_TRUE(win, NS_ERROR_FAILURE);
     nsCOMPtr<nsIDOMWindow> tmp;
     return win->Open(longDesc, NS_LITERAL_STRING(""), NS_LITERAL_STRING(""),
                      getter_AddRefs(tmp));
   }
-  return nsLinkableAccessible::DoAction(index);
+  return nsLinkableAccessible::DoAction(aIndex);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessibleHyperLink
 NS_IMETHODIMP
 nsHTMLImageAccessible::GetAnchorCount(PRInt32 *aAnchorCount)
 {
   NS_ENSURE_ARG_POINTER(aAnchorCount);
@@ -400,8 +437,34 @@ nsHTMLImageAccessible::GetAreaAccessible
     PutCacheEntry(*mAccessNodeCache, (void*)(aAreaNum), accessNode);
   }
 
   nsIAccessible *accessible = nsnull;
   CallQueryInterface(accessNode, &accessible);
 
   return accessible;
 }
+
+////////////////////////////////////////////////////////////////////////////////
+// Private methods
+
+PRBool
+nsHTMLImageAccessible::HasLongDesc()
+{
+  if (IsDefunct())
+    return PR_FALSE;
+
+  nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
+  return (content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::longDesc));
+}
+
+PRBool
+nsHTMLImageAccessible::IsValidLongDescIndex(PRUint8 aIndex)
+{
+  if (!HasLongDesc())
+    return PR_FALSE;
+
+  PRUint8 numActions = 0;
+  nsresult rv = nsLinkableAccessible::GetNumActions(&numActions);  
+  NS_ENSURE_SUCCESS(rv, PR_FALSE);
+
+  return (aIndex == numActions);
+}
--- a/accessible/src/html/nsHTMLImageAccessible.h
+++ b/accessible/src/html/nsHTMLImageAccessible.h
@@ -50,25 +50,24 @@
  */
 class nsHTMLImageAccessible : public nsLinkableAccessible,
                               public nsIAccessibleImage
 {
 
   NS_DECL_ISUPPORTS_INHERITED
 
 public:
-  //action0 may exist depends on whether an onclick is associated with it
-  enum { eAction_ShowLongDescription = 1 };
-
   nsHTMLImageAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
 
   // nsIAccessible
   NS_IMETHOD GetName(nsAString& _retval); 
   NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
   NS_IMETHOD GetRole(PRUint32 *_retval);
+  NS_IMETHOD GetNumActions(PRUint8 *aNumActions);
+  NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 index);
 
   // nsIAccessibleHyperLink
   NS_IMETHOD GetAnchorCount(PRInt32 *aAnchorCount);
   NS_IMETHOD GetURI(PRInt32 aIndex, nsIURI **aURI);
   NS_IMETHOD GetAnchor(PRInt32 aIndex, nsIAccessible **aAccessible);
 
   // nsPIAccessNode
@@ -90,12 +89,31 @@ protected:
 
   // Reference on linked map element if any.
   nsCOMPtr<nsIDOMHTMLMapElement> mMapElement;
 
   // Cache of area accessibles. We do not use common cache because images can
   // share area elements but we need to have separate area accessibles for
   // each image accessible.
   nsAccessNodeHashtable *mAccessNodeCache;
+
+private:
+  /**
+   * Determine if this image accessible has a longdesc attribute.
+   *
+   * @returns  true if the longdesc attribute is present.
+   */
+  PRBool HasLongDesc();
+  
+  /**
+   * Used by GetActionName and DoAction to ensure the index for opening the
+   * longdesc URL is valid.
+   * It is always assumed that the highest possible index opens the longdesc.
+   *
+   * @param aIndex  The 0-based index to be tested.
+   *
+   * @returns  true if index is valid for longdesc action.
+   */
+  PRBool IsValidLongDescIndex(PRUint8 aIndex);
 };
 
 #endif
 
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/nsHTMLSelectAccessible.cpp
@@ -508,18 +508,21 @@ NS_IMETHODIMP nsHTMLSelectOptionAccessib
     *aRole = nsIAccessibleRole::ROLE_OPTION;
   }
   return NS_OK;
 }
 
 /**
   * Get our Name from our Content's subtree
   */
-NS_IMETHODIMP nsHTMLSelectOptionAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsHTMLSelectOptionAccessible::GetName(nsAString& aName)
 {
+  aName.Truncate();
+
   // CASE #1 -- great majority of the cases
   // find the label attribute - this is what the W3C says we should use
   nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mDOMNode));
   if (!domElement)
     return NS_ERROR_FAILURE;
 
   nsresult rv = domElement->GetAttribute(NS_LITERAL_STRING("label"), aName) ;
   if (NS_SUCCEEDED(rv) && !aName.IsEmpty()) {
@@ -1378,18 +1381,21 @@ NS_IMETHODIMP nsHTMLComboboxButtonAccess
 {   
   NS_IF_ADDREF(*aParent = mParent);
   return NS_OK;
 }
 
 /** 
   * Gets the name from GetActionName()
   */
-NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsHTMLComboboxButtonAccessible::GetName(nsAString& aName)
 {
+  aName.Truncate();
+
   return GetActionName(eAction_Click, aName);
 }
 
 /**
   * As a nsHTMLComboboxButtonAccessible we can have the following states:
   *     STATE_PRESSED
   *     STATE_FOCUSED
   *     STATE_FOCUSABLE
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -730,16 +730,40 @@ nsHyperTextAccessible::HypertextOffsetsT
   *aStartOffset = -1;
 
   NS_ENSURE_ARG_POINTER(aEndNode);
   *aEndNode = nsnull;
 
   NS_ENSURE_ARG_POINTER(aEndOffset);
   *aEndOffset = -1;
 
+  // If the given offsets are 0 and associated editor is empty then return
+  // collapsed range with editor root element as range container.
+  if (aStartHTOffset == 0 && aEndHTOffset == 0) {
+    nsCOMPtr<nsIEditor> editor;
+    GetAssociatedEditor(getter_AddRefs(editor));
+    if (editor) {
+      PRBool isEmpty = PR_FALSE;
+      editor->GetDocumentIsEmpty(&isEmpty);
+      if (isEmpty) {
+        nsCOMPtr<nsIDOMElement> editorRootElm;
+        editor->GetRootElement(getter_AddRefs(editorRootElm));
+
+        nsCOMPtr<nsIDOMNode> editorRoot(do_QueryInterface(editorRootElm));
+        if (editorRoot) {
+          *aStartOffset = *aEndOffset = 0;
+          NS_ADDREF(*aStartNode = editorRoot);
+          NS_ADDREF(*aEndNode = editorRoot);
+
+          return NS_OK;
+        }
+      }
+    }
+  }
+
   nsCOMPtr<nsIAccessible> startAcc, endAcc;
   PRInt32 startOffset = aStartHTOffset, endOffset = aEndHTOffset;
   nsIFrame *startFrame = nsnull, *endFrame = nsnull;
 
   startFrame = GetPosAndText(startOffset, endOffset, nsnull, &endFrame, nsnull,
                              getter_AddRefs(startAcc), getter_AddRefs(endAcc));
   if (!startAcc || !endAcc)
     return NS_ERROR_FAILURE;
@@ -1175,22 +1199,34 @@ nsHyperTextAccessible::GetDefaultTextAtt
   NS_ADDREF(*aAttributes = attributes);
 
   if (!mDOMNode)
     return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIDOMElement> element = nsAccUtils::GetDOMElementFor(mDOMNode);
 
   nsCSSTextAttr textAttr(PR_TRUE, element, nsnull);
-  while (textAttr.iterate()) {
+  while (textAttr.Iterate()) {
     nsCAutoString name;
     nsAutoString value, oldValue;
-    if (textAttr.get(name, value))
+    if (textAttr.Get(name, value))
       attributes->SetStringProperty(name, value, oldValue);
   }
+
+  nsIFrame *sourceFrame = nsAccUtils::GetFrameFor(element);
+  if (sourceFrame) {
+    nsBackgroundTextAttr backgroundTextAttr(sourceFrame, nsnull);
+
+    nsAutoString value;
+    if (backgroundTextAttr.Get(value)) {
+      nsAccUtils::SetAccAttr(attributes,
+                             nsAccessibilityAtoms::backgroundColor, value);
+    }
+  }
+
   return NS_OK;
 }
 
 nsresult
 nsHyperTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   if (!mDOMNode) {
     return NS_ERROR_FAILURE;  // Node already shut down
@@ -2283,27 +2319,46 @@ nsHyperTextAccessible::GetCSSTextAttribu
                                             PRInt32 *aStartHTOffset,
                                             PRInt32 *aEndHTOffset,
                                             nsIPersistentProperties *aAttributes)
 {
   nsCOMPtr<nsIDOMElement> sourceElm(nsAccUtils::GetDOMElementFor(aSourceNode));
   nsCOMPtr<nsIDOMElement> rootElm(nsAccUtils::GetDOMElementFor(mDOMNode));
 
   nsCSSTextAttr textAttr(aIncludeDefAttrs, sourceElm, rootElm);
-  while (textAttr.iterate()) {
+  while (textAttr.Iterate()) {
     nsCAutoString name;
     nsAutoString value, oldValue;
-    if (aAttributes && textAttr.get(name, value))
+    if (aAttributes && textAttr.Get(name, value))
       aAttributes->SetStringProperty(name, value, oldValue);
 
     nsresult rv = GetRangeForTextAttr(aSourceNode, &textAttr,
                                       aStartHTOffset, aEndHTOffset);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
+  nsIFrame *sourceFrame = nsAccUtils::GetFrameFor(sourceElm);
+  if (sourceFrame) {
+    nsIFrame *rootFrame = nsnull;
+
+    if (!aIncludeDefAttrs)
+      rootFrame = nsAccUtils::GetFrameFor(rootElm);
+
+    nsBackgroundTextAttr backgroundTextAttr(sourceFrame, rootFrame);
+    nsAutoString value;
+    if (backgroundTextAttr.Get(value)) {
+      nsAccUtils::SetAccAttr(aAttributes,
+                             nsAccessibilityAtoms::backgroundColor, value);
+    }
+
+    nsresult rv = GetRangeForTextAttr(aSourceNode, &backgroundTextAttr,
+                                      aStartHTOffset, aEndHTOffset);
+    return rv;
+  }
+
   return NS_OK;
 }
 
 // nsHyperTextAccessible
 nsresult
 nsHyperTextAccessible::GetRangeForTextAttr(nsIDOMNode *aNode,
                                            nsTextAttr *aComparer,
                                            PRInt32 *aStartHTOffset,
@@ -2323,17 +2378,17 @@ nsHyperTextAccessible::GetRangeForTextAt
   //    to it through whole tree of the traversed sibling.
   // 3. Get the parent and cycle algorithm until the root node.
 
   // Navigate backwards (find the start offset).
   while (currNode && currNode != rootElm) {
     nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(currNode));
     NS_ENSURE_STATE(currElm);
 
-    if (currNode != aNode && !aComparer->equal(currElm)) {
+    if (currNode != aNode && !aComparer->Equal(currElm)) {
       PRInt32 startHTOffset = 0;
       nsCOMPtr<nsIAccessible> startAcc;
       nsresult rv = DOMPointToHypertextOffset(tmpNode, -1, &startHTOffset,
                                               getter_AddRefs(startAcc));
       NS_ENSURE_SUCCESS(rv, rv);
 
       if (!startAcc)
         startHTOffset = 0;
@@ -2359,17 +2414,17 @@ nsHyperTextAccessible::GetRangeForTextAt
   PRBool moveIntoSubtree = PR_TRUE;
   currNode = aNode;
   while (currNode && currNode != rootElm) {
     nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(currNode));
     NS_ENSURE_STATE(currElm);
 
     // Stop new end offset searching if the given text attribute changes its
     // value.
-    if (!aComparer->equal(currElm)) {
+    if (!aComparer->Equal(currElm)) {
       PRInt32 endHTOffset = 0;
       nsresult rv = DOMPointToHypertextOffset(currNode, -1, &endHTOffset);
       NS_ENSURE_SUCCESS(rv, rv);
 
       if (endHTOffset < *aEndHTOffset)
         *aEndHTOffset = endHTOffset;
 
       break;
@@ -2405,17 +2460,17 @@ nsHyperTextAccessible::FindEndOffsetInSu
   if (!aCurrNode)
     return PR_FALSE;
 
   nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(aCurrNode));
   NS_ENSURE_STATE(currElm);
 
   // If the given text attribute (pointed by nsTextAttr object) changes its
   // value on the traversed element then fit the end of range.
-  if (!aComparer->equal(currElm)) {
+  if (!aComparer->Equal(currElm)) {
     PRInt32 endHTOffset = 0;
     nsresult rv = DOMPointToHypertextOffset(aCurrNode, -1, &endHTOffset);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (endHTOffset < *aHTOffset)
       *aHTOffset = endHTOffset;
 
     return PR_TRUE;
@@ -2456,17 +2511,17 @@ nsHyperTextAccessible::FindStartOffsetIn
       return PR_TRUE;
   }
 
   nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(aCurrNode));
   NS_ENSURE_STATE(currElm);
 
   // If the given text attribute (pointed by nsTextAttr object) changes its
   // value on the traversed element then fit the start of range.
-  if (!aComparer->equal(currElm)) {
+  if (!aComparer->Equal(currElm)) {
     PRInt32 startHTOffset = 0;
     nsCOMPtr<nsIAccessible> startAcc;
     nsresult rv = DOMPointToHypertextOffset(aPrevNode, -1, &startHTOffset,
                                             getter_AddRefs(startAcc));
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (!startAcc)
       startHTOffset = 0;
--- a/accessible/src/msaa/nsAccessNodeWrap.cpp
+++ b/accessible/src/msaa/nsAccessNodeWrap.cpp
@@ -32,17 +32,16 @@
  * 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 "nsAccessNodeWrap.h"
-#include <tchar.h> 
 #include "ISimpleDOMNode_i.c"
 #include "nsAccessibilityAtoms.h"
 #include "nsIAccessibilityService.h"
 #include "nsIAccessible.h"
 #include "nsAttrName.h"
 #include "nsIDocument.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsIDOMNodeList.h"
@@ -67,16 +66,20 @@ LPFNNOTIFYWINEVENT nsAccessNodeWrap::gmN
 LPFNGETGUITHREADINFO nsAccessNodeWrap::gmGetGUIThreadInfo = nsnull;
 
 PRBool nsAccessNodeWrap::gIsEnumVariantSupportDisabled = 0;
 // Used to determine whether an IAccessible2 compatible screen reader is loaded.
 PRBool nsAccessNodeWrap::gIsIA2Disabled = PR_FALSE;
 
 nsIAccessibleTextChangeEvent *nsAccessNodeWrap::gTextEvent = nsnull;
 
+// Pref to disallow CtrlTab preview functionality if JAWS or Window-Eyes are
+// running.
+#define CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF "browser.ctrlTab.disallowForScreenReaders"
+
 
 /* For documentation of the accessibility architecture, 
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 /*
  * Class nsAccessNodeWrap
  */
@@ -587,17 +590,17 @@ void nsAccessNodeWrap::InitAccessibility
   }
 
   nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
   if (prefBranch) {
     prefBranch->GetBoolPref("accessibility.disableenumvariant", &gIsEnumVariantSupportDisabled);
   }
 
   if (!gmUserLib) {
-    gmUserLib =::LoadLibrary("USER32.DLL");
+    gmUserLib =::LoadLibraryW(L"USER32.DLL");
   }
 
   if (gmUserLib) {
     if (!gmNotifyWinEvent)
       gmNotifyWinEvent = (LPFNNOTIFYWINEVENT)GetProcAddress(gmUserLib,"NotifyWinEvent");
     if (!gmGetGUIThreadInfo)
       gmGetGUIThreadInfo = (LPFNGETGUITHREADINFO)GetProcAddress(gmUserLib,"GetGUIThreadInfo");
   }
@@ -657,17 +660,17 @@ GetHRESULT(nsresult aResult)
 
     default:
       return E_FAIL;
   }
 }
 
 PRBool nsAccessNodeWrap::IsOnlyMsaaCompatibleJawsPresent()
 {
-  HMODULE jhookhandle = ::GetModuleHandleW(NS_LITERAL_STRING("jhook").get());
+  HMODULE jhookhandle = ::GetModuleHandleW(L"jhook");
   if (!jhookhandle)
     return PR_FALSE;  // No JAWS, or some other screen reader, use IA2
 
   PRUnichar fileName[MAX_PATH];
   ::GetModuleFileNameW(jhookhandle, fileName, MAX_PATH);
 
   DWORD dummy;
   DWORD length = ::GetFileVersionInfoSizeW(fileName, &dummy);
@@ -686,14 +689,49 @@ PRBool nsAccessNodeWrap::IsOnlyMsaaCompa
 //  DWORD dwSecondLeft = LOWORD(dwFileVersionMS);
   DWORD dwSecondRight = HIWORD(dwFileVersionLS);
 //  DWORD dwRightMost = LOWORD(dwFileVersionLS);
 
   return (dwLeftMost < 8
           || (dwLeftMost == 8 && dwSecondRight < 2173));
 }
 
+void nsAccessNodeWrap::TurnOffNewTabSwitchingForJawsAndWE()
+{
+  HMODULE srHandle = ::GetModuleHandleW(L"jhook");
+  if (!srHandle) {
+    // No JAWS, try Window-Eyes
+    srHandle = ::GetModuleHandleW(L"gwm32inc");
+    if (!srHandle) {
+      // no screen reader we're interested in. Bail out.
+      return;
+    }
+  }
+
+  // Check to see if the pref for disallowing CtrlTab is already set.
+  // If so, bail out.
+  // If not, set it.
+  nsCOMPtr<nsIPrefBranch> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID));
+  if (prefs) {
+    PRBool hasDisallowNewCtrlTabPref = PR_FALSE;
+    nsresult rv = prefs->PrefHasUserValue(CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF,
+             &hasDisallowNewCtrlTabPref);
+    if (NS_SUCCEEDED(rv) && hasDisallowNewCtrlTabPref) {
+      // This pref has been set before. There is no default for it.
+      // Do nothing further, respect the setting that's there.
+      // That way, if noone touches it, it'll stay on after toggled once.
+      // If someone decided to turn it off, we respect that, too.
+      return;
+    }
+    
+    // Value has never been set, set it.
+    prefs->SetBoolPref(CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF, PR_TRUE);
+  }
+}
+
 void nsAccessNodeWrap::DoATSpecificProcessing()
 {
   if (IsOnlyMsaaCompatibleJawsPresent())
     // All versions below 8.0.2173 are not compatible
     gIsIA2Disabled  = PR_TRUE;
+
+  TurnOffNewTabSwitchingForJawsAndWE();
 }
--- a/accessible/src/msaa/nsAccessNodeWrap.h
+++ b/accessible/src/msaa/nsAccessNodeWrap.h
@@ -154,16 +154,19 @@ class nsAccessNodeWrap :  public nsAcces
     static HINSTANCE gmUserLib;
     static LPFNACCESSIBLEOBJECTFROMWINDOW gmAccessibleObjectFromWindow;
     static LPFNNOTIFYWINEVENT gmNotifyWinEvent;
     static LPFNGETGUITHREADINFO gmGetGUIThreadInfo;
 
     static int FilterA11yExceptions(unsigned int aCode, EXCEPTION_POINTERS *aExceptionInfo);
 
     static PRBool IsOnlyMsaaCompatibleJawsPresent();
+
+    static void TurnOffNewTabSwitchingForJawsAndWE();
+
     static void DoATSpecificProcessing();
   protected:
     void GetAccessibleFor(nsIDOMNode *node, nsIAccessible **newAcc);
     ISimpleDOMNode* MakeAccessNode(nsIDOMNode *node);
 
     static PRBool gIsEnumVariantSupportDisabled;
 
     /**
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -153,17 +153,17 @@ STDMETHODIMP nsAccessibleWrap::QueryInte
 
 STDMETHODIMP nsAccessibleWrap::AccessibleObjectFromWindow(HWND hwnd,
                                                           DWORD dwObjectID,
                                                           REFIID riid,
                                                           void **ppvObject)
 {
   // open the dll dynamically
   if (!gmAccLib)
-    gmAccLib =::LoadLibrary("OLEACC.DLL");
+    gmAccLib =::LoadLibraryW(L"OLEACC.DLL");
 
   if (gmAccLib) {
     if (!gmAccessibleObjectFromWindow)
       gmAccessibleObjectFromWindow = (LPFNACCESSIBLEOBJECTFROMWINDOW)GetProcAddress(gmAccLib,"AccessibleObjectFromWindow");
 
     if (gmAccessibleObjectFromWindow)
       return gmAccessibleObjectFromWindow(hwnd, dwObjectID, riid, ppvObject);
   }
--- a/accessible/src/xul/nsXULColorPickerAccessible.cpp
+++ b/accessible/src/xul/nsXULColorPickerAccessible.cpp
@@ -87,19 +87,22 @@ nsXULColorPickerTileAccessible::GetState
   PRBool isSelected = PR_FALSE;
   element->HasAttribute(NS_LITERAL_STRING("selected"), &isSelected);
   if (isFocused)
     *aState |= nsIAccessibleStates::STATE_SELECTED;
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsXULColorPickerTileAccessible::GetName(nsAString& _retval)
+NS_IMETHODIMP
+nsXULColorPickerTileAccessible::GetName(nsAString& aName)
 {
-  return GetXULName(_retval);
+  aName.Truncate();
+
+  return GetXULName(aName);
 }
 
 NS_IMETHODIMP nsXULColorPickerTileAccessible::GetValue(nsAString& _retval)
 {
   if (!mDOMNode)
     return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
--- a/accessible/src/xul/nsXULMenuAccessible.cpp
+++ b/accessible/src/xul/nsXULMenuAccessible.cpp
@@ -384,23 +384,26 @@ nsXULMenuitemAccessible::GetState(PRUint
     }
   }
   *aState|= (nsIAccessibleStates::STATE_FOCUSABLE |
              nsIAccessibleStates::STATE_SELECTABLE);
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsXULMenuitemAccessible::GetName(nsAString& _retval)
+NS_IMETHODIMP
+nsXULMenuitemAccessible::GetName(nsAString& aName)
 {
+  aName.Truncate();
+
   nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
   if (!element) {
     return NS_ERROR_FAILURE;
   }
-  element->GetAttribute(NS_LITERAL_STRING("label"), _retval); 
+  element->GetAttribute(NS_LITERAL_STRING("label"), aName); 
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsXULMenuitemAccessible::GetDescription(nsAString& aDescription)
 {
   nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
   if (!element) {
@@ -573,19 +576,21 @@ nsXULMenuSeparatorAccessible::GetState(P
   }
 
   *aState &= (nsIAccessibleStates::STATE_OFFSCREEN | 
               nsIAccessibleStates::STATE_INVISIBLE);
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsXULMenuSeparatorAccessible::GetName(nsAString& _retval)
+NS_IMETHODIMP
+nsXULMenuSeparatorAccessible::GetName(nsAString& aName)
 {
-  _retval.Truncate();
+  aName.Truncate();
+
   return NS_OK;
 }
 
 NS_IMETHODIMP nsXULMenuSeparatorAccessible::GetRole(PRUint32 *_retval)
 {
   *_retval = nsIAccessibleRole::ROLE_SEPARATOR;
   return NS_OK;
 }
@@ -747,19 +752,20 @@ nsXULMenubarAccessible::GetState(PRUint3
   }
 
   // Menu bar iteself is not actually focusable
   *aState &= ~nsIAccessibleStates::STATE_FOCUSABLE;
   return rv;
 }
 
 
-NS_IMETHODIMP nsXULMenubarAccessible::GetName(nsAString& _retval)
+NS_IMETHODIMP
+nsXULMenubarAccessible::GetName(nsAString& aName)
 {
-  _retval.AssignLiteral("Application");
+  aName.AssignLiteral("Application");
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsXULMenubarAccessible::GetRole(PRUint32 *_retval)
 {
   *_retval = nsIAccessibleRole::ROLE_MENUBAR;
   return NS_OK;
--- a/accessible/src/xul/nsXULSelectAccessible.cpp
+++ b/accessible/src/xul/nsXULSelectAccessible.cpp
@@ -105,16 +105,18 @@ nsXULColumnItemAccessible::GetState(PRUi
     *aExtraState = mDOMNode ? 0 : nsIAccessibleStates::EXT_STATE_DEFUNCT ;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULColumnItemAccessible::GetName(nsAString& aName)
 {
+  aName.Truncate();
+
   return GetXULName(aName);
 }
 
 NS_IMETHODIMP
 nsXULColumnItemAccessible::GetNumActions(PRUint8 *aNumActions)
 {
   NS_ENSURE_ARG_POINTER(aNumActions);
 
@@ -852,34 +854,37 @@ nsXULListitemAccessible::GetListAccessib
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULListitemAccessible. nsIAccessible
 
 /**
   * If there is a Listcell as a child ( not anonymous ) use it, otherwise
   *   default to getting the name from GetXULName
   */
-NS_IMETHODIMP nsXULListitemAccessible::GetName(nsAString& _retval)
+NS_IMETHODIMP
+nsXULListitemAccessible::GetName(nsAString& aName)
 {
+  aName.Truncate();
+
   if (!mDOMNode)
     return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIDOMNode> child;
   if (NS_SUCCEEDED(mDOMNode->GetFirstChild(getter_AddRefs(child)))) {
     nsCOMPtr<nsIDOMElement> childElement (do_QueryInterface(child));
     if (childElement) {
       nsAutoString tagName;
       childElement->GetLocalName(tagName);
       if (tagName.EqualsLiteral("listcell")) {
-        childElement->GetAttribute(NS_LITERAL_STRING("label"), _retval);
+        childElement->GetAttribute(NS_LITERAL_STRING("label"), aName);
         return NS_OK;
       }
     }
   }
-  return GetXULName(_retval);
+  return GetXULName(aName);
 }
 
 /**
   *
   */
 NS_IMETHODIMP nsXULListitemAccessible::GetRole(PRUint32 *aRole)
 {
   nsCOMPtr<nsIAccessible> listAcc = GetListAccessible();
--- a/accessible/src/xul/nsXULTabAccessible.cpp
+++ b/accessible/src/xul/nsXULTabAccessible.cpp
@@ -292,19 +292,21 @@ NS_IMETHODIMP nsXULTabsAccessible::GetNu
 
 /** no value */
 NS_IMETHODIMP nsXULTabsAccessible::GetValue(nsAString& _retval)
 {
   return NS_OK;
 }
 
 /** no name*/
-NS_IMETHODIMP nsXULTabsAccessible::GetName(nsAString& _retval)
+NS_IMETHODIMP
+nsXULTabsAccessible::GetName(nsAString& aName)
 {
-  _retval.Truncate();
+  aName.Truncate();
+
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTabpanelAccessible
 
 nsXULTabpanelAccessible::
   nsXULTabpanelAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
--- a/accessible/src/xul/nsXULTextAccessible.cpp
+++ b/accessible/src/xul/nsXULTextAccessible.cpp
@@ -51,18 +51,21 @@
   * For XUL descriptions and labels
   */
 nsXULTextAccessible::nsXULTextAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell):
 nsHyperTextAccessibleWrap(aDomNode, aShell)
 { 
 }
 
 /* wstring getName (); */
-NS_IMETHODIMP nsXULTextAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsXULTextAccessible::GetName(nsAString& aName)
 { 
+  aName.Truncate();
+
   nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
   if (!content) {
     return NS_ERROR_FAILURE;  // Node shut down
   }
   // if the value attr doesn't exist, the screen reader must get the accessible text
   // from the accessible text interface or from the children
   return content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::value, aName);
 }
@@ -112,18 +115,21 @@ nsXULTextAccessible::GetAccessibleRelate
 /**
   * For XUL tooltip
   */
 nsXULTooltipAccessible::nsXULTooltipAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell):
 nsLeafAccessible(aDomNode, aShell)
 { 
 }
 
-NS_IMETHODIMP nsXULTooltipAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsXULTooltipAccessible::GetName(nsAString& aName)
 {
+  aName.Truncate();
+
   return GetXULName(aName, PR_TRUE);
 }
 
 NS_IMETHODIMP
 nsXULTooltipAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
 {
   nsresult rv = nsLeafAccessible::GetState(aState, aExtraState);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -778,18 +778,21 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeit
 NS_IMETHODIMP nsXULTreeitemAccessible::Shutdown()
 {
   mTree = nsnull;
   mTreeView = nsnull;
   mColumn = nsnull;
   return nsLeafAccessible::Shutdown();
 }
 
-NS_IMETHODIMP nsXULTreeitemAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsXULTreeitemAccessible::GetName(nsAString& aName)
 {
+  aName.Truncate();
+
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   mTreeView->GetCellText(mRow, mColumn, aName);
   
   // If there is still no name try the cell value:
   // This is for graphical cells. We need tree/table view implementors to implement
   // FooView::GetCellValue to return a meaningful string for cases where there is
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -42,43 +42,48 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = accessible
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		moz.png \
+		longdesc_src.html \
+		common.js \
 		nsIAccessible_actions.js \
 		nsIAccessible_name.css \
 		nsIAccessible_name.xbl \
+		nsIAccessibleEditableText.js \
 		test_aria_activedescendant.html \
 		test_aria_role_article.html \
 		test_bug368835.xul \
 		test_bug420863.html \
 		test_cssattrs.html \
 		test_groupattrs.xul \
 	$(warning test_table_indexes.html temporarily disabled) \
 		test_nsIAccessible_actions.html \
 		test_nsIAccessible_actions.xul \
 		test_nsIAccessible_name.html \
 		test_nsIAccessible_name.xul \
+		test_nsIAccessibleDocument.html \
+		test_nsIAccessibleEditableText.html \
+		test_nsIAccessibleHyperLink.html \
+		test_nsIAccessibleHyperLink.xul \
+		test_nsIAccessibleHyperText.html \
+		test_nsIAccessibleImage.html \
 		test_nsIAccessibleTable_1.html \
 		test_nsIAccessibleTable_2.html \
 		test_nsIAccessibleTable_3.html \
 		test_nsIAccessibleTable_4.html \
 		test_nsIAccessibleTable_listboxes.xul \
-		test_nsIAccessibleDocument.html \
-		test_nsIAccessibleHyperLink.html \
-		test_nsIAccessibleHyperLink.xul \
-		test_nsIAccessibleHyperText.html \
-		test_nsIAccessibleImage.html \
 		test_nsOuterDocAccessible.html \
 		test_textattrs.html \
 		test_textboxes.html \
 		test_textboxes.xul \
 		testTextboxes.js \
 		test_bug428479.html \
 		test_bug429285.html \
+		test_bug434464.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/common.js
@@ -0,0 +1,118 @@
+////////////////////////////////////////////////////////////////////////////////
+// Interfaces
+
+const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
+
+const nsIAccessibleEvent = Components.interfaces.nsIAccessibleEvent;
+const nsIAccessibleStates = Components.interfaces.nsIAccessibleStates;
+const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
+const nsIAccessibleTypes = Components.interfaces.nsIAccessibleTypes;
+
+const nsIAccessibleRelation = Components.interfaces.nsIAccessibleRelation;
+
+const nsIAccessNode = Components.interfaces.nsIAccessNode;
+const nsIAccessible = Components.interfaces.nsIAccessible;
+
+const nsIAccessibleDocument = Components.interfaces.nsIAccessibleDocument;
+
+const nsIAccessibleText = Components.interfaces.nsIAccessibleText;
+const nsIAccessibleEditableText = Components.interfaces.nsIAccessibleEditableText;
+
+const nsIAccessibleHyperLink = Components.interfaces.nsIAccessibleHyperLink;
+const nsIAccessibleHyperText = Components.interfaces.nsIAccessibleHyperText;
+
+const nsIAccessibleImage = Components.interfaces.nsIAccessibleImage;
+const nsIAccessibleSelectable = Components.interfaces.nsIAccessibleSelectable;
+const nsIAccessibleTable = Components.interfaces.nsIAccessibleTable;
+const nsIAccessibleValue = Components.interfaces.nsIAccessibleValue;
+
+const nsIObserverService = Components.interfaces.nsIObserverService;
+
+const nsIDOMNode = Components.interfaces.nsIDOMNode;
+
+////////////////////////////////////////////////////////////////////////////////
+// General
+
+/**
+ * nsIAccessibleRetrieval, initialized when test is loaded.
+ */
+var gAccRetrieval = null;
+
+/**
+ * Return accessible for the given ID attribute or DOM element.
+ *
+ * @param aElmOrID     [in] the ID attribute or DOM element to get an accessible
+ *                     for
+ * @param aInterfaces  [in, optional] the accessible interface or the array of
+ *                     accessible interfaces to query it/them from obtained
+ *                     accessible
+ * @param aElmObj      [out, optional] object to store DOM element which
+ *                     accessible is created for
+ */
+function getAccessible(aElmOrID, aInterfaces, aElmObj)
+{
+  var elm = null;
+
+  if (aElmOrID instanceof nsIDOMNode) {
+    elm = aElmOrID;
+  } else {
+    var elm = document.getElementById(aElmOrID);
+    if (!elm) {
+      ok(false, "Can't get DOM element for " + aID);
+      return null;
+    }
+  }
+
+  if (aElmObj && (typeof aElmObj == "object"))
+    aElmObj.value = elm;
+
+  var acc = null;
+  try {
+    acc = gAccRetrieval.getAccessibleFor(elm);
+  } catch (e) {
+  }
+  
+  if (!acc) {
+    ok(false, "Can't get accessible for " + aID);
+    return null;
+  }
+  
+  if (!aInterfaces)
+    return acc;
+  
+  if (aInterfaces instanceof Array) {
+    for (var index = 0; index < aInterfaces.length; index++) {
+      try {
+        acc.QueryInterface(aInterfaces[index]);
+      } catch (e) {
+        ok(false, "Can't query " + aInterfaces[index] + " for " + aID);
+        return null;
+      }
+    }
+    return acc;
+  }
+  
+  try {
+    acc.QueryInterface(aInterfaces);
+  } catch (e) {
+    ok(false, "Can't query " + aInterfaces + " for " + aID);
+    return null;
+  }
+  
+  return acc;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Private
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+// General
+
+function initialize()
+{
+  gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+  getService(nsIAccessibleRetrieval);
+}
+
+addLoadEvent(initialize);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/longdesc_src.html
@@ -0,0 +1,8 @@
+<html>
+<head>
+<title>Mozilla logo</title>
+</head>
+<body>
+<p>This file would contain a longer description of the Mozilla logo, if I knew what it looked like.</p>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/nsIAccessibleEditableText.js
@@ -0,0 +1,105 @@
+function nsEditableText(aElmOrID)
+{
+  this.setTextContents = function setTextContents(aStr)
+  {
+    try {
+      this.mAcc.setTextContents(aStr);
+      
+      is(this.getValue(), aStr,
+         "setTextContents: Can't set " + aStr +
+         " to element with ID '" + this.mID + "'");
+    } catch (e) {
+      ok(false,
+         "setTextContents: Can't set " + aStr +
+         "to element with ID '" + this.mID +
+         "', value '" + this.getValue() + "', exception" + e);
+    }
+  }
+  
+  this.insertText = function insertText(aStr, aPos, aResStr)
+  {
+    try {
+      this.mAcc.insertText(aStr, aPos);
+      
+      is(this.getValue(), aResStr,
+         "insertText: Can't insert " + aStr + " at " + aPos +
+         " to element with ID '" + this.mID + "'");
+    } catch (e) {
+      ok(false,
+         "insertText: Can't insert " + aStr + " at " + aPos +
+         " to element with ID '" + this.mID +
+         "', value '" + this.getValue() + "', exception " + e);
+    }
+  }
+  
+  this.copyNPasteText = function copyNPasteText(aStartPos, aEndPos,
+                                                aPos, aResStr)
+  {
+    try {
+      this.mAcc.copyText(aStartPos, aEndPos);
+      this.mAcc.pasteText(aPos);
+      
+      is(this.getValue(), aResStr,
+         "copyText & pasteText: Can't copy text from " + aStartPos +
+         " to " + aEndPos + " and paste to " + aPos +
+         " for element with ID '" + this.mID + "'");
+    } catch (e) {
+      ok(false,
+         "copyText & pasteText: Can't copy text from " + aStartPos +
+         " to " + aEndPos + " and paste to " + aPos +
+         " for element with ID '" + this.mID +
+         "', value '" + this.getValue() + "', exception " + e);
+    }
+  }
+  
+  this.cutNPasteText = function copyNPasteText(aStartPos, aEndPos,
+                                               aPos, aResStr)
+  {
+    try {
+      this.mAcc.cutText(aStartPos, aEndPos);
+      this.mAcc.pasteText(aPos);
+      
+      is(this.getValue(), aResStr,
+         "cutText & pasteText: Can't cut text from " + aStartPos +
+         " to " + aEndPos + " and paste to " + aPos +
+         " for element with ID '" + this.mID + "'");
+    } catch (e) {
+      ok(false,
+         "cutText & pasteText: Can't cut text from " + aStartPos +
+         " to " + aEndPos + " and paste to " + aPos +
+         " for element with ID '" + this.mID +
+         "', value '" + this.getValue() + "', exception " + e);
+    }
+  }
+  
+  this.deleteText = function deleteText(aStartPos, aEndPos, aResStr)
+  {
+    try {
+      this.mAcc.deleteText(aStartPos, aEndPos);
+      
+      is(this.getValue(), aResStr,
+         "deleteText: Can't delete text from " + aStartPos +
+         " to " + aEndPos + " for element with ID '" + this.mID + "'");
+    } catch (e) {
+      ok(false,
+         "deleteText: Can't delete text from " + aStartPos +
+         " to " + aEndPos + " for element with ID '" + this.mID +
+         "', value " + this.getValue() + ", exception " + e);
+    }
+  }
+
+  this.getValue = function getValue()
+  {
+    if (this.mElm instanceof Components.interfaces.nsIDOMNSEditableElement)
+      return this.mElm.value;
+    if (this.mElm instanceof Components.interfaces.nsIDOMHTMLDocument)
+      return this.mElm.body.textContent;
+    return this.mElm.textContent;
+  }
+
+  var elmObj = { value: null };
+  this.mAcc = getAccessible(aElmOrID, nsIAccessibleEditableText, elmObj);
+
+  this.mElm = elmObj.value;
+  this.mID = aElmOrID;
+}
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_bug434464.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=434464
+-->
+<head>
+  <title>Test NSIAccessNode cache invalidation</title>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      var accRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+                       getService(Components.interfaces.nsIAccessibleRetrieval);
+
+      var parentElm = document.getElementById("parent");
+      if (!parentElm) {
+        ok(false, "no parent element for paragraph!");
+        SimpleTest.finish();
+      }
+
+      var elm = document.getElementById("para");
+      if (!elm) {
+        ok(false, "no element for paragraph!");
+        SimpleTest.finish();
+      }
+
+      // It's currently hidden. Ask for its parent's nsIAccessNode.
+      var parentElmAccNode = null;
+      try {
+        parentElmAccNode = accRetrieval.getAccessibleFor(parentElm).
+                     QueryInterface(Components.interfaces.nsIAccessNode);
+      } catch(e) {}
+
+      if (!parentElmAccNode) {
+        ok(false, "No accessNode for parent of hidden paragraph!");
+        SimpleTest.finish();
+      }
+
+      // Get the paragraph's accessNode.
+      var elmAccNode = null;
+      try {
+        elmAccNode = parentElmAccNode.firstChildNode;
+      } catch(e) {}
+
+      if (!elmAccNode) {
+        ok(false, "No accessNode for hidden paragraph!");
+        SimpleTest.finish();
+      }
+
+      // Now make the paragraph visible. This invalidates the just-retrieved
+      // AccessNode. An nsIAccessible should then be retrievable.
+      elm.style.display = "block";
+
+      // Now, get an accessible for it. Use a timeout so the layout engine can
+      // catch up.
+      window.setTimeout(
+        function()
+        {
+          var elmAcc = null;
+          try {
+            elmAcc = accRetrieval.getAccessibleFor(elm);
+          } catch(e) {}
+    
+          ok(elmAcc, "No accessible for paragraph after it became visible!");
+
+          SimpleTest.finish();
+        },
+      200);
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=434464">Mozilla Bug 434464</a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+  <div id="parent"><p style="display: none;" id="para">I'm hidden initially, but then made visible.</p></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_nsIAccessibleEditableText.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=452161
+-->
+<head>
+  <title>nsIAccessibleEditableText chrome tests</title>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/nsIAccessibleEditableText.js"></script>
+
+  <script type="application/javascript">
+    var gParagraphAcc;
+
+    function testEditable(aID)
+    {
+      var et = new nsEditableText(aID);
+
+      //////////////////////////////////////////////////////////////////////////
+      // insertText
+      et.insertText("hello", 0, "hello");
+      et.insertText("ma ", 0, "ma hello");
+      et.insertText("ma", 2, "mama hello");
+      et.insertText(" hello", 10, "mama hello hello");
+
+      // XXX: bug 452584
+
+      //////////////////////////////////////////////////////////////////////////
+      // setTextContents
+//      et.setTextContents("hello", "hello");
+//      et.setTextContents("olleh", "olleh");
+//      et.setTextContents("", "");
+
+      //////////////////////////////////////////////////////////////////////////
+      // deleteText
+//      et.deleteText(0, 5, "hello hello");
+//      et.deleteText(5, 6, "hellohello");
+//      et.deleteText(5, 10, "hello");
+//      et.deleteText(0, 5, "");
+
+      //////////////////////////////////////////////////////////////////////////
+      // copyNPasteText
+//      et.copyNPasteText(0, 0, 0, "");
+//      et.insertText("hello", 0, "hello");
+//      et.copyNPasteText(0, 1, 0, "hhello");
+//      et.copyNPasteText(5, 6, 6, "hhelloo");
+//      et.copyNPasteText(3, 4, 1, "hehelloo");
+
+      //////////////////////////////////////////////////////////////////////////
+//      // cutNPasteText
+//      et.cutNPasteText(0, 1, 1, "ehhelloo");
+//      et.cutNPasteText(1, 2, 0, "hehelloo");
+//      et.cutNPasteText(7, 8, 8, "hehelloo");
+    }
+
+    function doTest()
+    {
+      testEditable("input");
+      // testEditable("div"); XXX: bug 452599
+
+      var frame = document.getElementById("frame");
+      frame.contentDocument.designMode = "on";
+      testEditable(frame.contentDocument);
+      
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="nsIAccessibleEditableText chrome tests"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=452161">Mozilla Bug 452161</a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <input id="input"/>
+
+  <div id="div" contentEditable="true"/>
+
+  <iframe id="frame"/>
+</body>
+</html>
--- a/accessible/tests/mochitest/test_nsIAccessibleImage.html
+++ b/accessible/tests/mochitest/test_nsIAccessibleImage.html
@@ -80,17 +80,18 @@ https://bugzilla.mozilla.org/show_bug.cg
       }
 
       var width = {}, height = {};
       imageAcc.getImageSize(width, height);
       is(width.value, aWidth, "Wrong width for " + aID + "!");
       is(height.value, aHeight, "wrong height for " + aID + "!");
     }
 
-    function testThis(aID, aName, aSRC, aWidth, aHeight)
+    function testThis(aID, aName, aSRC, aWidth, aHeight,
+                      aNumActions, aActionNames)
     {
       var elem = document.getElementById(aID);
       var acc;
       try {
         acc = gAccRetrieval.getAccessibleFor(elem);
       } catch(e) {}
       ok(acc, "No accessible for " + aID + "!");
 
@@ -105,16 +106,26 @@ https://bugzilla.mozilla.org/show_bug.cg
       // bug 429659: Make sure the SRC attribute is set for any image
       var attributes;
       try {
         attributes = acc.attributes;
       } catch(e) {}
       ok(attributes, "no attributes on " + aID + "!");
       is(attributes.getStringProperty("src"), aSRC,
          "no correct src attribute for " + aID + "!");
+
+      if (aNumActions) {
+        is(acc.numActions, aNumActions,
+           "Wrong number of actions for " + aID + "!");
+
+        for (index = 0; index < aActionNames.length; index++) {
+          is(acc.getActionName(index), aActionNames[index],
+             "Wrong action name for " + aID + ", index " + index +"!");
+        }
+      }
     }
 
     function doTest()
     {
       gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
                        getService(Components.interfaces.nsIAccessibleRetrieval);
 
       // Test non-linked image
@@ -142,16 +153,33 @@ https://bugzilla.mozilla.org/show_bug.cg
       testThis("linkedImageEmptyAlt", "", "moz.png", 93, 42);
 
       // Test simple image with empty alt attribute and title
       testThis("nonLinkedImageEmptyAltAndTitle", "MozillaFoundation", "moz.png", 89, 38);
 
       // Test linked image with empty alt attribute and title
       testThis("linkedImageEmptyAltAndTitle", "Link to Mozilla Foundation", "moz.png", 93, 42);
 
+      // Image with long desc
+      var actionNamesArray = new Array("showlongdesc");
+      testThis("longdesc", "Image of Mozilla logo", "moz.png", 89, 38, 1,
+               actionNamesArray);
+
+      // Image with click and long desc
+      actionNamesArray = null;
+      actionNamesArray = new Array("click", "showlongdesc");
+      testThis("clickAndLongdesc", "Another image of Mozilla logo", "moz.png",
+               89, 38, 2, actionNamesArray);
+      
+      // Image with click
+      actionNamesArray = null;
+      actionNamesArray = new Array("click");
+      testThis("click", "A third image of Mozilla logo", "moz.png",
+               89, 38, 1, actionNamesArray);
+      
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addLoadEvent(doTest);
   </script>
 </head>
 <body>
@@ -177,10 +205,19 @@ https://bugzilla.mozilla.org/show_bug.cg
   <img id="nonLinkedImageEmptyAlt" src="moz.png" alt=""/>
   <br>Linked image with empty alt:<br>
   <a href="http://www.mozilla.org"><img id="linkedImageEmptyAlt" src="moz.png" alt=""/></a>
   <br>Simple image with empty alt and title:<br>
   <img id="nonLinkedImageEmptyAltAndTitle" src="moz.png" alt="" title="MozillaFoundation"/>
   <br>Linked image with empty alt and title:<br>
   <a href="http://www.mozilla.org"><img id="linkedImageEmptyAltAndTitle" src="moz.png" alt=""
      title="Link to Mozilla Foundation"/></a>
+  <br>Image with longdesc:<br>
+  <img id="longdesc" src="moz.png" longdesc="longdesc_src.html"
+       alt="Image of Mozilla logo"/>
+  <br>Image with click and longdesc:<br>
+  <img id="clickAndLongdesc" src="moz.png" longdesc="longdesc_src.html"
+       alt="Another image of Mozilla logo" onclick="alert('Clicked!');"/>
+  <br>Image with click:<br>
+  <img id="click" src="moz.png"
+       alt="A third image of Mozilla logo" onclick="alert('Clicked, too!');"/>
 </body>
 </html>
--- a/accessible/tests/mochitest/test_textattrs.html
+++ b/accessible/tests/mochitest/test_textattrs.html
@@ -23,102 +23,122 @@
      *
      * @param aID               the ID of DOM element having text accessible
      * @param aOffset           the offset inside text accessible to fetch
      *                          text attributes
      * @param aAttrs            the map of text attributes (name/value pairs)
      * @param aStartOffset      the start offset where text attributes are
      *                          applied
      * @param aEndOffset        the end offset where text attribute are applied
-     * @param aDefAttrs         the list of default text attributes (name/value
-     *                          pairs)
      */
     function testTextAttrs(aID, aOffset,
-                           aAttrs, aStartOffset, aEndOffset, aDefAttrs)
+                           aAttrs, aStartOffset, aEndOffset)
     {
-      var node = document.getElementById(aID);
-      if (!node) {
-        ok(false, "Can't get the element with ID " + aID);
+      var accessible = getTextAccessible(aID);
+      if (!accessible)
         return;
-      }
-
-      var accessible = null;
-      try {
-        accessible = gAccRetrieval.getAccessibleFor(node);
-        accessible.QueryInterface(nsIAccessibleText);
-      } catch (e) {
-      }
-
-      if (!accessible) {
-        ok(false, "Can't query nsIAccessibleText interface for " + aID);
-        return;
-      }
 
       var startOffset = { value: -1 };
       var endOffset = { value: -1 };
       var attrs = null;
       try {
         attrs = accessible.getTextAttributes(false,
                                              aOffset,
                                              startOffset, endOffset);
       } catch (e) {
       }
 
       if (!attrs) {
         ok(false, "Can't get text attributes for " + aID);
         return;
       }
 
-      var errorMsg = " for " + aID + "at offset " + aOffset;
+      var errorMsg = " for " + aID + " at offset " + aOffset;
       is(startOffset.value, aStartOffset,
          "Wrong start offset" + errorMsg);
       is(endOffset.value, aEndOffset,
           "Wrong end offset" + errorMsg);
 
       compareTextAttrs(errorMsg, attrs, aAttrs);
+   }
+
+   /**
+    * Test default text attributes.
+    *
+    * @param aID               the ID of DOM element having text accessible
+    * @param aDefAttrs         the list of default text attributes (name/value
+    *                          pairs)
+    */
+   function testDefaultTextAttrs(aID, aDefAttrs)
+   {
+     var accessible = getTextAccessible(aID);
+     if (!accessible)
+       return;
 
       var defAttrs = null;
       try{
         defAttrs = accessible.defaultTextAttributes;
       } catch (e) {
       }
 
       if (!defAttrs) {
         ok(false, "Can't get default attributes for " + aID);
         return;
       }
 
+      var errorMsg = ". Getting default attributes for " + aID;
       compareTextAttrs(errorMsg, defAttrs, aDefAttrs);
     }
 
+    function getTextAccessible(aID)
+    {
+      var node = document.getElementById(aID);
+      if (!node) {
+        ok(false, "Can't get the element with ID " + aID);
+        return;
+      }
+
+      var accessible = null;
+      try {
+        accessible = gAccRetrieval.getAccessibleFor(node);
+        accessible.QueryInterface(nsIAccessibleText);
+      } catch (e) {
+      }
+
+      if (!accessible)
+        ok(false, "Can't query nsIAccessibleText interface for " + aID);
+
+      return accessible;
+    }
+
     function compareTextAttrs(aErrorMsg, aAttrs, aExpectedAttrs)
     {
       var enumerate = aAttrs.enumerate();
       while (enumerate.hasMoreElements()) {
         var prop = enumerate.getNext().
           QueryInterface(Components.interfaces.nsIPropertyElement);
 
         if (!(prop.key in aExpectedAttrs))
           ok(false,
-             "Unexpected attribute '" + prop.key + "'" + aErrorMsg);
+             "Unexpected attribute '" + prop.key + "' having '" + prop.value + "'" + aErrorMsg);
         else
           is(prop.value, aExpectedAttrs[prop.key],
-             "Attribute '" + prop.key + "' has wrong value" + aErrorMsg);
+             "Attribute '" + prop.key + " 'has wrong value" + aErrorMsg);
       }
 
       for (var name in aExpectedAttrs) {
         var value = "";
         try {
           value = aAttrs.getStringProperty(name);
         } catch(e) {
         }
 
         if (!value)
           ok(false,
-             "There is no expected attribute '" + name + "'" + aErrorMsg);
+             "There is no expected attribute '" + name + "' " + aErrorMsg);
       }
     }
 
     var gObserverService = null;
     var gA11yEventObserver = null;
 
     function testSpellTextAttrs()
     {
@@ -162,26 +182,27 @@
             "font-size": "11px",
             "background-color": "rgb(255, 255, 255)",
             "font-weight": "400",
             "text-indent": "0px",
             "color": "rgb(0, 0, 0)",
             "font-family": "Lucida Grande",
             "text-position": "baseline"
           };
+          testDefaultTextAttrs(ID, defAttrs);
 
-          var attrs = { "background-color": "transparent" };
+          var attrs = { };
           var misspelledAttrs = {
-            "background-color": "transparent",
             "invalid": "spelling"
           };
 
-          testTextAttrs(ID, 0, attrs, 0, 11, defAttrs);
-          testTextAttrs(ID, 11, misspelledAttrs, 11, 17, defAttrs);
-          testTextAttrs(ID, 18, misspelledAttrs, 18, 22, defAttrs);
+          testTextAttrs(ID, 0, attrs, 0, 11);
+          testTextAttrs(ID, 11, misspelledAttrs, 11, 17);
+          testTextAttrs(ID, 17, attrs, 17, 18);
+          testTextAttrs(ID, 18, misspelledAttrs, 18, 22);
 
           is(gA11yEventObserver.mTextAttrChangedEventCounter, 2,
              "Wrong count of 'text attribute changed' events for " + ID);
 
           // Remove a11y events listener
           gObserverService.removeObserver(gA11yEventObserver,
                                           "accessible-event");
 
@@ -196,221 +217,238 @@
 
       //////////////////////////////////////////////////////////////////////////
       // area1
       var ID = "area1";
       var defAttrs = {
         "font-style": "normal",
         "text-align": "start",
         "font-size": "16px",
-        "background-color": "transparent",
+        "background-color": "rgb(255, 255, 255)",
         "font-weight": "400",
         "text-indent": "0px",
         "color": "rgb(0, 0, 0)",
         "font-family": "serif",
         "text-position": "baseline"
       };
 
+      testDefaultTextAttrs(ID, defAttrs);
+
       var attrs = {};
-      testTextAttrs(ID, 0, attrs, 0, 7, defAttrs);
+      testTextAttrs(ID, 0, attrs, 0, 7);
 
       attrs = {"font-weight": "401"};
-      testTextAttrs(ID, 7, attrs, 7, 11, defAttrs);
+      testTextAttrs(ID, 7, attrs, 7, 11);
 
       attrs = {};
-      testTextAttrs(ID, 12, attrs, 11, 18, defAttrs);
+      testTextAttrs(ID, 12, attrs, 11, 18);
 
       //////////////////////////////////////////////////////////////////////////
       // area2
       ID = "area2";
       defAttrs = {
         "font-style": "normal",
         "text-align": "start",
         "font-size": "16px",
-        "background-color": "transparent",
+        "background-color": "rgb(255, 255, 255)",
         "font-weight": "400",
         "text-indent": "0px",
         "color": "rgb(0, 0, 0)",
         "font-family": "serif",
         "text-position": "baseline"
       };
 
+      testDefaultTextAttrs(ID, defAttrs);
+
       attrs = {};
-      testTextAttrs(ID, 0, attrs, 0, 7, defAttrs);
+      testTextAttrs(ID, 0, attrs, 0, 7);
 
       attrs = {"font-weight": "401"};
-      testTextAttrs(ID, 7, attrs, 7, 12, defAttrs);
+      testTextAttrs(ID, 7, attrs, 7, 12);
 
       attrs = {"font-style": "italic", "font-weight": "401"};
-      testTextAttrs(ID, 13, attrs, 12, 19, defAttrs);
+      testTextAttrs(ID, 13, attrs, 12, 19);
 
       attrs = {"font-weight": "401"};
-      testTextAttrs(ID, 20, attrs, 19, 23, defAttrs);
+      testTextAttrs(ID, 20, attrs, 19, 23);
 
       attrs = {};
-      testTextAttrs(ID, 24, attrs, 23, 30, defAttrs);
+      testTextAttrs(ID, 24, attrs, 23, 30);
 
       //////////////////////////////////////////////////////////////////////////
       // area3
       ID = "area3";
       defAttrs = {
         "font-style": "normal",
         "text-align": "start",
         "font-size": "16px",
-        "background-color": "transparent",
+        "background-color": "rgb(0, 0, 255)",
         "font-weight": "400",
         "text-indent": "0px",
         "color": "rgb(0, 0, 0)",
         "font-family": "serif",
         "text-position": "baseline"
       };
 
+      testDefaultTextAttrs(ID, defAttrs);
+
       attrs = {"color": "rgb(0, 128, 0)"};
-      testTextAttrs(ID, 0, attrs, 0, 6, defAttrs);
+      testTextAttrs(ID, 0, attrs, 0, 6);
 
       attrs = {"color": "rgb(255, 0, 0)"};
-      testTextAttrs(ID, 6, attrs, 6, 26, defAttrs);
+      testTextAttrs(ID, 6, attrs, 6, 26);
 
       attrs = {"color": "rgb(0, 128, 0)"};
-      testTextAttrs(ID, 26, attrs, 26, 50, defAttrs);
+      testTextAttrs(ID, 26, attrs, 26, 27);
+
+      attrs = {"color": "rgb(0, 128, 0)", "background-color": "rgb(255, 255, 0)"};
+      testTextAttrs(ID, 27, attrs, 27, 50);
 
       //////////////////////////////////////////////////////////////////////////
       // area4
       ID = "area4";
       defAttrs = {
         "font-style": "normal",
         "text-align": "start",
         "font-size": "16px",
-        "background-color": "transparent",
+        "background-color": "rgb(255, 255, 255)",
         "font-weight": "400",
         "text-indent": "0px",
         "color": "rgb(0, 0, 0)",
         "font-family": "serif",
         "text-position": "baseline"
       };
 
+      testDefaultTextAttrs(ID, defAttrs);
+
       attrs = {"color": "rgb(0, 128, 0)"};
-      testTextAttrs(ID, 0, attrs, 0, 16, defAttrs);
+      testTextAttrs(ID, 0, attrs, 0, 16);
 
       attrs = {"color": "rgb(255, 0, 0)"};
-      testTextAttrs(ID, 16, attrs, 16, 33, defAttrs);
+      testTextAttrs(ID, 16, attrs, 16, 33);
 
       attrs = {"color": "rgb(0, 128, 0)"};
-      testTextAttrs(ID, 34, attrs, 33, 46, defAttrs);
+      testTextAttrs(ID, 34, attrs, 33, 46);
 
       //////////////////////////////////////////////////////////////////////////
       // area5
       ID = "area5";
       defAttrs = {
         "font-style": "normal",
         "text-align": "start",
         "font-size": "16px",
-        "background-color": "transparent",
+        "background-color": "rgb(255, 255, 255)",
         "font-weight": "400",
         "text-indent": "0px",
         "color": "rgb(0, 0, 0)",
         "font-family": "serif",
         "text-position": "baseline"
       };
 
+      testDefaultTextAttrs(ID, defAttrs);
+
       attrs = {"color": "rgb(0, 128, 0)"};
-      testTextAttrs(ID, 0, attrs, 0, 5, defAttrs);
+      testTextAttrs(ID, 0, attrs, 0, 5);
 
       attrs = {};
-      testTextAttrs(ID, 7, attrs, 5, 8, defAttrs);
+      testTextAttrs(ID, 7, attrs, 5, 8);
 
       attrs = {"color": "rgb(255, 0, 0)"};
-      testTextAttrs(ID, 9, attrs, 8, 11, defAttrs);
+      testTextAttrs(ID, 9, attrs, 8, 11);
 
       attrs = {};
-      testTextAttrs(ID, 11, attrs, 11, 18, defAttrs);
+      testTextAttrs(ID, 11, attrs, 11, 18);
 
       //////////////////////////////////////////////////////////////////////////
       // area6 (CSS vertical-align property, bug 445938)
       ID = "area6";
       defAttrs = {
         "font-style": "normal",
         "text-align": "start",
         "font-size": "16px",
-        "background-color": "transparent",
+        "background-color": "rgb(255, 255, 255)",
         "font-weight": "400",
         "text-indent": "0px",
         "color": "rgb(0, 0, 0)",
         "font-family": "serif",
         "text-position": "baseline"
       };
 
+      testDefaultTextAttrs(ID, defAttrs);
+
       attrs = {};
-      testTextAttrs(ID, 0, attrs, 0, 5, defAttrs);
+      testTextAttrs(ID, 0, attrs, 0, 5);
 
       attrs = {"text-position": "super", "font-size": "13px" };
-      testTextAttrs(ID, 5, attrs, 5, 13, defAttrs);
+      testTextAttrs(ID, 5, attrs, 5, 13);
 
       attrs = {};
-      testTextAttrs(ID, 13, attrs, 13, 27, defAttrs);
+      testTextAttrs(ID, 13, attrs, 13, 27);
 
       attrs = {"text-position": "super" };
-      testTextAttrs(ID, 27, attrs, 27, 35, defAttrs);
+      testTextAttrs(ID, 27, attrs, 27, 35);
 
       attrs = {};
-      testTextAttrs(ID, 35, attrs, 35, 39, defAttrs);
+      testTextAttrs(ID, 35, attrs, 35, 39);
 
       attrs = {"text-position": "sub", "font-size": "13px" };
-      testTextAttrs(ID, 39, attrs, 39, 50, defAttrs);
+      testTextAttrs(ID, 39, attrs, 39, 50);
 
       attrs = {};
-      testTextAttrs(ID, 50, attrs, 50, 55, defAttrs);
+      testTextAttrs(ID, 50, attrs, 50, 55);
 
       attrs = {"text-position": "sub" };
-      testTextAttrs(ID, 55, attrs, 55, 64, defAttrs);
+      testTextAttrs(ID, 55, attrs, 55, 64);
 
       //////////////////////////////////////////////////////////////////////////
       // area7
       ID = "area7";
       defAttrs = {
         "font-style": "normal",
         "text-align": "start",
         "font-size": "16px",
-        "background-color": "transparent",
+        "background-color": "rgb(255, 255, 255)",
         "font-weight": "400",
         "text-indent": "0px",
         "color": "rgb(0, 0, 0)",
         "font-family": "serif",
         "text-position": "baseline"
       };
 
+      testDefaultTextAttrs(ID, defAttrs);
+
       attrs = {"language": "ru"};
-      testTextAttrs(ID, 0, attrs, 0, 12, defAttrs);
+      testTextAttrs(ID, 0, attrs, 0, 12);
 
       attrs = {"language": "en"};
-      testTextAttrs(ID, 12, attrs, 12, 13, defAttrs);
+      testTextAttrs(ID, 12, attrs, 12, 13);
 
       attrs = {"language" :"en", "background-color": "rgb(0, 0, 255)"};
-      testTextAttrs(ID, 13, attrs, 13, 26, defAttrs);
+      testTextAttrs(ID, 13, attrs, 13, 26);
 
       attrs = {"language": "en" };
-      testTextAttrs(ID, 26, attrs, 26, 27, defAttrs);
+      testTextAttrs(ID, 26, attrs, 26, 27);
 
       attrs = {"language": "de"};
-      testTextAttrs(ID, 27, attrs, 27, 42, defAttrs);
+      testTextAttrs(ID, 27, attrs, 27, 42);
 
       attrs = {"language": "en"};
-      testTextAttrs(ID, 42, attrs, 42, 43, defAttrs);
+      testTextAttrs(ID, 42, attrs, 42, 43);
 
       attrs = {};
-      testTextAttrs(ID, 43, attrs, 43, 50, defAttrs);
+      testTextAttrs(ID, 43, attrs, 43, 50);
 
       attrs = {"color": "rgb(255, 0, 255)"};
-      testTextAttrs(ID, 50, attrs, 50, 57, defAttrs);
+      testTextAttrs(ID, 50, attrs, 50, 57);
 
       attrs = {"font-weight": "401", "color": "rgb(255, 0, 255)" };
-      testTextAttrs(ID, 57, attrs, 57, 61, defAttrs);
+      testTextAttrs(ID, 57, attrs, 57, 61);
 
       attrs = {"color": "rgb(255, 0, 255)"};
-      testTextAttrs(ID, 61, attrs, 61, 68, defAttrs);
+      testTextAttrs(ID, 61, attrs, 61, 68);
 
       //////////////////////////////////////////////////////////////////////////
       // test spelling text attributes
       testSpellTextAttrs(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addLoadEvent(doTest);
@@ -425,21 +463,21 @@
   </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <p id="area1">Normal <b>Bold</b> Normal</p>
   <p id="area2">Normal <b>Bold <i>Italic </i>Bold</b> Normal</p>
-  <p id="area3">
-    <span style="color: green">
+  <p id="area3" style="background-color: blue;">
+    <span style="color: green; background-color: rgb(0, 0, 255)">
       Green
       <span style="color: red">but children are red</span>
-    </span><span style="color: green">
+    </span><span style="color: green; background-color: rgb(255, 255, 0);">
       Another green section.
     </span>
   </p>
   <p id="area4">
     <span style="color: green">
       Green
     </span><span style="color: green">
       Green too
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -8,12 +8,15 @@ builtin(include, build/autoconf/gtk.m4)d
 builtin(include, build/autoconf/libIDL.m4)dnl
 builtin(include, build/autoconf/libIDL-2.m4)dnl
 builtin(include, build/autoconf/nspr.m4)dnl
 builtin(include, build/autoconf/nss.m4)dnl
 builtin(include, build/autoconf/libart.m4)dnl
 builtin(include, build/autoconf/pkg.m4)dnl
 builtin(include, build/autoconf/freetype2.m4)dnl
 builtin(include, build/autoconf/codeset.m4)dnl
-dnl
-define(MOZ_TOPSRCDIR,.)dnl MOZ_TOPSRCDIR is used in altoptions.m4
 builtin(include, build/autoconf/altoptions.m4)dnl
 
+# Read the user's .mozconfig script.  We can't do this in
+# configure.in: autoconf puts the argument parsing code above anything
+# expanded from configure.in, and we need to get the configure options
+# from .mozconfig in place before that argument parsing code.
+MOZ_READ_MOZCONFIG(.)
--- a/browser/app/module.ver
+++ b/browser/app/module.ver
@@ -1,8 +1,8 @@
 WIN32_MODULE_COMPANYNAME=Mozilla Corporation
 WIN32_MODULE_COPYRIGHT=©Firefox and Mozilla Developers, according to the MPL 1.1/GPL 2.0/LGPL 2.1 licenses, as applicable.
 WIN32_MODULE_PRODUCTVERSION=3,1,0,0
-WIN32_MODULE_PRODUCTVERSION_STRING=3.1a2
+WIN32_MODULE_PRODUCTVERSION_STRING=3.1b1pre
 WIN32_MODULE_TRADEMARKS=Firefox is a Trademark of The Mozilla Foundation.
 WIN32_MODULE_DESCRIPTION=Firefox
 WIN32_MODULE_PRODUCTNAME=Firefox
 WIN32_MODULE_NAME=Firefox
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -59,21 +59,19 @@
 #endif
 
 static void Output(const char *fmt, ... )
 {
   va_list ap;
   va_start(ap, fmt);
 
 #if defined(XP_WIN) && !MOZ_WINCONSOLE
-  char msg[2048];
-
-  _vsnprintf(msg, sizeof(msg), fmt, ap);
-
-  MessageBox(NULL, msg, "XULRunner", MB_OK | MB_ICONERROR);
+  PRUnichar msg[2048];
+  _vsnwprintf(msg, sizeof(msg)/sizeof(msg[0]), NS_ConvertUTF8toUTF16(fmt).get(), ap);
+  MessageBoxW(NULL, msg, L"XULRunner", MB_OK | MB_ICONERROR);
 #else
   vfprintf(stderr, fmt, ap);
 #endif
 
   va_end(ap);
 }
 
 /**
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -211,16 +211,17 @@ pref("browser.urlbar.doubleClickSelectsA
 #else
 pref("browser.urlbar.doubleClickSelectsAll", false);
 #endif
 pref("browser.urlbar.autoFill", false);
 pref("browser.urlbar.matchOnlyTyped", false);
 // 0: Match anywhere (e.g., middle of words)
 // 1: Match on word boundaries and then try matching anywhere
 // 2: Match only on word boundaries (e.g., after / or .)
+// 3: Match at the beginning of the url or title
 pref("browser.urlbar.matchBehavior", 1);
 pref("browser.urlbar.filter.javascript", true);
 
 // the maximum number of results to show in autocomplete when doing richResults
 pref("browser.urlbar.maxRichResults", 12);
 // Size of "chunks" affects the number of places to process between each search
 // timeout (ms). Too big and the UI will be unresponsive; too small and we'll
 // be waiting on the timeout too often without many results.
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1077,17 +1077,19 @@ function delayedStartup()
 
   // Attach a listener to watch for "command" events bubbling up from error
   // pages.  This lets us fix bugs like 401575 which require error page UI to
   // do privileged things, without letting error pages have any privilege
   // themselves.
   gBrowser.addEventListener("command", BrowserOnCommand, false);
 
   tabPreviews.init();
-  if (gPrefService.getBoolPref("browser.ctrlTab.mostRecentlyUsed"))
+  if ((!gPrefService.prefHasUserValue("browser.ctrlTab.disallowForScreenReaders") ||
+       !gPrefService.getBoolPref("browser.ctrlTab.disallowForScreenReaders")) &&
+       gPrefService.getBoolPref("browser.ctrlTab.mostRecentlyUsed"))
     ctrlTab.init();
 
   // Delayed initialization of the livemarks update timer.
   // Livemark updates don't need to start until after bookmark UI 
   // such as the toolbar has initialized. Starting 5 seconds after
   // delayedStartup in order to stagger this before the download
   // manager starts (see below).
   setTimeout(function() PlacesUtils.livemarks.start(), 5000);
@@ -5403,24 +5405,18 @@ var OfflineApps = {
              getService(Ci.nsIPermissionManager);
     pm.add(aURI, "offline-app",
            Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN);
   },
 
   // XXX: duplicated in preferences/advanced.js
   _getOfflineAppUsage: function (host)
   {
-    var cacheService = Components.classes["@mozilla.org/network/cache-service;1"].
-                       getService(Components.interfaces.nsICacheService);
-    var cacheSession = cacheService.createSession("HTTP-offline",
-                                                  Components.interfaces.nsICache.STORE_OFFLINE,
-                                                  true).
-                       QueryInterface(Components.interfaces.nsIOfflineCacheSession);
-    var usage = cacheSession.getDomainUsage(host);
-
+    // XXX Bug 442810: include offline cache usage.
+    var usage = 0;
     var storageManager = Components.classes["@mozilla.org/dom/storagemanager;1"].
                          getService(Components.interfaces.nsIDOMStorageManager);
     usage += storageManager.getUsage(host);
 
     return usage;
   },
 
   _checkUsage: function(aURI) {
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -126,17 +126,26 @@ nsContextMenu.prototype = {
     this.initMiscItems();
     this.initSpellingItems();
     this.initSaveItems();
     this.initClipboardItems();
     this.initMetadataItems();
   },
 
   initOpenItems: function CM_initOpenItems() {
-    var shouldShow = this.onSaveableLink ||
+    var isMailtoInternal = false;
+    if (this.onMailtoLink) {
+      var mailtoHandler = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
+                          getService(Ci.nsIExternalProtocolService).
+                          getProtocolHandlerInfo("mailto");
+      isMailtoInternal = (!mailtoHandler.alwaysAskBeforeHandling &&
+                          mailtoHandler.preferredAction == Ci.nsIHandlerInfo.useHelperApp &&
+                          (mailtoHandler.preferredApplicationHandler instanceof Ci.nsIWebHandlerApp));
+    }
+    var shouldShow = this.onSaveableLink || isMailtoInternal ||
                      (this.inDirList && this.onLink);
     this.showItem("context-openlink", shouldShow);
     this.showItem("context-openlinkintab", shouldShow);
     this.showItem("context-sep-open", shouldShow);
   },
 
   initNavigationItems: function CM_initNavigationItems() {
     var shouldShow = !(this.isContentSelected || this.onLink || this.onImage ||
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -183,20 +183,16 @@ gImageView.getCellProperties = function(
 
 var gImageHash = { };
 
 // localized strings (will be filled in when the document is loaded)
 // this isn't all of them, these are just the ones that would otherwise have been loaded inside a loop
 var gStrings = { };
 var gBundle;
 
-const DRAGSERVICE_CONTRACTID    = "@mozilla.org/widget/dragservice;1";
-const TRANSFERABLE_CONTRACTID   = "@mozilla.org/widget/transferable;1";
-const ARRAY_CONTRACTID          = "@mozilla.org/supports-array;1";
-const STRING_CONTRACTID         = "@mozilla.org/supports-string;1";
 const PERMISSION_CONTRACTID     = "@mozilla.org/permissionmanager;1";
 const PREFERENCES_CONTRACTID    = "@mozilla.org/preferences-service;1";
 const ATOM_CONTRACTID           = "@mozilla.org/atom-service;1";
 
 // a number of services I'll need later
 // the cache services
 const nsICacheService = Components.interfaces.nsICacheService;
 const ACCESS_READ     = Components.interfaces.nsICache.ACCESS_READ;
@@ -658,42 +654,26 @@ function onBeginLinkDrag(event,urlField,
   var tree = event.target;
   if (!("treeBoxObject" in tree))
     tree = tree.parentNode;
 
   var row = tree.treeBoxObject.getRowAt(event.clientX, event.clientY);
   if (row == -1)
     return;
 
-  // Getting drag-system needed services
-  var dragService = Components.classes[DRAGSERVICE_CONTRACTID].getService()
-                              .QueryInterface(Components.interfaces.nsIDragService);
-  var transArray = Components.classes[ARRAY_CONTRACTID]
-                             .createInstance(Components.interfaces.nsISupportsArray);
-  if (!transArray)
-    return;
-
-  var trans = Components.classes[TRANSFERABLE_CONTRACTID]
-                        .createInstance(Components.interfaces.nsITransferable);
-  if (!trans)
-    return;
-
   // Adding URL flavor
-  trans.addDataFlavor("text/x-moz-url");
   var col = tree.columns[urlField];
   var url = tree.view.getCellText(row, col);
   col = tree.columns[descField];
   var desc = tree.view.getCellText(row, col);
-  var stringURL = Components.classes[STRING_CONTRACTID]
-                            .createInstance(Components.interfaces.nsISupportsString);
-  stringURL.data = url + "\n" + desc;
-  trans.setTransferData("text/x-moz-url", stringURL, stringURL.data.length * 2 );
-  transArray.AppendElement(trans.QueryInterface(Components.interfaces.nsISupports));
 
-  dragService.invokeDragSession(event.target, transArray, null, dragService.DRAGDROP_ACTION_NONE);
+  var dt = event.dataTransfer;
+  dt.setData("text/x-moz-url", url + "\n" + desc);
+  dt.setData("text/url-list", url);
+  dt.setData("text/plain", url);
 }
 
 //******** Image Stuff
 function getSelectedImage(tree)
 {
   if (!gImageView.rowCount)
     return null;
 
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1538,17 +1538,17 @@
             if (currentIndex > index)
               newIndex = currentIndex-1;
             else if (currentIndex < index)
               newIndex = currentIndex;
             else {
               if ("owner" in aTab && aTab.owner &&
                   this.mPrefs.getBoolPref("browser.tabs.selectOwnerOnClose")) {
                 for (var i = 0; i < length; ++i) {
-                  tab = this.mTabContainer.childNodes[i];
+                  var tab = this.mTabContainer.childNodes[i];
                   if (tab == aTab.owner) {
                     newIndex = i;
                     break;
                   }
                 }
               }
               if (newIndex == -1)
                 newIndex = (index == length) ? index - 1 : index;
--- a/browser/components/distribution.js
+++ b/browser/components/distribution.js
@@ -71,16 +71,24 @@ DistributionCustomizer.prototype = {
   __annoSvc: null,
   get _annoSvc() {
     if (!this.__annoSvc)
       this.__annoSvc = Cc["@mozilla.org/browser/annotation-service;1"].
                    getService(Ci.nsIAnnotationService);
     return this.__annoSvc;
   },
 
+  __livemarkSvc: null,
+  get _livemarkSvc() {
+    if (!this.__livemarkSvc)
+      this.__livemarkSvc = Cc["@mozilla.org/browser/livemark-service;2"].
+                   getService(Ci.nsILivemarkService);
+    return this.__livemarkSvc;
+  },
+
   __dirSvc: null,
   get _dirSvc() {
     if (!this.__dirSvc)
       this.__dirSvc = Cc["@mozilla.org/file/directory_service;1"].
         getService(Ci.nsIProperties);
     return this.__dirSvc;
   },
 
@@ -174,16 +182,28 @@ DistributionCustomizer.prototype = {
         break;
 
       case "separator":
         if (iid < defaultItemId)
           index = prependIndex++;
         this._bmSvc.insertSeparator(parentId, index);
         break;
 
+      case "livemark":
+        if (iid < defaultItemId)
+          index = prependIndex++;
+
+        newId = this._livemarkSvc.
+          createLivemark(parentId,
+                         items[iid]["title"],
+                         this._makeURI(items[iid]["siteLink"]),
+                         this._makeURI(items[iid]["feedLink"]),
+                         index);
+        break;
+
       case "bookmark":
       default:
         if (iid < defaultItemId)
           index = prependIndex++;
 
         newId = this._bmSvc.insertBookmark(parentId,
                                            this._makeURI(items[iid]["link"]),
                                            index, items[iid]["title"]);
@@ -213,18 +233,26 @@ DistributionCustomizer.prototype = {
     // (we also check here to be consistent with applyPrefDefaults below)
     if (!sections["Global"])
       return;
     let globalPrefs = enumToObject(this._ini.getKeys("Global"));
     if (!(globalPrefs["id"] && globalPrefs["version"] && globalPrefs["about"]))
       return;
 
     let bmProcessed = false;
-    let bmProcessedPref = "distribution." +
-      this._ini.getString("Global", "id") + ".bookmarksProcessed";
+    let bmProcessedPref;
+
+    try {
+        bmProcessedPref = this._ini.getString("Global",
+                                              "bookmarks.initialized.pref");
+    } catch (e) {
+      bmProcessedPref = "distribution." +
+        this._ini.getString("Global", "id") + ".bookmarksProcessed";
+    }
+
     try {
       bmProcessed = this._prefs.getBoolPref(bmProcessedPref);
     } catch (e) {}
 
     if (!bmProcessed) {
       if (sections["BookmarksMenu"])
         this._parseBookmarksSection(this._bmSvc.bookmarksMenuFolder,
                                     "BookmarksMenu");
--- a/browser/components/migration/src/nsIEProfileMigrator.cpp
+++ b/browser/components/migration/src/nsIEProfileMigrator.cpp
@@ -862,17 +862,17 @@ static GUID IEPStoreSiteAuthGUID = { 0x5
 
 nsresult
 nsIEProfileMigrator::CopyPasswords(PRBool aReplace)
 {
   HRESULT hr;
   nsresult rv;
   nsVoidArray signonsFound;
 
-  HMODULE pstoreDLL = ::LoadLibrary("pstorec.dll");
+  HMODULE pstoreDLL = ::LoadLibraryW(L"pstorec.dll");
   if (!pstoreDLL) {
     // XXXben TODO
     // Need to figure out what to do here on Windows 98 etc... it may be that the key is universal read
     // and we can just blunder into the registry and use CryptUnprotect to get the data out. 
     return NS_ERROR_FAILURE;
   }
 
   PStoreCreateInstancePtr PStoreCreateInstance = (PStoreCreateInstancePtr)::GetProcAddress(pstoreDLL, "PStoreCreateInstance");
@@ -1186,17 +1186,17 @@ nsIEProfileMigrator::GetUserNameAndPass(
 //
 // "Quite Easily Done". ;-)
 // 
 nsresult
 nsIEProfileMigrator::CopyFormData(PRBool aReplace)
 {
   HRESULT hr;
 
-  HMODULE pstoreDLL = ::LoadLibrary("pstorec.dll");
+  HMODULE pstoreDLL = ::LoadLibraryW(L"pstorec.dll");
   if (!pstoreDLL) {
     // XXXben TODO
     // Need to figure out what to do here on Windows 98 etc... it may be that the key is universal read
     // and we can just blunder into the registry and use CryptUnprotect to get the data out. 
     return NS_ERROR_FAILURE;
   }
 
   PStoreCreateInstancePtr PStoreCreateInstance = (PStoreCreateInstancePtr)::GetProcAddress(pstoreDLL, "PStoreCreateInstance");
@@ -1419,30 +1419,29 @@ nsIEProfileMigrator::CopySmartKeywords(P
   return NS_OK;
 }
 
 void 
 nsIEProfileMigrator::ResolveShortcut(const nsString &aFileName, char** aOutURL) 
 {
   HRESULT result;
 
-  IUniformResourceLocator* urlLink = nsnull;
+  IUniformResourceLocatorW* urlLink = nsnull;
   result = ::CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
-                              IID_IUniformResourceLocator, (void**)&urlLink);
+                              IID_IUniformResourceLocatorW, (void**)&urlLink);
   if (SUCCEEDED(result) && urlLink) {
     IPersistFile* urlFile = nsnull;
     result = urlLink->QueryInterface(IID_IPersistFile, (void**)&urlFile);
     if (SUCCEEDED(result) && urlFile) {
       result = urlFile->Load(aFileName.get(), STGM_READ);
       if (SUCCEEDED(result) ) {
-        LPSTR lpTemp = nsnull;
+        LPWSTR lpTemp = nsnull;
         result = urlLink->GetURL(&lpTemp);
         if (SUCCEEDED(result) && lpTemp) {
-          *aOutURL = PL_strdup(lpTemp);
-
+          *aOutURL = (char*)ToNewUTF8String(nsDependentString(lpTemp));
           // free the string that GetURL alloc'd
           ::CoTaskMemFree(lpTemp);
         }
       }
       urlFile->Release();
     }
     urlLink->Release();
   }
--- a/browser/components/preferences/advanced.js
+++ b/browser/components/preferences/advanced.js
@@ -211,23 +211,18 @@ var gAdvancedPane = {
     document.documentElement.openWindow("Browser:Permissions",
                                         "chrome://browser/content/preferences/permissions.xul",
                                         "", params);
   },
 
   // XXX: duplicated in browser.js
   _getOfflineAppUsage: function (host)
   {
-    var cacheService = Components.classes["@mozilla.org/network/cache-service;1"].
-                       getService(Components.interfaces.nsICacheService);
-    var cacheSession = cacheService.createSession("HTTP-offline",
-                                                  Components.interfaces.nsICache.STORE_OFFLINE,
-                                                  true).
-                       QueryInterface(Components.interfaces.nsIOfflineCacheSession);
-    var usage = cacheSession.getDomainUsage(host);
+    // XXX Bug 442710: include offline cache usage.
+    var usage = 0;
 
     var storageManager = Components.classes["@mozilla.org/dom/storagemanager;1"].
                          getService(Components.interfaces.nsIDOMStorageManager);
     usage += storageManager.getUsage(host);
 
     return usage;
   },
 
--- a/browser/components/sessionstore/test/Makefile.in
+++ b/browser/components/sessionstore/test/Makefile.in
@@ -37,13 +37,13 @@
 DEPTH		= ../../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 
-DIRS +=	chrome \
+DIRS +=	browser \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/browser/components/sessionstore/test/browser/Makefile.in
+++ b/browser/components/sessionstore/test/browser/Makefile.in
@@ -40,13 +40,15 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = browser/components/sessionstore/test/browser 
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = \
+	browser_350525.js \
+	browser_393716.js \
 	browser_448741.js \
 	$(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser/browser_350525.js
@@ -0,0 +1,100 @@
+function test() {
+  /** Test for Bug 350525 **/
+  
+  function test(aLambda) {
+    try {
+      return aLambda() || true;
+    }
+    catch (ex) { }
+    return false;
+  }
+  
+  // test setup
+  let tabbrowser = getBrowser();
+  waitForExplicitFinish();
+  
+  // component
+  let ssComponent = test(function() Cc["@mozilla.org/browser/sessionstore;1"]);
+  ok(ssComponent, "reference the sessionstore component");
+  
+  // service
+  let ss = test(function() ssComponent.getService(Ci.nsISessionStore));
+  ok(ss, "reference the sessionstore service");
+  
+  ////////////////////////////
+  // setWindowValue, et al. //
+  ////////////////////////////
+  let key = "Unique name: " + Date.now();
+  let value = "Unique value: " + Math.random();
+  
+  // test adding
+  ok(test(function() ss.setWindowValue(window, key, value)), "set a window value");
+  
+  // test retrieving
+  is(ss.getWindowValue(window, key), value, "stored window value matches original");
+  
+  // test deleting 
+  ok(test(function() ss.deleteWindowValue(window, key)), "delete the window value");
+  
+  // value should not exist post-delete
+  is(ss.getWindowValue(window, key), "", "window value was deleted");
+  
+  /////////////////////////
+  // setTabValue, et al. //
+  /////////////////////////
+  key = "Unique name: " + Math.random();
+  value = "Unique value: " + Date.now();
+  let tab = tabbrowser.addTab();
+  
+  // test adding
+  ok(test(function() ss.setTabValue(tab, key, value)), "store a tab value");
+  
+  // test retrieving
+  is(ss.getTabValue(tab, key), value, "stored tab value match original");
+  
+  // test deleting 
+  ok(test(function() ss.deleteTabValue(tab, key)), "delete the tab value");
+  // value should not exist post-delete
+  is(ss.getTabValue(tab, key), "", "tab value was deleted");
+  
+  // clean up
+  tabbrowser.removeTab(tab);
+  
+  /////////////////////////////////////
+  // getClosedTabCount, undoCloseTab //
+  /////////////////////////////////////
+  
+  // get closed tab count
+  let count = ss.getClosedTabCount(window);
+  let max_tabs_undo = gPrefService.getIntPref("browser.sessionstore.max_tabs_undo");
+  ok(0 <= count && count <= max_tabs_undo,
+     "getClosedTabCount returns zero or at most max_tabs_undo");
+  
+  // create a new tab
+  let testURL = "about:";
+  tab = tabbrowser.addTab(testURL);
+  tab.linkedBrowser.addEventListener("load", function(aEvent) {
+    // make sure that the next closed tab will increase getClosedTabCount
+    gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", max_tabs_undo + 1);
+    
+    // remove tab
+    tabbrowser.removeTab(tab);
+    
+    // getClosedTabCount
+    var newcount = ss.getClosedTabCount(window);
+    ok(newcount > count, "after closing a tab, getClosedTabCount has been incremented");
+    
+    // undoCloseTab
+    ok(test(function() ss.undoCloseTab(window, 0)), "undoCloseTab doesn't throw")
+    tab = tabbrowser.selectedTab;
+    
+    tab.linkedBrowser.addEventListener("load", function(aEvent) {
+      is(this.currentURI.spec, testURL, "correct tab was reopened");
+      
+      // clean up
+      gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", max_tabs_undo);
+      tabbrowser.removeTab(tab);
+      finish();
+    }, true);
+  }, true);
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser/browser_393716.js
@@ -0,0 +1,78 @@
+function test() {
+  /** Test for Bug 393716 **/
+  
+  // set up the basics (SessionStore service, tabbrowser)
+  try {
+    var ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
+  }
+  catch (ex) { }
+  ok(ss, "SessionStore service is available");
+  let tabbrowser = getBrowser();
+  waitForExplicitFinish();
+  
+  /////////////////
+  // getTabState //
+  /////////////////
+  let key = "Unique key: " + Date.now();
+  let value = "Unique value: " + Math.random();
+  let testURL = "about:config";
+  
+  // create a new tab
+  let tab = tabbrowser.addTab(testURL);
+  ss.setTabValue(tab, key, value);
+  tab.linkedBrowser.addEventListener("load", function(aEvent) {
+    // get the tab's state
+    let state = ss.getTabState(tab);
+    ok(state, "get the tab's state");
+    
+    // verify the tab state's integrity
+    state = eval("(" + state + ")");
+    ok(state instanceof Object && state.entries instanceof Array && state.entries.length > 0,
+       "state object seems valid");
+    ok(state.entries.length == 1 && state.entries[0].url == testURL,
+       "Got the expected state object (test URL)");
+    ok(state.extData && state.extData[key] == value,
+       "Got the expected state object (test manually set tab value)");
+    
+    // clean up
+    tabbrowser.removeTab(tab);
+  }, true);
+  
+  //////////////////////////////////
+  // setTabState and duplicateTab //
+  //////////////////////////////////
+  let key2 = "key2";
+  let value2 = "Value " + Math.random();
+  let value3 = "Another value: " + Date.now();
+  let state = { entries: [{ url: testURL }], extData: { key2: value2 } };
+  
+  // create a new tab
+  let tab2 = tabbrowser.addTab();
+  // set the tab's state
+  ss.setTabState(tab2, state.toSource());
+  tab2.linkedBrowser.addEventListener("load", function(aEvent) {
+    // verify the correctness of the restored tab
+    ok(ss.getTabValue(tab2, key2) == value2 && this.currentURI.spec == testURL,
+       "the tab's state was correctly restored");
+    
+    // add text data
+    let textbox = this.contentDocument.getElementById("textbox");
+    textbox.wrappedJSObject.value = value3;
+    
+    // duplicate the tab
+    let duplicateTab = ss.duplicateTab(window, tab2);
+    tabbrowser.removeTab(tab2);
+    
+    duplicateTab.linkedBrowser.addEventListener("load", function(aEvent) {
+      // verify the correctness of the duplicated tab
+      ok(ss.getTabValue(duplicateTab, key2) == value2 && this.currentURI.spec == testURL,
+         "correctly duplicated the tab's state");
+      let textbox = this.contentDocument.getElementById("textbox");
+      is(textbox.wrappedJSObject.value, value3, "also duplicated text data");
+      
+      // clean up
+      tabbrowser.removeTab(duplicateTab);
+      finish();
+    }, true);
+  }, true);
+}
deleted file mode 100644
--- a/browser/components/sessionstore/test/chrome/Makefile.in
+++ /dev/null
@@ -1,52 +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
-# Mozilla Foundation.
-# Portions created by the Initial Developer are Copyright (C) 2007
-# 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@
-relativesrcdir  = browser/components/sessionstore/test/chrome 
-
-include $(DEPTH)/config/autoconf.mk
-include $(topsrcdir)/config/rules.mk
-
-_TEST_FILES = \
-	test_bug350525.xul \
-	test_bug393716.xul \
-	$(NULL)
-
-libs:: $(_TEST_FILES)
-	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
deleted file mode 100644
--- a/browser/components/sessionstore/test/chrome/test_bug350525.xul
+++ /dev/null
@@ -1,132 +0,0 @@
-<?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=350525
--->
-<window title="Mozilla Bug 350525"
-  xmlns:html="http://www.w3.org/1999/xhtml"
-  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-  xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
-  <title>Test for Bug 350525</title>
-  <script type="application/javascript" 
-          src="chrome://mochikit/content/MochiKit/packed.js"></script>
-  <script type="application/javascript" 
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>      
-<body  xmlns="http://www.w3.org/1999/xhtml">
-  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=350525">Mozilla Bug 350525</a>
-
-  <p id="display"></p>
-
-  <pre id="test">
-  <script class="testbody" type="application/javascript">
-
-    /** Test for Bug 350525 **/
-
-    const Cc = Components.classes;
-    const Ci = Components.interfaces;
-    const Cr = Components.results;
-
-    // component
-    try {
-      Cc["@mozilla.org/browser/sessionstore;1"];
-      ok(1==1, "Able to reference the sessionstore component?");
-    } catch(ex) {
-      alert(ex);
-      ok(1==2, "Able to reference the sessionstore component?");
-    }
-
-    // service
-    try {
-      var ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
-      ok(true, "Able to reference the sessionstore service?");
-    } catch(ex) {
-      ok(false, "Able to reference the sessionstore service?");
-    }
-
-    // get current window, tabbrowser
-    var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
-    var windowEnumerator = wm.getEnumerator("navigator:browser");
-    var currentWindow = windowEnumerator.getNext();
-    var tabbrowser = currentWindow.getBrowser(); 
-
-    /*****************
-    undoCloseTab, getClosedTabCount
-    *****************/
-
-    // get closed tab count
-    var count = ss.getClosedTabCount(currentWindow);
-    ok(count > -1, "getClosedTabCount returns zero or more?");
-
-    // create a new tab
-    var newTab = tabbrowser.addTab("http://www.mozilla.org");
-
-    // remove tab
-    tabbrowser.removeTab(newTab);
-
-    // getClosedTabCount
-    var newcount = ss.getClosedTabCount(currentWindow);
-    todo(newcount > count, "After closing a tab, getClosedTabCount has been incremented? " + newcount + " > " + count);
-
-    // undoCloseTab
-    var undid = ss.undoCloseTab(currentWindow, null);
-    ok(undid != -1, "undoCloseTab throws?");
-
-    // clean up
-    tabbrowser.removeAllTabsBut(tabbrowser.selectedTab);
-
-    /*****************
-    setWindowValue
-    *****************/
-    var key = "key1";
-    var value = "value1";
-
-    // create a new tab
-    var newTab = tabbrowser.addTab("http://www.mozilla.org");
-
-    // test adding
-    ok(ss.setWindowValue(currentWindow, key, value) != -1, "Able to set a window value?");
-
-    // test retrieving
-    var storedValue = ss.getWindowValue(currentWindow, key);
-    is(value, storedValue, "Stored window value matches original?");
-
-    // test deleting 
-    ok(ss.deleteWindowValue(currentWindow, key) != -1, "Delete window value?");
-
-    // value should not exist post-delete
-    is(ss.getWindowValue(currentWindow, key), "", "Fetching deleted window value fails?");
-
-    // clean up
-    tabbrowser.removeTab(newTab);
-
-    /*********************
-    tabValues
-    *********************/
-    key = "key1";
-    value = "value1";
-
-    // create a new tab
-    newTab = tabbrowser.addTab("http://www.mozilla.org");
-
-    // test adding
-    ok(ss.setTabValue(newTab, key, value) != -1, "Able to store a tab value?");
-
-    // test retrieving
-    var storedValue = ss.getTabValue(newTab, key);
-    ok(value==storedValue, "Stored tab value match original?");
-
-    // test deleting 
-    ok(ss.deleteTabValue(newTab, key) != -1, "Able to delete a tab value?");
-    // value should not exist post-delete
-    ok(ss.getTabValue(newTab, key) == "", "Unable to retrieve deleted tab value?");
-
-    // clean up
-    tabbrowser.removeTab(newTab);
-
-  </script>
-  </pre>
-</body>
-
-</window>
deleted file mode 100644
--- a/browser/components/sessionstore/test/chrome/test_bug393716.xul
+++ /dev/null
@@ -1,101 +0,0 @@
-<?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=393716
--->
-<window title="Mozilla Bug 393716"
-  xmlns:html="http://www.w3.org/1999/xhtml"
-  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-  xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
-  <title>Test for Bug 393716</title>
-  <script type="application/javascript" 
-          src="chrome://mochikit/content/MochiKit/packed.js"></script>
-  <script type="application/javascript" 
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>      
-<body xmlns="http://www.w3.org/1999/xhtml">
-  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=393716">Mozilla Bug 393716</a>
-
-  <p id="display"></p>
-
-  <pre id="test">
-  <script class="testbody" type="application/javascript">
-  <![CDATA[
-
-    const Cc = Components.classes;
-    const Ci = Components.interfaces;
-
-    // set up the basics (SessionStore service, tabbrowser)
-    try {
-      var ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
-    } catch (ex) {
-      ok(false, "SessionStore service available?");
-    }
-    try {
-      var windowEnumerator = Cc["@mozilla.org/appshell/window-mediator;1"].
-                               getService(Ci.nsIWindowMediator).
-                               getEnumerator("navigator:browser");
-      var currentWindow = windowEnumerator.getNext();
-      var tabbrowser = currentWindow.getBrowser(); 
-    } catch (ex) {
-      ok(false, "tabbrowser available?");
-    }
-
-    /**************
-     * getTabState
-     **************/
-    var key = "key1", value = "value1";
-
-    // create a new tab
-    var newTab = tabbrowser.addTab();
-    ss.setTabValue(newTab, key, value);
-
-    // get the tab's state
-    var state = ss.getTabState(newTab);
-    ok(state, "Able to get the tab's state?");
-
-    // verify the tab state's integrity
-    state = eval("(" + state + ")");
-    ok(state instanceof Object && state.entries instanceof Array && state.entries.length > 0,
-       "Got a valid state object?");
-    ok(state.entries.length == 1 && state.entries[0].url == "about:blank",
-       "Got the expected state object (test URL)?");
-    ok(state.extData && state.extData[key] == value,
-       "Got the expected state object (test manually set tab value)?");
-
-    // clean up
-    tabbrowser.removeTab(newTab);
-
-    /*****************************
-     * setTabState / duplicateTab
-     *****************************/
-    key = "key2";
-    value = "value2";
-    state = { entries: [{ url: "about:blank" }], extData: { key2: value } };
-
-    // create a new tab
-    newTab = tabbrowser.addTab();
-
-    // set the tab's state
-    ss.setTabState(newTab, state.toSource());
-
-    // verify the correctness of the restored tab
-    ok(ss.getTabValue(newTab, key) == value, "Correctly restored the tab's state?");
-
-    // duplicate the tab
-    var duplicateTab = ss.duplicateTab(currentWindow, newTab);
-
-    // verify the correctness of the duplicated tab
-    ok(ss.getTabValue(duplicateTab, key) == value, "Correctly duplicated the tab's state?");
-
-    // clean up
-    tabbrowser.removeTab(newTab);
-    tabbrowser.removeTab(duplicateTab);
-
-  ]]>
-  </script>
-  </pre>
-</body>
-
-</window>
--- a/browser/config/version.txt
+++ b/browser/config/version.txt
@@ -1,1 +1,1 @@
-3.1a2
+3.1b1pre
--- a/browser/installer/unix/packages-static
+++ b/browser/installer/unix/packages-static
@@ -85,16 +85,17 @@ bin/components/cookie.xpt
 bin/components/directory.xpt
 bin/components/docshell.xpt
 bin/components/dom.xpt
 bin/components/dom_base.xpt
 bin/components/dom_canvas.xpt
 bin/components/dom_core.xpt
 bin/components/dom_css.xpt
 bin/components/dom_events.xpt
+bin/components/dom_geolocation.xpt
 bin/components/dom_html.xpt
 bin/components/dom_offline.xpt
 bin/components/dom_json.xpt
 bin/components/dom_range.xpt
 bin/components/dom_sidebar.xpt
 bin/components/dom_storage.xpt
 bin/components/dom_stylesheets.xpt
 bin/components/dom_traversal.xpt
@@ -235,16 +236,17 @@ bin/components/nsLivemarkService.js
 bin/components/nsTaggingService.js
 bin/components/nsDefaultCLH.js
 bin/components/nsContentPrefService.js
 bin/components/nsContentDispatchChooser.js
 bin/components/nsHandlerService.js
 bin/components/nsWebHandlerApp.js
 bin/components/libdbusservice.so
 bin/components/aboutRobots.js
+bin/components/nsBadCertHandler.js
 
 ; Modules
 bin/modules/*
 
 ; Safe Browsing
 bin/components/nsSafebrowsingApplication.js
 bin/components/nsUrlClassifierListManager.js
 bin/components/nsUrlClassifierLib.js
--- a/browser/installer/windows/packages-static
+++ b/browser/installer/windows/packages-static
@@ -92,16 +92,17 @@ bin\components\cookie.xpt
 bin\components\directory.xpt
 bin\components\docshell_base.xpt
 bin\components\dom.xpt
 bin\components\dom_base.xpt
 bin\components\dom_canvas.xpt
 bin\components\dom_core.xpt
 bin\components\dom_css.xpt
 bin\components\dom_events.xpt
+bin\components\dom_geolocation.xpt
 bin\components\dom_html.xpt
 bin\components\dom_offline.xpt
 bin\components\dom_json.xpt
 bin\components\dom_range.xpt
 bin\components\dom_sidebar.xpt
 bin\components\dom_storage.xpt
 bin\components\dom_stylesheets.xpt
 bin\components\dom_traversal.xpt
@@ -241,16 +242,17 @@ bin\components\txEXSLTRegExFunctions.js
 bin\components\nsLivemarkService.js
 bin\components\nsTaggingService.js
 bin\components\nsDefaultCLH.js
 bin\components\nsContentPrefService.js
 bin\components\nsContentDispatchChooser.js
 bin\components\nsHandlerService.js
 bin\components\nsWebHandlerApp.js
 bin\components\aboutRobots.js
+bin\components\nsBadCertHandler.js
 
 ; Modules
 bin\modules\*
 
 ; Safe Browsing
 bin\components\nsSafebrowsingApplication.js
 bin\components\nsUrlClassifierListManager.js
 bin\components\nsUrlClassifierLib.js
--- a/browser/locales/Makefile.in
+++ b/browser/locales/Makefile.in
@@ -314,8 +314,28 @@ else
 	  sed -e "s/%AB_CD%/$(AB_CD)/" > $(FINAL_TARGET)/updater.ini
 endif
 endif
 
 ifdef MOZ_CRASHREPORTER
 libs:: $(addprefix $(LOCALE_SRCDIR)/,crashreporter/crashreporter-override.ini)
 	$(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)
 endif
+
+# This variable is to allow the wget-en-US target to know which ftp server to download from
+ifndef EN_US_BINARY_URL 
+EN_US_BINARY_URL = $(error You must set EN_US_BINARY_URL)
+endif
+
+# This make target allows us to wget the latest en-US binary from a specified website
+# The make installers-% target needs the en-US binary in dist/
+# and for the windows repackages we need the .installer.exe in dist/sea
+wget-en-US:
+ifndef WGET
+	$(error Wget not installed)
+endif
+	@$(WGET) -nv --output-document $(_ABS_DIST)/$(PACKAGE) $(EN_US_BINARY_URL)/$(PACKAGE)
+	@echo "Downloaded $(EN_US_BINARY_URL)/$(PACKAGE) to $(_ABS_DIST)/$(PACKAGE)"
+ifeq ($(OS_ARCH), WINNT)
+	$(NSINSTALL) -D $(_ABS_DIST)/install/sea
+	@$(WGET) -nv --output-document $(_ABS_DIST)/install/sea/$(PKG_BASENAME).installer.exe $(EN_US_BINARY_URL)/$(PKG_BASENAME).installer.exe
+	@echo "Downloaded $(EN_US_BINARY_URL)/$(PKG_BASENAME).installer.exe to $(_ABS_DIST)/install/sea/$(PKG_BASENAME)"
+endif
--- a/build/autoconf/altoptions.m4
+++ b/build/autoconf/altoptions.m4
@@ -147,11 +147,8 @@ echo "
 
 dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file
 AC_DEFUN([MOZ_READ_MOZCONFIG],
 [AC_REQUIRE([AC_INIT_BINSH])dnl
 # Read in '.mozconfig' script to set the initial options.
 # See the mozconfig2configure script for more details.
 _AUTOCONF_TOOLS_DIR=`dirname [$]0`/[$1]/build/autoconf
 . $_AUTOCONF_TOOLS_DIR/mozconfig2configure])
-
-dnl This gets inserted at the top of the configure script
-MOZ_READ_MOZCONFIG(MOZ_TOPSRCDIR)
new file mode 100644
--- /dev/null
+++ b/build/package/mac_osx/installdmg.ex
@@ -0,0 +1,44 @@
+#!/usr/bin/expect
+# ***** 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 Corporation Code.
+#
+# The Initial Developer of the Original Code is
+# Clint Talbert.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#  Armen Zambrano Gasparnian <armenzg@mozilla.com>
+#  Axel Hecht <l10n@mozilla.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+spawn hdiutil attach -readonly -mountroot /tmp -private -noautoopen $argv
+expect {
+"byte" {send "G"; exp_continue}
+"END" {send "\r"; exp_continue}
+"Y/N?" {send "Y\r"; exp_continue}
+}
--- a/build/pgo/automation.py.in
+++ b/build/pgo/automation.py.in
@@ -274,16 +274,17 @@ user_pref("dom.max_script_run_time", 0);
 user_pref("signed.applets.codebase_principal_support", true);
 user_pref("security.warn_submit_insecure", false);
 user_pref("browser.shell.checkDefaultBrowser", false);
 user_pref("browser.warnOnQuit", false);
 user_pref("accessibility.typeaheadfind.autostart", false);
 user_pref("javascript.options.showInConsole", true);
 user_pref("layout.debug.enable_data_xbl", true);
 user_pref("browser.EULA.override", true);
+user_pref("javascript.options.jit.content", false);
 
 user_pref("camino.warn_when_closing", false); // Camino-only, harmless to others
 """
   prefs.append(part)
 
   locations = readLocations()
 
   # Grant God-power to all the privileged servers on which tests run.
--- a/caps/src/Makefile.in
+++ b/caps/src/Makefile.in
@@ -68,16 +68,17 @@ REQUIRES	= xpcom \
 		  content \
 		  layout \
 		  $(NULL)
 
 CPPSRCS		= \
 		nsPrincipal.cpp \
 		nsSystemPrincipal.cpp \
 		nsNullPrincipal.cpp \
+		nsNullPrincipalURI.cpp \
 		nsJSPrincipals.cpp \
 		nsScriptSecurityManager.cpp \
 		nsSecurityManagerFactory.cpp \
 		$(NULL)
 
 ifdef XPC_IDISPATCH_SUPPORT
 DEFINES += -DXPC_IDISPATCH_SUPPORT
 endif
--- a/caps/src/nsNullPrincipal.cpp
+++ b/caps/src/nsNullPrincipal.cpp
@@ -38,27 +38,26 @@
 
 /**
  * This is the principal that has no rights and can't be accessed by
  * anything other than itself and chrome; null principals are not
  * same-origin with anything but themselves.
  */
 
 #include "nsNullPrincipal.h"
+#include "nsNullPrincipalURI.h"
 #include "nsMemory.h"
 #include "nsIUUIDGenerator.h"
 #include "nsID.h"
 #include "nsNetUtil.h"
 #include "nsIClassInfoImpl.h"
 #include "nsNetCID.h"
 #include "nsDOMError.h"
 #include "nsScriptSecurityManager.h"
 
-static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
-
 NS_IMPL_QUERY_INTERFACE2_CI(nsNullPrincipal,
                             nsIPrincipal,
                             nsISerializable)
 NS_IMPL_CI_INTERFACE_GETTER2(nsNullPrincipal,
                              nsIPrincipal,
                              nsISerializable)
 
 NS_IMETHODIMP_(nsrefcnt) 
@@ -114,32 +113,24 @@ nsNullPrincipal::Init()
 
   // Use an nsCString so we only do the allocation once here and then share
   // with nsJSPrincipals
   nsCString str;
   str.SetCapacity(prefixLen + suffixLen);
 
   str.Append(NS_NULLPRINCIPAL_PREFIX);
   str.Append(chars);
-  
+
   if (str.Length() != prefixLen + suffixLen) {
     NS_WARNING("Out of memory allocating null-principal URI");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  // Use CID so we're sure we get the impl we want.  Note that creating the URI
-  // directly is ok because we have our own private URI scheme.  In effect,
-  // we're being a protocol handler.
-  mURI = do_CreateInstance(kSimpleURICID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = mURI->SetSpec(str);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_TryToSetImmutable(mURI);
+  mURI = new nsNullPrincipalURI(str);
+  NS_ENSURE_TRUE(mURI, NS_ERROR_OUT_OF_MEMORY);
 
   return mJSPrincipals.Init(this, str);
 }
 
 /**
  * nsIPrincipal implementation
  */
 
new file mode 100644
--- /dev/null
+++ b/caps/src/nsNullPrincipalURI.cpp
@@ -0,0 +1,262 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab
+ * ***** 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 the
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.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 "nsNullPrincipalURI.h"
+#include "nsNetUtil.h"
+#include "nsEscape.h"
+#include "nsCRT.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//// nsNullPrincipalURI
+
+nsNullPrincipalURI::nsNullPrincipalURI(const nsCString &aSpec)
+{
+  PRInt32 dividerPosition = aSpec.FindChar(':');
+  NS_ASSERTION(dividerPosition != -1, "Malformed URI!");
+
+  PRInt32 n = aSpec.Left(mScheme, dividerPosition);
+  NS_ASSERTION(n == dividerPosition, "Storing the scheme failed!");
+
+  PRInt32 count = aSpec.Length() - dividerPosition - 1;
+  n = aSpec.Mid(mPath, dividerPosition + 1, count);
+  NS_ASSERTION(n == count, "Storing the path failed!");
+
+  ToLowerCase(mScheme);
+}
+
+static NS_DEFINE_CID(kNullPrincipalURIImplementationCID,
+                     NS_NULLPRINCIPALURI_IMPLEMENTATION_CID);
+
+NS_IMPL_THREADSAFE_ADDREF(nsNullPrincipalURI)
+NS_IMPL_THREADSAFE_RELEASE(nsNullPrincipalURI)
+
+NS_INTERFACE_MAP_BEGIN(nsNullPrincipalURI)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  if (aIID.Equals(kNullPrincipalURIImplementationCID))
+    foundInterface = static_cast<nsIURI *>(this);
+  else
+  NS_INTERFACE_MAP_ENTRY(nsIURI)
+NS_INTERFACE_MAP_END
+
+////////////////////////////////////////////////////////////////////////////////
+//// nsIURI
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetAsciiHost(nsACString &_host)
+{
+  _host.Truncate();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetAsciiSpec(nsACString &_spec)
+{
+  nsCAutoString buffer;
+  (void)GetSpec(buffer);
+  NS_EscapeURL(buffer, esc_OnlyNonASCII | esc_AlwaysCopy, _spec);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetHost(nsACString &_host)
+{
+  _host.Truncate();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetHost(const nsACString &aHost)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetHostPort(nsACString &_host)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetHostPort(const nsACString &aHost)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetOriginCharset(nsACString &_charset)
+{
+  _charset.Truncate();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetPassword(nsACString &_password)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetPassword(const nsACString &aPassword)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetPath(nsACString &_path)
+{
+  // We want to give a full copy of the string and not share a string buffer
+  _path = nsDependentCString(mPath);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetPath(const nsACString &aPath)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetPrePath(nsACString &_prePath)
+{
+  _prePath = mScheme + NS_LITERAL_CSTRING(":");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetPort(PRInt32 *_port)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetPort(PRInt32 aPort)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetScheme(nsACString &_scheme)
+{
+  // We want to give a full copy of the string and not share a string buffer
+  _scheme = nsDependentCString(mScheme);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetScheme(const nsACString &aScheme)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetSpec(nsACString &_spec)
+{
+  _spec = mScheme + NS_LITERAL_CSTRING(":") + mPath;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetSpec(const nsACString &aSpec)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetUsername(nsACString &_username)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetUsername(const nsACString &aUsername)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetUserPass(nsACString &_userPass)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetUserPass(const nsACString &aUserPass)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::Clone(nsIURI **_newURI)
+{
+  nsCOMPtr<nsIURI> uri =
+    new nsNullPrincipalURI(mScheme + NS_LITERAL_CSTRING(":") + mPath);
+  NS_ENSURE_TRUE(uri, NS_ERROR_OUT_OF_MEMORY);
+  uri.forget(_newURI);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::Equals(nsIURI *aOther, PRBool *_equals)
+{
+  *_equals = PR_FALSE;
+  nsNullPrincipalURI *otherURI;
+  nsresult rv = aOther->QueryInterface(kNullPrincipalURIImplementationCID,
+                                       (void **)&otherURI);
+  if (NS_SUCCEEDED(rv)) {
+    *_equals = (0 == strcmp(mScheme.get(), otherURI->mScheme.get()) &&
+                0 == strcmp(mPath.get(), otherURI->mPath.get()));
+    NS_RELEASE(otherURI);
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::Resolve(const nsACString &aRelativePath,
+                            nsACString &_resolvedURI)
+{
+  _resolvedURI = aRelativePath;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SchemeIs(const char *aScheme, PRBool *_schemeIs)
+{
+  *_schemeIs = (0 == nsCRT::strcasecmp(mScheme.get(), aScheme));
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/caps/src/nsNullPrincipalURI.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab
+ * ***** 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 the
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.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 ***** */
+
+/**
+ * This wraps nsSimpleURI so that all calls to it are done on the main thread.
+ */
+
+#ifndef __nsNullPrincipalURI_h__
+#define __nsNullPrincipalURI_h__
+
+#include "nsIURI.h"
+#include "nsAutoPtr.h"
+#include "nsString.h"
+
+// {51fcd543-3b52-41f7-b91b-6b54102236e6}
+#define NS_NULLPRINCIPALURI_IMPLEMENTATION_CID \
+  {0x51fcd543, 0x3b52, 0x41f7, \
+    {0xb9, 0x1b, 0x6b, 0x54, 0x10, 0x22, 0x36, 0xe6} }
+
+class nsNullPrincipalURI : public nsIURI
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIURI
+
+  nsNullPrincipalURI(const nsCString &aSpec);
+
+private:
+  nsCString mScheme;
+  nsCString mPath;
+};
+
+#endif // __nsNullPrincipalURI_h__
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -311,128 +311,17 @@ nsScriptSecurityManager::GetSafeJSContex
     return cx;
 }
 
 /* static */
 PRBool
 nsScriptSecurityManager::SecurityCompareURIs(nsIURI* aSourceURI,
                                              nsIURI* aTargetURI)
 {
-    // Note that this is not an Equals() test on purpose -- for URIs that don't
-    // support host/port, we want equality to basically be object identity, for
-    // security purposes.  Otherwise, for example, two javascript: URIs that
-    // are otherwise unrelated could end up "same origin", which would be
-    // unfortunate.
-    if (aSourceURI && aSourceURI == aTargetURI)
-    {
-        return PR_TRUE;
-    }
-
-    if (!aTargetURI || !aSourceURI) 
-    {
-        return PR_FALSE;
-    }
-
-    // If either URI is a nested URI, get the base URI
-    nsCOMPtr<nsIURI> sourceBaseURI = NS_GetInnermostURI(aSourceURI);
-    nsCOMPtr<nsIURI> targetBaseURI = NS_GetInnermostURI(aTargetURI);
-
-    if (!sourceBaseURI || !targetBaseURI)
-        return PR_FALSE;
-
-    // Compare schemes
-    nsCAutoString targetScheme;
-    PRBool sameScheme = PR_FALSE;
-    if (NS_FAILED( targetBaseURI->GetScheme(targetScheme) ) ||
-        NS_FAILED( sourceBaseURI->SchemeIs(targetScheme.get(), &sameScheme) ) ||
-        !sameScheme)
-    {
-        // Not same-origin if schemes differ
-        return PR_FALSE;
-    }
-
-    // special handling for file: URIs
-    if (targetScheme.EqualsLiteral("file"))
-    {
-        // in traditional unsafe behavior all files are the same origin
-        if (!sStrictFileOriginPolicy)
-            return PR_TRUE;
-
-        nsCOMPtr<nsIFileURL> sourceFileURL(do_QueryInterface(sourceBaseURI));
-        nsCOMPtr<nsIFileURL> targetFileURL(do_QueryInterface(targetBaseURI));
-
-        if (!sourceFileURL || !targetFileURL)
-            return PR_FALSE;
-
-        nsCOMPtr<nsIFile> sourceFile, targetFile;
-
-        sourceFileURL->GetFile(getter_AddRefs(sourceFile));
-        targetFileURL->GetFile(getter_AddRefs(targetFile));
-
-        if (!sourceFile || !targetFile)
-            return PR_FALSE;
-
-        // Otherwise they had better match
-        PRBool filesAreEqual = PR_FALSE;
-        nsresult rv = sourceFile->Equals(targetFile, &filesAreEqual);
-        return NS_SUCCEEDED(rv) && filesAreEqual;
-    }
-
-    // Special handling for mailnews schemes
-    if (targetScheme.EqualsLiteral("imap") ||
-        targetScheme.EqualsLiteral("mailbox") ||
-        targetScheme.EqualsLiteral("news"))
-    {
-        // Each message is a distinct trust domain; use the 
-        // whole spec for comparison
-        nsCAutoString targetSpec;
-        nsCAutoString sourceSpec;
-        return ( NS_SUCCEEDED( targetBaseURI->GetSpec(targetSpec) ) &&
-                 NS_SUCCEEDED( sourceBaseURI->GetSpec(sourceSpec) ) &&
-                 targetSpec.Equals(sourceSpec) );
-    }
-
-    // Compare hosts
-    nsCAutoString targetHost;
-    nsCAutoString sourceHost;
-    if (NS_FAILED( targetBaseURI->GetHost(targetHost) ) ||
-        NS_FAILED( sourceBaseURI->GetHost(sourceHost) ) ||
-        !targetHost.Equals(sourceHost, nsCaseInsensitiveCStringComparator()))
-    {
-        // Not same-origin if hosts differ
-        return PR_FALSE;
-    }
-
-    // Compare ports
-    PRInt32 targetPort;
-    nsresult rv = targetBaseURI->GetPort(&targetPort);
-    PRInt32 sourcePort;
-    if (NS_SUCCEEDED(rv))
-        rv = sourceBaseURI->GetPort(&sourcePort);
-    PRBool result = NS_SUCCEEDED(rv) && targetPort == sourcePort;
-    // If the port comparison failed, see if either URL has a
-    // port of -1. If so, replace -1 with the default port
-    // for that scheme.
-    if (NS_SUCCEEDED(rv) && !result &&
-        (sourcePort == -1 || targetPort == -1))
-    {
-        NS_ENSURE_TRUE(sIOService, PR_FALSE);
-
-        PRInt32 defaultPort = NS_GetDefaultPort(targetScheme.get());
-        if (defaultPort == -1)
-            return PR_FALSE; // No default port for this scheme
-
-        if (sourcePort == -1)
-            sourcePort = defaultPort;
-        else if (targetPort == -1)
-            targetPort = defaultPort;
-        result = targetPort == sourcePort;
-    }
-
-    return result;
+    return NS_SecurityCompareURIs(aSourceURI, aTargetURI, sStrictFileOriginPolicy);
 }
 
 NS_IMETHODIMP
 nsScriptSecurityManager::GetChannelPrincipal(nsIChannel* aChannel,
                                              nsIPrincipal** aPrincipal)
 {
     NS_PRECONDITION(aChannel, "Must have channel!");
     nsCOMPtr<nsISupports> owner;
--- a/client.mk
+++ b/client.mk
@@ -84,21 +84,19 @@ endif
 
 ifndef TOPSRCDIR
 ifeq (,$(wildcard client.mk))
 $(error Must run from the client.mk directory, or specify TOPSRCDIR)
 endif
 TOPSRCDIR = $(CWD)
 endif
 
-ifeq (Darwin,$(shell uname -s))
-AUTOCONF ?= autoconf213
-else
-AUTOCONF ?= $(shell which autoconf-2.13 autoconf2.13 autoconf213 | head -1)
-endif
+# try to find autoconf 2.13 - discard errors from 'which'
+# MacOS X 10.4 sends "no autoconf*" errors to stdout, discard those via grep
+AUTOCONF ?= $(shell which autoconf-2.13 autoconf2.13 autoconf213 2>/dev/null | grep -v '^no autoconf' | head -1)
 
 MKDIR := mkdir
 SH := /bin/sh
 ifndef MAKE
 MAKE := gmake
 endif
 PERL ?= perl
 PYTHON ?= python
@@ -159,16 +157,17 @@ ifdef MOZ_OBJDIR
   MOZ_MAKE = $(MAKE) $(MOZ_MAKE_FLAGS) -C $(OBJDIR)
 else
   OBJDIR := $(TOPSRCDIR)
   MOZ_MAKE := $(MAKE) $(MOZ_MAKE_FLAGS)
 endif
 
 endif # MOZ_BUILD_PROJECTS
 
+# 'configure' scripts generated by autoconf.
 CONFIGURES := $(TOPSRCDIR)/configure
 CONFIGURES += $(TOPSRCDIR)/nsprpub/configure
 
 #######################################################################
 # Rules
 # 
 
 # The default rule is build
@@ -271,30 +270,25 @@ CONFIG_STATUS = $(wildcard $(OBJDIR)/con
 CONFIG_CACHE  = $(wildcard $(OBJDIR)/config.cache)
 
 ifdef RUN_AUTOCONF_LOCALLY
 EXTRA_CONFIG_DEPS := \
 	$(TOPSRCDIR)/aclocal.m4 \
 	$(wildcard $(TOPSRCDIR)/build/autoconf/*.m4) \
 	$(NULL)
 
-$(TOPSRCDIR)/configure: $(TOPSRCDIR)/configure.in $(EXTRA_CONFIG_DEPS)
+$(CONFIGURES): %: %.in $(EXTRA_CONFIG_DEPS)
 	@echo Generating $@ using autoconf
-	cd $(TOPSRCDIR); $(AUTOCONF)
-
-$(TOPSRCDIR)/nsprpub/configure: $(TOPSRCDIR)/nsprpub/configure.in $(EXTRA_CONFIG_DEPS)
-	@echo Generating $@ using autoconf
-	cd $(TOPSRCDIR)/nsprpub; $(AUTOCONF)
+	cd $(@D); $(AUTOCONF)
 endif
 
 CONFIG_STATUS_DEPS := \
-	$(TOPSRCDIR)/configure \
+	$(wildcard $(CONFIGURES)) \
 	$(TOPSRCDIR)/allmakefiles.sh \
 	$(TOPSRCDIR)/.mozconfig.mk \
-	$(wildcard $(TOPSRCDIR)/nsprpub/configure) \
 	$(wildcard $(TOPSRCDIR)/directory/c-sdk/configure) \
 	$(wildcard $(TOPSRCDIR)/config/milestone.txt) \
 	$(wildcard $(TOPSRCDIR)/config/chrome-versions.sh) \
   $(wildcard $(addsuffix confvars.sh,$(wildcard $(TOPSRCDIR)/*/))) \
 	$(NULL)
 
 # configure uses the program name to determine @srcdir@. Calling it without
 #   $(TOPSRCDIR) will set @srcdir@ to "."; otherwise, it is set to the full
@@ -304,17 +298,19 @@ ifeq ($(TOPSRCDIR),$(OBJDIR))
 else
   CONFIGURE = $(TOPSRCDIR)/configure
 endif
 
 ifdef MOZ_TOOLS
   CONFIGURE = $(TOPSRCDIR)/configure
 endif
 
-configure:: $(CONFIGURES)
+configure-files: $(CONFIGURES)
+
+configure:: configure-files
 ifdef MOZ_BUILD_PROJECTS
 	@if test ! -d $(MOZ_OBJDIR); then $(MKDIR) $(MOZ_OBJDIR); else true; fi
 endif
 	@if test ! -d $(OBJDIR); then $(MKDIR) $(OBJDIR); else true; fi
 	@echo cd $(OBJDIR);
 	@echo $(CONFIGURE) $(CONFIGURE_ARGS)
 	@cd $(OBJDIR) && $(BUILD_PROJECT_ARG) $(CONFIGURE_ENV_ARGS) $(CONFIGURE) $(CONFIGURE_ARGS) \
 	  || ( echo "*** Fix above errors and then restart with\
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -390,16 +390,17 @@ UNZIP		= @UNZIP@
 ZIP		= @ZIP@
 XARGS		= @XARGS@
 STRIP		= @STRIP@
 DOXYGEN		= @DOXYGEN@
 MAKE		= @MAKE@
 PBBUILD_BIN	= @PBBUILD@
 SDP		= @SDP@
 NSINSTALL_BIN	= @NSINSTALL_BIN@
+WGET		= @WGET@
 
 ifdef MOZ_NATIVE_JPEG
 JPEG_CFLAGS	= @JPEG_CFLAGS@
 JPEG_LIBS	= @JPEG_LIBS@
 JPEG_REQUIRES	=
 else
 JPEG_CFLAGS	= @MOZ_JPEG_CFLAGS@
 JPEG_LIBS	= @MOZ_JPEG_LIBS@
--- a/config/milestone.txt
+++ b/config/milestone.txt
@@ -5,9 +5,9 @@
 #    x.x.x.x
 #    x.x.x+
 #
 # Referenced by milestone.pl.
 # Hopefully I'll be able to automate replacement of *all*
 # hardcoded milestones in the tree from these two files.
 #--------------------------------------------------------
 
-1.9.1a2
+1.9.1b1pre
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1128,17 +1128,17 @@ ifeq ($(OS_ARCH),OpenVMS)
 	  fi; \
 	fi
 ifdef IS_COMPONENT
 	@if test ! -f $(VMS_SYMVEC_FILE); then \
 	  echo Creating generic component options file $(VMS_SYMVEC_FILE); \
 	  cp $(VMS_SYMVEC_FILE_COMP) $(VMS_SYMVEC_FILE); \
 	fi
 endif
-endif
+endif # OpenVMS
 ifdef NO_LD_ARCHIVE_FLAGS
 ifdef SHARED_LIBRARY_LIBS
 	@rm -f $(SUB_SHLOBJS)
 	@for lib in $(SHARED_LIBRARY_LIBS); do $(AR_EXTRACT) $${lib}; $(CLEANUP2); done
 ifeq ($(OS_ARCH),Darwin)
 	@echo Making symlinks to the original object files in the archive libraries $(SHARED_LIBRARY_LIBS)
 	@for lib in $(SHARED_LIBRARY_LIBS); do \
 		libdir=`echo $$lib|sed -e 's,/[^/]*\.a,,'`; \
@@ -1166,17 +1166,17 @@ endif
 	$(MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(PROBE_LOBJS) $(RESFILE) $(LDFLAGS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
 	@rm -f $(PROBE_LOBJS)
 	@rm -f $(DTRACE_PROBE_OBJ)
 	@for lib in $(MOZILLA_PROBE_LIBS); do \
 		if [ -L $${lib} ]; then rm -f `readlink $${lib}`; fi; \
 	done
 	@rm -f $(MOZILLA_PROBE_LIBS)
 
-else
+else # ! DTRACE_LIB_DEPENDENT
 	$(MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(DTRACE_PROBE_OBJ) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
 endif # DTRACE_LIB_DEPENDENT
 
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
 ifdef MSMANIFEST_TOOL
 ifdef EMBED_MANIFEST_AT
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
--- a/configure.in
+++ b/configure.in
@@ -1369,16 +1369,34 @@ if test "$GNU_CXX"; then
            *)
         _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wcast-align"
            ;;
        esac
     fi
 
     _DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -include $(DEPTH)/mozilla-config.h'
     _USE_CPP_INCLUDE_FLAG=1
+
+    AC_CACHE_CHECK(whether the compiler supports -Wno-invalid-offsetof,
+                   ac_has_wno_invalid_offsetof,
+        [
+            AC_LANG_SAVE
+            AC_LANG_CPLUSPLUS
+            _SAVE_CXXFLAGS="$CXXFLAGS"
+            CXXFLAGS="$CXXFLAGS ${_COMPILER_PREFIX}-Wno-invalid-offsetof"
+            AC_TRY_COMPILE([],
+                           [return(0);],
+                           ac_has_wno_invalid_offsetof="yes",
+                           ac_has_wno_invalid_offsetof="no")
+            CXXFLAGS="$_SAVE_CXXFLAGS"
+            AC_LANG_RESTORE
+        ])
+    if test "$ac_has_wno_invalid_offsetof" = "yes"; then
+        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-Wno-invalid-offsetof"
+    fi
 else
     _DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -D_MOZILLA_CONFIG_H_ $(ACDEFINES)'
 fi
 
 dnl gcc can come with its own linker so it is better to use the pass-thru calls
 dnl MKSHLIB_FORCE_ALL is used to force the linker to include all object
 dnl files present in an archive. MKSHLIB_UNFORCE_ALL reverts the linker to
 dnl normal behavior.
@@ -1453,17 +1471,16 @@ AC_CACHE_VAL(ac_cv_static_assertion_macr
                  ac_cv_static_assertion_macros_work="no",
                  )
   AC_LANG_RESTORE
  ])
 AC_MSG_RESULT("$ac_cv_static_assertion_macros_work")
 if test "$ac_cv_static_assertion_macros_work" = "no"; then
     AC_MSG_ERROR([Compiler cannot compile macros used in autoconf tests.])
 fi
-
 fi # COMPILE_ENVIRONMENT
 
 dnl ========================================================
 dnl Checking for 64-bit OS
 dnl ========================================================
 if test "$COMPILE_ENVIRONMENT"; then
 AC_LANG_SAVE
 AC_LANG_C
@@ -4625,16 +4642,20 @@ content/xslt)
 standalone) 
   MOZ_APP_NAME=mozilla
   MOZ_APP_DISPLAYNAME=Mozilla
   MOZ_APP_VERSION=$MOZILLA_VERSION
   ;;
 
 esac
 
+if test -z "$MOZ_XUL_APP"; then
+	AC_MSG_ERROR([builds with unsetting MOZ_XUL_APP in confvars.sh are not supported.])
+fi
+
 AC_SUBST(MOZ_BUILD_APP)
 AC_SUBST(MOZ_XUL_APP)
 AC_SUBST(MOZ_PHOENIX)
 AC_SUBST(MOZ_STANDALONE_COMPOSER)
 AC_SUBST(MOZ_XULRUNNER)
 
 AC_DEFINE_UNQUOTED(MOZ_BUILD_APP,$MOZ_BUILD_APP)
 
@@ -4771,17 +4792,17 @@ cairo-mac|cairo-cocoa)
     else
         MOZ_WIDGET_TOOLKIT=mac
     fi
     MOZ_GFX_TOOLKIT=cairo
     MOZ_USER_DIR="Mozilla"
     AC_DEFINE(XP_MACOSX)
     AC_DEFINE(TARGET_CARBON)
     AC_DEFINE(TARGET_API_MAC_CARBON)
-    TK_LIBS='-framework Carbon -framework CoreAudio -framework AudioToolbox -framework AudioUnit'
+    TK_LIBS='-framework Carbon -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework AddressBook'
     TK_CFLAGS="-I${MACOS_SDK_DIR}/Developer/Headers/FlatCarbon"
     CFLAGS="$CFLAGS $TK_CFLAGS"
     CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
     ;;
 esac
 
 if test "$MOZ_ENABLE_XREMOTE"; then
     AC_DEFINE(MOZ_ENABLE_XREMOTE)
@@ -5770,16 +5791,21 @@ AC_SUBST(MOZ_INSTALLER)
 AC_MSG_CHECKING([for tar archiver])
 AC_CHECK_PROGS(TAR, gnutar gtar tar, "")
 if test -z "$TAR"; then
     AC_MSG_ERROR([no tar archiver found in \$PATH])
 fi
 AC_MSG_RESULT([$TAR])
 AC_SUBST(TAR)
 
+AC_MSG_CHECKING([for wget])
+AC_CHECK_PROGS(WGET, wget, "")
+AC_MSG_RESULT([$WGET])
+AC_SUBST(WGET)
+
 dnl ========================================================
 dnl Updater
 dnl ========================================================
 
 MOZ_ARG_DISABLE_BOOL(updater,
 [  --disable-updater       Disable building of updater],
     MOZ_UPDATER=,
     MOZ_UPDATER=1 )
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -96,16 +96,17 @@ class nsIScriptContext;
 class nsIRunnable;
 template<class E> class nsCOMArray;
 class nsIPref;
 class nsVoidArray;
 struct JSRuntime;
 class nsICaseConversion;
 class nsIUGenCategory;
 class nsIWidget;
+class nsIDragSession;
 class nsPIDOMWindow;
 #ifdef MOZ_XTF
 class nsIXTFService;
 #endif
 #ifdef IBMBIDI
 class nsIBidiKeyboard;
 #endif
 
@@ -1214,16 +1215,21 @@ public:
 
   /**
    * Hide any XUL popups associated with aDocument, including any documents
    * displayed in child frames.
    */
   static void HidePopupsInDocument(nsIDocument* aDocument);
 
   /**
+   * Retrieve the current drag session, or null if no drag is currently occuring
+   */
+  static already_AddRefed<nsIDragSession> GetDragSession();
+
+  /**
    * Return true if aURI is a local file URI (i.e. file://).
    */
   static PRBool URIIsLocalFile(nsIURI *aURI);
 
   /**
    * If aContent is an HTML element with a DOM level 0 'name', then
    * return the name. Otherwise return null.
    */
@@ -1240,16 +1246,21 @@ public:
   static void GetOfflineAppManifest(nsIDOMWindow *aWindow, nsIURI **aURI);
 
   /**
    * Check whether an application should be allowed to use offline APIs.
    */
   static PRBool OfflineAppAllowed(nsIURI *aURI);
 
   /**
+   * Check whether an application should be allowed to use offline APIs.
+   */
+  static PRBool OfflineAppAllowed(nsIPrincipal *aPrincipal);
+
+  /**
    * Increases the count of blockers preventing scripts from running.
    * NOTE: You might want to use nsAutoScriptBlocker rather than calling
    * this directly
    */
   static void AddScriptBlocker();
 
   /**
    * Decreases the count of blockers preventing scripts from running.
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -92,18 +92,18 @@ class nsIDocumentObserver;
 class nsBindingManager;
 class nsIDOMNodeList;
 class mozAutoSubtreeModified;
 struct JSObject;
 class nsFrameLoader;
 
 // IID for the nsIDocument interface
 #define NS_IDOCUMENT_IID      \
-    { 0x5f0203a8, 0xd926, 0x4adf, \
-      { 0xba, 0x96, 0xe6, 0xc3, 0xe6, 0xbb, 0x1b, 0xe5 } }
+  { 0xd5b1e3c5, 0x85dc, 0x403e, \
+    { 0xbb, 0x4a, 0x54, 0x66, 0xdc, 0xbe, 0x15, 0x69 } }
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 //----------------------------------------------------------------------
 
 // Document interface.  This is implemented by all document objects in
 // Gecko.
@@ -565,16 +565,21 @@ public:
    * for event/script handling. Do not process any events/script if the method
    * returns null, but aHasHadScriptHandlingObject is true.
    */
   virtual nsIScriptGlobalObject*
     GetScriptHandlingObject(PRBool& aHasHadScriptHandlingObject) const = 0;
   virtual void SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject) = 0;
 
   /**
+   * Sets script handling object to null and marks that document has had one.
+   */
+  virtual void ClearScriptHandlingObject() = 0;
+
+  /**
    * Get the object that is used as the scope for all of the content
    * wrappers whose owner document is this document. Unlike the script global
    * object, this will only return null when the global object for this
    * document is truly gone. Use this object when you're trying to find a
    * content wrapper in XPConnect.
    */
   virtual nsIScriptGlobalObject* GetScopeObject() = 0;
 
@@ -893,16 +898,24 @@ public:
   virtual void ClearBoxObjectFor(nsIContent *aContent) = 0;
 
   /**
    * Get the compatibility mode for this document
    */
   nsCompatibility GetCompatibilityMode() const {
     return mCompatMode;
   }
+  
+  /**
+   * Check whether we've ever fired a DOMTitleChanged event for this
+   * document.
+   */
+  PRBool HaveFiredDOMTitleChange() const {
+    return mHaveFiredTitleChange;
+  }
 
   /**
    * See GetXBLChildNodesFor on nsBindingManager
    */
   virtual nsresult GetXBLChildNodesFor(nsIContent* aContent,
                                        nsIDOMNodeList** aResult) = 0;
 
   /**
@@ -1055,16 +1068,19 @@ protected:
 
   // True if we're loaded as data and therefor has any dangerous stuff, such
   // as scripts and plugins, disabled.
   PRPackedBool mLoadedAsData;
 
   // If true, whoever is creating the document has gotten it to the
   // point where it's safe to start layout on it.
   PRPackedBool mMayStartLayout;
+  
+  // True iff we've ever fired a DOMTitleChanged event for this document
+  PRPackedBool mHaveFiredTitleChange;
 
   // The bidi options for this document.  What this bitfield means is
   // defined in nsBidiUtils.h
   PRUint32 mBidiOptions;
 
   nsCString mContentLanguage;
   nsCString mContentType;
 
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -54,16 +54,17 @@ REQUIRES	= xpcom \
 		  layout \
 		  widget \
 		  view \
 		  locale \
 		  htmlparser \
 		  js \
 		  webshell \
 		  necko \
+		  nkcache \
 		  mimetype \
 		  exthandler \
 		  chardet \
 		  caps \
 		  lwbrk \
 		  uconv \
 		  docshell \
 		  pref \
--- a/content/base/src/nsContentAreaDragDrop.cpp
+++ b/content/base/src/nsContentAreaDragDrop.cpp
@@ -40,24 +40,25 @@
 
 // Local Includes
 #include "nsContentAreaDragDrop.h"
 
 // Helper Classes
 #include "nsString.h"
 
 // Interfaces needed to be included
+#include "nsIVariant.h"
 #include "nsIDOMNSUIEvent.h"
 #include "nsIDOMUIEvent.h"
 #include "nsISelection.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMNSEvent.h"
-#include "nsIDOMMouseEvent.h"
+#include "nsIDOMDragEvent.h"
 #include "nsIDOMAbstractView.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentRange.h"
 #include "nsIDOMRange.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIFormControl.h"
 #include "nsISelectionPrivate.h"
@@ -68,38 +69,38 @@
 #include "nsIDragSession.h"
 #include "nsComponentManagerUtils.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsServiceManagerUtils.h"
 #include "nsNetUtil.h"
 #include "nsIFile.h"
 #include "nsIWebNavigation.h"
-#include "nsIClipboardDragDropHooks.h"
-#include "nsIClipboardDragDropHookList.h"
 #include "nsIDocShell.h"
 #include "nsIContent.h"
 #include "nsIImageLoadingContent.h"
 #include "nsINameSpaceManager.h"
 #include "nsUnicharUtils.h"
 #include "nsIURL.h"
 #include "nsIImage.h"
 #include "nsIDocument.h"
 #include "nsIScriptSecurityManager.h"
+#include "nsIPrincipal.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIFrame.h"
 #include "nsRange.h"
 #include "nsIWebBrowserPersist.h"
 #include "nsEscape.h"
 #include "nsContentUtils.h"
 #include "nsIMIMEService.h"
 #include "imgIRequest.h"
 #include "nsContentCID.h"
+#include "nsDOMDataTransfer.h"
 #include "nsISelectionController.h"
 #include "nsFrameSelection.h"
 #include "nsIDOMEventTarget.h"
 #include "nsWidgetsCID.h"
 
 static NS_DEFINE_CID(kHTMLConverterCID,        NS_HTMLFORMATCONVERTER_CID);
 
 // private clipboard data flavors for html copy, used by editor when pasting
@@ -109,53 +110,62 @@ static NS_DEFINE_CID(kHTMLConverterCID, 
 
 NS_IMPL_ADDREF(nsContentAreaDragDrop)
 NS_IMPL_RELEASE(nsContentAreaDragDrop)
 
 NS_INTERFACE_MAP_BEGIN(nsContentAreaDragDrop)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMDragListener)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMDragListener)
     NS_INTERFACE_MAP_ENTRY(nsIDOMDragListener)
-    NS_INTERFACE_MAP_ENTRY(nsIFlavorDataProvider)
     NS_INTERFACE_MAP_ENTRY(nsIDragDropHandler)
 NS_INTERFACE_MAP_END
 
 
 class NS_STACK_CLASS nsTransferableFactory
 {
 public:
-  nsTransferableFactory(nsIDOMEvent* inMouseEvent,
-                        nsIFlavorDataProvider *inFlavorDataProvider);
-  nsresult Produce(PRBool *aDragSelection, nsITransferable** outTrans);
+  nsTransferableFactory(nsIDOMWindow* aWindow,
+                        nsIContent* aTarget,
+                        nsIContent* aSelectionTargetNode,
+                        PRBool aIsAltKeyPressed);
+  nsresult Produce(nsDOMDataTransfer* aDataTransfer,
+                   PRBool* aCanDrag,
+                   PRBool* aDragSelection,
+                   nsIContent** aDragNode);
 
 private:
-  nsresult ConvertStringsToTransferable(nsITransferable** outTrans);
+  void AddString(nsDOMDataTransfer* aDataTransfer,
+                 const nsAString& aFlavor,
+                 const nsAString& aData,
+                 nsIPrincipal* aPrincipal);
+  nsresult AddStringsToDataTransfer(nsIContent* aDragNode,
+                                    nsDOMDataTransfer* aDataTransfer);
   static nsresult GetDraggableSelectionData(nsISelection* inSelection,
-                                            nsIDOMNode* inRealTargetNode,
-                                            nsIDOMNode **outImageOrLinkNode,
+                                            nsIContent* inRealTargetNode,
+                                            nsIContent **outImageOrLinkNode,
                                             PRBool* outDragSelectedText);
-  static already_AddRefed<nsIDOMNode> FindParentLinkNode(nsIDOMNode* inNode);
-  static void GetAnchorURL(nsIDOMNode* inNode, nsAString& outURL);
-  static void GetNodeString(nsIDOMNode* inNode, nsAString & outNodeString);
+  static already_AddRefed<nsIContent> FindParentLinkNode(nsIContent* inNode);
+  static void GetAnchorURL(nsIContent* inNode, nsAString& outURL);
+  static void GetNodeString(nsIContent* inNode, nsAString & outNodeString);
   static void CreateLinkText(const nsAString& inURL, const nsAString & inText,
                               nsAString& outLinkText);
   static void GetSelectedLink(nsISelection* inSelection,
-                              nsIDOMNode **outLinkNode);
+                              nsIContent **outLinkNode);
 
   // if inNode is null, use the selection from the window
   static nsresult SerializeNodeOrSelection(nsIDOMWindow* inWindow,
-                                           nsIDOMNode* inNode,
+                                           nsIContent* inNode,
                                            nsAString& outResultString,
                                            nsAString& outHTMLContext,
                                            nsAString& outHTMLInfo);
 
-  PRBool mInstanceAlreadyUsed;
-
-  nsCOMPtr<nsIDOMEvent> mMouseEvent;
-  nsCOMPtr<nsIFlavorDataProvider> mFlavorDataProvider;
+  nsCOMPtr<nsIDOMWindow> mWindow;
+  nsCOMPtr<nsIContent> mTarget;
+  nsCOMPtr<nsIContent> mSelectionTargetNode;
+  PRPackedBool mIsAltKeyPressed;
 
   nsString mUrlString;
   nsString mImageSourceString;
   nsString mImageDestFileName;
   nsString mTitleString;
   // will be filled automatically if you fill urlstring
   nsString mHtmlString;
   nsString mContextString;
@@ -287,101 +297,63 @@ nsContentAreaDragDrop::DragOver(nsIDOMEv
     nsuiEvent->GetPreventDefault(&preventDefault);
   if ( preventDefault )
     return NS_OK;
 
   // if the drag originated w/in this content area, bail
   // early. This avoids loading a URL dragged from the content
   // area into the very same content area (which is almost never
   // the desired action).
-  nsCOMPtr<nsIDragService> dragService =
-    do_GetService("@mozilla.org/widget/dragservice;1");
-  if (!dragService)
-    return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIDragSession> session;
-  dragService->GetCurrentSession(getter_AddRefs(session));
+  nsCOMPtr<nsIDragSession> session = nsContentUtils::GetDragSession();
+  NS_ENSURE_TRUE(session, NS_OK);
+
+  PRBool dropAllowed = PR_TRUE;
 
-  if (session) {
-    // if the client has provided an override callback, check if we
-    // the drop is allowed. If it allows it, we should still protect
-    // against dropping w/in the same document.
-    PRBool dropAllowed = PR_TRUE;
-    nsCOMPtr<nsISimpleEnumerator> enumerator;
-    GetHookEnumeratorFromEvent(inEvent, getter_AddRefs(enumerator));
+  nsCOMPtr<nsIDOMDocument> sourceDoc;
+  session->GetSourceDocument(getter_AddRefs(sourceDoc));
+  nsCOMPtr<nsIDOMDocument> eventDoc;
+  GetEventDocument(inEvent, getter_AddRefs(eventDoc));
+
+  if (sourceDoc == eventDoc) {  // common case
+    dropAllowed = PR_FALSE;
+  } else if (sourceDoc && eventDoc) {
+    // dig deeper
+    // XXXbz we need better ways to get from a document to the docshell!
+    nsCOMPtr<nsIDocument> sourceDocument(do_QueryInterface(sourceDoc));
+    nsCOMPtr<nsIDocument> eventDocument(do_QueryInterface(eventDoc));
+    NS_ASSERTION(sourceDocument, "Confused document object");
+    NS_ASSERTION(eventDocument, "Confused document object");
 
-    if (enumerator) {
-      PRBool hasMoreHooks = PR_FALSE;
-      while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
-             && hasMoreHooks) {
-        nsCOMPtr<nsISupports> isupp;
-        if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp)))) {
-          break;
-        }
+    nsPIDOMWindow* sourceWindow = sourceDocument->GetWindow();
+    nsPIDOMWindow* eventWindow = eventDocument->GetWindow();
+
+    if (sourceWindow && eventWindow) {
+      nsCOMPtr<nsIDocShellTreeItem> sourceShell =
+        do_QueryInterface(sourceWindow->GetDocShell());
+      nsCOMPtr<nsIDocShellTreeItem> eventShell =
+        do_QueryInterface(eventWindow->GetDocShell());
 
-        nsCOMPtr<nsIClipboardDragDropHooks> override =
-          do_QueryInterface(isupp);
+      if (sourceShell && eventShell) {
+        // Whew.  Almost there.  Get the roots that are of the same type
+        // (otherwise we'll always end up with the root docshell for the
+        // window, and drag/drop from chrom to content won't work).
+        nsCOMPtr<nsIDocShellTreeItem> sourceRoot;
+        nsCOMPtr<nsIDocShellTreeItem> eventRoot;
+        sourceShell->GetSameTypeRootTreeItem(getter_AddRefs(sourceRoot));
+        eventShell->GetSameTypeRootTreeItem(getter_AddRefs(eventRoot));
 
-        if (override) {
-#ifdef DEBUG
-          nsresult hookResult =
-#endif
-          override->AllowDrop(inEvent, session, &dropAllowed);
-          NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in AllowDrop");
-
-          if (!dropAllowed) {
-            break;
-          }
+        if (sourceRoot && sourceRoot == eventRoot) {
+          dropAllowed = PR_FALSE;
         }
       }
     }
-
-    nsCOMPtr<nsIDOMDocument> sourceDoc;
-    session->GetSourceDocument(getter_AddRefs(sourceDoc));
-    nsCOMPtr<nsIDOMDocument> eventDoc;
-    GetEventDocument(inEvent, getter_AddRefs(eventDoc));
-
-    if (sourceDoc == eventDoc) {  // common case
-      dropAllowed = PR_FALSE;
-    } else if (sourceDoc && eventDoc) {
-      // dig deeper
-      // XXXbz we need better ways to get from a document to the docshell!
-      nsCOMPtr<nsIDocument> sourceDocument(do_QueryInterface(sourceDoc));
-      nsCOMPtr<nsIDocument> eventDocument(do_QueryInterface(eventDoc));
-      NS_ASSERTION(sourceDocument, "Confused document object");
-      NS_ASSERTION(eventDocument, "Confused document object");
-
-      nsPIDOMWindow* sourceWindow = sourceDocument->GetWindow();
-      nsPIDOMWindow* eventWindow = eventDocument->GetWindow();
-
-      if (sourceWindow && eventWindow) {
-        nsCOMPtr<nsIDocShellTreeItem> sourceShell =
-          do_QueryInterface(sourceWindow->GetDocShell());
-        nsCOMPtr<nsIDocShellTreeItem> eventShell =
-          do_QueryInterface(eventWindow->GetDocShell());
-
-        if (sourceShell && eventShell) {
-          // Whew.  Almost there.  Get the roots that are of the same type
-          // (otherwise we'll always end up with the root docshell for the
-          // window, and drag/drop from chrom to content won't work).
-          nsCOMPtr<nsIDocShellTreeItem> sourceRoot;
-          nsCOMPtr<nsIDocShellTreeItem> eventRoot;
-          sourceShell->GetSameTypeRootTreeItem(getter_AddRefs(sourceRoot));
-          eventShell->GetSameTypeRootTreeItem(getter_AddRefs(eventRoot));
-
-          if (sourceRoot && sourceRoot == eventRoot) {
-            dropAllowed = PR_FALSE;
-          }
-        }
-      }
-    }
-
-    session->SetCanDrop(dropAllowed);
   }
 
+  session->SetCanDrop(dropAllowed);
   return NS_OK;
 }
 
 
 //
 // DragExit
 //
 // Called when an OS drag is in process and the mouse is over a gecko
@@ -492,27 +464,18 @@ nsContentAreaDragDrop::DragDrop(nsIDOMEv
 
   if (preventDefault) {
     return NS_OK;
   }
 
   // pull the transferable out of the drag service. at the moment, we
   // only care about the first item of the drag. We don't allow
   // dropping multiple items into a content area.
-  nsCOMPtr<nsIDragService> dragService =
-    do_GetService("@mozilla.org/widget/dragservice;1");
-  if (!dragService) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIDragSession> session;
-  dragService->GetCurrentSession(getter_AddRefs(session));
-  if (!session) {
-    return NS_ERROR_FAILURE;
-  }
+  nsCOMPtr<nsIDragSession> session = nsContentUtils::GetDragSession();
+  NS_ENSURE_TRUE(session, NS_OK);
 
   nsCOMPtr<nsITransferable> trans =
     do_CreateInstance("@mozilla.org/widget/transferable;1");
   if (!trans) {
     return NS_ERROR_FAILURE;
   }
 
   // add the relevant flavors. order is important (highest fidelity to lowest)
@@ -520,45 +483,16 @@ nsContentAreaDragDrop::DragDrop(nsIDOMEv
   trans->AddDataFlavor(kURLMime);
   trans->AddDataFlavor(kFileMime);
   trans->AddDataFlavor(kUnicodeMime);
 
   // again, we only care about the first object
   nsresult rv = session->GetData(trans, 0);
 
   if (NS_SUCCEEDED(rv)) {
-    // if the client has provided an override callback, call it. It may
-    // still return that we should continue processing.
-    nsCOMPtr<nsISimpleEnumerator> enumerator;
-    GetHookEnumeratorFromEvent(inMouseEvent, getter_AddRefs(enumerator));
-
-    if (enumerator) {
-      PRBool actionCanceled = PR_TRUE;
-      PRBool hasMoreHooks = PR_FALSE;
-      while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
-             && hasMoreHooks) {
-        nsCOMPtr<nsISupports> isupp;
-        if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp))))
-          break;
-        nsCOMPtr<nsIClipboardDragDropHooks> override =
-          do_QueryInterface(isupp);
-
-        if (override) {
-#ifdef DEBUG
-          nsresult hookResult =
-#endif
-          override->OnPasteOrDrop(inMouseEvent, trans, &actionCanceled);
-          NS_ASSERTION(NS_SUCCEEDED(hookResult),
-                       "hook failure in OnPasteOrDrop");
-          if (!actionCanceled)
-            return NS_OK;
-        }
-      }
-    }
-
     nsXPIDLCString flavor;
     nsCOMPtr<nsISupports> dataWrapper;
     PRUint32 dataLen = 0;
     rv = trans->GetAnyTransferData(getter_Copies(flavor),
                                    getter_AddRefs(dataWrapper), &dataLen);
     if (NS_SUCCEEDED(rv) && dataLen > 0) {
       // get the url from one of several possible formats
       nsAutoString url;
@@ -660,194 +594,64 @@ nsContentAreaDragDrop::GetEventDocument(
     nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(view));
 
     if (window) {
       window->GetDocument(outDocument);
     }
   }
 }
 
-nsresult
-nsContentAreaDragDrop::GetHookEnumeratorFromEvent(nsIDOMEvent* inEvent,
-                                                  nsISimpleEnumerator **outEnumerator)
-{
-  *outEnumerator = nsnull;
-
-  nsCOMPtr<nsIDOMDocument> domdoc;
-  GetEventDocument(inEvent, getter_AddRefs(domdoc));
-  nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
-  NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
-
-  nsCOMPtr<nsISupports> container = doc->GetContainer();
-  nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
-  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
-
-  nsCOMPtr<nsIClipboardDragDropHookList> hookList = do_GetInterface(docShell);
-  NS_ENSURE_TRUE(hookList, NS_ERROR_FAILURE);
-  nsCOMPtr<nsISimpleEnumerator> enumerator;
-  hookList->GetHookEnumerator(getter_AddRefs(enumerator));
-  NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
-
-  *outEnumerator = enumerator;
-  NS_ADDREF(*outEnumerator);
-
-  return NS_OK;
-}
-
 //
 // DragGesture
 //
-// Determine if the user has started to drag something and kick off
-// an OS-level drag if it's applicable
-//
 NS_IMETHODIMP
 nsContentAreaDragDrop::DragGesture(nsIDOMEvent* inMouseEvent)
 {
-  // first check that someone hasn't already handled this event
-  PRBool preventDefault = PR_TRUE;
-  nsCOMPtr<nsIDOMNSUIEvent> nsuiEvent(do_QueryInterface(inMouseEvent));
-  if (nsuiEvent) {
-    nsuiEvent->GetPreventDefault(&preventDefault);
-  }
-
-  if (preventDefault) {
-    return NS_OK;
-  }
-
-  // if the client has provided an override callback, check if we
-  // should continue
-  nsCOMPtr<nsISimpleEnumerator> enumerator;
-  GetHookEnumeratorFromEvent(inMouseEvent, getter_AddRefs(enumerator));
-
-  if (enumerator) {
-    PRBool allow = PR_TRUE;
-    PRBool hasMoreHooks = PR_FALSE;
-    while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
-           && hasMoreHooks) {
-      nsCOMPtr<nsISupports> isupp;
-      if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp))))
-        break;
-
-      nsCOMPtr<nsIClipboardDragDropHooks> override = do_QueryInterface(isupp);
-      if (override) {
-#ifdef DEBUG
-        nsresult hookResult =
-#endif
-        override->AllowStartDrag(inMouseEvent, &allow);
-        NS_ASSERTION(NS_SUCCEEDED(hookResult),
-                     "hook failure in AllowStartDrag");
-
-        if (!allow)
-          return NS_OK;
-      }
-    }
-  }
-
-  PRBool isSelection = PR_FALSE;
-  nsCOMPtr<nsITransferable> trans;
-  nsTransferableFactory factory(inMouseEvent, static_cast<nsIFlavorDataProvider*>(this));
-  factory.Produce(&isSelection, getter_AddRefs(trans));
-
-  if (trans) {
-    // if the client has provided an override callback, let them manipulate
-    // the flavors or drag data
-    nsCOMPtr<nsISimpleEnumerator> enumerator;
-    GetHookEnumeratorFromEvent(inMouseEvent, getter_AddRefs(enumerator));
-    if (enumerator) {
-      PRBool hasMoreHooks = PR_FALSE;
-      PRBool doContinueDrag = PR_TRUE;
-      while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
-             && hasMoreHooks) {
-        nsCOMPtr<nsISupports> isupp;
-        if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp))))
-          break;
-        nsCOMPtr<nsIClipboardDragDropHooks> override =
-          do_QueryInterface(isupp);
+  return NS_OK;
+}
 
-        if (override) {
-#ifdef DEBUG
-          nsresult hookResult =
-#endif
-          override->OnCopyOrDrag(inMouseEvent, trans, &doContinueDrag);
-          NS_ASSERTION(NS_SUCCEEDED(hookResult),
-                       "hook failure in OnCopyOrDrag");
-
-          if (!doContinueDrag) {
-            return NS_OK;
-          }
-        }
-      }
-    }
-
-    nsCOMPtr<nsISupportsArray> transArray =
-      do_CreateInstance("@mozilla.org/supports-array;1");
-    if (!transArray) {
-      return NS_ERROR_FAILURE;
-    }
-
-    transArray->InsertElementAt(trans, 0);
-
-    // kick off the drag
-    nsCOMPtr<nsIDOMEventTarget> target;
-    inMouseEvent->GetTarget(getter_AddRefs(target));
-    nsCOMPtr<nsIDragService> dragService =
-      do_GetService("@mozilla.org/widget/dragservice;1");
+nsresult
+nsContentAreaDragDrop::GetDragData(nsIDOMWindow* aWindow,
+                                   nsIContent* aTarget,
+                                   nsIContent* aSelectionTargetNode,
+                                   PRBool aIsAltKeyPressed,
+                                   nsDOMDataTransfer* aDataTransfer,
+                                   PRBool* aCanDrag,
+                                   PRBool* aDragSelection,
+                                   nsIContent** aDragNode)
+{
+  NS_ENSURE_TRUE(aSelectionTargetNode, NS_ERROR_INVALID_ARG);
 
-    if (!dragService) {
-      return NS_ERROR_FAILURE;
-    }
-
-    PRUint32 action = nsIDragService::DRAGDROP_ACTION_COPY +
-                      nsIDragService::DRAGDROP_ACTION_MOVE +
-                      nsIDragService::DRAGDROP_ACTION_LINK;
-
-    nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(inMouseEvent));
+  *aCanDrag = PR_TRUE;
 
-    if (isSelection) {
-      nsCOMPtr<nsIContent> targetContent(do_QueryInterface(target));
-      nsIDocument* doc = targetContent->GetCurrentDoc();
-      if (doc) {
-        nsIPresShell* presShell = doc->GetPrimaryShell();
-        if (presShell) {
-          nsISelection* selection =
-            presShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
-          return dragService->InvokeDragSessionWithSelection(selection,
-                                                             transArray,
-                                                             action,
-                                                             mouseEvent);
-        }
-      }
-    }
-
-    nsCOMPtr<nsIDOMNode> targetNode(do_QueryInterface(target));
-    dragService->InvokeDragSessionWithImage(targetNode, transArray, nsnull,
-                                            action, nsnull, 0, 0, mouseEvent);
-  }
-
-  return NS_OK;
+  nsTransferableFactory
+    factory(aWindow, aTarget, aSelectionTargetNode, aIsAltKeyPressed);
+  return factory.Produce(aDataTransfer, aCanDrag, aDragSelection, aDragNode);
 }
 
 
 NS_IMETHODIMP
 nsContentAreaDragDrop::HandleEvent(nsIDOMEvent *event)
 {
   return NS_OK;
 
 }
 
 #if 0
 #pragma mark -
 #endif
 
+NS_IMPL_ISUPPORTS1(nsContentAreaDragDropDataProvider, nsIFlavorDataProvider)
+
 // SaveURIToFile
 // used on platforms where it's possible to drag items (e.g. images)
 // into the file system
 nsresult
-nsContentAreaDragDrop::SaveURIToFile(nsAString& inSourceURIString,
-                                     nsIFile* inDestFile)
+nsContentAreaDragDropDataProvider::SaveURIToFile(nsAString& inSourceURIString,
+                                                 nsIFile* inDestFile)
 {
   nsCOMPtr<nsIURI> sourceURI;
   nsresult rv = NS_NewURI(getter_AddRefs(sourceURI), inSourceURIString);
   if (NS_FAILED(rv)) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIURL> sourceURL = do_QueryInterface(sourceURI);
@@ -860,37 +664,37 @@ nsContentAreaDragDrop::SaveURIToFile(nsA
 
   // we rely on the fact that the WPB is refcounted by the channel etc,
   // so we don't keep a ref to it. It will die when finished.
   nsCOMPtr<nsIWebBrowserPersist> persist =
     do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1",
                       &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return persist->SaveURI(sourceURI, nsnull, nsnull, nsnull, nsnull,
-                          inDestFile);
+  return persist->SaveURI(sourceURI, nsnull, nsnull, nsnull, nsnull, inDestFile);
 }
 
 // This is our nsIFlavorDataProvider callback. There are several
 // assumptions here that make this work:
 //
 // 1. Someone put a kFilePromiseURLMime flavor into the transferable
 //    with the source URI of the file to save (as a string). We did
-//    that above.
+//    that in AddStringsToDataTransfer.
 //
 // 2. Someone put a kFilePromiseDirectoryMime flavor into the
 //    transferable with an nsILocalFile for the directory we are to
 //    save in. That has to be done by platform-specific code (in
-//    widget), // which gets the destination directory from
-//    OS-specific drag // information.
+//    widget), which gets the destination directory from
+//    OS-specific drag information.
 //
 NS_IMETHODIMP
-nsContentAreaDragDrop::GetFlavorData(nsITransferable *aTransferable,
-                                     const char *aFlavor, nsISupports **aData,
-                                     PRUint32 *aDataLen)
+nsContentAreaDragDropDataProvider::GetFlavorData(nsITransferable *aTransferable,
+                                                 const char *aFlavor,
+                                                 nsISupports **aData,
+                                                 PRUint32 *aDataLen)
 {
   NS_ENSURE_ARG_POINTER(aData && aDataLen);
   *aData = nsnull;
   *aDataLen = 0;
 
   nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
 
   if (strcmp(aFlavor, kFilePromiseMime) == 0) {
@@ -932,75 +736,74 @@ nsContentAreaDragDrop::GetFlavorData(nsI
       return NS_ERROR_FAILURE;
 
     nsCOMPtr<nsIFile> file;
     rv = destDirectory->Clone(getter_AddRefs(file));
     NS_ENSURE_SUCCESS(rv, rv);
 
     file->Append(targetFilename);
 
-    // now save the file
     rv = SaveURIToFile(sourceURLString, file);
-
     // send back an nsILocalFile
     if (NS_SUCCEEDED(rv)) {
       CallQueryInterface(file, aData);
       *aDataLen = sizeof(nsIFile*);
     }
   }
 
   return rv;
 }
 
-nsTransferableFactory::nsTransferableFactory(nsIDOMEvent* inMouseEvent,
-                                             nsIFlavorDataProvider *dataProvider)
-  : mInstanceAlreadyUsed(PR_FALSE),
-    mMouseEvent(inMouseEvent),
-    mFlavorDataProvider(dataProvider)
+nsTransferableFactory::nsTransferableFactory(nsIDOMWindow* aWindow,
+                                             nsIContent* aTarget,
+                                             nsIContent* aSelectionTargetNode,
+                                             PRBool aIsAltKeyPressed)
+  : mWindow(aWindow),
+    mTarget(aTarget),
+    mSelectionTargetNode(aSelectionTargetNode),
+    mIsAltKeyPressed(aIsAltKeyPressed)
 {
 }
 
 
 //
 // FindParentLinkNode
 //
 // Finds the parent with the given link tag starting at |inNode|. If
 // it gets up to the root without finding it, we stop looking and
 // return null.
 //
-already_AddRefed<nsIDOMNode>
-nsTransferableFactory::FindParentLinkNode(nsIDOMNode* inNode)
+already_AddRefed<nsIContent>
+nsTransferableFactory::FindParentLinkNode(nsIContent* inNode)
 {
-  nsCOMPtr<nsIContent> content(do_QueryInterface(inNode));
+  nsIContent* content = inNode;
   if (!content) {
     // That must have been the document node; nothing else to do here;
     return nsnull;
   }
 
   for (; content; content = content->GetParent()) {
     if (nsContentUtils::IsDraggableLink(content)) {
-      nsIDOMNode* node = nsnull;
-      CallQueryInterface(content, &node);
-      return node;
+      NS_ADDREF(content);
+      return content;
     }
   }
 
   return nsnull;
 }
 
 
 //
 // GetAnchorURL
 //
 void
-nsTransferableFactory::GetAnchorURL(nsIDOMNode* inNode, nsAString& outURL)
+nsTransferableFactory::GetAnchorURL(nsIContent* inNode, nsAString& outURL)
 {
   nsCOMPtr<nsIURI> linkURI;
-  nsCOMPtr<nsIContent> content = do_QueryInterface(inNode);
-  if (!content || !content->IsLink(getter_AddRefs(linkURI))) {
+  if (!inNode || !inNode->IsLink(getter_AddRefs(linkURI))) {
     // Not a link
     outURL.Truncate();
     return;
   }
 
   nsCAutoString spec;
   linkURI->GetSpec(spec);
   CopyUTF8toUTF16(spec, outURL);
@@ -1032,190 +835,166 @@ nsTransferableFactory::CreateLinkText(co
 
 
 //
 // GetNodeString
 //
 // Gets the text associated with a node
 //
 void
-nsTransferableFactory::GetNodeString(nsIDOMNode* inNode,
+nsTransferableFactory::GetNodeString(nsIContent* inNode,
                                      nsAString & outNodeString)
 {
+  nsCOMPtr<nsIDOMNode> node = do_QueryInterface(inNode);
+
   outNodeString.Truncate();
 
   // use a range to get the text-equivalent of the node
   nsCOMPtr<nsIDOMDocument> doc;
-  inNode->GetOwnerDocument(getter_AddRefs(doc));
+  node->GetOwnerDocument(getter_AddRefs(doc));
   nsCOMPtr<nsIDOMDocumentRange> docRange(do_QueryInterface(doc));
   if (docRange) {
     nsCOMPtr<nsIDOMRange> range;
     docRange->CreateRange(getter_AddRefs(range));
     if (range) {
-      range->SelectNode(inNode);
+      range->SelectNode(node);
       range->ToString(outNodeString);
     }
   }
 }
 
 
 nsresult
-nsTransferableFactory::Produce(PRBool* aDragSelection,
-                               nsITransferable** outTrans)
+nsTransferableFactory::Produce(nsDOMDataTransfer* aDataTransfer,
+                               PRBool* aCanDrag,
+                               PRBool* aDragSelection,
+                               nsIContent** aDragNode)
 {
-  if (mInstanceAlreadyUsed) {
-    return NS_ERROR_FAILURE;
-  }
+  NS_PRECONDITION(aCanDrag && aDragSelection && aDataTransfer && aDragNode,
+                  "null pointer passed to Produce");
+  NS_ASSERTION(mWindow, "window not set");
+  NS_ASSERTION(mSelectionTargetNode, "selection target node should have been set");
 
-  if (!outTrans || !mMouseEvent || !mFlavorDataProvider) {
-    return NS_ERROR_FAILURE;
-  }
+  *aDragNode = nsnull;
 
-  mInstanceAlreadyUsed = PR_TRUE;
-  *outTrans = nsnull;
+  nsIContent* dragNode = nsnull;
 
-  nsCOMPtr<nsIDOMWindow> window;
-  PRBool isAltKeyDown = PR_FALSE;
   mIsAnchor = PR_FALSE;
 
-  {
-    nsCOMPtr<nsIDOMUIEvent> uiEvent(do_QueryInterface(mMouseEvent));
-    if (!uiEvent) {
-      return NS_OK;
-    }
-
-    // find the selection to see what we could be dragging and if
-    // what we're dragging is in what is selected.
-    nsCOMPtr<nsIDOMAbstractView> view;
-    uiEvent->GetView(getter_AddRefs(view));
-    window = do_QueryInterface(view);
-    if (!window) {
-      return NS_OK;
-    }
-  }
-
-  {
-    nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(mMouseEvent));
-    if (mouseEvent) {
-      mouseEvent->GetAltKey(&isAltKeyDown);
-    }
-  }
-
+  // find the selection to see what we could be dragging and if
+  // what we're dragging is in what is selected.
   nsCOMPtr<nsISelection> selection;
-  window->GetSelection(getter_AddRefs(selection));
+  mWindow->GetSelection(getter_AddRefs(selection));
   if (!selection) {
     return NS_OK;
   }
 
+  // check if the node is inside a form control. If so, dragging will be
+  // handled in editor code (nsPlaintextDataTransfer::DoDrag). Don't set
+  // aCanDrag to false however, as we still want to allow the drag.
+  nsCOMPtr<nsIContent> findFormNode = mSelectionTargetNode;
+  nsIContent* findFormParent = findFormNode->GetParent();
+  while (findFormParent) {
+    nsCOMPtr<nsIFormControl> form(do_QueryInterface(findFormParent));
+    if (form && form->GetType() != NS_FORM_OBJECT)
+      return NS_OK;
+    findFormParent = findFormParent->GetParent();
+  }
+    
   // if set, serialize the content under this node
-  nsCOMPtr<nsIDOMNode> nodeToSerialize;
-  PRBool useSelectedText = PR_FALSE;
+  nsCOMPtr<nsIContent> nodeToSerialize;
   *aDragSelection = PR_FALSE;
 
   {
     PRBool haveSelectedContent = PR_FALSE;
 
     // possible parent link node
-    nsCOMPtr<nsIDOMNode> parentLink;
-    nsCOMPtr<nsIDOMNode> draggedNode;
+    nsCOMPtr<nsIContent> parentLink;
+    nsCOMPtr<nsIContent> draggedNode;
 
     {
-      nsCOMPtr<nsIDOMEventTarget> target;
-      mMouseEvent->GetTarget(getter_AddRefs(target));
-
       // only drag form elements by using the alt key,
       // otherwise buttons and select widgets are hard to use
 
       // Note that while <object> elements implement nsIFormControl, we should
       // really allow dragging them if they happen to be images.
-      nsCOMPtr<nsIFormControl> form(do_QueryInterface(target));
-      if (form && !isAltKeyDown && form->GetType() != NS_FORM_OBJECT) {
+      nsCOMPtr<nsIFormControl> form(do_QueryInterface(mTarget));
+      if (form && !mIsAltKeyPressed && form->GetType() != NS_FORM_OBJECT) {
+        *aCanDrag = PR_FALSE;
         return NS_OK;
       }
 
-      draggedNode = do_QueryInterface(target);
+      draggedNode = mTarget;
     }
 
     nsCOMPtr<nsIDOMHTMLAreaElement>   area;   // client-side image map
     nsCOMPtr<nsIImageLoadingContent>  image;
     nsCOMPtr<nsIDOMHTMLAnchorElement> link;
 
-    {
-      // Get the real target and see if it is in the selection
-      nsCOMPtr<nsIDOMNode> realTargetNode;
+    nsCOMPtr<nsIContent> selectedImageOrLinkNode;
+    GetDraggableSelectionData(selection, mSelectionTargetNode,
+                              getter_AddRefs(selectedImageOrLinkNode),
+                              &haveSelectedContent);
 
-      {
-        nsCOMPtr<nsIDOMNSEvent> internalEvent = do_QueryInterface(mMouseEvent);
-        if (internalEvent) {
-          nsCOMPtr<nsIDOMEventTarget> realTarget;
-          internalEvent->GetExplicitOriginalTarget(getter_AddRefs(realTarget));
-          realTargetNode = do_QueryInterface(realTarget);
-        }
+    // either plain text or anchor text is selected
+    if (haveSelectedContent) {
+      link = do_QueryInterface(selectedImageOrLinkNode);
+      if (link && mIsAltKeyPressed) {
+        // if alt is pressed, select the link text instead of drag the link
+        *aCanDrag = PR_FALSE;
+        return NS_OK;
       }
 
-      {
-        nsCOMPtr<nsIDOMNode> selectedImageOrLinkNode;
-        GetDraggableSelectionData(selection, realTargetNode,
-                                  getter_AddRefs(selectedImageOrLinkNode),
-                                  &haveSelectedContent);
-
-        // either plain text or anchor text is selected
-        if (haveSelectedContent) {
-          link = do_QueryInterface(selectedImageOrLinkNode);
-          if (link && isAltKeyDown) {
-            return NS_OK;
-          }
+      *aDragSelection = PR_TRUE;
+    } else if (selectedImageOrLinkNode) {
+      // an image is selected
+      image = do_QueryInterface(selectedImageOrLinkNode);
+    } else {
+      // nothing is selected -
+      //
+      // look for draggable elements under the mouse
+      //
+      // if the alt key is down, don't start a drag if we're in an
+      // anchor because we want to do selection.
+      parentLink = FindParentLinkNode(draggedNode);
+      if (parentLink && mIsAltKeyPressed) {
+        *aCanDrag = PR_FALSE;
+        return NS_OK;
+      }
 
-          useSelectedText = PR_TRUE;
-          *aDragSelection = PR_TRUE;
-        } else if (selectedImageOrLinkNode) {
-          // an image is selected
-          image = do_QueryInterface(selectedImageOrLinkNode);
-        } else {
-          // nothing is selected -
-          //
-          // look for draggable elements under the mouse
-          //
-          // if the alt key is down, don't start a drag if we're in an
-          // anchor because we want to do selection.
-          parentLink = FindParentLinkNode(draggedNode);
-          if (parentLink && isAltKeyDown) {
-            return NS_OK;
-          }
-
-          area  = do_QueryInterface(draggedNode);
-          image = do_QueryInterface(draggedNode);
-          link  = do_QueryInterface(draggedNode);
-        }
-      }
+      area  = do_QueryInterface(draggedNode);
+      image = do_QueryInterface(draggedNode);
+      link  = do_QueryInterface(draggedNode);
     }
 
     {
       // set for linked images, and links
-      nsCOMPtr<nsIDOMNode> linkNode;
+      nsCOMPtr<nsIContent> linkNode;
 
       if (area) {
         // use the alt text (or, if missing, the href) as the title
         area->GetAttribute(NS_LITERAL_STRING("alt"), mTitleString);
         if (mTitleString.IsEmpty()) {
           // this can be a relative link
           area->GetAttribute(NS_LITERAL_STRING("href"), mTitleString);
         }
 
         // we'll generate HTML like <a href="absurl">alt text</a>
         mIsAnchor = PR_TRUE;
 
         // gives an absolute link
-        GetAnchorURL(area, mUrlString);
+        GetAnchorURL(draggedNode, mUrlString);
 
         mHtmlString.AssignLiteral("<a href=\"");
         mHtmlString.Append(mUrlString);
         mHtmlString.AppendLiteral("\">");
         mHtmlString.Append(mTitleString);
         mHtmlString.AppendLiteral("</a>");
+
+        dragNode = draggedNode;
       } else if (image) {
         mIsAnchor = PR_TRUE;
         // grab the href as the url, use alt text as the title of the
         // area if it's there.  the drag data is the image tag and src
         // attribute.
         nsCOMPtr<nsIURI> imageURI;
         image->GetCurrentURI(getter_AddRefs(imageURI));
         if (imageURI) {
@@ -1305,45 +1084,47 @@ nsTransferableFactory::Produce(PRBool* a
         }
 
         if (parentLink) {
           // If we are dragging around an image in an anchor, then we
           // are dragging the entire anchor
           linkNode = parentLink;
           nodeToSerialize = linkNode;
         } else {
-          nodeToSerialize = draggedNode;
+          nodeToSerialize = do_QueryInterface(draggedNode);
         }
+        dragNode = nodeToSerialize;
       } else if (link) {
         // set linkNode. The code below will handle this
-        linkNode = link;    // XXX test this
+        linkNode = do_QueryInterface(link);    // XXX test this
         GetNodeString(draggedNode, mTitleString);
       } else if (parentLink) {
         // parentLink will always be null if there's selected content
         linkNode = parentLink;
         nodeToSerialize = linkNode;
       } else if (!haveSelectedContent) {
         // nothing draggable
         return NS_OK;
       }
 
       if (linkNode) {
         mIsAnchor = PR_TRUE;
         GetAnchorURL(linkNode, mUrlString);
+        dragNode = linkNode;
       }
     }
   }
 
-  if (nodeToSerialize || useSelectedText) {
+  if (nodeToSerialize || *aDragSelection) {
     // if we have selected text, use it in preference to the node
-    if (useSelectedText) {
+    if (*aDragSelection) {
       nodeToSerialize = nsnull;
     }
 
-    SerializeNodeOrSelection(window, nodeToSerialize,
+    SerializeNodeOrSelection(mWindow, nodeToSerialize,
                              mHtmlString, mContextString, mInfoString);
 
     nsCOMPtr<nsIFormatConverter> htmlConverter =
       do_CreateInstance(kHTMLConverterCID);
     NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE);
 
     nsCOMPtr<nsISupportsString> html =
       do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
@@ -1369,173 +1150,141 @@ nsTransferableFactory::Produce(PRBool* a
   if (mTitleString.IsEmpty()) {
     mTitleString = mUrlString;
   }
 
   // if we haven't constructed a html version, make one now
   if (mHtmlString.IsEmpty() && !mUrlString.IsEmpty())
     CreateLinkText(mUrlString, mTitleString, mHtmlString);
 
-  return ConvertStringsToTransferable(outTrans);
+  // if there is no drag node, which will be the case for a selection, just
+  // use the selection target node.
+  nsresult rv = AddStringsToDataTransfer(
+           dragNode ? dragNode : mSelectionTargetNode.get(), aDataTransfer);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  NS_IF_ADDREF(*aDragNode = dragNode);
+  return NS_OK;
+}
+
+void
+nsTransferableFactory::AddString(nsDOMDataTransfer* aDataTransfer,
+                                 const nsAString& aFlavor,
+                                 const nsAString& aData,
+                                 nsIPrincipal* aPrincipal)
+{
+  nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
+  if (variant) {
+    variant->SetAsAString(aData);
+    aDataTransfer->SetDataWithPrincipal(aFlavor, variant, 0, aPrincipal);
+  }
 }
 
 nsresult
-nsTransferableFactory::ConvertStringsToTransferable(nsITransferable** outTrans)
+nsTransferableFactory::AddStringsToDataTransfer(nsIContent* aDragNode,
+                                                nsDOMDataTransfer* aDataTransfer)
 {
-  // now create the transferable and stuff data into it.
-  nsCOMPtr<nsITransferable> trans =
-    do_CreateInstance("@mozilla.org/widget/transferable;1");
-  NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
+  NS_ASSERTION(aDragNode, "adding strings for null node");
+
+  // set all of the data to have the principal of the node where the data came from
+  nsIPrincipal* principal = aDragNode->NodePrincipal();
 
   // add a special flavor if we're an anchor to indicate that we have
   // a URL in the drag data
   if (!mUrlString.IsEmpty() && mIsAnchor) {
     nsAutoString dragData(mUrlString);
     dragData.AppendLiteral("\n");
     dragData += mTitleString;
 
-    nsCOMPtr<nsISupportsString> urlPrimitive =
-      do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
-    NS_ENSURE_TRUE(urlPrimitive, NS_ERROR_FAILURE);
-
-    urlPrimitive->SetData(dragData);
-    trans->SetTransferData(kURLMime, urlPrimitive,
-                           dragData.Length() * sizeof(PRUnichar));
-
-    nsCOMPtr<nsISupportsString> urlDataPrimitive =
-      do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
-    NS_ENSURE_TRUE(urlDataPrimitive, NS_ERROR_FAILURE);
-
-    urlDataPrimitive->SetData(mUrlString);
-    trans->SetTransferData(kURLDataMime, urlDataPrimitive,
-                           mUrlString.Length() * sizeof(PRUnichar));
-
-    nsCOMPtr<nsISupportsString> urlDescPrimitive =
-      do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
-    NS_ENSURE_TRUE(urlDescPrimitive, NS_ERROR_FAILURE);
-
-    urlDescPrimitive->SetData(mTitleString);
-    trans->SetTransferData(kURLDescriptionMime, urlDescPrimitive,
-                           mTitleString.Length() * sizeof(PRUnichar));
+    AddString(aDataTransfer, NS_LITERAL_STRING(kURLMime), dragData, principal);
+    AddString(aDataTransfer, NS_LITERAL_STRING(kURLDataMime), mUrlString, principal);
+    AddString(aDataTransfer, NS_LITERAL_STRING(kURLDescriptionMime), mTitleString, principal);
+    AddString(aDataTransfer, NS_LITERAL_STRING("text/uri-list"), mUrlString, principal);
   }
 
   // add a special flavor, even if we don't have html context data
-  nsCOMPtr<nsISupportsString> context =
-    do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
-  NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
-
-  nsAutoString contextData(mContextString);
-  context->SetData(contextData);
-  trans->SetTransferData(kHTMLContext, context, contextData.Length() * 2);
+  AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), mContextString, principal);
 
   // add a special flavor if we have html info data
-  if (!mInfoString.IsEmpty()) {
-    nsCOMPtr<nsISupportsString> info =
-      do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
-    NS_ENSURE_TRUE(info, NS_ERROR_FAILURE);
-
-    nsAutoString infoData(mInfoString);
-    info->SetData(infoData);
-    trans->SetTransferData(kHTMLInfo, info, infoData.Length() * 2);
-  }
+  if (!mInfoString.IsEmpty())
+    AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), mInfoString, principal);
 
   // add the full html
-  nsCOMPtr<nsISupportsString> htmlPrimitive =
-    do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
-  NS_ENSURE_TRUE(htmlPrimitive, NS_ERROR_FAILURE);
-
-  htmlPrimitive->SetData(mHtmlString);
-  trans->SetTransferData(kHTMLMime, htmlPrimitive,
-                         mHtmlString.Length() * sizeof(PRUnichar));
+  AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLMime), mHtmlString, principal);
 
-  // add the plain (unicode) text. we use the url for text/unicode
-  // data if an anchor is being dragged, rather than the title text of
-  // the link or the alt text for an anchor image.
-  nsCOMPtr<nsISupportsString> textPrimitive =
-    do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
-  NS_ENSURE_TRUE(textPrimitive, NS_ERROR_FAILURE);
-
-  textPrimitive->SetData(mIsAnchor ? mUrlString : mTitleString);
-  trans->SetTransferData(kUnicodeMime, textPrimitive,
-                         (mIsAnchor ? mUrlString.Length() :
-                          mTitleString.Length()) * sizeof(PRUnichar));
+  // add the plain text. we use the url for text/plain data if an anchor is
+  // being dragged, rather than the title text of the link or the alt text for
+  // an anchor image.
+  AddString(aDataTransfer, NS_LITERAL_STRING(kTextMime),
+            mIsAnchor ? mUrlString : mTitleString, principal);
 
   // add image data, if present. For now, all we're going to do with
   // this is turn it into a native data flavor, so indicate that with
   // a new flavor so as not to confuse anyone who is really registered
   // for image/gif or image/jpg.
   if (mImage) {
-    nsCOMPtr<nsISupportsInterfacePointer> ptrPrimitive =
-      do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID);
-    NS_ENSURE_TRUE(ptrPrimitive, NS_ERROR_FAILURE);
+    nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
+    if (variant) {
+      variant->SetAsISupports(mImage);
+      aDataTransfer->SetDataWithPrincipal(NS_LITERAL_STRING(kNativeImageMime),
+                                          variant, 0, principal);
+    }
 
-    ptrPrimitive->SetData(mImage);
-    trans->SetTransferData(kNativeImageMime, ptrPrimitive,
-                           sizeof(nsISupportsInterfacePointer*));
     // assume the image comes from a file, and add a file promise. We
     // register ourselves as a nsIFlavorDataProvider, and will use the
     // GetFlavorData callback to save the image to disk.
-    trans->SetTransferData(kFilePromiseMime, mFlavorDataProvider,
-                           nsITransferable::kFlavorHasDataProvider);
-
-    nsCOMPtr<nsISupportsString> imageUrlPrimitive =
-      do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
-    NS_ENSURE_TRUE(imageUrlPrimitive, NS_ERROR_FAILURE);
 
-    imageUrlPrimitive->SetData(mImageSourceString);
-    trans->SetTransferData(kFilePromiseURLMime, imageUrlPrimitive,
-                           mImageSourceString.Length() * sizeof(PRUnichar));
+    nsCOMPtr<nsIFlavorDataProvider> dataProvider =
+      new nsContentAreaDragDropDataProvider();
+    if (dataProvider) {
+      nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
+      if (variant) {
+        variant->SetAsISupports(dataProvider);
+        aDataTransfer->SetDataWithPrincipal(NS_LITERAL_STRING(kFilePromiseMime),
+                                            variant, 0, principal);
+      }
+    }
 
-    nsCOMPtr<nsISupportsString> imageFileNamePrimitive =
-      do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
-    NS_ENSURE_TRUE(imageFileNamePrimitive, NS_ERROR_FAILURE);
-
-    imageFileNamePrimitive->SetData(mImageDestFileName);
-    trans->SetTransferData(kFilePromiseDestFilename, imageFileNamePrimitive,
-                           mImageDestFileName.Length() * sizeof(PRUnichar));
+    AddString(aDataTransfer, NS_LITERAL_STRING(kFilePromiseURLMime),
+              mImageSourceString, principal);
+    AddString(aDataTransfer, NS_LITERAL_STRING(kFilePromiseDestFilename),
+              mImageDestFileName, principal);
 
     // if not an anchor, add the image url
     if (!mIsAnchor) {
-      nsCOMPtr<nsISupportsString> urlDataPrimitive =
-        do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
-      NS_ENSURE_TRUE(urlDataPrimitive, NS_ERROR_FAILURE);
-
-      urlDataPrimitive->SetData(mUrlString);
-      trans->SetTransferData(kURLDataMime, urlDataPrimitive,
-                             mUrlString.Length() * sizeof(PRUnichar));
+      AddString(aDataTransfer, NS_LITERAL_STRING(kURLDataMime), mUrlString, principal);
+      AddString(aDataTransfer, NS_LITERAL_STRING("text/uri-list"), mUrlString, principal);
     }
   }
 
-  *outTrans = trans;
-  NS_IF_ADDREF(*outTrans);
-
   return NS_OK;
 }
 
 // note that this can return NS_OK, but a null out param (by design)
 // static
 nsresult
 nsTransferableFactory::GetDraggableSelectionData(nsISelection* inSelection,
-                                                 nsIDOMNode* inRealTargetNode,
-                                                 nsIDOMNode **outImageOrLinkNode,
+                                                 nsIContent* inRealTargetNode,
+                                                 nsIContent **outImageOrLinkNode,
                                                  PRBool* outDragSelectedText)
 {
   NS_ENSURE_ARG(inSelection);
   NS_ENSURE_ARG(inRealTargetNode);
   NS_ENSURE_ARG_POINTER(outImageOrLinkNode);
 
   *outImageOrLinkNode = nsnull;
   *outDragSelectedText = PR_FALSE;
 
   PRBool selectionContainsTarget = PR_FALSE;
 
   PRBool isCollapsed = PR_FALSE;
   inSelection->GetIsCollapsed(&isCollapsed);
   if (!isCollapsed) {
-    inSelection->ContainsNode(inRealTargetNode, PR_FALSE,
+    nsCOMPtr<nsIDOMNode> realTargetNode = do_QueryInterface(inRealTargetNode);
+    inSelection->ContainsNode(realTargetNode, PR_FALSE,
                               &selectionContainsTarget);
 
     if (selectionContainsTarget) {
       // track down the anchor node, if any, for the url
       nsCOMPtr<nsIDOMNode> selectionStart;
       inSelection->GetAnchorNode(getter_AddRefs(selectionStart));
 
       nsCOMPtr<nsIDOMNode> selectionEnd;
@@ -1559,18 +1308,17 @@ nsTransferableFactory::GetDraggableSelec
             if (selStartContent) {
               PRInt32 childOffset =
                 (anchorOffset < focusOffset) ? anchorOffset : focusOffset;
               nsIContent *childContent =
                 selStartContent->GetChildAt(childOffset);
               // if we find an image, we'll fall into the node-dragging code,
               // rather the the selection-dragging code
               if (nsContentUtils::IsDraggableImage(childContent)) {
-                CallQueryInterface(childContent, outImageOrLinkNode);
-
+                NS_ADDREF(*outImageOrLinkNode = childContent);
                 return NS_OK;
               }
             }
           }
         }
       }
 
       // see if the selection is a link;  if so, its node will be returned
@@ -1581,30 +1329,31 @@ nsTransferableFactory::GetDraggableSelec
     }
   }
 
   return NS_OK;
 }
 
 // static
 void nsTransferableFactory::GetSelectedLink(nsISelection* inSelection,
-                                            nsIDOMNode **outLinkNode)
+                                            nsIContent **outLinkNode)
 {
   *outLinkNode = nsnull;
 
-  nsCOMPtr<nsIDOMNode> selectionStart;
-  inSelection->GetAnchorNode(getter_AddRefs(selectionStart));
-  nsCOMPtr<nsIDOMNode> selectionEnd;
-  inSelection->GetFocusNode(getter_AddRefs(selectionEnd));
+  nsCOMPtr<nsIDOMNode> selectionStartNode;
+  inSelection->GetAnchorNode(getter_AddRefs(selectionStartNode));
+  nsCOMPtr<nsIDOMNode> selectionEndNode;
+  inSelection->GetFocusNode(getter_AddRefs(selectionEndNode));
 
   // simple case:  only one node is selected
   // see if it or its parent is an anchor, then exit
 
-  if (selectionStart == selectionEnd) {
-    nsCOMPtr<nsIDOMNode> link = FindParentLinkNode(selectionStart);
+  if (selectionStartNode == selectionEndNode) {
+    nsCOMPtr<nsIContent> selectionStart = do_QueryInterface(selectionStartNode);
+    nsCOMPtr<nsIContent> link = FindParentLinkNode(selectionStart);
     if (link) {
       link.swap(*outLinkNode);
     }
 
     return;
   }
 
   // more complicated case:  multiple nodes are selected
@@ -1622,87 +1371,89 @@ void nsTransferableFactory::GetSelectedL
     nsCOMPtr<nsIDOMRange> range;
     inSelection->GetRangeAt(0, getter_AddRefs(range));
     if (!range) {
       return;
     }
 
     nsCOMPtr<nsIDOMNode> tempNode;
     range->GetStartContainer( getter_AddRefs(tempNode));
-    if (tempNode != selectionStart) {
-      selectionEnd = selectionStart;
-      selectionStart = tempNode;
+    if (tempNode != selectionStartNode) {
+      selectionEndNode = selectionStartNode;
+      selectionStartNode = tempNode;
       inSelection->GetAnchorOffset(&endOffset);
       inSelection->GetFocusOffset(&startOffset);
     } else {
       inSelection->GetAnchorOffset(&startOffset);
       inSelection->GetFocusOffset(&endOffset);
     }
   }
 
   // trim leading node if the string is empty or
   // the selection starts at the end of the text
 
   nsAutoString nodeStr;
-  selectionStart->GetNodeValue(nodeStr);
+  selectionStartNode->GetNodeValue(nodeStr);
   if (nodeStr.IsEmpty() ||
       startOffset+1 >= static_cast<PRInt32>(nodeStr.Length())) {
-    nsCOMPtr<nsIDOMNode> curr = selectionStart;
+    nsCOMPtr<nsIDOMNode> curr = selectionStartNode;
     nsIDOMNode* next;
 
     while (curr) {
       curr->GetNextSibling(&next);
 
       if (next) {
-        selectionStart = dont_AddRef(next);
+        selectionStartNode = dont_AddRef(next);
         break;
       }
 
       curr->GetParentNode(&next);
       curr = dont_AddRef(next);
     }
   }
 
   // trim trailing node if the selection ends before its text begins
 
   if (endOffset == 0) {
-    nsCOMPtr<nsIDOMNode> curr = selectionEnd;
+    nsCOMPtr<nsIDOMNode> curr = selectionEndNode;
     nsIDOMNode* next;
 
     while (curr) {
       curr->GetPreviousSibling(&next);
 
       if (next){
-        selectionEnd = dont_AddRef(next);
+        selectionEndNode = dont_AddRef(next);
         break;
       }
 
       curr->GetParentNode(&next);
       curr = dont_AddRef(next);
     }
   }
 
   // see if the leading & trailing nodes are part of the
   // same anchor - if so, return the anchor node
-  nsCOMPtr<nsIDOMNode> link = FindParentLinkNode(selectionStart);
+  nsCOMPtr<nsIContent> selectionStart = do_QueryInterface(selectionStartNode);
+  nsCOMPtr<nsIContent> link = FindParentLinkNode(selectionStart);
   if (link) {
-    nsCOMPtr<nsIDOMNode> link2 = FindParentLinkNode(selectionEnd);
+    nsCOMPtr<nsIContent> selectionEnd = do_QueryInterface(selectionEndNode);
+    nsCOMPtr<nsIContent> link2 = FindParentLinkNode(selectionEnd);
 
     if (link == link2) {
       NS_IF_ADDREF(*outLinkNode = link);
     }
   }
 
   return;
 }
 
 // static
 nsresult
 nsTransferableFactory::SerializeNodeOrSelection(nsIDOMWindow* inWindow,
-                                                nsIDOMNode* inNode,
+                                                nsIContent* inNode,
                                                 nsAString& outResultString,
                                                 nsAString& outContext,
                                                 nsAString& outInfo)
 {
   NS_ENSURE_ARG_POINTER(inWindow);
 
   nsresult rv;
   nsCOMPtr<nsIDocumentEncoder> encoder =
@@ -1712,21 +1463,22 @@ nsTransferableFactory::SerializeNodeOrSe
   nsCOMPtr<nsIDOMDocument> domDoc;
   inWindow->GetDocument(getter_AddRefs(domDoc));
   NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
 
   PRUint32 flags = nsIDocumentEncoder::OutputAbsoluteLinks |
                    nsIDocumentEncoder::OutputEncodeHTMLEntities;
   nsCOMPtr<nsIDOMRange> range;
   nsCOMPtr<nsISelection> selection;
-  if (inNode) {
+  nsCOMPtr<nsIDOMNode> node = do_QueryInterface(inNode);
+  if (node) {
     // make a range around this node
     rv = NS_NewRange(getter_AddRefs(range));
     NS_ENSURE_SUCCESS(rv, rv);
-    rv = range->SelectNode(inNode);
+    rv = range->SelectNode(node);
     NS_ENSURE_SUCCESS(rv, rv);
   } else {
     inWindow->GetSelection(getter_AddRefs(selection));
     flags |= nsIDocumentEncoder::OutputSelectionOnly;
   }
 
   rv = encoder->Init(domDoc, NS_LITERAL_STRING(kHTMLMime), flags);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/content/base/src/nsContentAreaDragDrop.h
+++ b/content/base/src/nsContentAreaDragDrop.h
@@ -53,16 +53,17 @@ class nsITransferable;
 class nsIImage;
 class nsIPresShell;
 class nsPresContext;
 class nsIContent;
 class nsIDocument;
 class nsIURI;
 class nsIFile;
 class nsISimpleEnumerator;
+class nsDOMDataTransfer;
 
 // {1f34bc80-1bc7-11d6-a384-d705dd0746fc}
 #define NS_CONTENTAREADRAGDROP_CID             \
 { 0x1f34bc80, 0x1bc7, 0x11d6, \
   { 0xa3, 0x84, 0xd7, 0x05, 0xdd, 0x07, 0x46, 0xfc } }
 
 #define NS_CONTENTAREADRAGDROP_CONTRACTID "@mozilla.org:/content/content-area-dragdrop;1"
 
@@ -71,64 +72,98 @@ class nsISimpleEnumerator;
 // class nsContentAreaDragDrop
 //
 // The class that listens to the chrome events handles anything
 // related to drag and drop. Registers itself with the DOM with
 // AddChromeListeners() and removes itself with
 // RemoveChromeListeners().
 //
 class nsContentAreaDragDrop : public nsIDOMDragListener,
-                              public nsIDragDropHandler,
-                              public nsIFlavorDataProvider
+                              public nsIDragDropHandler
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDRAGDROPHANDLER
-  NS_DECL_NSIFLAVORDATAPROVIDER
   
   nsContentAreaDragDrop();
   virtual ~nsContentAreaDragDrop();
 
   // nsIDOMDragListener
   NS_IMETHOD DragEnter(nsIDOMEvent* aMouseEvent);
   NS_IMETHOD DragOver(nsIDOMEvent* aMouseEvent);
   NS_IMETHOD DragExit(nsIDOMEvent* aMouseEvent);
   NS_IMETHOD DragDrop(nsIDOMEvent* aMouseEvent);
   NS_IMETHOD DragGesture(nsIDOMEvent* aMouseEvent);
   NS_IMETHOD Drag(nsIDOMEvent* aMouseEvent);
   NS_IMETHOD DragEnd(nsIDOMEvent* aMouseEvent);
   NS_IMETHOD HandleEvent(nsIDOMEvent *event);
 
+  /**
+   * Determine what data in the content area, if any, is being dragged.
+   *
+   * aWindow - the window containing the target node
+   * aTarget - the mousedown event target that started the drag
+   * aSelectionTargetNode - the node where the drag event should be fired
+   * aIsAltKeyPressed - true if the Alt key is pressed. In some cases, this
+   *                    will prevent the drag from occuring. For example,
+   *                    holding down Alt over a link should select the text,
+   *                    not drag the link.
+   * aDataTransfer - the dataTransfer for the drag event.
+   * aCanDrag - [out] set to true if the drag may proceed, false to stop the
+   *            drag entirely
+   * aDragSelection - [out] set to true to indicate that a selection is being
+   *                  dragged, rather than a specific node
+   * aDragNode - [out] the link, image or area being dragged, or null if the
+   *             drag occured on another element.
+   */
+  static nsresult GetDragData(nsIDOMWindow* aWindow,
+                              nsIContent* aTarget,
+                              nsIContent* aSelectionTargetNode,
+                              PRBool aIsAltKeyPressed,
+                              nsDOMDataTransfer* aDataTransfer,
+                              PRBool* aCanDrag,
+                              PRBool* aDragSelection,
+                              nsIContent** aDragNode);
+
 private:
 
   // Add/remove the relevant listeners
   nsresult AddDragListener();
   nsresult RemoveDragListener();
 
   // utility routines
   static void NormalizeSelection(nsIDOMNode* inBaseNode,
                                  nsISelection* inSelection);
   static void GetEventDocument(nsIDOMEvent* inEvent,
                                nsIDOMDocument** outDocument);
 
-  static nsresult SaveURIToFile(nsAString& inSourceURIString,
-                                nsIFile* inDestFile);
-
-  void ExtractURLFromData(const nsACString & inFlavor,
-                          nsISupports* inDataWrapper, PRUint32 inDataLen,
-                          nsAString & outURL);
-  nsresult GetHookEnumeratorFromEvent(nsIDOMEvent* inEvent,
-                                      nsISimpleEnumerator** outEnumerator);
+  static void ExtractURLFromData(const nsACString & inFlavor,
+                                 nsISupports* inDataWrapper, PRUint32 inDataLen,
+                                 nsAString & outURL);
 
   PRPackedBool mListenerInstalled;
 
   nsCOMPtr<nsPIDOMEventTarget> mEventTarget;
 
   // weak ref, this is probably my owning webshell
   // FIXME: we set this and never null it out.  That's bad!  See bug 332187.
   nsIWebNavigation* mNavigator;
 
 };
 
+// this is used to save images to disk lazily when the image data is asked for
+// during the drop instead of when it is added to the drag data transfer. This
+// ensures that the image data is only created when an image drop is allowed.
+class nsContentAreaDragDropDataProvider : public nsIFlavorDataProvider
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIFLAVORDATAPROVIDER
+
+  virtual ~nsContentAreaDragDropDataProvider() {}
+
+  nsresult SaveURIToFile(nsAString& inSourceURIString,
+                         nsIFile* inDestFile);
+};
 
 
 #endif /* nsContentAreaDragDrop_h__ */
 
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -66,16 +66,19 @@
 #include "nsIContentViewer.h"
 #include "nsIAtom.h"
 #include "nsGkAtoms.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsNetCID.h"
 #include "nsIOfflineCacheUpdate.h"
+#include "nsIApplicationCache.h"
+#include "nsIApplicationCacheContainer.h"
+#include "nsIApplicationCacheService.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIDOMLoadStatus.h"
 #include "nsICookieService.h"
 #include "nsIPrompt.h"
 #include "nsServiceManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsParserUtils.h"
 #include "nsCRT.h"
@@ -89,16 +92,20 @@
 #include "nsIDOMNSDocument.h"
 #include "nsIRequest.h"
 #include "nsNodeUtils.h"
 #include "nsIDOMNode.h"
 #include "nsThreadUtils.h"
 #include "nsPresShellIterator.h"
 #include "nsPIDOMWindow.h"
 #include "mozAutoDocUpdate.h"
+#include "nsIWebNavigation.h"
+#include "nsIDocumentLoader.h"
+#include "nsICachingChannel.h"
+#include "nsICacheEntryDescriptor.h"
 
 PRLogModuleInfo* gContentSinkLogModuleInfo;
 
 class nsScriptLoaderObserverProxy : public nsIScriptLoaderObserver
 {
 public:
   nsScriptLoaderObserverProxy(nsIScriptLoaderObserver* aInner)
     : mInner(do_GetWeakReference(aInner))
@@ -840,71 +847,314 @@ nsContentSink::PrefetchHref(const nsAStr
               mDocumentBaseURI);
     if (uri) {
       nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aSource);
       prefetchService->PrefetchURI(uri, mDocumentURI, domNode, aExplicit);
     }
   }
 }
 
+nsresult
+nsContentSink::GetChannelCacheKey(nsIChannel* aChannel, nsACString& aCacheKey)
+{
+  aCacheKey.Truncate();
+
+  nsresult rv;
+  nsCOMPtr<nsICachingChannel> cachingChannel = do_QueryInterface(aChannel, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsISupports> token;
+  rv = cachingChannel->GetCacheToken(getter_AddRefs(token));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsICacheEntryDescriptor> descriptor = do_QueryInterface(token, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = descriptor->GetKey(aCacheKey);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
+nsresult
+nsContentSink::SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
+                                 nsIURI *aManifestURI,
+                                 PRBool aIsTopDocument,
+                                 PRBool aFetchedWithHTTPGetOrEquiv,
+                                 CacheSelectionAction *aAction)
+{
+  *aAction = CACHE_SELECTION_NONE;
+
+  nsCOMPtr<nsIApplicationCacheContainer> applicationCacheDocument =
+    do_QueryInterface(mDocument);
+  NS_ASSERTION(applicationCacheDocument,
+               "mDocument must implement nsIApplicationCacheContainer.");
+
+  nsresult rv;
+
+  // We might decide on a new application cache...
+  nsCOMPtr<nsIApplicationCache> applicationCache = aLoadApplicationCache;
+
+  if (applicationCache) {
+    nsCAutoString groupID;
+    rv = applicationCache->GetGroupID(groupID);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsCOMPtr<nsIURI> groupURI;
+    rv = NS_NewURI(getter_AddRefs(groupURI), groupID);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    PRBool equal = PR_FALSE;
+    rv = groupURI->Equals(aManifestURI, &equal);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (!equal) {
+      // This is a foreign entry, mark it as such.  If this is a
+      // toplevel load, force a reload to avoid loading the foreign
+      // entry.  The next attempt will not choose this cache entry
+      // (because it has been marked foreign).
+
+      nsCAutoString cachekey;
+      rv = GetChannelCacheKey(mDocument->GetChannel(), cachekey);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      rv = applicationCache->MarkEntry(cachekey,
+                                       nsIApplicationCache::ITEM_FOREIGN);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      if (aIsTopDocument) {
+        *aAction = CACHE_SELECTION_RELOAD;
+      }
+
+      return NS_OK;
+    }
+
+    if (aIsTopDocument) {
+      // This is a top level document and the http manifest attribute
+      // URI is equal to the manifest URI of the cache the document
+      // was loaded from - associate the document with that cache and
+      // invoke the cache update process.
+      rv = applicationCacheDocument->SetApplicationCache(applicationCache);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      *aAction = CACHE_SELECTION_UPDATE;
+    }
+  }
+  else {
+    // The document was not loaded from an application cache
+    // Here we know the manifest has the same origin as the
+    // document. There is call to CheckMayLoad() on it above.
+
+    if (!aFetchedWithHTTPGetOrEquiv) {
+      // The document was not loaded using HTTP GET or equivalent
+      // method. The spec says to run the cache selection algorithm w/o
+      // the manifest specified but we can just do return NS_OK here.
+
+      return NS_OK;
+    }
+
+    // If there is an existing application cache for this manifest,
+    // associate it with the document.
+    nsCAutoString manifestURISpec;
+    rv = aManifestURI->GetAsciiSpec(manifestURISpec);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsCOMPtr<nsIApplicationCacheService> appCacheService =
+      do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID);
+    if (!appCacheService) {
+      // No application cache service, nothing to do here.
+      return NS_OK;
+    }
+
+    rv = appCacheService->GetActiveCache(manifestURISpec,
+                                         getter_AddRefs(applicationCache));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (applicationCache) {
+      rv = applicationCacheDocument->SetApplicationCache(applicationCache);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+    else {
+      // XXX bug 443023: if there is already a scheduled update or
+      // update in progress we have to add this document as
+      // an implicit entry.
+    }
+
+    // Always do an update in this case
+    *aAction = CACHE_SELECTION_UPDATE;
+  }
+
+  if (applicationCache) {
+    // We are now associated with an application cache.  This item
+    // should be marked as an implicit entry.
+    nsCAutoString cachekey;
+    rv = GetChannelCacheKey(mDocument->GetChannel(), cachekey);
+    if (NS_SUCCEEDED(rv)) {
+      rv = applicationCache->MarkEntry(cachekey,
+                                       nsIApplicationCache::ITEM_IMPLICIT);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+  }
+
+  return NS_OK;
+}
+
+nsresult
+nsContentSink::SelectDocAppCacheNoManifest(nsIApplicationCache *aLoadApplicationCache,
+                                           PRBool aIsTopDocument,
+                                           nsIURI **aManifestURI,
+                                           CacheSelectionAction *aAction)
+{
+  *aManifestURI = nsnull;
+  *aAction = CACHE_SELECTION_NONE;
+
+  if (!aIsTopDocument || !aLoadApplicationCache) {
+    return NS_OK;
+  }
+
+  nsresult rv;
+
+  // The document was loaded from an application cache, use that
+  // application cache as the document's application cache.
+  nsCOMPtr<nsIApplicationCacheContainer> applicationCacheDocument =
+    do_QueryInterface(mDocument);
+  NS_ASSERTION(applicationCacheDocument,
+               "mDocument must implement nsIApplicationCacheContainer.");
+
+  rv = applicationCacheDocument->SetApplicationCache(aLoadApplicationCache);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Return the uri and invoke the update process for the selected
+  // application cache.
+  nsCAutoString groupID;
+  rv = aLoadApplicationCache->GetGroupID(groupID);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = NS_NewURI(aManifestURI, groupID);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *aAction = CACHE_SELECTION_UPDATE;
+
+  return NS_OK;
+}
+
 void
 nsContentSink::ProcessOfflineManifest(nsIContent *aElement)
 {
+  // Only check the manifest for root document nodes.
+  if (aElement != mDocument->GetRootContent()) {
+    return;
+  }
+
+  nsresult rv;
+
   // Check for a manifest= attribute.
   nsAutoString manifestSpec;
   aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::manifest, manifestSpec);
 
-  if (manifestSpec.IsEmpty() ||
-      manifestSpec.FindChar('#') != kNotFound) {
-    return;
+  // Grab the application cache the document was loaded from, if any.
+  nsCOMPtr<nsIApplicationCache> applicationCache;
+
+  nsCOMPtr<nsIApplicationCacheContainer> applicationCacheChannel =
+    do_QueryInterface(mDocument->GetChannel());
+  if (applicationCacheChannel) {
+    rv = applicationCacheChannel->GetApplicationCache(
+      getter_AddRefs(applicationCache));
+    if (NS_FAILED(rv)) {
+      return;
+    }
   }
 
-  // We only care about manifests in toplevel windows.
-  nsCOMPtr<nsPIDOMWindow> pwindow =
-    do_QueryInterface(mDocument->GetScriptGlobalObject());
-  if (!pwindow) {
-    return;
-  }
-
-  nsCOMPtr<nsIDOMWindow> window =
-    do_QueryInterface(pwindow->GetOuterWindow());
-  if (!window) {
-    return;
-  }
-
-  nsCOMPtr<nsIDOMWindow> parent;
-  window->GetParent(getter_AddRefs(parent));
-  if (parent.get() != window.get()) {
+  if (manifestSpec.IsEmpty() && !applicationCache) {
+    // Not loaded from an application cache, and no manifest
+    // attribute.  Nothing to do here.
     return;
   }
 
-  // Only update if the document has permission to use offline APIs.
-  if (!nsContentUtils::OfflineAppAllowed(mDocumentURI)) {
+  // The manifest attribute is handled differently if the document is
+  // not toplevel.
+  nsCOMPtr<nsIDOMWindow> window = mDocument->GetWindow();
+  if (!window)
     return;
+  nsCOMPtr<nsIDOMWindow> parent;
+  window->GetParent(getter_AddRefs(parent));
+  PRBool isTop = (parent == window);
+
+  CacheSelectionAction action = CACHE_SELECTION_NONE;
+  nsCOMPtr<nsIURI> manifestURI;
+
+  if (manifestSpec.IsEmpty()) {
+    rv = SelectDocAppCacheNoManifest(applicationCache,
+                                     isTop,
+                                     getter_AddRefs(manifestURI),
+                                     &action);
+    if (NS_FAILED(rv)) {
+      return;
+    }
+  }
+  else {
+    nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(manifestURI),
+                                              manifestSpec, mDocument,
+                                              mDocumentURI);
+    if (!manifestURI) {
+      return;
+    }
+
+    // Documents must list a manifest from the same origin
+    rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, PR_TRUE);
+    if (NS_FAILED(rv)) {
+      return;
+    }
+
+    // Only continue if the document has permission to use offline APIs.
+    if (!nsContentUtils::OfflineAppAllowed(mDocument->NodePrincipal())) {
+      return;
+    }
+
+    PRBool fetchedWithHTTPGetOrEquiv = PR_FALSE;
+    nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mDocument->GetChannel()));
+    if (httpChannel) {
+      nsCAutoString method;
+      rv = httpChannel->GetRequestMethod(method);
+      if (NS_SUCCEEDED(rv))
+        fetchedWithHTTPGetOrEquiv = method.Equals("GET");
+    }
+
+    rv = SelectDocAppCache(applicationCache, manifestURI, isTop,
+                           fetchedWithHTTPGetOrEquiv, &action);
+    if (NS_FAILED(rv)) {
+      return;
+    }
   }
 
-  nsCOMPtr<nsIURI> manifestURI;
-  nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(manifestURI),
-                                            manifestSpec, mDocument,
-                                            mDocumentURI);
-  if (!manifestURI) {
+  switch (action)
+  {
+  case CACHE_SELECTION_NONE:
     return;
-  }
+  case CACHE_SELECTION_UPDATE: {
+    nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
+      do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
 
-  // Documents must list a manifest from the same origin
-  nsresult rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, PR_TRUE);
-  if (NS_FAILED(rv)) {
-    return;
+    if (updateService) {
+      nsCOMPtr<nsIDOMDocument> domdoc = do_QueryInterface(mDocument);
+      updateService->ScheduleOnDocumentStop(manifestURI, mDocumentURI, domdoc);
+    }
+    break;
   }
+  case CACHE_SELECTION_RELOAD: {
+    // This situation occurs only for toplevel documents, see bottom
+    // of SelectDocAppCache method.
+    NS_ASSERTION(isTop, "Should only reload toplevel documents!");
+    nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(mDocShell);
 
-  // Start the update
-  nsCOMPtr<nsIDOMDocument> domdoc = do_QueryInterface(mDocument);
-  nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
-    do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
-  updateService->ScheduleOnDocumentStop(manifestURI, mDocumentURI, domdoc);
+    webNav->Stop(nsIWebNavigation::STOP_ALL);
+    webNav->Reload(nsIWebNavigation::LOAD_FLAGS_NONE);
+    break;
+  }
+  }
 }
 
 void
 nsContentSink::ScrollToRef()
 {
   if (mRef.IsEmpty()) {
     return;
   }
@@ -1414,16 +1664,20 @@ nsContentSink::EndUpdate(nsIDocument *aD
   if (aUpdateType != UPDATE_CONTENT_STATE && !--mInNotification) {
     UpdateChildCounts();
   }
 }
 
 void
 nsContentSink::DidBuildModelImpl(void)
 {
+  if (!mDocument->HaveFiredDOMTitleChange()) {
+    mDocument->NotifyPossibleTitleChange(PR_FALSE);
+  }
+
   // Cancel a timer if we had one out there
   if (mNotificationTimer) {
     SINK_TRACE(gContentSinkLogModuleInfo, SINK_TRACE_REFLOW,
                ("nsContentSink::DidBuildModel: canceling notification "
                 "timeout"));
     mNotificationTimer->Cancel();
     mNotificationTimer = 0;
   }	
--- a/content/base/src/nsContentSink.h
+++ b/content/base/src/nsContentSink.h
@@ -71,16 +71,17 @@ class nsIDocShell;
 class nsICSSLoader;
 class nsIParser;
 class nsIAtom;
 class nsIChannel;
 class nsIContent;
 class nsIViewManager;
 class nsNodeInfoManager;
 class nsScriptLoader;
+class nsIApplicationCache;
 
 #ifdef NS_DEBUG
 
 extern PRLogModuleInfo* gContentSinkLogModuleInfo;
 
 #define SINK_TRACE_CALLS              0x1
 #define SINK_TRACE_REFLOW             0x2
 #define SINK_ALWAYS_REFLOW            0x4
@@ -145,16 +146,35 @@ class nsContentSink : public nsICSSLoade
   virtual void EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType);
 
   virtual void UpdateChildCounts() = 0;
 
 protected:
   nsContentSink();
   virtual ~nsContentSink();
 
+  enum CacheSelectionAction {
+    // There is no offline cache manifest specified by the document,
+    // or the document was loaded from a cache other than the one it
+    // specifies via its manifest attribute and IS NOT a top-level
+    // document, or an error occurred during the cache selection
+    // algorithm.
+    CACHE_SELECTION_NONE = 0,
+
+    // The offline cache manifest must be updated.
+    CACHE_SELECTION_UPDATE = 1,
+
+    // The document was loaded from a cache other than the one it
+    // specifies via its manifest attribute and IS a top-level
+    // document.  In this case, the document is marked as foreign in
+    // the cache it was loaded from and must be reloaded from the
+    // correct cache (the one it specifies).
+    CACHE_SELECTION_RELOAD = 2
+  };
+
   nsresult Init(nsIDocument* aDoc, nsIURI* aURI,
                 nsISupports* aContainer, nsIChannel* aChannel);
 
   nsresult ProcessHTTPHeaders(nsIChannel* aChannel);
   nsresult ProcessHeaderData(nsIAtom* aHeader, const nsAString& aValue,
                              nsIContent* aContent = nsnull);
   nsresult ProcessLinkHeader(nsIContent* aElement,
                              const nsAString& aLinkData);
@@ -166,16 +186,70 @@ protected:
                                     const nsSubstring& aHref,
                                     PRBool aAlternate,
                                     const nsSubstring& aTitle,
                                     const nsSubstring& aType,
                                     const nsSubstring& aMedia);
 
   void PrefetchHref(const nsAString &aHref, nsIContent *aSource,
                     PRBool aExplicit);
+
+  // Gets the cache key (used to identify items in a cache) of the channel.
+  nsresult GetChannelCacheKey(nsIChannel* aChannel, nsACString& aCacheKey);
+
+  // There is an offline cache manifest attribute specified and the
+  // document is allowed to use the offline cache.  Process the cache
+  // selection algorithm for this document and the manifest. Result is
+  // an action that must be taken on the manifest, see
+  // CacheSelectionAction enum above.
+  //
+  // @param aLoadApplicationCache
+  //        The application cache from which the load originated, if
+  //        any.
+  // @param aManifestURI
+  //        The manifest URI listed in the document.
+  // @param aIsTopDocument
+  //        TRUE if this is a toplevel document.
+  // @param aFetchedWithHTTPGetOrEquiv
+  //        TRUE if this was fetched using the HTTP GET method.
+  // @param aAction
+  //        Out parameter, returns the action that should be performed
+  //        by the calling function.
+  nsresult SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
+                             nsIURI *aManifestURI,
+                             PRBool aIsTopDocument,
+                             PRBool aFetchedWithHTTPGetOrEquiv,
+                             CacheSelectionAction *aAction);
+
+  // There is no offline cache manifest attribute specified.  Process
+  // the cache selection algorithm w/o the manifest. Result is an
+  // action that must be taken, see CacheSelectionAction enum
+  // above. In case the offline cache manifest has to be updated the
+  // manifest URI is returned in aManifestURI.
+  //
+  // @param aLoadApplicationCache
+  //        The application cache from which the load originated, if
+  //        any.
+  // @param aIsTopDocument
+  //        TRUE if this is a toplevel document.
+  // @param aManifestURI
+  //        Out parameter, returns the manifest URI of the cache that
+  //        was selected.
+  // @param aAction
+  //        Out parameter, returns the action that should be performed
+  //        by the calling function.
+  nsresult SelectDocAppCacheNoManifest(nsIApplicationCache *aLoadApplicationCache,
+                                       PRBool aIsTopDocument,
+                                       nsIURI **aManifestURI,
+                                       CacheSelectionAction *aAction);
+
+  // Searches for the offline cache manifest attribute and calls one
+  // of the above defined methods to select the document's application
+  // cache, let it be associated with the document and eventually
+  // schedule the cache update process.
   void ProcessOfflineManifest(nsIContent *aElement);
 
   // Tries to scroll to the URI's named anchor. Once we've successfully
   // done that, further calls to this method will be ignored.
   void ScrollToRef();
   nsresult RefreshIfEnabled(nsIViewManager* vm);
 
   // Start layout.  If aIgnorePendingSheets is true, this will happen even if
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -149,16 +149,17 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "nsIPermissionManager.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIRunnable.h"
 #include "nsDOMJSUtils.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValue.h"
 #include "nsReferencedElement.h"
 #include "nsIUGenCategory.h"
+#include "nsIDragService.h"
 
 #ifdef IBMBIDI
 #include "nsIBidiKeyboard.h"
 #endif
 #include "nsCycleCollectionParticipant.h"
 
 // for ReportToConsole
 #include "nsIStringBundle.h"
@@ -412,23 +413,26 @@ nsContentUtils::InitializeEventTable() {
     { &nsGkAtoms::onclose,                       { NS_XUL_CLOSE, EventNameType_XUL }},
     { &nsGkAtoms::onpopupshowing,                { NS_XUL_POPUP_SHOWING, EventNameType_XUL }},
     { &nsGkAtoms::onpopupshown,                  { NS_XUL_POPUP_SHOWN, EventNameType_XUL }},
     { &nsGkAtoms::onpopuphiding,                 { NS_XUL_POPUP_HIDING, EventNameType_XUL }},
     { &nsGkAtoms::onpopuphidden,                 { NS_XUL_POPUP_HIDDEN, EventNameType_XUL }},
     { &nsGkAtoms::oncommand,                     { NS_XUL_COMMAND, EventNameType_XUL }},
     { &nsGkAtoms::onbroadcast,                   { NS_XUL_BROADCAST, EventNameType_XUL }},
     { &nsGkAtoms::oncommandupdate,               { NS_XUL_COMMAND_UPDATE, EventNameType_XUL }},
-    { &nsGkAtoms::ondragenter,                   { NS_DRAGDROP_ENTER, EventNameType_XUL }},
-    { &nsGkAtoms::ondragover,                    { NS_DRAGDROP_OVER_SYNTH, EventNameType_XUL }},
+    { &nsGkAtoms::ondragenter,                   { NS_DRAGDROP_ENTER, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::ondragover,                    { NS_DRAGDROP_OVER_SYNTH, EventNameType_HTMLXUL }},
     { &nsGkAtoms::ondragexit,                    { NS_DRAGDROP_EXIT_SYNTH, EventNameType_XUL }},
-    { &nsGkAtoms::ondragdrop,                    { NS_DRAGDROP_DROP, EventNameType_XUL }},
+    { &nsGkAtoms::ondragdrop,                    { NS_DRAGDROP_DRAGDROP, EventNameType_XUL }},
     { &nsGkAtoms::ondraggesture,                 { NS_DRAGDROP_GESTURE, EventNameType_XUL }},
-    { &nsGkAtoms::ondrag,                        { NS_DRAGDROP_DRAG, EventNameType_XUL }},
-    { &nsGkAtoms::ondragend,                     { NS_DRAGDROP_END, EventNameType_XUL }},
+    { &nsGkAtoms::ondrag,                        { NS_DRAGDROP_DRAG, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::ondragend,                     { NS_DRAGDROP_END, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::ondragstart,                   { NS_DRAGDROP_START, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::ondragleave,                   { NS_DRAGDROP_LEAVE_SYNTH, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::ondrop,                        { NS_DRAGDROP_DROP, EventNameType_HTMLXUL }},
     { &nsGkAtoms::onoverflow,                    { NS_SCROLLPORT_OVERFLOW, EventNameType_XUL }},
     { &nsGkAtoms::onunderflow,                   { NS_SCROLLPORT_UNDERFLOW, EventNameType_XUL }}
 #ifdef MOZ_SVG
    ,{ &nsGkAtoms::onSVGLoad,                     { NS_SVG_LOAD, EventNameType_None }},
     { &nsGkAtoms::onSVGUnload,                   { NS_SVG_UNLOAD, EventNameType_None }},
     { &nsGkAtoms::onSVGAbort,                    { NS_SVG_ABORT, EventNameType_None }},
     { &nsGkAtoms::onSVGError,                    { NS_SVG_ERROR, EventNameType_None }},
     { &nsGkAtoms::onSVGResize,                   { NS_SVG_RESIZE, EventNameType_None }},
@@ -799,51 +803,27 @@ nsContentUtils::GetOfflineAppManifest(ns
   nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec,
                                             topDoc, topDoc->GetBaseURI());
 }
 
 /* static */
 PRBool
 nsContentUtils::OfflineAppAllowed(nsIURI *aURI)
 {
-  nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
-  if (!innerURI)
-    return PR_FALSE;
-
-  // only http and https applications can use offline APIs.
-  PRBool match;
-  nsresult rv = innerURI->SchemeIs("http", &match);
-  NS_ENSURE_SUCCESS(rv, PR_FALSE);
-
-  if (!match) {
-    rv = innerURI->SchemeIs("https", &match);
-    NS_ENSURE_SUCCESS(rv, PR_FALSE);
-    if (!match) {
-      return PR_FALSE;
-    }
-  }
-
-  nsCOMPtr<nsIPermissionManager> permissionManager =
-    do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
-  if (!permissionManager) {
-    return PR_FALSE;
-  }
-
-  PRUint32 perm;
-  permissionManager->TestExactPermission(innerURI, "offline-app", &perm);
-
-  if (perm == nsIPermissionManager::UNKNOWN_ACTION) {
-    return GetBoolPref("offline-apps.allow_by_default");
-  }
-
-  if (perm == nsIPermissionManager::DENY_ACTION) {
-    return PR_FALSE;
-  }
-
-  return PR_TRUE;
+  return NS_OfflineAppAllowed(aURI, sPrefBranch);
+}
+
+/* static */
+PRBool
+nsContentUtils::OfflineAppAllowed(nsIPrincipal *aPrincipal)
+{
+  nsCOMPtr<nsIURI> codebaseURI;
+  aPrincipal->GetURI(getter_AddRefs(codebaseURI));
+
+  return OfflineAppAllowed(codebaseURI);
 }
 
 // static
 void
 nsContentUtils::Shutdown()
 {
   sInitialized = PR_FALSE;
 
@@ -4303,16 +4283,28 @@ nsContentUtils::HidePopupsInDocument(nsI
     nsCOMPtr<nsIDocShellTreeItem> docShellToHide = do_QueryInterface(container);
     if (docShellToHide)
       pm->HidePopupsInDocShell(docShellToHide);
   }
 #endif
 }
 
 /* static */
+already_AddRefed<nsIDragSession>
+nsContentUtils::GetDragSession()
+{
+  nsIDragSession* dragSession = nsnull;
+  nsCOMPtr<nsIDragService> dragService =
+    do_GetService("@mozilla.org/widget/dragservice;1");
+  if (dragService)
+    dragService->GetCurrentSession(&dragSession);
+  return dragSession;
+}
+
+/* static */
 PRBool
 nsContentUtils::URIIsLocalFile(nsIURI *aURI)
 {
   PRBool isFile;
   nsCOMPtr<nsINetUtil> util = do_QueryInterface(sIOService);
 
   return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
                                 nsIProtocolHandler::URI_IS_LOCAL_FILE,
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1138,16 +1138,17 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMNode)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsPIDOMEventTarget)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOM3Node)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOM3Document)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsISupportsWeakReference)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIRadioGroupContainer)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMNodeSelector)
+    NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIApplicationCacheContainer)
     // nsNodeSH::PreCreate() depends on the identity pointer being the
     // same as nsINode (which nsIDocument inherits), so if you change
     // the below line, make sure nsNodeSH::PreCreate() still does the
     // right thing!
     NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsDocument, nsISupports, nsIDocument)
   NS_INTERFACE_TABLE_END
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsDocument)
   if (aIID.Equals(NS_GET_IID(nsIDOMXPathEvaluator)) ||
@@ -1949,16 +1950,32 @@ nsDocument::GetPrincipal()
 
 void
 nsDocument::SetPrincipal(nsIPrincipal *aNewPrincipal)
 {
   mNodeInfoManager->SetDocumentPrincipal(aNewPrincipal);
 }
 
 NS_IMETHODIMP
+nsDocument::GetApplicationCache(nsIApplicationCache **aApplicationCache)
+{
+  NS_IF_ADDREF(*aApplicationCache = mApplicationCache);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocument::SetApplicationCache(nsIApplicationCache *aApplicationCache)
+{
+  mApplicationCache = aApplicationCache;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDocument::GetContentType(nsAString& aContentType)
 {
   CopyUTF8toUTF16(mContentType, aContentType);
 
   return NS_OK;
 }
 
 void
@@ -3020,16 +3037,17 @@ nsDocument::SetScriptGlobalObject(nsIScr
         loadGroup->RemoveRequest(mOnloadBlocker, nsnull, NS_OK);
       }
     }
   }
 
   mScriptGlobalObject = aScriptGlobalObject;
 
   if (aScriptGlobalObject) {
+    mScriptObject = nsnull;
     mHasHadScriptHandlingObject = PR_TRUE;
     // Go back to using the docshell for the layout history state
     mLayoutHistoryState = nsnull;
     mScopeObject = do_GetWeakReference(aScriptGlobalObject);
   }
 
   // Remember the pointer to our window (or lack there of), to avoid
   // having to QI every time it's asked for.
@@ -4457,16 +4475,17 @@ nsDocument::NotifyPossibleTitleChange(PR
     mPendingTitleChangeEvent = event;
   }
 }
 
 void
 nsDocument::DoNotifyPossibleTitleChange()
 {
   mPendingTitleChangeEvent.Forget();
+  mHaveFiredTitleChange = PR_TRUE;
 
   nsAutoString title;
   GetTitle(title);
 
   nsPresShellIterator iter(this);
   nsCOMPtr<nsIPresShell> shell;
   while ((shell = iter.GetNextShell())) {
     nsCOMPtr<nsISupports> container = shell->GetPresContext()->GetContainer();
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -88,16 +88,18 @@
 #include "nsIRequest.h"
 #include "nsILoadGroup.h"
 #include "nsTObserverArray.h"
 #include "nsStubMutationObserver.h"
 #include "nsIChannel.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsContentList.h"
 #include "nsGkAtoms.h"
+#include "nsIApplicationCache.h"
+#include "nsIApplicationCacheContainer.h"
 
 // Put these here so all document impls get them automatically
 #include "nsHTMLStyleSheet.h"
 #include "nsIHTMLCSSStyleSheet.h"
 
 #include "nsStyleSet.h"
 #include "nsXMLEventsManager.h"
 #include "pldhash.h"
@@ -403,16 +405,17 @@ class nsDocument : public nsIDocument,
                    public nsIDOM3Document,
                    public nsSupportsWeakReference,
                    public nsIDOMEventTarget,
                    public nsIDOM3EventTarget,
                    public nsIDOMNSEventTarget,
                    public nsIScriptObjectPrincipal,
                    public nsIRadioGroupContainer,
                    public nsIDOMNodeSelector,
+                   public nsIApplicationCacheContainer,
                    public nsStubMutationObserver
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   virtual void Reset(nsIChannel *aChannel, nsILoadGroup *aLoadGroup);
   virtual void ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
                           nsIPrincipal* aPrincipal);
@@ -556,16 +559,22 @@ public:
    */
   virtual nsIScriptGlobalObject* GetScriptGlobalObject() const;
   virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aGlobalObject);
 
   virtual nsIScriptGlobalObject*
     GetScriptHandlingObject(PRBool& aHasHadScriptHandlingObject) const;
   virtual void SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject);
 
+  virtual void ClearScriptHandlingObject()
+  {
+    mScriptObject = nsnull;
+    mHasHadScriptHandlingObject = PR_TRUE;
+  }
+
   virtual nsIScriptGlobalObject* GetScopeObject();
 
   /**
    * Return the window containing the document (the outer window).
    */
   virtual nsPIDOMWindow *GetWindow();
 
   /**
@@ -747,16 +756,19 @@ public:
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
 
   // nsIScriptObjectPrincipal
   virtual nsIPrincipal* GetPrincipal();
 
+  // nsIApplicationCacheContainer
+  NS_DECL_NSIAPPLICATIONCACHECONTAINER
+
   virtual nsresult Init();
   
   virtual nsresult AddXMLEventsContent(nsIContent * aXMLEventsElement);
 
   virtual nsresult CreateElem(nsIAtom *aName, nsIAtom *aPrefix,
                               PRInt32 aNamespaceID,
                               PRBool aDocumentDefaultType,
                               nsIContent **aResult);
@@ -1016,16 +1028,20 @@ protected:
 
   nsCOMPtr<nsIScriptEventManager> mScriptEventManager;
 
   nsString mBaseTarget;
 
   // Our update nesting level
   PRUint32 mUpdateNestLevel;
 
+  // The application cache that this document is associated with, if
+  // any.  This can change during the lifetime of the document.
+  nsCOMPtr<nsIApplicationCache> mApplicationCache;
+
 private:
   friend class nsUnblockOnloadEvent;
 
   void PostUnblockOnloadEvent();
   void DoUnblockOnload();
 
   /**
    * See if aDocument is a child of this.  If so, return the frame element in
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -2786,19 +2786,21 @@ nsGenericElement::doPreHandleEvent(nsICo
   //FIXME! Document how this event retargeting works, Bug 329124.
   aVisitor.mCanHandle = PR_TRUE;
 
   // Don't propagate mouseover and mouseout events when mouse is moving
   // inside native anonymous content.
   PRBool isAnonForEvents = aContent->IsRootOfNativeAnonymousSubtree();
   if ((aVisitor.mEvent->message == NS_MOUSE_ENTER_SYNTH ||
        aVisitor.mEvent->message == NS_MOUSE_EXIT_SYNTH) &&
-      // This is an optimization - try to stop event propagation when
-      // event has just possibly been retargeted.
-      static_cast<nsISupports*>(aContent) == aVisitor.mEvent->target) {
+      // Check if we should stop event propagation when event has just been
+      // dispatched or when we're about to propagate from
+      // native anonymous subtree.
+      ((static_cast<nsISupports*>(aContent) == aVisitor.mEvent->originalTarget &&
+        !aContent->IsInNativeAnonymousSubtree()) || isAnonForEvents)) {
      nsCOMPtr<nsIContent> relatedTarget =
        do_QueryInterface(static_cast<nsMouseEvent*>
                                     (aVisitor.mEvent)->relatedTarget);
     if (relatedTarget &&
         relatedTarget->GetOwnerDoc() == aContent->GetOwnerDoc()) {
 
       // If current target is anonymous for events or we know that related
       // target is descendant of an element which is anonymous for events,
@@ -2818,29 +2820,47 @@ nsGenericElement::doPreHandleEvent(nsICo
             // native anonymous subtree. The case where anonOwner is still
             // inside native anonymous subtree will be handled when event
             // propagates up in the DOM tree.
             while (anonOwner != anonOwnerRelated &&
                    anonOwnerRelated->IsInNativeAnonymousSubtree()) {
               anonOwnerRelated = FindNativeAnonymousSubtreeOwner(anonOwnerRelated);
             }
             if (anonOwner == anonOwnerRelated) {
-              nsCOMPtr<nsIContent> target =
+#ifdef DEBUG_smaug
+              nsCOMPtr<nsIContent> originalTarget =
                 do_QueryInterface(aVisitor.mEvent->originalTarget);
-              // Because XBL and native anon content both do event re-targeting,
-              // static_cast<nsISupports*>(aContent) == aVisitor.mEvent->target
-              // optimization may not always work. So be paranoid and make
-              // sure we never stop event propagation when we shouldn't!
-              if (relatedTarget->FindFirstNonNativeAnonymous() ==
-                  target->FindFirstNonNativeAnonymous()) {
-                aVisitor.mParentTarget = nsnull;
-                // Event should not propagate to non-anon content.
-                aVisitor.mCanHandle = isAnonForEvents;
-                return NS_OK;
+              nsAutoString ot, ct, rt;
+              if (originalTarget) {
+                originalTarget->Tag()->ToString(ot);
               }
+              aContent->Tag()->ToString(ct);
+              relatedTarget->Tag()->ToString(rt);
+              printf("Stopping %s propagation:"
+                     "\n\toriginalTarget=%s \n\tcurrentTarget=%s %s"
+                     "\n\trelatedTarget=%s %s \n%s",
+                     (aVisitor.mEvent->message == NS_MOUSE_ENTER_SYNTH)
+                       ? "mouseover" : "mouseout",
+                     NS_ConvertUTF16toUTF8(ot).get(),
+                     NS_ConvertUTF16toUTF8(ct).get(),
+                     isAnonForEvents
+                       ? "(is native anonymous)"
+                       : (aContent->IsInNativeAnonymousSubtree()
+                           ? "(is in native anonymous subtree)" : ""),
+                     NS_ConvertUTF16toUTF8(rt).get(),
+                     relatedTarget->IsInNativeAnonymousSubtree()
+                       ? "(is in native anonymous subtree)" : "",
+                     (originalTarget && relatedTarget->FindFirstNonNativeAnonymous() ==
+                       originalTarget->FindFirstNonNativeAnonymous())
+                       ? "" : "Wrong event propagation!?!\n");
+#endif
+              aVisitor.mParentTarget = nsnull;
+              // Event should not propagate to non-anon content.
+              aVisitor.mCanHandle = isAnonForEvents;
+              return NS_OK;
             }
           }
         }
       }
     }
   }
 
   nsCOMPtr<nsIContent> parent = aContent->GetParent();
@@ -4126,19 +4146,19 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   // nsNodeSH::PreCreate() depends on the identity pointer being the
   // same as nsINode (which nsIContent inherits), so if you change the
   // below line, make sure nsNodeSH::PreCreate() still does the right
   // thing!
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsGenericElement, nsIContent)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS_WITH_DESTROY(nsGenericElement, 
-							nsIContent,
-							nsNodeUtils::LastRelease(this))
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS_WITH_DESTROY(nsGenericElement,
+                                                        nsIContent,
+                                                        nsNodeUtils::LastRelease(this))
 
 nsresult
 nsGenericElement::PostQueryInterface(REFNSIID aIID, void** aInstancePtr)
 {
   nsIDocument *document = GetOwnerDoc();
   if (document) {
     return document->BindingManager()->GetBindingImplementation(this, aIID,
                                                                 aInstancePtr);
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -399,18 +399,16 @@ class nsNSElementTearoff;
 class nsGenericElement : public nsIContent
 {
 public:
   nsGenericElement(nsINodeInfo *aNodeInfo);
   virtual ~nsGenericElement();
 
   friend class nsNSElementTearoff;
 
-  friend class nsNSElementTearoff;
-
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   /**
    * Called during QueryInterface to give the binding manager a chance to
    * get an interface for this element.
    */
   nsresult PostQueryInterface(REFNSIID aIID, void** aInstancePtr);
 
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -306,20 +306,24 @@ GK_ATOM(DOMNodeRemovedFromDocument, "DOM
 GK_ATOM(DOMSubtreeModified, "DOMSubtreeModified")
 GK_ATOM(double_, "double")
 GK_ATOM(drag, "drag")
 GK_ATOM(dragdrop, "dragdrop")
 GK_ATOM(dragend, "dragend")
 GK_ATOM(dragenter, "dragenter")
 GK_ATOM(dragevent, "dragevent")
 GK_ATOM(dragexit, "dragexit")
+GK_ATOM(draggable, "draggable")
 GK_ATOM(draggesture, "draggesture")
 GK_ATOM(dragging, "dragging")
+GK_ATOM(dragleave, "dragleave")
 GK_ATOM(dragover, "dragover")
 GK_ATOM(dragSession, "dragSession")
+GK_ATOM(dragstart, "dragstart")
+GK_ATOM(drop, "drop")
 GK_ATOM(dropAfter, "dropAfter")
 GK_ATOM(dropBefore, "dropBefore")
 GK_ATOM(dropOn, "dropOn")
 GK_ATOM(dt, "dt")
 GK_ATOM(editable, "editable")
 GK_ATOM(editing, "editing")
 GK_ATOM(editor, "editor")
 GK_ATOM(editorDisplayList, "EditorDisplay-List")
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -393,17 +393,17 @@ nsRange::ComparePoint(nsIDOMNode* aParen
   
   PRInt32 cmp;
   if ((cmp = nsContentUtils::ComparePoints(parent, aOffset,
                                            mStartParent, mStartOffset)) <= 0) {
     
     *aResult = cmp;
   }
   else if (nsContentUtils::ComparePoints(mEndParent, mEndOffset,
-                                         parent, aOffset) == -1) {
+                                         parent, aOffset) <= 0) {
     *aResult = 1;
   }
   else {
     *aResult = 0;
   }
   
   return NS_OK;
 }
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -880,25 +880,19 @@ nsXMLHttpRequest::ConvertBodyToText(nsAS
 
   PRInt32 dataLen = mResponseBody.Length();
   if (!dataLen)
     return NS_OK;
 
   nsresult rv = NS_OK;
 
   nsCAutoString dataCharset;
-  nsCOMPtr<nsIDOM3Document> document(do_QueryInterface(mDocument));
+  nsCOMPtr<nsIDocument> document(do_QueryInterface(mDocument));
   if (document) {
-    nsAutoString inputEncoding;
-    document->GetInputEncoding(inputEncoding);
-    if (DOMStringIsNull(inputEncoding)) {
-      dataCharset.AssignLiteral("UTF-8");
-    } else {
-      CopyUTF16toUTF8(inputEncoding, dataCharset);
-    }
+    dataCharset = document->GetDocumentCharacterSet();
   } else {
     if (NS_FAILED(DetectCharset(dataCharset)) || dataCharset.IsEmpty()) {
       // MS documentation states UTF-8 is default for responseText
       dataCharset.AssignLiteral("UTF-8");
     }
   }
 
   if (dataCharset.EqualsLiteral("ASCII")) {
@@ -1059,16 +1053,18 @@ nsXMLHttpRequest::Abort()
 
   // The ChangeState call above calls onreadystatechange handlers which
   // if they load a new url will cause nsXMLHttpRequest::OpenRequest to clear
   // the abort state bit. If this occurs we're not uninitialized (bug 361773).
   if (mState & XML_HTTP_REQUEST_ABORTED) {
     ChangeState(XML_HTTP_REQUEST_UNINITIALIZED, PR_FALSE);  // IE seems to do it
   }
 
+  mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
+
   return NS_OK;
 }
 
 /* string getAllResponseHeaders (); */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetAllResponseHeaders(char **_retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
@@ -1933,19 +1929,25 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
           nsMemory::Free(iid);
 
         // document?
         nsCOMPtr<nsIDOMDocument> doc(do_QueryInterface(supports));
         if (doc) {
           nsCOMPtr<nsIDOMSerializer> serializer(do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID, &rv));
           if (NS_FAILED(rv)) return rv;
 
-          nsCOMPtr<nsIDocument> baseDoc(do_QueryInterface(doc));
-          if (baseDoc) {
-            charset = baseDoc->GetDocumentCharacterSet();
+          nsCOMPtr<nsIDOM3Document> dom3doc(do_QueryInterface(doc));
+          if (dom3doc) {
+            nsAutoString inputEncoding;
+            dom3doc->GetInputEncoding(inputEncoding);
+            if (DOMStringIsNull(inputEncoding)) {
+              charset.AssignLiteral("UTF-8");
+            } else {
+              CopyUTF16toUTF8(inputEncoding, charset);
+            }
           }
 
           // Serialize to a stream so that the encoding used will
           // match the document's.
           nsCOMPtr<nsIStorageStream> storStream;
           rv = NS_NewStorageStream(4096, PR_UINT32_MAX, getter_AddRefs(storStream));
           NS_ENSURE_SUCCESS(rv, rv);
 
@@ -2337,18 +2339,16 @@ nsXMLHttpRequest::BeforeUnload(nsIDOMEve
   return NS_OK;
 }
 
 nsresult
 nsXMLHttpRequest::Abort(nsIDOMEvent* aEvent)
 {
   Abort();
 
-  mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
-
   return NS_OK;
 }
 
 nsresult
 nsXMLHttpRequest::Error(nsIDOMEvent* aEvent)
 {
   mDocument = nsnull;
   ChangeState(XML_HTTP_REQUEST_COMPLETED);
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -179,22 +179,24 @@ include $(topsrcdir)/config/rules.mk
 		file_XHR_pass3.txt \
 		file_XHR_pass3.txt^headers^ \
 		file_XHR_fail1.txt \
 		file_XHR_fail1.txt^headers^ \
 		test_bug428847.html \
 		file_bug428847-1.xhtml \
 		file_bug428847-2.xhtml \
 		test_bug425201.html \
+		test_bug431701.html \
 		test_bug431833.html \
 		test_bug435425.html \
 		bug435425.sjs \
 		bug435425_redirect.sjs \
 		test_bug438519.html \
 		test_bug444722.html \
+		test_bug451376.html \
 		test_text_replaceWholeText.html \
 		test_text_wholeText.html \
 		wholeTexty-helper.xml \
 		test_bug444030.xhtml \
 		test_NodeIterator_basics_filters.xhtml \
 		test_NodeIterator_mutations_1.xhtml \
 		test_NodeIterator_mutations_2.html \
 		test_bug28293.html \
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug431701.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=431701
+-->
+<head>
+  <title>Test for Bug 431701</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=431701">Mozilla Bug 431701</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <iframe id="one"></iframe>
+  <iframe id="two"></iframe>
+  <iframe id="three"></iframe>
+  <iframe id="four"></iframe>
+  <iframe id="five"></iframe>
+  <iframe id="six"></iframe>
+  <iframe id="seven"></iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 431701 **/
+SimpleTest.waitForExplicitFinish();
+
+var docSources = [
+  "data:text/html,<html></html>",
+  "data:text/html;charset=UTF-8,<html></html>",
+  "data:text/html;charset=ISO-8859-1,<html></html>",
+  "data:text/xml,<html></html>",
+  "data:text/xml,<?xml version='1.0'?><html></html>",
+  "data:text/xml,<?xml version='1.0' encoding='UTF-8'?><html></html>",
+  "data:text/xml,<?xml version='1.0' encoding='ISO-8859-1'?><html></html>",
+];
+
+for (var i = 0; i < docSources.length; ++i) {
+  document.getElementsByTagName("iframe")[i].src = docSources[i];
+}
+
+function frameDoc(id) {
+  return function() { return $(id).contentDocument; };
+}
+
+function createDoc() {
+  return document.implementation.createDocument('', 'html', null);
+}
+
+function xhrDoc(idx) {
+  return function() {
+    // Defy same-origin restrictions!
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    var xhr = new XMLHttpRequest();
+    xhr.open("GET", docSources[idx], false);
+    xhr.send();
+    return xhr.responseXML;
+  };
+}
+
+// Each row has the document getter function, then the characterSet,
+// inputEncoding, xmlEncoding expected for that document.
+
+var tests = [
+ [ frameDoc("one"), "ISO-8859-1", "ISO-8859-1", null ],
+ [ frameDoc("two"), "UTF-8", "UTF-8", null ],
+ [ frameDoc("three"), "ISO-8859-1", "ISO-8859-1", null ],
+ [ frameDoc("four"), "UTF-8", "UTF-8", null ],
+ [ frameDoc("five"), "UTF-8", "UTF-8", null ],
+ [ frameDoc("six"), "UTF-8", "UTF-8", "UTF-8"],
+ [ frameDoc("seven"), "ISO-8859-1", "ISO-8859-1", "ISO-8859-1" ],
+ [ createDoc, "UTF-8", null, null ],
+ [ xhrDoc(4), "UTF-8", "UTF-8", null ],
+ [ xhrDoc(5), "UTF-8", "UTF-8", "UTF-8" ],
+ [ xhrDoc(6), "ISO-8859-1", "ISO-8859-1", "ISO-8859-1" ],
+];
+
+function doTest(idx) {
+  var [docGetter, expectedCharacterSet,
+       expectedInputEncoding, expectedXMLEncoding] = tests[idx];
+  var doc = docGetter();
+
+  // Have to be careful here to catch null vs ""
+  is(doc.characterSet, expectedCharacterSet, "Test " + idx + " characterSet");
+  is(doc.inputEncoding, expectedInputEncoding,
+     "Test " + idx + " inputEncoding");
+  is(doc.xmlEncoding, expectedXMLEncoding, "Test " + idx + " xmlEncoding");
+}
+
+addLoadEvent(function() {
+  // sanity check
+  isnot("", null, "Shouldn't be equal!");
+
+  for (var i = 0; i < tests.length; ++i) {
+    doTest(i);
+  }
+
+  // Now check what xhr does
+  var xhr = new XMLHttpRequest();
+  xhr.open("POST", document.location.href);
+  xhr.send(createDoc());
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  is(xhr.channel.QueryInterface(Components.interfaces.nsIHttpChannel)
+                .getRequestHeader("Content-Type"),
+     "application/xml; charset=UTF-8", "Testing correct type on the wire");
+  xhr.abort();
+                     
+  SimpleTest.finish();
+});
+
+
+
+
+</script>
+</pre>
+</body>
+</html>
+
--- a/content/base/test/test_bug435425.html
+++ b/content/base/test/test_bug435425.html
@@ -30,17 +30,18 @@ function logEvent(evt) {
   while ((currentEvents.length != i) &&
          currentEvents[i].optional &&
          ((currentEvents[i].type != evt.type) ||
           (!evt.target instanceof currentEvents[i].target))) {
     ++i;
   }
   ok(i != currentEvents.length, "Extra or wrong event?");
   is(evt.type, currentEvents[i].type, "Wrong event!")
-  ok(evt.target instanceof currentEvents[i].target, "Wrong event target [" + evt.type + "]!");
+  ok(evt.target instanceof currentEvents[i].target,
+     "Wrong event target [" + evt.target + "," + evt.type + "]!");
   // If we handled non-optional event, remove all optional events before the 
   // handled event and then the non-optional event from the list.
   if (!currentEvents[i].optional) {
     for (;i != -1; --i) {
       currentEvents.shift();
     }
   }
 }
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug451376.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=451376
+-->
+<head>
+  <title>Test for Bug 451376</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+
+<body onload="doTest()">
+  <a target="_blank"
+     title="IAccessibleText::attributes provides incorrect info after a mis-spelled word"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=451376">Mozilla Bug 451376</a>
+  <p id="display"></p>
+  <div id="content" style="display:none">
+  </div>
+  <pre id="test">
+
+  <div id="area"><button>btn1</button>text<button>btn2</button></div>
+
+  <script class="testbody" type="text/javascript">
+    SimpleTest.waitForExplicitFinish();
+
+    function testRange(aRangeID,
+                       aStartNode, aStartOffset,
+                       aEndNode, aEndOffset,
+                       aBeforeRangeNode, aBeforeRangeOffset,
+                       aInRangeNode, aInRangeOffset,
+                       aAfterRangeNode, aAfterRangeOffset)
+    {
+      var range = document.createRange().
+        QueryInterface(Components.interfaces.nsIDOMNSRange);
+
+      range.setStart(aStartNode, aStartOffset);
+      range.setEnd(aEndNode, aEndOffset);
+
+      if (aBeforeRangeNode)
+        is(range.comparePoint(aBeforeRangeNode, aBeforeRangeOffset), -1,
+           "Wrong result for the point before the range '" + aRangeID + "'");
+      if (aInRangeNode)
+        is(range.comparePoint(aInRangeNode, aInRangeOffset), 0,
+           "Wrong result for the point inside the range '" + aRangeID + "'");
+      if (aAfterRangeNode)
+        is(range.comparePoint(aAfterRangeNode, aAfterRangeOffset), 1,
+           "Wrong result for the point after the range '" + aRangeID + "'");
+    }
+
+    function doTest()
+    {
+      var area = document.getElementById("area");
+      var btn1 = area.firstChild;
+      var text = btn1.nextSibling;
+      var btn2 = area.lastChild;
+
+      testRange("range1", area, 0, area, 1,
+                null, 0,
+                area, 0,
+                area, 1);
+
+      testRange("range2", text, 2, text, 4,
+                text, 0,
+                text, 3,
+                text, 4);
+
+      testRange("range3", text, 4, area, 2,
+                text, 0,
+                text, 4,
+                area, 2);
+
+      SimpleTest.finish();
+    }
+  </script>
+</pre>
+</body>
+</html>
+
--- a/content/base/test/test_title.html
+++ b/content/base/test/test_title.html
@@ -71,16 +71,17 @@ function testDynamics() {
       var t = doc.getElementById("t"); t.textContent = "Hello";
     });
   testDynamic("html2", "Foo", "Removing HTML <title>", function(doc){
       var t = doc.getElementById("t"); t.parentNode.removeChild(t);
     });
   testDynamic("html3", "Hello", "Appending HTML <title> element to root element", function(doc){
       var t = doc.createElement("title"); t.textContent = "Hello"; doc.documentElement.appendChild(t);
     });
+
   testDynamic("xhtml3", "Hello", "Setting 'title' clears existing <title> contents", function(doc){
       doc.title = "Hello";
     }, function(doc, desc) {
       is(doc.documentElement.firstChild.data, "Hello", desc);
       is(doc.documentElement.firstChild.nextSibling, null, desc);
     });
   // This one does nothing and won't fire an event
   document.getElementById("xhtml4").contentDocument.title = "Hello";
@@ -128,35 +129,17 @@ function testDynamics() {
     for (description in inProgress) {
       ok(!inProgress[description], description + ": DOMTitleChange not fired");
     }
     SimpleTest.finish();
   }
   setTimeout(end, 500);
 }
 
-function acid() {
-      var doctype = document.implementation.createDocumentType("html", "-//W3C//DTD XHTML 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
-      is(doctype.ownerDocument, null, "doctype's ownerDocument was wrong after creation");
-      var doc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", doctype);
-      doc.documentElement.appendChild(doc.createElementNS("http://www.w3.org/1999/xhtml", "head"));
-      doc.documentElement.appendChild(doc.createElementNS("http://www.w3.org/1999/xhtml", "body"));
-      var t = doc.createElementNS("http://www.w3.org/1999/xhtml", "title");
-      doc.documentElement.firstChild.appendChild(t);
-      // ok we have a conforming XHTML1 doc in |doc| now.
-      is(doctype.ownerDocument, doc, "doctype's ownerDocument didn't change when it was assigned to another document");
-      is(doc.title, "", "document had unexpected title");
-      t.textContent = "Sparrow";
-      is(doc.title, "Sparrow", "document.title did not update dynamically");
-      doc.body.appendChild(doc.createElementNS("http://www.w3.org/1999/xhtml", "form"));
-      is(doc.forms.length, 1, "document.forms not updated after inserting a form");
-}
-
 function runTests() {
   testStatics();
-  // acid();
   testDynamics();
 }
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -3141,16 +3141,23 @@ nsCanvasRenderingContext2D::GetImageData
     jsval *retvalPtr;
     ncc->GetRetValPtr(&retvalPtr);
     *retvalPtr = OBJECT_TO_JSVAL(result);
     ncc->SetReturnValueWasSet(PR_TRUE);
 
     return NS_OK;
 }
 
+extern "C" {
+#include "jstypes.h"
+JS_FRIEND_API(JSBool)
+js_ArrayToJSUint8Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+                        JSUint8 *dest);
+}
+
 // void putImageData (in ImageData d, in float x, in float y);
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::PutImageData()
 {
     nsresult rv;
 
     if (!mValid)
         return NS_ERROR_FAILURE;
@@ -3211,59 +3218,85 @@ nsCanvasRenderingContext2D::PutImageData
         arrayLen < (jsuint)(w * h * 4))
         return NS_ERROR_DOM_SYNTAX_ERR;
 
     nsAutoArrayPtr<PRUint8> imageBuffer(new (std::nothrow) PRUint8[w * h * 4]);
     if (!imageBuffer)
         return NS_ERROR_OUT_OF_MEMORY;
 
     PRUint8 *imgPtr = imageBuffer.get();
-    jsval vr, vg, vb, va;
-    PRUint8 ir, ig, ib, ia;
-    for (int32 j = 0; j < h; j++) {
-        for (int32 i = 0; i < w; i++) {
-            if (!JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 0, &vr) ||
-                !JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 1, &vg) ||
-                !JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 2, &vb) ||
-                !JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 3, &va))
-                return NS_ERROR_DOM_SYNTAX_ERR;
-
-            if (JSVAL_IS_INT(vr))         ir = (PRUint8) JSVAL_TO_INT(vr);
-            else if (JSVAL_IS_DOUBLE(vr)) ir = (PRUint8) (*JSVAL_TO_DOUBLE(vr));
-            else return NS_ERROR_DOM_SYNTAX_ERR;
-
-
-            if (JSVAL_IS_INT(vg))         ig = (PRUint8) JSVAL_TO_INT(vg);
-            else if (JSVAL_IS_DOUBLE(vg)) ig = (PRUint8) (*JSVAL_TO_DOUBLE(vg));
-            else return NS_ERROR_DOM_SYNTAX_ERR;
-
-            if (JSVAL_IS_INT(vb))         ib = (PRUint8) JSVAL_TO_INT(vb);
-            else if (JSVAL_IS_DOUBLE(vb)) ib = (PRUint8) (*JSVAL_TO_DOUBLE(vb));
-            else return NS_ERROR_DOM_SYNTAX_ERR;
-
-            if (JSVAL_IS_INT(va))         ia = (PRUint8) JSVAL_TO_INT(va);
-            else if (JSVAL_IS_DOUBLE(va)) ia = (PRUint8) (*JSVAL_TO_DOUBLE(va));
-            else return NS_ERROR_DOM_SYNTAX_ERR;
-
-            // Convert to premultiplied color (losslessly if the input came from getImageData)
-            ir = (ir*ia + 254) / 255;
-            ig = (ig*ia + 254) / 255;
-            ib = (ib*ia + 254) / 255;
+
+    JSBool ok = js_ArrayToJSUint8Buffer(ctx, dataArray, 0, w*h*4, imageBuffer);
+
+    // no fast path? go slow.
+    if (!ok) {
+        jsval vr, vg, vb, va;
+        PRUint8 ir, ig, ib, ia;
+        for (int32 j = 0; j < h; j++) {
+            for (int32 i = 0; i < w; i++) {
+                if (!JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 0, &vr) ||
+                    !JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 1, &vg) ||
+                    !JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 2, &vb) ||
+                    !JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 3, &va))
+                    return NS_ERROR_DOM_SYNTAX_ERR;
+
+                if (JSVAL_IS_INT(vr))         ir = (PRUint8) JSVAL_TO_INT(vr);
+                else if (JSVAL_IS_DOUBLE(vr)) ir = (PRUint8) (*JSVAL_TO_DOUBLE(vr));
+                else return NS_ERROR_DOM_SYNTAX_ERR;
+
+                if (JSVAL_IS_INT(vg))         ig = (PRUint8) JSVAL_TO_INT(vg);
+                else if (JSVAL_IS_DOUBLE(vg)) ig = (PRUint8) (*JSVAL_TO_DOUBLE(vg));
+                else return NS_ERROR_DOM_SYNTAX_ERR;
+
+                if (JSVAL_IS_INT(vb))         ib = (PRUint8) JSVAL_TO_INT(vb);
+                else if (JSVAL_IS_DOUBLE(vb)) ib = (PRUint8) (*JSVAL_TO_DOUBLE(vb));
+                else return NS_ERROR_DOM_SYNTAX_ERR;
+
+                if (JSVAL_IS_INT(va))         ia = (PRUint8) JSVAL_TO_INT(va);
+                else if (JSVAL_IS_DOUBLE(va)) ia = (PRUint8) (*JSVAL_TO_DOUBLE(va));
+                else return NS_ERROR_DOM_SYNTAX_ERR;
+
+                // Convert to premultiplied color (losslessly if the input came from getImageData)
+                ir = (ir*ia + 254) / 255;
+                ig = (ig*ia + 254) / 255;
+                ib = (ib*ia + 254) / 255;
 
 #ifdef IS_LITTLE_ENDIAN
-            *imgPtr++ = ib;
-            *imgPtr++ = ig;
-            *imgPtr++ = ir;
-            *imgPtr++ = ia;
+                *imgPtr++ = ib;
+                *imgPtr++ = ig;
+                *imgPtr++ = ir;
+                *imgPtr++ = ia;
 #else
-            *imgPtr++ = ia;
-            *imgPtr++ = ir;
-            *imgPtr++ = ig;
-            *imgPtr++ = ib;
+                *imgPtr++ = ia;
+                *imgPtr++ = ir;
+                *imgPtr++ = ig;
+                *imgPtr++ = ib;
 #endif
+            }
+        }
+    } else {
+        /* Walk through and premultiply and swap rgba */
+        /* XXX SSE me */
+        PRUint8 ir, ig, ib, ia;
+        PRUint8 *ptr = imgPtr;
+        for (int32 i = 0; i < w*h; i++) {
+#ifdef IS_LITTLE_ENDIAN
+            ir = ptr[0];
+            ig = ptr[1];
+            ib = ptr[2];
+            ia = ptr[3];
+            ptr[0] = (ib*ia + 254) / 255;
+            ptr[1] = (ig*ia + 254) / 255;
+            ptr[2] = (ir*ia + 254) / 255;
+#else
+            ptr[0] = (ptr[0]*ptr[3] + 254) / 255;
+            ptr[1] = (ptr[1]*ptr[3] + 254) / 255;
+            ptr[2] = (ptr[2]*ptr[3] + 254) / 255;
+#endif
+            ptr += 4;
         }
     }
 
     nsRefPtr<gfxImageSurface> imgsurf = new gfxImageSurface(imageBuffer.get(),
                                                             gfxIntSize(w, h),
                                                             w * 4,
                                                             gfxASurface::ImageFormatARGB32);
     if (!imgsurf || imgsurf->CairoStatus())
--- a/content/events/public/nsIPrivateDOMEvent.h
+++ b/content/events/public/nsIPrivateDOMEvent.h
@@ -78,16 +78,18 @@ nsresult
 NS_NewDOMDataContainerEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent *aEvent);
 nsresult
 NS_NewDOMUIEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsGUIEvent *aEvent);
 nsresult
 NS_NewDOMMouseEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsInputEvent *aEvent);
 nsresult
 NS_NewDOMMouseScrollEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsInputEvent *aEvent);
 nsresult
+NS_NewDOMDragEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsDragEvent *aEvent);
+nsresult
 NS_NewDOMKeyboardEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsKeyEvent *aEvent);
 nsresult
 NS_NewDOMMutationEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsMutationEvent* aEvent);
 nsresult
 NS_NewDOMPopupBlockedEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsPopupBlockedEvent* aEvent);
 nsresult
 NS_NewDOMTextEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsTextEvent* aEvent);
 nsresult
--- a/content/events/src/Makefile.in
+++ b/content/events/src/Makefile.in
@@ -71,32 +71,34 @@ CPPSRCS		= \
 		nsEventStateManager.cpp \
 		nsDOMEvent.cpp \
 		nsDOMDataContainerEvent.cpp \
 		nsDOMUIEvent.cpp \
 		nsDOMKeyboardEvent.cpp \
 		nsDOMTextEvent.cpp \
 		nsDOMMouseEvent.cpp \
 		nsDOMMouseScrollEvent.cpp \
+		nsDOMDragEvent.cpp \
 		nsDOMMutationEvent.cpp \
 		nsDOMPopupBlockedEvent.cpp \
 		nsDOMBeforeUnloadEvent.cpp \
 		nsDOMPageTransitionEvent.cpp \
 		nsDOMXULCommandEvent.cpp \
 		nsDOMCommandEvent.cpp \
 		nsDOMMessageEvent.cpp \
 		nsPrivateTextRange.cpp \
 		nsDOMEventGroup.cpp \
 		nsXMLEventsManager.cpp \
 		nsXMLEventsElement.cpp \
 		nsPLDOMEvent.cpp \
 		nsEventDispatcher.cpp \
 		nsIMEStateManager.cpp \
 		nsQueryContentEventHandler.cpp \
 		nsDOMProgressEvent.cpp \
+		nsDOMDataTransfer.cpp \
 		$(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES	= \
new file mode 100644
--- /dev/null
+++ b/content/events/src/nsDOMDataTransfer.cpp
@@ -0,0 +1,768 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Neil Deakin <enndeakin@gmail.com>
+ *
+ * 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 "nsDOMDataTransfer.h"
+
+#include "prlog.h"
+#include "nsAutoPtr.h"
+#include "nsString.h"
+#include "nsIServiceManager.h"
+#include "nsIVariant.h"
+#include "nsISupportsPrimitives.h"
+#include "nsDOMClassInfo.h"
+#include "nsDOMLists.h"
+#include "nsGUIEvent.h"
+#include "nsDOMError.h"
+#include "nsIDragService.h"
+#include "nsIScriptableRegion.h"
+#include "nsContentUtils.h"
+
+NS_IMPL_CYCLE_COLLECTION_2(nsDOMDataTransfer, mDragTarget, mDragImage)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMDataTransfer)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMDataTransfer)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMDataTransfer)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMDataTransfer)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMNSDataTransfer)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMDataTransfer)
+  NS_INTERFACE_MAP_ENTRY_DOM_CLASSINFO(DataTransfer)
+NS_INTERFACE_MAP_END
+
+// the size of the array
+const char nsDOMDataTransfer::sEffects[8][9] = {
+  "none", "copy", "move", "copyMove", "link", "copyLink", "linkMove", "all"
+};
+
+nsDOMDataTransfer::nsDOMDataTransfer()
+  : mEventType(NS_DRAGDROP_START),
+    mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE),
+    mEffectAllowed(nsIDragService::DRAGDROP_ACTION_UNINITIALIZED),
+    mReadOnly(PR_FALSE),
+    mIsExternal(PR_FALSE),
+    mDragImageX(0),
+    mDragImageY(0)
+{
+}
+
+nsDOMDataTransfer::nsDOMDataTransfer(PRUint32 aEventType, PRUint32 aAction)
+  : mEventType(aEventType),
+    mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE),
+    mReadOnly(PR_TRUE),
+    mIsExternal(PR_TRUE),
+    mDragImageX(0),
+    mDragImageY(0)
+{
+  mEffectAllowed = aAction &
+                   (nsIDragService::DRAGDROP_ACTION_COPY |
+                    nsIDragService::DRAGDROP_ACTION_LINK |
+                    nsIDragService::DRAGDROP_ACTION_MOVE);
+
+  CacheExternalFormats();
+}
+
+nsDOMDataTransfer::nsDOMDataTransfer(PRUint32 aEventType,
+                                     const PRUint32 aEffectAllowed,
+                                     PRBool aIsExternal,
+                                     nsTArray<nsTArray<TransferItem> >& aItems,
+                                     nsIDOMElement* aDragImage,
+                                     PRUint32 aDragImageX,
+                                     PRUint32 aDragImageY)
+  : mEventType(aEventType),
+    mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE),
+    mEffectAllowed(aEffectAllowed),
+    mReadOnly(PR_TRUE),
+    mIsExternal(aIsExternal),
+    mItems(aItems),
+    mDragImage(aDragImage),
+    mDragImageX(aDragImageX),
+    mDragImageY(aDragImageY)
+{
+  // The items are copied from aItems into mItems. There is no need to copy
+  // the actual data in the items as the data transfer will be read only. The
+  // draggesture and dragstart events are the only times when items are
+  // modifiable, but those events should have been using the first constructor
+  // above.
+  NS_ASSERTION(aEventType != NS_DRAGDROP_GESTURE &&
+               aEventType != NS_DRAGDROP_START,
+               "invalid event type for nsDOMDataTransfer constructor");
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::GetDropEffect(nsAString& aDropEffect)
+{
+  aDropEffect.AssignASCII(sEffects[mDropEffect]);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::SetDropEffect(const nsAString& aDropEffect)
+{
+  // the drop effect can only be 'none', 'copy', 'move' or 'link'.
+  for (PRUint32 e = 0; e <= nsIDragService::DRAGDROP_ACTION_LINK; e++) {
+    if (aDropEffect.EqualsASCII(sEffects[e])) {
+      // don't allow copyMove
+      if (e != (nsIDragService::DRAGDROP_ACTION_COPY |
+                nsIDragService::DRAGDROP_ACTION_MOVE))
+        mDropEffect = e;
+      break;
+    }
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::GetEffectAllowed(nsAString& aEffectAllowed)
+{
+  if (mEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
+    aEffectAllowed.AssignLiteral("uninitialized");
+  else
+    aEffectAllowed.AssignASCII(sEffects[mEffectAllowed]);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::SetEffectAllowed(const nsAString& aEffectAllowed)
+{
+  if (aEffectAllowed.EqualsLiteral("uninitialized")) {
+    mEffectAllowed = nsIDragService::DRAGDROP_ACTION_UNINITIALIZED;
+    return NS_OK;
+  }
+
+  PR_STATIC_ASSERT(nsIDragService::DRAGDROP_ACTION_NONE == 0);
+  PR_STATIC_ASSERT(nsIDragService::DRAGDROP_ACTION_COPY == 1);
+  PR_STATIC_ASSERT(nsIDragService::DRAGDROP_ACTION_MOVE == 2);
+  PR_STATIC_ASSERT(nsIDragService::DRAGDROP_ACTION_LINK == 4);
+
+  for (PRUint32 e = 0; e < NS_ARRAY_LENGTH(sEffects); e++) {
+    if (aEffectAllowed.EqualsASCII(sEffects[e])) {
+      mEffectAllowed = e;
+      break;
+    }
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::GetDropEffectInt(PRUint32* aDropEffect)
+{
+  *aDropEffect = mDropEffect;
+  return  NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::SetDropEffectInt(PRUint32 aDropEffect)
+{
+  mDropEffect = aDropEffect;
+  return  NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::GetEffectAllowedInt(PRUint32* aEffectAllowed)
+{
+  *aEffectAllowed = mEffectAllowed;
+  return  NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::SetEffectAllowedInt(PRUint32 aEffectAllowed)
+{
+  mEffectAllowed = aEffectAllowed;
+  return  NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::GetTypes(nsIDOMDOMStringList** aTypes)
+{
+  return MozTypesAt(0, aTypes);
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::GetData(const nsAString& aFormat, nsAString& aData)
+{
+  // return an empty string if data for the format was not found
+  aData.Truncate();
+
+  nsCOMPtr<nsIVariant> data;
+  nsresult rv = MozGetDataAt(aFormat, 0, getter_AddRefs(data));
+  if (rv == NS_ERROR_DOM_INDEX_SIZE_ERR)
+    return NS_OK;
+
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (data) {
+    nsAutoString stringdata;
+    data->GetAsAString(stringdata);
+
+    // for the URL type, parse out the first URI from the list. The URIs are
+    // separated by newlines
+    if (aFormat.EqualsLiteral("URL")) {
+      PRInt32 lastidx = 0, idx;
+      PRInt32 length = stringdata.Length();
+      while (lastidx < length) {
+        idx = stringdata.FindChar('\n', lastidx);
+        // lines beginning with # are comments
+        if (stringdata[lastidx] == '#') {
+          if (idx == -1)
+            break;
+        }
+        else {
+          if (idx == -1)
+            aData.Assign(Substring(stringdata, lastidx));
+          else
+            aData.Assign(Substring(stringdata, lastidx, idx - lastidx));
+          aData = nsContentUtils::TrimWhitespace(aData, PR_TRUE);
+          return NS_OK;
+        }
+        lastidx = idx + 1;
+      }
+    }
+    else {
+      aData = stringdata;
+    }
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::SetData(const nsAString& aFormat, const nsAString& aData)
+{
+  nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
+  NS_ENSURE_TRUE(variant, NS_ERROR_OUT_OF_MEMORY);
+
+  variant->SetAsAString(aData);
+
+  return MozSetDataAt(aFormat, variant, 0);
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::ClearData(const nsAString& aFormat)
+{
+  nsresult rv = MozClearDataAt(aFormat, 0);
+  return (rv == NS_ERROR_DOM_INDEX_SIZE_ERR) ? NS_OK : rv;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::GetMozItemCount(PRUint32* aCount)
+{
+  *aCount = mItems.Length();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::MozTypesAt(PRUint32 aIndex, nsIDOMDOMStringList** aTypes)
+{
+  *aTypes = nsnull;
+
+  nsRefPtr<nsDOMStringList> types = new nsDOMStringList();
+  NS_ENSURE_TRUE(types, NS_ERROR_OUT_OF_MEMORY);
+
+  if (aIndex < mItems.Length()) {
+    // note that you can retrieve the types regardless of their principal
+    nsTArray<TransferItem>& item = mItems[aIndex];
+    for (PRUint32 i = 0; i < item.Length(); i++)
+      types->Add(item[i].mFormat);
+  }
+
+  *aTypes = types;
+  NS_ADDREF(*aTypes);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::MozGetDataAt(const nsAString& aFormat,
+                                PRUint32 aIndex,
+                                nsIVariant** aData)
+{
+  *aData = nsnull;
+
+  if (aFormat.IsEmpty())
+    return NS_OK;
+
+  if (aIndex >= mItems.Length())
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+
+  nsAutoString format;
+  GetRealFormat(aFormat, format);
+
+  nsTArray<TransferItem>& item = mItems[aIndex];
+
+  // allow access to any data in the drop and dragdrop events, or if the
+  // UniversalBrowserRead privilege is set, otherwise only allow access to
+  // data from the same principal.
+  nsIPrincipal* principal = nsnull;
+  if (mEventType != NS_DRAGDROP_DROP && mEventType != NS_DRAGDROP_DRAGDROP &&
+      !nsContentUtils::IsCallerTrustedForCapability("UniversalBrowserRead"))
+    principal = GetCurrentPrincipal();
+
+  PRUint32 count = item.Length();
+  for (PRUint32 i = 0; i < count; i++) {
+    TransferItem& formatitem = item[i];
+    if (formatitem.mFormat.Equals(format)) {
+      PRBool subsumes;
+      if (formatitem.mPrincipal && principal &&
+          (NS_FAILED(principal->Subsumes(formatitem.mPrincipal, &subsumes)) || !subsumes))
+        return NS_ERROR_DOM_SECURITY_ERR;
+
+      if (!formatitem.mData)
+        FillInExternalDragData(formatitem, aIndex);
+      *aData = formatitem.mData;
+      NS_IF_ADDREF(*aData);
+      return NS_OK;
+    }
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::MozSetDataAt(const nsAString& aFormat,
+                                nsIVariant* aData,
+                                PRUint32 aIndex)
+{
+  NS_ENSURE_TRUE(aData, NS_ERROR_NULL_POINTER);
+
+  if (aFormat.IsEmpty())
+    return NS_OK;
+
+  if (mReadOnly)
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+
+  // Specifying an index less than the current length will replace an existing
+  // item. Specifying an index equal to the current length will add a new item.
+  if (aIndex > mItems.Length())
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+
+  // don't allow non-chrome to add file data
+  // XXX perhaps this should also limit any non-string type as well
+  if ((aFormat.EqualsLiteral("application/x-moz-file-promise") ||
+       aFormat.EqualsLiteral("application/x-moz-file")) &&
+       !nsContentUtils::IsCallerChrome()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  return SetDataWithPrincipal(aFormat, aData, aIndex, GetCurrentPrincipal());
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::MozClearDataAt(const nsAString& aFormat, PRUint32 aIndex)
+{
+  if (mReadOnly)
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+
+  if (aIndex >= mItems.Length())
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+
+  nsAutoString format;
+  GetRealFormat(aFormat, format);
+
+  nsIPrincipal* principal = GetCurrentPrincipal();
+
+  // if the format is empty, clear all formats
+  PRBool clearall = format.IsEmpty();
+
+  nsTArray<TransferItem>& item = mItems[aIndex];
+  // count backwards so that the count and index don't have to be adjusted
+  // after removing an element
+  for (PRInt32 i = item.Length() - 1; i >= 0; i--) {
+    TransferItem& formatitem = item[i];
+    if (clearall || formatitem.mFormat.Equals(format)) {
+      // don't allow removing data that has a stronger principal
+      PRBool subsumes;
+      if (formatitem.mPrincipal && principal &&
+          (NS_FAILED(principal->Subsumes(formatitem.mPrincipal, &subsumes)) || !subsumes))
+        return NS_ERROR_DOM_SECURITY_ERR;
+
+      item.RemoveElementAt(i);
+
+      // if a format was specified, break out. Otherwise, loop around until
+      // all formats have been removed
+      if (!clearall)
+        break;
+    }
+  }
+
+  // if the last format for an item is removed, remove the entire item
+  if (!item.Length())
+     mItems.RemoveElementAt(aIndex);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::SetDragImage(nsIDOMElement* aImage, PRInt32 aX, PRInt32 aY)
+{
+  if (mReadOnly)
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+
+  mDragImage = aImage;
+  mDragImageX = aX;
+  mDragImageY = aY;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::AddElement(nsIDOMElement* aElement)
+{
+  NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
+
+  if (mReadOnly)
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+
+  mDragTarget = do_QueryInterface(aElement);
+
+  return NS_OK;
+}
+
+nsresult
+nsDOMDataTransfer::Clone(PRUint32 aEventType,
+                         nsIDOMDataTransfer** aNewDataTransfer)
+{
+  nsDOMDataTransfer* newDataTransfer =
+    new nsDOMDataTransfer(aEventType, mEffectAllowed, mIsExternal,
+                          mItems, mDragImage, mDragImageX, mDragImageY);
+  NS_ENSURE_TRUE(newDataTransfer, NS_ERROR_OUT_OF_MEMORY);
+
+  *aNewDataTransfer = newDataTransfer;
+  NS_ADDREF(*aNewDataTransfer);
+  return NS_OK;
+}
+
+void
+nsDOMDataTransfer::GetTransferables(nsISupportsArray** aArray)
+{
+  *aArray = nsnull;
+
+  nsCOMPtr<nsISupportsArray> transArray =
+    do_CreateInstance("@mozilla.org/supports-array;1");
+  if (!transArray)
+    return;
+
+  PRBool added = PR_FALSE;
+  PRUint32 count = mItems.Length();
+  for (PRUint32 i = 0; i < count; i++) {
+
+    nsTArray<TransferItem>& item = mItems[i];
+    PRUint32 count = item.Length();
+    if (!count)
+      continue;
+
+    nsCOMPtr<nsITransferable> transferable =
+      do_CreateInstance("@mozilla.org/widget/transferable;1");
+    if (!transferable)
+      return;
+
+    for (PRUint32 f = 0; f < count; f++) {
+      TransferItem& formatitem = item[f];
+      if (!formatitem.mData) // skip empty items
+        continue;
+
+      PRUint32 length;
+      nsCOMPtr<nsISupports> convertedData;
+      if (!ConvertFromVariant(formatitem.mData, getter_AddRefs(convertedData), &length))
+        continue;
+
+      // the underlying drag code uses text/unicode, so use that instead of text/plain
+      const char* format;
+      NS_ConvertUTF16toUTF8 utf8format(formatitem.mFormat);
+      if (utf8format.EqualsLiteral("text/plain"))
+        format = kUnicodeMime;
+      else
+        format = utf8format.get();
+
+      // if a converter is set for a format, set the converter for the
+      // transferable and don't add the item
+      nsCOMPtr<nsIFormatConverter> converter = do_QueryInterface(convertedData);
+      if (converter) {
+        transferable->AddDataFlavor(format);
+        transferable->SetConverter(converter);
+        continue;
+      }
+
+      nsresult rv = transferable->SetTransferData(format, convertedData, length);
+      if (NS_FAILED(rv))
+        return;
+
+      added = PR_TRUE;
+    }
+
+    // only append the transferable if data was successfully added to it
+    if (added)
+      transArray->AppendElement(transferable);
+  }
+
+  NS_ADDREF(*aArray = transArray);
+}
+
+PRBool
+nsDOMDataTransfer::ConvertFromVariant(nsIVariant* aVariant,
+                                      nsISupports** aSupports,
+                                      PRUint32* aLength)
+{
+  *aSupports = nsnull;
+  *aLength = 0;
+
+  PRUint16 type;
+  aVariant->GetDataType(&type);
+  if (type == nsIDataType::VTYPE_INTERFACE ||
+      type == nsIDataType::VTYPE_INTERFACE_IS) {
+    if (NS_FAILED(aVariant->GetAsISupports(aSupports)))
+      return PR_FALSE;
+
+    // for flavour data providers, use kFlavorHasDataProvider (which has the
+    // value 0) as the length.
+    nsCOMPtr<nsIFlavorDataProvider> fdp = do_QueryInterface(*aSupports);
+    *aLength = fdp ? sizeof(nsISupports) : nsITransferable::kFlavorHasDataProvider;
+  }
+
+  PRUnichar* chrs;
+  nsresult rv = aVariant->GetAsWString(&chrs);
+  if (NS_FAILED(rv))
+    return PR_FALSE;
+
+  nsCOMPtr<nsISupportsString>
+    strSupports(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
+  if (!strSupports)
+    return PR_FALSE;
+
+  nsAutoString str(chrs);
+  strSupports->SetData(str);
+
+  *aSupports = strSupports;
+  NS_ADDREF(*aSupports);
+
+  // each character is two bytes
+  *aLength = str.Length() << 1;
+
+  return PR_TRUE;
+}
+
+void
+nsDOMDataTransfer::ClearAll()
+{
+  mItems.Clear();
+}
+
+nsresult
+nsDOMDataTransfer::SetDataWithPrincipal(const nsAString& aFormat,
+                                        nsIVariant* aData,
+                                        PRUint32 aIndex,
+                                        nsIPrincipal* aPrincipal)
+{
+  nsAutoString format;
+  GetRealFormat(aFormat, format);
+
+  // check if the item for the format already exists. In that case,
+  // just replace it.
+  TransferItem* formatitem;
+  if (aIndex < mItems.Length()) {
+    nsTArray<TransferItem>& item = mItems[aIndex];
+    PRUint32 count = item.Length();
+    for (PRUint32 i = 0; i < count; i++) {
+      TransferItem& itemformat = item[i];
+      if (itemformat.mFormat.Equals(format)) {
+        // don't allow replacing data that has a stronger principal
+        PRBool subsumes;
+        if (itemformat.mPrincipal && aPrincipal &&
+            (NS_FAILED(aPrincipal->Subsumes(itemformat.mPrincipal, &subsumes)) || !subsumes))
+          return NS_ERROR_DOM_SECURITY_ERR;
+
+        itemformat.mPrincipal = aPrincipal;
+        itemformat.mData = aData;
+        return NS_OK;
+      }
+    }
+
+    // add a new format
+    formatitem = item.AppendElement();
+  }
+  else {
+    NS_ASSERTION(aIndex == mItems.Length(), "Index out of range");
+
+    // add a new index
+    nsTArray<TransferItem>* item = mItems.AppendElement();
+    NS_ENSURE_TRUE(item, NS_ERROR_OUT_OF_MEMORY);
+
+    formatitem = item->AppendElement();
+  }
+
+  NS_ENSURE_TRUE(formatitem, NS_ERROR_OUT_OF_MEMORY);
+
+  formatitem->mFormat = format;
+  formatitem->mPrincipal = aPrincipal;
+  formatitem->mData = aData;
+
+  return NS_OK;
+}
+
+nsIPrincipal*
+nsDOMDataTransfer::GetCurrentPrincipal()
+{
+  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
+
+  nsCOMPtr<nsIPrincipal> currentPrincipal;
+  ssm->GetSubjectPrincipal(getter_AddRefs(currentPrincipal));
+  if (!currentPrincipal)
+    ssm->GetSystemPrincipal(getter_AddRefs(currentPrincipal));
+
+  return currentPrincipal.get();
+}
+
+void
+nsDOMDataTransfer::GetRealFormat(const nsAString& aInFormat, nsAString& aOutFormat)
+{
+  // treat text/unicode as equivalent to text/plain
+  if (aInFormat.EqualsLiteral("Text") || aInFormat.EqualsLiteral("text/unicode"))
+    aOutFormat.AssignLiteral("text/plain");
+  else if (aInFormat.EqualsLiteral("URL"))
+    aOutFormat.AssignLiteral("text/uri-list");
+  else
+    aOutFormat.Assign(aInFormat);
+}
+
+void
+nsDOMDataTransfer::CacheExternalFormats()
+{
+  // Called during the constructor to cache the formats available from an
+  // external drag. The data associated with each format will be set to null.
+  // This data will instead only be retrieved in FillInExternalDragData when
+  // asked for, as it may be time consuming for the source application to
+  // generate it.
+
+  nsCOMPtr<nsIDragService> dragService =
+    do_GetService("@mozilla.org/widget/dragservice;1");
+  if (!dragService)
+    return;
+
+  nsCOMPtr<nsIDragSession> dragSession;
+  dragService->GetCurrentSession(getter_AddRefs(dragSession));
+  if (!dragSession)
+    return;
+
+  // make sure that the system principal is used for external drags
+  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
+  nsCOMPtr<nsIPrincipal> sysPrincipal;
+  ssm->GetSystemPrincipal(getter_AddRefs(sysPrincipal));
+
+  // there isn't a way to get a list of the formats that might be available on
+  // all platforms, so just check for the types that can actually be imported
+  // XXXndeakin there are some other formats but those are platform specific.
+  const char* formats[] = { kFileMime, kHTMLMime, kURLMime, kURLDataMime, kUnicodeMime };
+
+  PRUint32 count;
+  dragSession->GetNumDropItems(&count);
+  for (PRUint32 c = 0; c < count; c++) {
+    for (PRUint32 f = 0; f < NS_ARRAY_LENGTH(formats); f++) {
+      // IsDataFlavorSupported doesn't take an index as an argument and just
+      // checks if any of the items support a particular flavor, even though
+      // the GetData method does take an index. Here, we just assume that
+      // every item being dragged has the same set of flavors.
+      PRBool supported;
+      dragSession->IsDataFlavorSupported(formats[f], &supported);
+      // if the format is supported, add an item to the array with null as
+      // the data. When retrieved, GetRealData will read the data.
+      if (supported) {
+        if (formats[f] == kUnicodeMime) {
+          SetDataWithPrincipal(NS_LITERAL_STRING("text/plain"), nsnull, c, sysPrincipal);
+        }
+        else {
+          if (formats[f] == kURLDataMime)
+            SetDataWithPrincipal(NS_LITERAL_STRING("text/uri-list"), nsnull, c, sysPrincipal);
+          SetDataWithPrincipal(NS_ConvertUTF8toUTF16(formats[f]), nsnull, c, sysPrincipal);
+        }
+      }
+    }
+  }
+}
+
+void
+nsDOMDataTransfer::FillInExternalDragData(TransferItem& aItem, PRUint32 aIndex)
+{
+  NS_PRECONDITION(mIsExternal, "Not an external drag");
+
+  if (!aItem.mData) {
+    nsCOMPtr<nsITransferable> trans =
+      do_CreateInstance("@mozilla.org/widget/transferable;1");
+    if (!trans)
+      return;
+
+    NS_ConvertUTF16toUTF8 utf8format(aItem.mFormat);
+    const char* format = utf8format.get();
+    if (strcmp(format, "text/plain") == 0)
+      format = kUnicodeMime;
+    else if (strcmp(format, "text/uri-list") == 0)
+      format = kURLDataMime;
+
+    nsCOMPtr<nsIDragService> dragService =
+      do_GetService("@mozilla.org/widget/dragservice;1");
+    if (!dragService)
+      return;
+
+    nsCOMPtr<nsIDragSession> dragSession;
+    dragService->GetCurrentSession(getter_AddRefs(dragSession));
+    if (!dragSession)
+      return;
+
+    trans->AddDataFlavor(format);
+    dragSession->GetData(trans, aIndex);
+
+    PRUint32 length = 0;
+    nsCOMPtr<nsISupports> data;
+    trans->GetTransferData(format, getter_AddRefs(data), &length);
+    if (!data)
+      return;
+
+    nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
+    if (!variant)
+      return;
+
+    nsCOMPtr<nsISupportsString> supportsstr = do_QueryInterface(data);
+    if (supportsstr) {
+      nsAutoString str;
+      supportsstr->GetData(str);
+      variant->SetAsAString(str);
+    }
+    else {
+      variant->SetAsISupports(data);
+    }
+    aItem.mData = variant;
+  }
+}
new file mode 100644
--- /dev/null
+++ b/content/events/src/nsDOMDataTransfer.h
@@ -0,0 +1,191 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Neil Deakin <enndeakin@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsDOMDataTransfer_h__
+#define nsDOMDataTransfer_h__
+
+#include "nsString.h"
+#include "nsTArray.h"
+#include "nsIVariant.h"
+#include "nsIPrincipal.h"
+#include "nsIDOMDataTransfer.h"
+#include "nsIDragService.h"
+#include "nsIDOMElement.h"
+#include "nsCycleCollectionParticipant.h"
+
+class nsITransferable;
+
+/**
+ * TransferItem is used to hold data for a particular format. Each piece of
+ * data has a principal set from the caller which added it. This allows a
+ * caller that wishes to retrieve the data to only be able to access the data
+ * it is allowed to, yet still allow a chrome caller to retrieve any of the
+ * data.
+ */
+struct TransferItem {
+  nsString mFormat;
+  nsCOMPtr<nsIPrincipal> mPrincipal;
+  nsCOMPtr<nsIVariant> mData;
+};
+
+class nsDOMDataTransfer : public nsIDOMDataTransfer,
+                          public nsIDOMNSDataTransfer
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_NSIDOMDATATRANSFER
+  NS_DECL_NSIDOMNSDATATRANSFER
+
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMDataTransfer, nsIDOMDataTransfer)
+
+  friend class nsDOMDragEvent;
+  friend class nsEventStateManager;
+
+protected:
+
+  // the constructors are protected so only our friends can call them
+
+  // default constructor used for the dragstart/draggesture event and
+  // synthetic events
+  nsDOMDataTransfer();
+
+  // this constructor must only be used to create a dataTransfer for a drag
+  // that was started without using a data transfer, either an external drag,
+  // that is, a drag where the source is another application, or a drag
+  // started by calling the drag service directly.
+  nsDOMDataTransfer(PRUint32 aEventType, PRUint32 aAction);
+
+  // this constructor is used only by the Clone method to copy the fields as
+  // needed to a new data transfer.
+  nsDOMDataTransfer(PRUint32 aEventType,
+                    const PRUint32 aEffectAllowed,
+                    PRBool aIsExternal,
+                    nsTArray<nsTArray<TransferItem> >& aItems,
+                    nsIDOMElement* aDragImage,
+                    PRUint32 aDragImageX,
+                    PRUint32 aDragImageY);
+
+  static const char sEffects[8][9];
+
+public:
+
+  void GetDragTarget(nsIDOMElement** aDragTarget)
+  {
+    *aDragTarget = mDragTarget;
+    NS_IF_ADDREF(*aDragTarget);
+  }
+
+  // a readonly dataTransfer cannot have new data added or existing data removed.
+  // Only the dropEffect and effectAllowed may be modified.
+  void SetReadOnly() { mReadOnly = PR_TRUE; }
+
+  // converts the data into an array of nsITransferable objects to be used for
+  // drag and drop or clipboard operations.
+  void GetTransferables(nsISupportsArray** transferables);
+
+  // converts the data in the variant to an nsISupportString if possible or
+  // an nsISupports or null otherwise.
+  PRBool ConvertFromVariant(nsIVariant* aVariant,
+                            nsISupports** aSupports,