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 id1611
push userbhearsum@mozilla.com
push dateFri, 29 Aug 2008 13:34:51 +0000
treeherderautoland@1ac4ead1f4fc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
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,
+                            PRUint32* aLength);
+
+  // clears all of the data
+  void ClearAll();
+
+  // Similar to SetData except also specifies the principal to store.
+  // aData may be null when called from CacheExternalFormats.