Bug 722872 - Part 1: Add nsITransferable::Init(nsILoadContext*), enforce that it's called in debug builds, and add nsIDOMDocument* arguments to nsIClipboardHelper methods; r=roc
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 16 Apr 2012 22:14:01 -0400
changeset 97783 93e55dcf0e2ee8fcd9d21def6d9787317856e1ac
parent 97782 6a386d638a1ac6e7f911b3908b1987e4be6b0b46
child 97784 dbf7b4c5e8fcb1f2b1ef57c52aa7f5a5f63d9e40
push id22999
push useremorley@mozilla.com
push dateThu, 28 Jun 2012 08:03:15 +0000
treeherdermozilla-central@bf8f2961d0cc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs722872
milestone16.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 722872 - Part 1: Add nsITransferable::Init(nsILoadContext*), enforce that it's called in debug builds, and add nsIDOMDocument* arguments to nsIClipboardHelper methods; r=roc This patch does the following: * It adds nsITransferable::Init(nsILoadContext*). The load context might be null, which means that the transferable is non-private, but if it's non-null, we extract the boolean value for the privacy mode and store it in the transferable. * It adds checks in debug builds to make sure that Init is always called, in form of fatal assertions. * It adds nsIDOMDocument* agruments to nsIClipboardHelper methods which represent the document that the string is coming from. nsIClipboardHelper implementation internally gets the nsILoadContext from that and passes it on to the transferable upon creation. The reason that I did this was that nsIClipboardHelper is supposed to be a high-level helper, and in most of its call sites, we have easy access to a document object. * It modifies all of the call sites of the above interfaces according to this change. * It adds a GetLoadContext helper to nsIDocument to help with changing the call sites.
accessible/tests/mochitest/common.js
browser/base/content/browser.js
browser/base/content/nsContextMenu.js
browser/base/content/pageinfo/pageInfo.js
browser/base/content/sanitizeDialog.js
browser/base/content/test/browser_bug321000.js
browser/base/content/test/browser_middleMouse_inherit.js
browser/base/content/urlbarBindings.xml
browser/components/downloads/content/downloads.js
browser/components/places/content/controller.js
browser/devtools/highlighter/inspector.jsm
browser/devtools/sourceeditor/source-editor-orion.jsm
browser/devtools/sourceeditor/test/browser_bug695035_middle_click_paste.js
browser/devtools/sourceeditor/test/head.js
browser/devtools/styleinspector/CssHtmlTree.jsm
browser/devtools/styleinspector/CssRuleView.jsm
browser/devtools/webconsole/HUDService.jsm
browser/devtools/webconsole/test/browser_webconsole_bug_642615_autocomplete.js
content/base/public/nsCopySupport.h
content/base/public/nsIDocument.h
content/base/src/nsCopySupport.cpp
content/base/test/test_bug166235.html
content/base/test/test_copypaste.html
content/events/src/nsDOMDataTransfer.cpp
content/events/src/nsDOMDataTransfer.h
content/events/src/nsEventStateManager.cpp
dom/ipc/ContentParent.cpp
dom/tests/mochitest/general/test_clipboard_events.html
editor/libeditor/html/nsHTMLDataTransfer.cpp
editor/libeditor/html/tests/test_CF_HTML_clipboard.html
editor/libeditor/html/tests/test_bug489202.xul
editor/libeditor/html/tests/test_bug520189.html
editor/libeditor/html/tests/test_bug525389.html
editor/libeditor/text/nsPlaintextDataTransfer.cpp
editor/libeditor/text/tests/test_bug596333.html
editor/libeditor/text/tests/test_bug681229.html
gfx/thebes/gfxASurface.cpp
layout/base/nsDocumentViewer.cpp
mobile/android/chrome/content/browser.js
mobile/xul/chrome/content/ContextCommands.js
mobile/xul/chrome/content/console.js
mobile/xul/chrome/content/content.js
mobile/xul/chrome/tests/browser_tapping_edit.js
services/sync/tps/extensions/mozmill/resource/modules/inspection.js
testing/mochitest/tests/SimpleTest/specialpowersAPI.js
toolkit/components/console/content/consoleBindings.xml
toolkit/components/passwordmgr/content/passwordManager.js
toolkit/components/viewconfig/content/config.js
toolkit/components/viewsource/content/viewSource.js
toolkit/content/aboutSupport.js
toolkit/content/nsDragAndDrop.js
toolkit/content/tests/chrome/test_autocomplete_delayOnPaste.xul
toolkit/content/tests/chrome/test_bug253481.xul
toolkit/mozapps/downloads/content/downloads.js
toolkit/mozapps/downloads/tests/chrome/test_multi_select.xul
widget/cocoa/nsChildView.mm
widget/nsIClipboardHelper.idl
widget/nsITransferable.idl
widget/os2/nsDragService.cpp
widget/tests/test_bug444800.xul
widget/tests/test_bug462106.xul
widget/tests/test_bug466599.xul
widget/tests/test_bug565392.html
widget/tests/test_bug673301.xul
widget/windows/tests/TestWinDND.cpp
widget/xpwidgets/nsClipboardHelper.cpp
widget/xpwidgets/nsClipboardPrivacyHandler.cpp
widget/xpwidgets/nsTransferable.cpp
widget/xpwidgets/nsTransferable.h
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -549,28 +549,36 @@ function eventTypeToString(aEventType)
 /**
  * Convert relation type to human readable string.
  */
 function relationTypeToString(aRelationType)
 {
   return gAccRetrieval.getStringRelationType(aRelationType);
 }
 
+function getLoadContext() {
+  const Ci = Components.interfaces;
+  return window.QueryInterface(Ci.nsIInterfaceRequestor)
+               .getInterface(Ci.nsIWebNavigation)
+               .QueryInterface(Ci.nsILoadContext);
+}
+
 /**
  * Return text from clipboard.
  */
 function getTextFromClipboard()
 {
   var clip = Components.classes["@mozilla.org/widget/clipboard;1"].
     getService(Components.interfaces.nsIClipboard);
   if (!clip)
     return;
 
   var trans = Components.classes["@mozilla.org/widget/transferable;1"].
     createInstance(Components.interfaces.nsITransferable);
+  trans.init(getLoadContext());
   if (!trans)
     return;
 
   trans.addDataFlavor("text/unicode");
   clip.getData(trans, clip.kGlobalClipboard);
 
   var str = new Object();
   var strLength = new Object();
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2222,28 +2222,35 @@ function getPostDataStream(aStringData, 
   var mimeStream = Cc["@mozilla.org/network/mime-input-stream;1"].
                    createInstance(Ci.nsIMIMEInputStream);
   mimeStream.addHeader("Content-Type", aType);
   mimeStream.addContentLength = true;
   mimeStream.setData(dataStream);
   return mimeStream.QueryInterface(Ci.nsIInputStream);
 }
 
+function getLoadContext() {
+  return window.QueryInterface(Ci.nsIInterfaceRequestor)
+               .getInterface(Ci.nsIWebNavigation)
+               .QueryInterface(Ci.nsILoadContext);
+}
+
 function readFromClipboard()
 {
   var url;
 
   try {
     // Get clipboard.
     var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
                               .getService(Components.interfaces.nsIClipboard);
 
     // Create transferable that will transfer the text.
     var trans = Components.classes["@mozilla.org/widget/transferable;1"]
                           .createInstance(Components.interfaces.nsITransferable);
+    trans.init(getLoadContext());
 
     trans.addDataFlavor("text/unicode");
 
     // If available, use selection clipboard, otherwise global one
     if (clipboard.supportsSelectionClipboard())
       clipboard.getData(trans, clipboard.kSelectionClipboard);
     else
       clipboard.getData(trans, clipboard.kGlobalClipboard);
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -1112,17 +1112,17 @@ nsContextMenu.prototype = {
       addresses = textToSubURI.unEscapeURIForUI(characterSet, addresses);
     }
     catch(ex) {
       // Do nothing.
     }
 
     var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
                     getService(Ci.nsIClipboardHelper);
-    clipboard.copyString(addresses);
+    clipboard.copyString(addresses, document);
   },
 
   ///////////////
   // Utilities //
   ///////////////
 
   // Show/hide one item (specified via name or the item element itself).
   showItem: function(aItemOrId, aShow) {
@@ -1448,17 +1448,17 @@ nsContextMenu.prototype = {
         media.dispatchEvent(event);
         break;
     }
   },
 
   copyMediaLocation : function () {
     var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
                     getService(Ci.nsIClipboardHelper);
-    clipboard.copyString(this.mediaURL);
+    clipboard.copyString(this.mediaURL, document);
   },
 
   get imageURL() {
     if (this.onImage)
       return this.mediaURL;
     return "";
   }
 };
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -1238,17 +1238,17 @@ function doCopy()
         view.performActionOnRow("copy", row);
 
         tmp = elem.getAttribute("copybuffer");
         if (tmp)
           text.push(tmp);
         elem.removeAttribute("copybuffer");
       }
     }
-    gClipboardHelper.copyString(text.join("\n"));
+    gClipboardHelper.copyString(text.join("\n"), document);
   }
 }
 
 function doSelectAll()
 {
   var elem = document.commandDispatcher.focusedElement;
 
   if (elem && "treeBoxObject" in elem)
--- a/browser/base/content/sanitizeDialog.js
+++ b/browser/base/content/sanitizeDialog.js
@@ -649,16 +649,17 @@ var gContiguousSelectionTreeHelper = {
     // This part is a hack.  What we really want is a grab and slide, not
     // drag and drop.  Start a move drag session with dummy data and a
     // dummy region.  Set the region's coordinates to (Infinity, Infinity)
     // so it's drawn offscreen and its size to (1, 1).
     var arr = Cc["@mozilla.org/supports-array;1"].
               createInstance(Ci.nsISupportsArray);
     var trans = Cc["@mozilla.org/widget/transferable;1"].
                 createInstance(Ci.nsITransferable);
+    trans.init(null);
     trans.setTransferData('dummy-flavor', null, 0);
     arr.AppendElement(trans);
     var reg = Cc["@mozilla.org/gfx/region;1"].
               createInstance(Ci.nsIScriptableRegion);
     reg.setToRect(Infinity, Infinity, 1, 1);
     var ds = Cc["@mozilla.org/widget/dragservice;1"].
              getService(Ci.nsIDragService);
     ds.invokeDragSession(aEvent.target, arr, reg, ds.DRAGDROP_ACTION_MOVE);
--- a/browser/base/content/test/browser_bug321000.js
+++ b/browser/base/content/test/browser_bug321000.js
@@ -27,17 +27,17 @@ function test() {
   waitForExplicitFinish();
 
   let cbHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].
                  getService(Ci.nsIClipboardHelper);
 
   // Put a multi-line string in the clipboard.
   // Setting the clipboard value is an async OS operation, so we need to poll
   // the clipboard for valid data before going on.
-  waitForClipboard(kTestString, function() { cbHelper.copyString(kTestString); },
+  waitForClipboard(kTestString, function() { cbHelper.copyString(kTestString, document); },
                    next_test, finish);
 }
 
 function next_test() {
   if (gTests.length)
     test_paste(gTests.shift());
   else
     finish();
--- a/browser/base/content/test/browser_middleMouse_inherit.js
+++ b/browser/base/content/test/browser_middleMouse_inherit.js
@@ -20,17 +20,17 @@ function test() {
     let pagePrincipal = gBrowser.contentPrincipal;
 
     // copy javascript URI to the clipboard
     let url = "javascript:1+1";
     waitForClipboard(url,
       function() {
         Components.classes["@mozilla.org/widget/clipboardhelper;1"]
                   .getService(Components.interfaces.nsIClipboardHelper)
-                  .copyString(url);
+                  .copyString(url, document);
       },
       function () {
         // Middle click on the content area
         info("Middle clicking");
         EventUtils.sendMouseEvent({type: "click", button: 1}, gBrowser);
       },
       function() {
         ok(false, "Failed to copy URL to the clipboard");
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -545,17 +545,17 @@
               urlbar.value = urlbar.inputField.value.substring(0, start) +
                              urlbar.inputField.value.substring(end);
               urlbar.selectionStart = urlbar.selectionEnd = start;
               SetPageProxyState("invalid");
             }
 
             Cc["@mozilla.org/widget/clipboardhelper;1"]
               .getService(Ci.nsIClipboardHelper)
-              .copyString(val);
+              .copyString(val, document);
           },
           supportsCommand: function(aCommand) {
             switch (aCommand) {
               case "cmd_copy":
               case "cmd_cut":
                 return true;
             }
             return false;
@@ -746,17 +746,17 @@
           return;
 
         var val = this._getSelectedValueForClipboard();
         if (!val)
           return;
 
         Cc["@mozilla.org/widget/clipboardhelper;1"]
           .getService(Ci.nsIClipboardHelper)
-          .copyStringToClipboard(val, Ci.nsIClipboard.kSelectionClipboard);
+          .copyStringToClipboard(val, document, Ci.nsIClipboard.kSelectionClipboard);
       ]]></handler>
     </handlers>
 
   </binding>
 
   <!-- Note: this binding is applied to the autocomplete popup used in the Search bar and in web page content -->
   <binding id="browser-autocomplete-result-popup" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-result-popup">
     <implementation>
--- a/browser/components/downloads/content/downloads.js
+++ b/browser/components/downloads/content/downloads.js
@@ -1162,17 +1162,17 @@ DownloadsViewItemController.prototype = 
     {
       openURL(this.dataItem.referrer);
     },
 
     downloadsCmd_copyLocation: function DVIC_downloadsCmd_copyLocation()
     {
       let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]
                       .getService(Ci.nsIClipboardHelper);
-      clipboard.copyString(this.dataItem.uri);
+      clipboard.copyString(this.dataItem.uri, document);
     },
 
     downloadsCmd_doDefault: function DVIC_downloadsCmd_doDefault()
     {
       const nsIDM = Ci.nsIDownloadManager;
 
       // Determine the default command for the current item.
       let defaultCommand = function () {
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -371,16 +371,17 @@ PlacesController.prototype = {
                                        Ci.nsIClipboard.kGlobalClipboard);
     if (hasPlacesData)
       return this._view.insertionPoint != null;
 
     // if the clipboard doesn't have TYPE_X_MOZ_PLACE_* data, we also allow
     // pasting of valid "text/unicode" and "text/x-moz-url" data
     var xferable = Cc["@mozilla.org/widget/transferable;1"].
                    createInstance(Ci.nsITransferable);
+    xferable.init(null);
 
     xferable.addDataFlavor(PlacesUtils.TYPE_X_MOZ_URL);
     xferable.addDataFlavor(PlacesUtils.TYPE_UNICODE);
     clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
 
     try {
       // getAnyTransferData will throw if no data is available.
       var data = { }, type = { };
@@ -1056,16 +1057,17 @@ PlacesController.prototype = {
   },
 
   get clipboardAction () {
     let action = {};
     let actionOwner;
     try {
       let xferable = Cc["@mozilla.org/widget/transferable;1"].
                      createInstance(Ci.nsITransferable);
+      xferable.init(null);
       xferable.addDataFlavor(PlacesUtils.TYPE_X_MOZ_PLACE_ACTION)
       this.clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
       xferable.getTransferData(PlacesUtils.TYPE_X_MOZ_PLACE_ACTION, action, {});
       [action, actionOwner] =
         action.value.QueryInterface(Ci.nsISupportsString).data.split(",");
     } catch(ex) {
       // Paste from external sources don't have any associated action, just
       // fallback to a copy action.
@@ -1085,16 +1087,17 @@ PlacesController.prototype = {
       // This clears the logical clipboard, doesn't remove data.
       this.clipboard.emptyClipboard(Ci.nsIClipboard.kGlobalClipboard);
     }
   },
 
   _clearClipboard: function PC__clearClipboard() {
     let xferable = Cc["@mozilla.org/widget/transferable;1"].
                    createInstance(Ci.nsITransferable);
+    xferable.init(null);
     // Empty transferables may cause crashes, so just add an unknown type.
     const TYPE = "text/x-moz-place-empty";
     xferable.addDataFlavor(TYPE);
     xferable.setTransferData(TYPE, PlacesUtils.toISupportsString(""), 0);
     this.clipboard.setData(xferable, null, Ci.nsIClipboard.kGlobalClipboard);
   },
 
   _populateClipboard: function PC__populateClipboard(aNodes, aAction) {
@@ -1130,16 +1133,17 @@ PlacesController.prototype = {
     function addData(type, data) {
       xferable.addDataFlavor(type);
       xferable.setTransferData(type, PlacesUtils.toISupportsString(data),
                                data.length * 2);
     }
 
     let xferable = Cc["@mozilla.org/widget/transferable;1"].
                    createInstance(Ci.nsITransferable);
+    xferable.init(null);
     let hasData = false;
     // This order matters here!  It controls how this and other applications
     // select data to be inserted based on type.
     contents.forEach(function (content) {
       if (content.entries.length > 0) {
         hasData = true;
         let glue =
           content.type == PlacesUtils.TYPE_X_MOZ_PLACE ? "," : PlacesUtils.endl;
@@ -1219,16 +1223,17 @@ PlacesController.prototype = {
     let ip = this._view.insertionPoint;
     if (!ip)
       throw Cr.NS_ERROR_NOT_AVAILABLE;
 
     let action = this.clipboardAction;
 
     let xferable = Cc["@mozilla.org/widget/transferable;1"].
                    createInstance(Ci.nsITransferable);
+    xferable.init(null);
     // This order matters here!  It controls the preferred flavors for this
     // paste operation.
     [ PlacesUtils.TYPE_X_MOZ_PLACE,
       PlacesUtils.TYPE_X_MOZ_URL,
       PlacesUtils.TYPE_UNICODE,
     ].forEach(function (type) xferable.addDataFlavor(type));
 
     this.clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
--- a/browser/devtools/highlighter/inspector.jsm
+++ b/browser/devtools/highlighter/inspector.jsm
@@ -1099,26 +1099,26 @@ InspectorUI.prototype = {
   },
 
   /**
    * Copy the innerHTML of the selected Node to the clipboard. Called via the
    * Inspector:CopyInner command.
    */
   copyInnerHTML: function IUI_copyInnerHTML()
   {
-    clipboardHelper.copyString(this.selection.innerHTML);
+    clipboardHelper.copyString(this.selection.innerHTML, this.selection.ownerDocument);
   },
 
   /**
    * Copy the outerHTML of the selected Node to the clipboard. Called via the
    * Inspector:CopyOuter command.
    */
   copyOuterHTML: function IUI_copyOuterHTML()
   {
-    clipboardHelper.copyString(this.selection.outerHTML);
+    clipboardHelper.copyString(this.selection.outerHTML, this.selection.ownerDocument);
   },
 
   /**
    * Delete the selected node. Called via the Inspector:DeleteNode command.
    */
   deleteNode: function IUI_deleteNode()
   {
     let selection = this.selection;
--- a/browser/devtools/sourceeditor/source-editor-orion.jsm
+++ b/browser/devtools/sourceeditor/source-editor-orion.jsm
@@ -758,16 +758,17 @@ SourceEditor.prototype = {
     this._primarySelectionTimeout = null;
 
     let text = this.getSelectedText();
     if (!text) {
       return;
     }
 
     clipboardHelper.copyStringToClipboard(text,
+                                          this.parentElement.ownerDocument,
                                           Ci.nsIClipboard.kSelectionClipboard);
   },
 
   /**
    * Highlight the current line using the Orion annotation model.
    *
    * @private
    * @param object aEvent
--- a/browser/devtools/sourceeditor/test/browser_bug695035_middle_click_paste.js
+++ b/browser/devtools/sourceeditor/test/browser_bug695035_middle_click_paste.js
@@ -49,16 +49,17 @@ function editorLoaded()
   editor.setText(initialText);
 
   let expectedString = "foobarBug695035-" + Date.now();
 
   let doCopy = function() {
     let clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].
                           getService(Ci.nsIClipboardHelper);
     clipboardHelper.copyStringToClipboard(expectedString,
+                                          testWin.document,
                                           Ci.nsIClipboard.kSelectionClipboard);
   };
 
   let onCopy = function() {
     editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onPaste);
 
     EventUtils.synthesizeMouse(editor.editorElement, 10, 10, {}, testWin);
     EventUtils.synthesizeMouse(editor.editorElement, 11, 11, {button: 1}, testWin);
--- a/browser/devtools/sourceeditor/test/head.js
+++ b/browser/devtools/sourceeditor/test/head.js
@@ -1,14 +1,20 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
+function getLoadContext() {
+  return window.QueryInterface(Ci.nsIInterfaceRequestor)
+               .getInterface(Ci.nsIWebNavigation)
+               .QueryInterface(Ci.nsILoadContext);
+}
+
 /*
  * Polls the X11 primary selection buffer waiting for the expected value. A known
  * value different than the expected value is put on the clipboard first (and
  * also polled for) so we can be sure the value we get isn't just the expected
  * value because it was already in the buffer.
  *
  * @param aExpectedStringOrValidatorFn
  *        The string value that is expected to be in the X11 primary selection buffer
@@ -48,16 +54,17 @@ function waitForSelection(aExpectedStrin
         ok(false, "Timed out while polling the X11 primary selection buffer.");
         reset();
         failureFn();
         return;
       }
 
       let transferable = Cc["@mozilla.org/widget/transferable;1"].
                          createInstance(Ci.nsITransferable);
+      transferable.init(getLoadContext());
       transferable.addDataFlavor(requestedFlavor);
 
       clipboard.getData(transferable, clipboard.kSelectionClipboard);
 
       let str = {};
       let strLength = {};
 
       transferable.getTransferData(requestedFlavor, str, strLength);
@@ -84,16 +91,17 @@ function waitForSelection(aExpectedStrin
 
     // First we wait for a known value different from the expected one.
     var preExpectedVal = waitForSelection._monotonicCounter +
                          "-waitForSelection-known-value";
 
     let clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].
                           getService(Ci.nsIClipboardHelper);
     clipboardHelper.copyStringToClipboard(preExpectedVal,
+                                          document,
                                           Ci.nsIClipboard.kSelectionClipboard);
 
     wait(function(aData) aData == preExpectedVal,
          function() {
            // Call the original setup fn
            aSetupFn();
            wait(inputValidatorFn, aSuccessFn, aFailureFn, requestedFlavor);
          }, aFailureFn, "text/unicode");
--- a/browser/devtools/styleinspector/CssHtmlTree.jsm
+++ b/browser/devtools/styleinspector/CssHtmlTree.jsm
@@ -561,17 +561,17 @@ CssHtmlTree.prototype = {
     let text = win.getSelection().toString();
 
     // Tidy up block headings by moving CSS property names and their values onto
     // the same line and inserting a colon between them.
     text = text.replace(/(.+)\r?\n\s+/g, "$1: ");
 
     // Remove any MDN link titles
     text = text.replace(CssHtmlTree.HELP_LINK_TITLE, "");
-    clipboardHelper.copyString(text);
+    clipboardHelper.copyString(text, this.doc);
 
     if (aEvent) {
       aEvent.preventDefault();
     }
   },
 
   /**
    * Copy declaration.
@@ -591,17 +591,17 @@ CssHtmlTree.prototype = {
           break;
         }
       }
     }
     if (node) {
       let name = node.querySelector(".property-name").textContent;
       let value = node.querySelector(".property-value").textContent;
 
-      clipboardHelper.copyString(name + ": " + value + ";");
+      clipboardHelper.copyString(name + ": " + value + ";", this.doc);
     }
   },
 
   /**
    * Copy property name.
    *
    * @param aEvent The event object
    */
@@ -616,17 +616,17 @@ CssHtmlTree.prototype = {
       while (node = node.parentElement) {
         if (node.classList.contains("property-view")) {
           break;
         }
       }
     }
     if (node) {
       node = node.querySelector(".property-name");
-      clipboardHelper.copyString(node.textContent);
+      clipboardHelper.copyString(node.textContent, this.doc);
     }
   },
 
   /**
    * Copy property value.
    *
    * @param aEvent The event object
    */
@@ -641,17 +641,17 @@ CssHtmlTree.prototype = {
       while (node = node.parentElement) {
         if (node.classList.contains("property-view")) {
           break;
         }
       }
     }
     if (node) {
       node = node.querySelector(".property-value");
-      clipboardHelper.copyString(node.textContent);
+      clipboardHelper.copyString(node.textContent, this.doc);
     }
   },
 
   /**
    * Destructor for CssHtmlTree.
    */
   destroy: function CssHtmlTree_destroy()
   {
--- a/browser/devtools/styleinspector/CssRuleView.jsm
+++ b/browser/devtools/styleinspector/CssRuleView.jsm
@@ -1159,17 +1159,17 @@ CssRuleView.prototype = {
 
     // Remove inherited from: line
     let inheritedFrom = _strings.
       GetStringFromName("rule.inheritedSource");
     inheritedFrom = inheritedFrom.replace(/\s%S\s\(%S\)/g, "");
     rx = new RegExp("(\r?\n)" + inheritedFrom + ".*", "g");
     text = text.replace(rx, "$1");
 
-    clipboardHelper.copyString(text);
+    clipboardHelper.copyString(text, this.doc);
 
     if (aEvent) {
       aEvent.preventDefault();
     }
   },
 
   /**
    * Copy a rule from the rule view.
@@ -1216,17 +1216,17 @@ CssRuleView.prototype = {
     let out = selector + " {" + terminator;
     for (let i = 0; i < propertyNames.length; i++) {
       let name = propertyNames[i].textContent;
       let value = propertyValues[i].textContent;
       out += "    " + name + ": " + value + ";" + terminator;
     }
     out += "}" + terminator;
 
-    clipboardHelper.copyString(out);
+    clipboardHelper.copyString(out, this.doc);
   },
 
   /**
    * Copy a declaration from the rule view.
    *
    * @param aEvent The event object
    */
   _onCopyDeclaration: function CssRuleView_onCopyDeclaration(aEvent)
@@ -1255,17 +1255,17 @@ CssRuleView.prototype = {
     for (let computedList of computedLists) {
       computedList.parentNode.removeChild(computedList);
     }
 
     let propertyName = node.querySelector(".ruleview-propertyname").textContent;
     let propertyValue = node.querySelector(".ruleview-propertyvalue").textContent;
     let out = propertyName + ": " + propertyValue + ";";
 
-    clipboardHelper.copyString(out);
+    clipboardHelper.copyString(out, this.doc);
   },
 
   /**
    * Copy a property name from the rule view.
    *
    * @param aEvent The event object
    */
   _onCopyProperty: function CssRuleView_onCopyProperty(aEvent)
@@ -1275,17 +1275,17 @@ CssRuleView.prototype = {
       return;
     }
 
     if (!node.classList.contains("ruleview-propertyname")) {
       node = node.querySelector(".ruleview-propertyname");
     }
 
     if (node) {
-      clipboardHelper.copyString(node.textContent);
+      clipboardHelper.copyString(node.textContent, this.doc);
     }
   },
 
  /**
    * Copy a property value from the rule view.
    *
    * @param aEvent The event object
    */
@@ -1296,17 +1296,17 @@ CssRuleView.prototype = {
       return;
     }
 
     if (!node.classList.contains("ruleview-propertyvalue")) {
       node = node.querySelector(".ruleview-propertyvalue");
     }
 
     if (node) {
-      clipboardHelper.copyString(node.textContent);
+      clipboardHelper.copyString(node.textContent, this.doc);
     }
   }
 };
 
 /**
  * Create a RuleEditor.
  *
  * @param CssRuleView aRuleView
--- a/browser/devtools/webconsole/HUDService.jsm
+++ b/browser/devtools/webconsole/HUDService.jsm
@@ -1007,17 +1007,17 @@ HUD_SERVICE.prototype =
         let timestampString = l10n.timestampString(item.timestamp);
         if (newGroup) {
           strings.push("--");
           newGroup = false;
         }
         strings.push("[" + timestampString + "] " + item.clipboardText);
       }
     }
-    clipboardHelper.copyString(strings.join("\n"));
+    clipboardHelper.copyString(strings.join("\n"), this.doc);
   }
 };
 
 //////////////////////////////////////////////////////////////////////////
 // HeadsUpDisplay
 //////////////////////////////////////////////////////////////////////////
 
 /**
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_642615_autocomplete.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_642615_autocomplete.js
@@ -23,17 +23,17 @@ function consoleOpened(HUD) {
   // wait for key "u"
   function onCompletionValue() {
     completionValue = jsterm.completeNode.value;
 
     // Arguments: expected, setup, success, failure.
     waitForClipboard(
       stringToCopy,
       function() {
-        clipboardHelper.copyString(stringToCopy);
+        clipboardHelper.copyString(stringToCopy, document);
       },
       onClipboardCopy,
       finishTest);
   }
 
   function onClipboardCopy() {
     updateEditUIVisibility();
     goDoCommand("cmd_paste");
--- a/content/base/public/nsCopySupport.h
+++ b/content/base/public/nsCopySupport.h
@@ -12,32 +12,34 @@
 class nsISelection;
 class nsIDocument;
 class nsIImageLoadingContent;
 class nsIContent;
 class nsITransferable;
 class nsACString;
 class nsAString;
 class nsIPresShell;
+class nsILoadContext;
 
 class nsCopySupport
 {
   // class of static helper functions for copy support
   public:
     static nsresult HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16 aClipboardID);
     static nsresult DoHooks(nsIDocument *aDoc, nsITransferable *aTrans,
                             bool *aDoPutOnClipboard);
     static nsresult IsPlainTextContext(nsISelection *aSel, nsIDocument *aDoc, bool *aIsPlainTextContext);
 
     // Get the selection, or entire document, in the format specified by the mime type
     // (text/html or text/plain). If aSel is non-null, use it, otherwise get the entire
     // doc.
     static nsresult GetContents(const nsACString& aMimeType, PRUint32 aFlags, nsISelection *aSel, nsIDocument *aDoc, nsAString& outdata);
     
     static nsresult ImageCopy(nsIImageLoadingContent* aImageElement,
+                              nsILoadContext* aLoadContext,
                               PRInt32 aCopyFlags);
 
     // Get the selection as a transferable. Similar to HTMLCopy except does
     // not deal with the clipboard.
     static nsresult GetTransferableForSelection(nsISelection* aSelection,
                                                 nsIDocument* aDocument,
                                                 nsITransferable** aTransferable);
 
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -30,16 +30,17 @@
 #include "nsPIDOMWindow.h"
 #include "nsSMILAnimationController.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIFrameRequestCallback.h"
 #include "nsEventStates.h"
 #include "nsIStructuredCloneContainer.h"
 #include "nsIBFCacheEntry.h"
+#include "nsILoadContext.h"
 
 class nsIContent;
 class nsPresContext;
 class nsIPresShell;
 class nsIDocShell;
 class nsStyleSet;
 class nsIStyleSheet;
 class nsIStyleRule;
@@ -883,16 +884,29 @@ public:
     nsISupports* container = nsnull;
     if (mDocumentContainer)
       CallQueryReferent(mDocumentContainer.get(), &container);
 
     return container;
   }
 
   /**
+   * Get the container's load context for this document.
+   */
+  nsILoadContext* GetLoadContext() const
+  {
+    nsCOMPtr<nsISupports> container = GetContainer();
+    if (container) {
+      nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(container);
+      return loadContext;
+    }
+    return nsnull;
+  }
+
+  /**
    * Set and get XML declaration. If aVersion is null there is no declaration.
    * aStandalone takes values -1, 0 and 1 indicating respectively that there
    * was no standalone parameter in the declaration, that it was given as no,
    * or that it was given as yes.
    */
   virtual void SetXMLDeclaration(const PRUnichar *aVersion,
                                  const PRUnichar *aEncoding,
                                  const PRInt32 aStandalone) = 0;
--- a/content/base/src/nsCopySupport.cpp
+++ b/content/base/src/nsCopySupport.cpp
@@ -177,16 +177,17 @@ SelectionCopyHelper(nsISelection *aSel, 
     if (NS_FAILED(rv))
       return rv;
   }
 
   if ((doPutOnClipboard && clipboard) || aTransferable != nsnull) {
     // Create a transferable for putting data on the Clipboard
     nsCOMPtr<nsITransferable> trans = do_CreateInstance(kCTransferableCID);
     if (trans) {
+      trans->Init(aDoc->GetLoadContext());
       if (bIsHTMLCopy) {
         // Set up a format converter so that clipboard flavor queries work.
         // This converter isn't really used for conversions.
         nsCOMPtr<nsIFormatConverter> htmlConverter =
           do_CreateInstance(kHTMLConverterCID);
         trans->SetConverter(htmlConverter);
 
         if (!buffer.IsEmpty()) {
@@ -454,23 +455,25 @@ nsCopySupport::GetContents(const nsACStr
   
   // encode the selection
   return docEncoder->EncodeToString(outdata);
 }
 
 
 nsresult
 nsCopySupport::ImageCopy(nsIImageLoadingContent* aImageElement,
+                         nsILoadContext* aLoadContext,
                          PRInt32 aCopyFlags)
 {
   nsresult rv;
 
   // create a transferable for putting data on the Clipboard
   nsCOMPtr<nsITransferable> trans(do_CreateInstance(kCTransferableCID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
+  trans->Init(aLoadContext);
 
   if (aCopyFlags & nsIContentViewerEdit::COPY_IMAGE_TEXT) {
     // get the location from the element
     nsCOMPtr<nsIURI> uri;
     rv = aImageElement->GetCurrentURI(getter_AddRefs(uri));
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
 
--- a/content/base/test/test_bug166235.html
+++ b/content/base/test/test_bug166235.html
@@ -17,42 +17,50 @@ https://bugzilla.mozilla.org/show_bug.cg
   
 </div>
 <textarea id="input"></textarea>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 166235 **/
   var Cc = SpecialPowers.wrap(Components).classes;
+  var Ci = SpecialPowers.wrap(Components).interfaces;
 
   var webnav = SpecialPowers.wrap(window).QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                                          .getInterface(Components.interfaces.nsIWebNavigation)
 
   var docShell = webnav.QueryInterface(Components.interfaces.nsIDocShell);
 
   var documentViewer = docShell.contentViewer
                                .QueryInterface(Components.interfaces.nsIContentViewerEdit);
 
   var clipboard = Cc["@mozilla.org/widget/clipboard;1"]
                     .getService(Components.interfaces.nsIClipboard);
 
   var textarea = SpecialPowers.wrap(document).getElementById('input');
 
+  function getLoadContext() {
+    return SpecialPowers.wrap(window).QueryInterface(Ci.nsIInterfaceRequestor)
+                                     .getInterface(Ci.nsIWebNavigation)
+                                     .QueryInterface(Ci.nsILoadContext);
+  }
+
   function copyChildrenToClipboard(id) {
     textarea.blur();
     clipboard.emptyClipboard(1);
     window.getSelection().selectAllChildren(document.getElementById(id));
     documentViewer.copySelection();
 
     is(clipboard.hasDataMatchingFlavors(["text/unicode"], 1,1), true);
     is(clipboard.hasDataMatchingFlavors(["text/html"], 1,1), true);
   }
   function getClipboardData(mime) {
     var transferable = Cc['@mozilla.org/widget/transferable;1']
                          .createInstance(Components.interfaces.nsITransferable);
+    transferable.init(getLoadContext());
     transferable.addDataFlavor(mime);
     clipboard.getData(transferable, 1);
     var data = SpecialPowers.wrap({});
     transferable.getTransferData(mime, data, {}) ;
     return data;
   }
   function testClipboardValue(mime, expected, test) {
     var data = getClipboardData(mime);
--- a/content/base/test/test_copypaste.html
+++ b/content/base/test/test_copypaste.html
@@ -30,16 +30,23 @@ function modifySelection(s) {
   g.addRange(a);
   window.setTimeout(function () {
       e.parentNode.removeChild(e);
       g.removeAllRanges();
       g.addRange(l);
   }, 0)
 }
 
+function getLoadContext() {
+  var Ci = SpecialPowers.wrap(Components).interfaces;
+  return SpecialPowers.wrap(window).QueryInterface(Ci.nsIInterfaceRequestor)
+                                   .getInterface(Ci.nsIWebNavigation)
+                                   .QueryInterface(Ci.nsILoadContext);
+}
+
 function testCopyPaste () {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 
   var webnav = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                      .getInterface(Components.interfaces.nsIWebNavigation)
 
   var docShell = webnav.QueryInterface(Components.interfaces.nsIDocShell);
 
@@ -81,16 +88,17 @@ function testCopyPaste () {
     textarea.blur();
     clipboard.emptyClipboard(1);
     window.getSelection().selectAllChildren(document.getElementById(id));
     copySelectionToClipboard();
   }
   function getClipboardData(mime) {
     var transferable = Components.classes['@mozilla.org/widget/transferable;1']
                                  .createInstance(Components.interfaces.nsITransferable);
+    transferable.init(getLoadContext());
     transferable.addDataFlavor(mime);
     clipboard.getData(transferable, 1);
     var data = {};
     transferable.getTransferData(mime, data, {}) ;
     return data;
   }
   function testClipboardValue(mime, expected) {
     var data = getClipboardData(mime);
--- a/content/events/src/nsDOMDataTransfer.cpp
+++ b/content/events/src/nsDOMDataTransfer.cpp
@@ -622,38 +622,50 @@ nsDOMDataTransfer::Clone(PRUint32 aEvent
   NS_ENSURE_TRUE(newDataTransfer, NS_ERROR_OUT_OF_MEMORY);
 
   *aNewDataTransfer = newDataTransfer;
   NS_ADDREF(*aNewDataTransfer);
   return NS_OK;
 }
 
 void
-nsDOMDataTransfer::GetTransferables(nsISupportsArray** aArray)
+nsDOMDataTransfer::GetTransferables(nsISupportsArray** aArray,
+                                    nsIDOMNode* aDragTarget)
 {
+  MOZ_ASSERT(aDragTarget);
+
   *aArray = nsnull;
 
   nsCOMPtr<nsISupportsArray> transArray =
     do_CreateInstance("@mozilla.org/supports-array;1");
   if (!transArray)
     return;
 
+  nsCOMPtr<nsINode> dragNode = do_QueryInterface(aDragTarget);
+  if (!dragNode)
+    return;
+  nsIDocument* doc = dragNode->GetCurrentDoc();
+  if (!doc)
+    return;
+  nsILoadContext* loadContext = doc->GetLoadContext();
+
   bool added = 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;
+    transferable->Init(loadContext);
 
     for (PRUint32 f = 0; f < count; f++) {
       TransferItem& formatitem = item[f];
       if (!formatitem.mData) // skip empty items
         continue;
 
       PRUint32 length;
       nsCOMPtr<nsISupports> convertedData;
--- a/content/events/src/nsDOMDataTransfer.h
+++ b/content/events/src/nsDOMDataTransfer.h
@@ -92,17 +92,18 @@ public:
   }
 
   // a readonly dataTransfer cannot have new data added or existing data removed.
   // Only the dropEffect and effectAllowed may be modified.
   void SetReadOnly() { mReadOnly = true; }
 
   // converts the data into an array of nsITransferable objects to be used for
   // drag and drop or clipboard operations.
-  void GetTransferables(nsISupportsArray** transferables);
+  void GetTransferables(nsISupportsArray** transferables,
+                        nsIDOMNode* aDragTarget);
 
   // converts the data in the variant to an nsISupportString if possible or
   // an nsISupports or null otherwise.
   bool ConvertFromVariant(nsIVariant* aVariant,
                             nsISupports** aSupports,
                             PRUint32* aLength);
 
   // clears all of the data
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -2312,17 +2312,17 @@ nsEventStateManager::DoDefaultDragStart(
              nsIDragService::DRAGDROP_ACTION_MOVE |
              nsIDragService::DRAGDROP_ACTION_LINK;
 
   // get any custom drag image that was set
   PRInt32 imageX, imageY;
   nsIDOMElement* dragImage = aDataTransfer->GetDragImage(&imageX, &imageY);
 
   nsCOMPtr<nsISupportsArray> transArray;
-  aDataTransfer->GetTransferables(getter_AddRefs(transArray));
+  aDataTransfer->GetTransferables(getter_AddRefs(transArray), dragTarget);
   if (!transArray)
     return false;
 
   // XXXndeakin don't really want to create a new drag DOM event
   // here, but we need something to pass to the InvokeDragSession
   // methods.
   nsCOMPtr<nsIDOMEvent> domEvent;
   NS_NewDOMDragEvent(getter_AddRefs(domEvent), aPresContext, aDragEvent);
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -502,16 +502,17 @@ ContentParent::RecvSetClipboardText(cons
         do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, true);
     
     rv = dataWrapper->SetData(text);
     NS_ENSURE_SUCCESS(rv, true);
     
     nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
     NS_ENSURE_SUCCESS(rv, true);
+    trans->Init(nsnull);
     
     // If our data flavor has already been added, this will fail. But we don't care
     trans->AddDataFlavor(kUnicodeMime);
     
     nsCOMPtr<nsISupports> nsisupportsDataWrapper =
         do_QueryInterface(dataWrapper);
     
     rv = trans->SetTransferData(kUnicodeMime, nsisupportsDataWrapper,
@@ -526,16 +527,17 @@ bool
 ContentParent::RecvGetClipboardText(const PRInt32& whichClipboard, nsString* text)
 {
     nsresult rv;
     nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
     NS_ENSURE_SUCCESS(rv, true);
 
     nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
     NS_ENSURE_SUCCESS(rv, true);
+    trans->Init(nsnull);
     
     clipboard->GetData(trans, whichClipboard);
     nsCOMPtr<nsISupports> tmp;
     PRUint32 len;
     rv = trans->GetTransferData(kUnicodeMime, getter_AddRefs(tmp), &len);
     if (NS_FAILED(rv))
         return false;
 
--- a/dom/tests/mochitest/general/test_clipboard_events.html
+++ b/dom/tests/mochitest/general/test_clipboard_events.html
@@ -69,20 +69,27 @@ window.onfocus = function()
   
   SimpleTest.finish();
 }
 
 // Calling .focus begins the test run.
 SimpleTest.waitForExplicitFinish();
 window.focus();
 
+function getLoadContext() {
+  return window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+               .getInterface(Components.interfaces.nsIWebNavigation)
+               .QueryInterface(Components.interfaces.nsILoadContext);
+}
+
 function getClipboardText() {
   var trans = Components.classes["@mozilla.org/widget/transferable;1"]
     .createInstance();
   trans = trans.QueryInterface(Components.interfaces.nsITransferable);
+  trans.init(getLoadContext());
   trans.addDataFlavor("text/unicode");
   
   var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
     .getService();
   clipboard = clipboard.QueryInterface(Components.interfaces.nsIClipboard);
   clipboard.getData(trans, clipboard.kGlobalClipboard);
 
   var str = new Object();
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -88,16 +88,17 @@
 #include "prmem.h"
 #include "nsStreamUtils.h"
 #include "nsIPrincipal.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsContentUtils.h"
 #include "mozilla/Preferences.h"
 #include "nsIParserUtils.h"
+#include "nsILoadContext.h"
 
 using namespace mozilla;
 
 const PRUnichar nbsp = 160;
 
 #define kInsertCookie  "_moz_Insert Here_moz_"
 
 #define NS_FOUND_TARGET NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR, 3)
@@ -980,16 +981,20 @@ NS_IMETHODIMP nsHTMLEditor::PrepareHTMLT
 {
   // Create generic Transferable for getting the data
   nsresult rv = CallCreateInstance("@mozilla.org/widget/transferable;1", aTransferable);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Get the nsITransferable interface for getting the data from the clipboard
   if (aTransferable)
   {
+    nsCOMPtr<nsIDocument> destdoc = GetDocument();
+    nsILoadContext* loadContext = destdoc ? destdoc->GetLoadContext() : nsnull;
+    (*aTransferable)->Init(loadContext);
+
     // Create the desired DataFlavor for the type of data
     // we want to get out of the transferable
     // This should only happen in html editors, not plaintext
     if (!IsPlaintextEditor())
     {
       if (!aHavePrivFlavor) 
       {
         (*aTransferable)->AddDataFlavor(kNativeHTMLMime);
@@ -1530,23 +1535,25 @@ NS_IMETHODIMP nsHTMLEditor::Paste(PRInt3
   {
     nsCOMPtr<nsISupports> contextDataObj, infoDataObj;
     PRUint32 contextLen, infoLen;
     nsCOMPtr<nsISupportsString> textDataObj;
 
     nsCOMPtr<nsITransferable> contextTrans =
                   do_CreateInstance("@mozilla.org/widget/transferable;1");
     NS_ENSURE_TRUE(contextTrans, NS_ERROR_NULL_POINTER);
+    contextTrans->Init(nsnull);
     contextTrans->AddDataFlavor(kHTMLContext);
     clipboard->GetData(contextTrans, aSelectionType);
     contextTrans->GetTransferData(kHTMLContext, getter_AddRefs(contextDataObj), &contextLen);
 
     nsCOMPtr<nsITransferable> infoTrans =
                   do_CreateInstance("@mozilla.org/widget/transferable;1");
     NS_ENSURE_TRUE(infoTrans, NS_ERROR_NULL_POINTER);
+    infoTrans->Init(nsnull);
     infoTrans->AddDataFlavor(kHTMLInfo);
     clipboard->GetData(infoTrans, aSelectionType);
     infoTrans->GetTransferData(kHTMLInfo, getter_AddRefs(infoDataObj), &infoLen);
 
     if (contextDataObj)
     {
       nsAutoString text;
       textDataObj = do_QueryInterface(contextDataObj);
@@ -1770,16 +1777,20 @@ NS_IMETHODIMP nsHTMLEditor::PasteAsPlain
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Create generic Transferable for getting the data
   nsCOMPtr<nsITransferable> trans =
                  do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
 
+  nsCOMPtr<nsIDocument> destdoc = GetDocument();
+  nsILoadContext* loadContext = destdoc ? destdoc->GetLoadContext() : nsnull;
+  trans->Init(loadContext);
+
   // We only handle plaintext pastes here
   trans->AddDataFlavor(kUnicodeMime);
 
   // Get the Data from the clipboard
   clipboard->GetData(trans, aSelectionType);
 
   // Now we ask the transferable for the data
   // it still owns the data, we just have a pointer to it.
--- a/editor/libeditor/html/tests/test_CF_HTML_clipboard.html
+++ b/editor/libeditor/html/tests/test_CF_HTML_clipboard.html
@@ -22,16 +22,22 @@ https://bugzilla.mozilla.org/show_bug.cg
 /** Test for Bug 572642 **/
 
 function copyCF_HTML(cfhtml, success, failure) {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   const Cc = Components.classes;
   const Ci = Components.interfaces;
   const CF_HTML = "application/x-moz-nativehtml";
 
+  function getLoadContext() {
+    return window.QueryInterface(Ci.nsIInterfaceRequestor)
+                 .getInterface(Ci.nsIWebNavigation)
+                 .QueryInterface(Ci.nsILoadContext);
+  }
+
   var cb = Cc["@mozilla.org/widget/clipboard;1"].
            getService(Ci.nsIClipboard);
 
   var counter = 0;
   function copyCF_HTML_worker(success, failure) {
     if (++counter > 50) {
       ok(false, "Timed out while polling clipboard for pasted data");
       failure();
@@ -42,31 +48,33 @@ function copyCF_HTML(cfhtml, success, fa
     var flavors = [CF_HTML];
     if (!cb.hasDataMatchingFlavors(flavors, flavors.length, cb.kGlobalClipboard)) {
       setTimeout(function() copyCF_HTML_worker(success, failure), 100);
       return;
     }
 
     var trans = Cc["@mozilla.org/widget/transferable;1"].
                 createInstance(Ci.nsITransferable);
+    trans.init(getLoadContext());
     trans.addDataFlavor(CF_HTML);
     cb.getData(trans, cb.kGlobalClipboard);
     var data = {};
     try {
       trans.getTransferData(CF_HTML, data, {});
       data = data.value.QueryInterface(Ci.nsISupportsCString).data;
     } catch (e) {
       setTimeout(function() copyCF_HTML_worker(success, failure), 100);
       return;
     }
     success();
   }
 
   var trans = Cc["@mozilla.org/widget/transferable;1"].
               createInstance(Ci.nsITransferable);
+  trans.init(getLoadContext());
   trans.addDataFlavor(CF_HTML);
   var data = Cc["@mozilla.org/supports-cstring;1"].
              createInstance(Ci.nsISupportsCString);
   data.data = cfhtml;
   trans.setTransferData(CF_HTML, data, cfhtml.length);
   cb.setData(trans, null, cb.kGlobalClipboard);
   copyCF_HTML_worker(success, failure);
 }
--- a/editor/libeditor/html/tests/test_bug489202.xul
+++ b/editor/libeditor/html/tests/test_bug489202.xul
@@ -28,21 +28,28 @@ https://bugzilla.mozilla.org/show_bug.cg
   </body>
   <script class="testbody" type="application/javascript">
   <![CDATA[
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils);
   var Cc = Components.classes;
   var Ci = Components.interfaces;
 
+function getLoadContext() {
+  return window.QueryInterface(Ci.nsIInterfaceRequestor)
+               .getInterface(Ci.nsIWebNavigation)
+               .QueryInterface(Ci.nsILoadContext);
+}
+
 function runTest() {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 
   var trans = Cc["@mozilla.org/widget/transferable;1"]
       .createInstance(Ci.nsITransferable);
+  trans.init(getLoadContext());
   trans.addDataFlavor("text/html");
   var test_data = '<meta/><a href="http://mozilla.org/">mozilla.org</a>';
   var cstr = Cc["@mozilla.org/supports-string;1"]
       .createInstance(Ci.nsISupportsString);
   cstr.data = test_data;
   trans.setTransferData("text/html", cstr, test_data.length*2);
 
   window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
--- a/editor/libeditor/html/tests/test_bug520189.html
+++ b/editor/libeditor/html/tests/test_bug520189.html
@@ -543,28 +543,36 @@ function doNextTest() {
     return;
   }
 
   runTest(tests[testCounter]);
 
   doNextTest();
 }
 
+function getLoadContext() {
+  const Ci = Components.interfaces;
+  return window.QueryInterface(Ci.nsIInterfaceRequestor)
+               .getInterface(Ci.nsIWebNavigation)
+               .QueryInterface(Ci.nsILoadContext);
+}
+
 function runTest(test) {
   var elem = document.getElementById(test.id);
   if ("isIFrame" in test) {
     elem.contentDocument.designMode = "on";
     elem.contentWindow.focus();
   } else
     elem.focus();
 
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 
   var trans = Components.classes["@mozilla.org/widget/transferable;1"]
                         .createInstance(Components.interfaces.nsITransferable);
+  trans.init(getLoadContext());
   var data = Components.classes["@mozilla.org/supports-string;1"]
                        .createInstance(Components.interfaces.nsISupportsString);
   data.data = test.payload;
   trans.addDataFlavor("text/html");
   trans.setTransferData("text/html", data, data.data.length * 2);
 
   if ("indirectPaste" in test) {
     var editor, win;
--- a/editor/libeditor/html/tests/test_bug525389.html
+++ b/editor/libeditor/html/tests/test_bug525389.html
@@ -7,16 +7,22 @@
 
 <script class="testbody" type="application/javascript">
 
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils);
   var Cc = Components.classes;
   var Ci = Components.interfaces;
 
+function getLoadContext() {
+  return window.QueryInterface(Ci.nsIInterfaceRequestor)
+               .getInterface(Ci.nsIWebNavigation)
+               .QueryInterface(Ci.nsILoadContext);
+}
+
 function runTest() {
   var pasteCount = 0;
   var pasteFunc = function (event) { pasteCount++; };
 
   function verifyContent(s) {
     var e = document.getElementById('i1');
     var doc = e.contentDocument;
     is(doc.body.innerHTML, s, "");
@@ -44,16 +50,17 @@ function runTest() {
     e.removeEventListener("paste", pasteFunc, false);
 
     return e;
   }
 
   function getTransferableFromClipboard(asHTML) {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
     var trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
+    trans.init(getLoadContext());
     if (asHTML) {
       trans.addDataFlavor("text/html");
     } else {
       trans.addDataFlavor("text/unicode");
     }    
     var clip = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
     clip.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
     return trans;
@@ -83,16 +90,17 @@ function runTest() {
     }
 
     // We cannot use plain strings, we have to use nsSupportsString.
     var supportsStringClass = Components.classes["@mozilla.org/supports-string;1"];
     var ssData = supportsStringClass.createInstance(Ci.nsISupportsString);
 
     // Create the transferable.
     var trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);  
+    trans.init(getLoadContext());
 
     // Add the data to the transferable.
     if (asHTML) {
       trans.addDataFlavor("text/html");
       ssData.data = doc.body.innerHTML;
       trans.setTransferData("text/html", ssData, ssData.length * 2);
     } else {
       trans.addDataFlavor("text/unicode");
--- a/editor/libeditor/text/nsPlaintextDataTransfer.cpp
+++ b/editor/libeditor/text/nsPlaintextDataTransfer.cpp
@@ -25,17 +25,16 @@
 #include "nsISupportsPrimitives.h"
 
 // Drag & Drop, Clipboard
 #include "nsIClipboard.h"
 #include "nsITransferable.h"
 #include "nsIDragService.h"
 #include "nsIDOMUIEvent.h"
 #include "nsCopySupport.h"
-#include "nsITransferable.h"
 
 // Misc
 #include "nsEditorUtils.h"
 #include "nsContentCID.h"
 #include "nsISelectionPrivate.h"
 #include "nsFrameSelection.h"
 #include "nsEventDispatcher.h"
 #include "nsContentUtils.h"
@@ -45,16 +44,20 @@ using namespace mozilla;
 NS_IMETHODIMP nsPlaintextEditor::PrepareTransferable(nsITransferable **transferable)
 {
   // Create generic Transferable for getting the data
   nsresult rv = CallCreateInstance("@mozilla.org/widget/transferable;1", transferable);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Get the nsITransferable interface for getting the data from the clipboard
   if (transferable) {
+    nsCOMPtr<nsIDocument> destdoc = GetDocument();
+    nsILoadContext* loadContext = destdoc ? destdoc->GetLoadContext() : nsnull;
+    (*transferable)->Init(loadContext);
+
     (*transferable)->AddDataFlavor(kUnicodeMime);
     (*transferable)->AddDataFlavor(kMozTextInternal);
   };
   return NS_OK;
 }
 
 nsresult nsPlaintextEditor::InsertTextAt(const nsAString &aStringToInsert,
                                          nsIDOMNode *aDestinationNode,
--- a/editor/libeditor/text/tests/test_bug596333.html
+++ b/editor/libeditor/text/tests/test_bug596333.html
@@ -14,24 +14,24 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 596333 **/
+const Ci = Components.interfaces;
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() SimpleTest.executeSoon(runTest));
 
 var gMisspeltWords;
 
 function getEditor() {
-  var Ci = Components.interfaces;
   return document.getElementById("edit")
                  .QueryInterface(Ci.nsIDOMNSEditableElement)
                  .editor;
 }
 
 function getSpellCheckSelection() {
   var editor = getEditor();
   var selcon = editor.selectionController;
@@ -46,22 +46,29 @@ function append(str) {
   edit.selectionStart = edit.selectionEnd = edit.value.length;
   var editor = getEditor();
 
   for (var i = 0; i < str.length; ++i) {
     synthesizeKey(str[i], {});
   }
 }
 
+function getLoadContext() {
+  return window.QueryInterface(Ci.nsIInterfaceRequestor)
+               .getInterface(Ci.nsIWebNavigation)
+               .QueryInterface(Ci.nsILoadContext);
+}
+
 function paste(str) {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 
   var edit = document.getElementById("edit");
   var Cc = Components.classes, Ci = Components.interfaces;
   var trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
+  trans.init(getLoadContext());
   var s = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
   s.data = str;
   trans.setTransferData("text/unicode", s, str.length * 2);
 
   getEditor().pasteTransferable(trans);
 }
 
 function runOnFocus() {
--- a/editor/libeditor/text/tests/test_bug681229.html
+++ b/editor/libeditor/text/tests/test_bug681229.html
@@ -27,17 +27,17 @@ SimpleTest.waitForFocus(function() {
   t.focus();
 
   const kValue = "a\r\nb";
   const kExpectedValue = (navigator.platform.indexOf("Win") == 0) ?
     "a\nb" : kValue;
 
   SimpleTest.waitForClipboard(kExpectedValue,
     function() {
-      SpecialPowers.copyString(kValue);
+      SpecialPowers.copyString(kValue, document);
     },
     function() {
       synthesizeKey("V", {accelKey: true});
       is(t.value, "a\nb", "The carriage return has been correctly sanitized");
       SimpleTest.finish();
     },
     function() {
       SimpleTest.finish();
--- a/gfx/thebes/gfxASurface.cpp
+++ b/gfx/thebes/gfxASurface.cpp
@@ -790,17 +790,17 @@ gfxASurface::WriteAsPNG_internal(FILE* a
   nsCString string("data:image/png;base64,");
   string.Append(encodedImg);
 
   if (aFile) {
     fprintf(aFile, "%s", string.BeginReading());
   } else {
     nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
     if (clipboard) {
-      clipboard->CopyString(NS_ConvertASCIItoUTF16(string));
+      clipboard->CopyString(NS_ConvertASCIItoUTF16(string), nsnull);
     }
   }
 
   PR_Free(encodedImg);
 
   return;
 }
 #endif
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -84,16 +84,17 @@
 #include "nsFocusManager.h"
 
 #include "nsIScrollableFrame.h"
 #include "nsIHTMLDocument.h"
 #include "nsGfxCIID.h"
 #include "nsStyleSheetService.h"
 #include "nsURILoader.h"
 #include "nsRenderingContext.h"
+#include "nsILoadContext.h"
 
 #include "nsIPrompt.h"
 #include "imgIContainer.h" // image animation mode constants
 
 //--------------------------
 // Printing Include
 //---------------------------
 #ifdef NS_PRINTING
@@ -2525,28 +2526,30 @@ NS_IMETHODIMP DocumentViewerImpl::CopyLi
   if (locationText.IsEmpty())
     return NS_ERROR_FAILURE;
 
   nsresult rv = NS_OK;
   nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // copy the href onto the clipboard
-  return clipboard->CopyString(locationText);
+  nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(mDocument);
+  return clipboard->CopyString(locationText, doc);
 }
 
 NS_IMETHODIMP DocumentViewerImpl::CopyImage(PRInt32 aCopyFlags)
 {
   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
   nsCOMPtr<nsIImageLoadingContent> node;
   GetPopupImageNode(getter_AddRefs(node));
   // make noise if we're not in an image
   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
 
-  return nsCopySupport::ImageCopy(node, aCopyFlags);
+  nsCOMPtr<nsILoadContext> loadContext(do_QueryReferent(mContainer));
+  return nsCopySupport::ImageCopy(node, loadContext, aCopyFlags);
 }
 
 
 NS_IMETHODIMP DocumentViewerImpl::GetCopyable(bool *aCopyable)
 {
   NS_ENSURE_ARG_POINTER(aCopyable);
   *aCopyable = nsCopySupport::CanCopy(mDocument);
   return NS_OK;
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1636,17 +1636,17 @@ var SelectionHandler = {
       if (element.ownerDocument.defaultView == this._view) {
         let offset = this._getViewOffset();
         let pointInSelection = (aX - offset.x > this.cache.rect.left  &&
                                 aX - offset.x < this.cache.rect.right) &&
                                (aY - offset.y > this.cache.rect.top &&
                                 aY - offset.y < this.cache.rect.bottom);
         if (pointInSelection) {
           let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
-          clipboard.copyString(selectedText);
+          clipboard.copyString(selectedText, element.ownerDocument);
           NativeWindow.toast.show(Strings.browser.GetStringFromName("selectionHelper.textCopied"), "short");
         }
       }
     }
 
     this._isRTL = false;
     this._view = null;
     this.cache = null;
@@ -4812,19 +4812,19 @@ var ClipboardHelper = {
     return this.clipboard = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
   },
 
   copy: function(aElement) {
     let selectionStart = aElement.selectionStart;
     let selectionEnd = aElement.selectionEnd;
     if (selectionStart != selectionEnd) {
       string = aElement.value.slice(selectionStart, selectionEnd);
-      this.clipboardHelper.copyString(string);
+      this.clipboardHelper.copyString(string, aElement.ownerDocument);
     } else {
-      this.clipboardHelper.copyString(aElement.value);
+      this.clipboardHelper.copyString(aElement.value, aElement.ownerDocument);
     }
   },
 
   select: function(aElement) {
     if (!aElement || !(aElement instanceof Ci.nsIDOMNSEditableElement))
       return;
     let target = aElement.QueryInterface(Ci.nsIDOMNSEditableElement);
     target.editor.selectAll();
--- a/mobile/xul/chrome/content/ContextCommands.js
+++ b/mobile/xul/chrome/content/ContextCommands.js
@@ -1,17 +1,17 @@
 // -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 var ContextCommands = {
   copy: function cc_copy() {
     let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
-    clipboard.copyString(ContextHelper.popupState.string);
+    clipboard.copyString(ContextHelper.popupState.string, Browser.contentWindow.document);
 
     let target = ContextHelper.popupState.target;
     if (target)
       target.focus();
   },
 
 #ifdef ANDROID
   selectInput: function cc_selectInput() {
@@ -67,32 +67,32 @@ var ContextCommands = {
     ContentAreaUtils.internalSave(popupState.mediaURL, null, null,
                                   popupState.contentDisposition,
                                   popupState.contentType, false, "SaveImageTitle",
                                   null, browser.documentURI, true, null);
   },
 
   copyLink: function cc_copyLink() {
     let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
-    clipboard.copyString(ContextHelper.popupState.linkURL);
+    clipboard.copyString(ContextHelper.popupState.linkURL, Browser.contentWindow.document);
   },
 
   copyEmail: function cc_copyEmail() {
       let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
-      clipboard.copyString(ContextHelper.popupState.linkURL.substr(ContextHelper.popupState.linkURL.indexOf(':')+1));
+      clipboard.copyString(ContextHelper.popupState.linkURL.substr(ContextHelper.popupState.linkURL.indexOf(':')+1), Browser.contentWindow.document);
   },
 
   copyPhone: function cc_copyPhone() {
       let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
-      clipboard.copyString(ContextHelper.popupState.linkURL.substr(ContextHelper.popupState.linkURL.indexOf(':')+1));
+      clipboard.copyString(ContextHelper.popupState.linkURL.substr(ContextHelper.popupState.linkURL.indexOf(':')+1), Browser.contentWindow.document);
   },
 
   copyImageLocation: function cc_copyImageLocation() {
       let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
-      clipboard.copyString(ContextHelper.popupState.mediaURL);
+      clipboard.copyString(ContextHelper.popupState.mediaURL, Browser.contentWindow.document);
   },
 
   shareLink: function cc_shareLink() {
     let state = ContextHelper.popupState;
     SharingUI.show(state.linkURL, state.linkTitle);
   },
 
   shareMedia: function cc_shareMedia() {
--- a/mobile/xul/chrome/content/console.js
+++ b/mobile/xul/chrome/content/console.js
@@ -258,17 +258,17 @@ let ConsoleView = {
   onEvalKeyPress: function cv_onEvalKeyPress(aEvent) {
     if (aEvent.keyCode == 13)
       this.evaluateTypein();
   },
 
   onConsoleBoxKeyPress: function cv_onConsoleBoxKeyPress(aEvent) {
     if ((aEvent.charCode == 99 || aEvent.charCode == 67) && aEvent.ctrlKey && this._list && this._list.selectedItem) {
       let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
-      clipboard.copyString(this._list.selectedItem.getAttribute("msg"));
+      clipboard.copyString(this._list.selectedItem.getAttribute("msg"), document);
     }
   },
 
   evaluateTypein: function cv_evaluateTypein() {
     this._evalCode = this._evalTextbox.value;
     this.loadOrDisplayResult();
   },
 
--- a/mobile/xul/chrome/content/content.js
+++ b/mobile/xul/chrome/content/content.js
@@ -1488,17 +1488,17 @@ var SelectionHandler = {
             this.contentWindow.getSelection().removeAllRanges();
           this.contentWindow = null;
         } catch(e) {
           Cu.reportError(e);
         }
 
         if (pointInSelection && this.selectedText.length) {
           let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
-          clipboard.copyString(this.selectedText);
+          clipboard.copyString(this.selectedText, this.contentWindow.document);
           sendAsyncMessage("Browser:SelectionCopied", { succeeded: true });
         } else {
           sendAsyncMessage("Browser:SelectionCopied", { succeeded: false });
         }
         break;
       }
 
       case "Browser:SelectionMove": {
--- a/mobile/xul/chrome/tests/browser_tapping_edit.js
+++ b/mobile/xul/chrome/tests/browser_tapping_edit.js
@@ -232,17 +232,17 @@ gTests.push({
     let plainEdit = browser.contentDocument.getElementById("plain-edit");
     plainEdit.readOnly = false;
     plainEdit.value = "Every time we fix a bug, Stuart call's the President";
     plainEdit.selectionStart = 0;
     plainEdit.selectionEnd = 0;
 
     // Put some data on the clipboard to get "paste" to be active
     let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
-    clipboard.copyString("We are testing Firefox");
+    clipboard.copyString("We are testing Firefox", content.document);
     
     let event = content.document.createEvent("PopupEvents");
     event.initEvent("contextmenu", true, true);
     plainEdit.dispatchEvent(event);
   }
 });
 
 //------------------------------------------------------------------------------
--- a/services/sync/tps/extensions/mozmill/resource/modules/inspection.js
+++ b/services/sync/tps/extensions/mozmill/resource/modules/inspection.js
@@ -226,17 +226,17 @@ var isMagicAnonymousDiv = function (_doc
           return true;
         }
   }
   return false;
 }
 
 var copyToClipboard = function(str){
   const gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"] .getService(Components.interfaces.nsIClipboardHelper);
-  gClipboardHelper.copyString(str);
+  gClipboardHelper.copyString(str, _window.document);
 }
 
 var getControllerAndDocument = function (_document, _window) {
   var windowtype = _window.document.documentElement.getAttribute('windowtype');
   var controllerString, documentString, activeTab;
 
   // TODO replace with object based cases
   switch(windowtype) {
--- a/testing/mochitest/tests/SimpleTest/specialpowersAPI.js
+++ b/testing/mochitest/tests/SimpleTest/specialpowersAPI.js
@@ -933,20 +933,20 @@ SpecialPowersAPI.prototype = {
   getNodeBaseURIObject: function(aNode) {
       return aNode.baseURIObject;
   },
 
   getDocumentURIObject: function(aDocument) {
       return aDocument.documentURIObject;
   },
 
-  copyString: function(str) {
+  copyString: function(str, doc) {
     Components.classes["@mozilla.org/widget/clipboardhelper;1"].
       getService(Components.interfaces.nsIClipboardHelper).
-      copyString(str);
+      copyString(str, doc);
   },
 
   openDialog: function(win, args) {
     return win.openDialog.apply(win, args);
   },
 
   // :jdm gets credit for this.  ex: getPrivilegedProps(window, 'location.href');
   getPrivilegedProps: function(obj, props) {
@@ -991,33 +991,35 @@ SpecialPowersAPI.prototype = {
   
   getClipboardData: function(flavor) {  
     if (this._cb == null)
       this._cb = Components.classes["@mozilla.org/widget/clipboard;1"].
                             getService(Components.interfaces.nsIClipboard);
 
     var xferable = Components.classes["@mozilla.org/widget/transferable;1"].
                    createInstance(Components.interfaces.nsITransferable);
+    xferable.init(this._getDocShell(content.window)
+                      .QueryInterface(Components.interfaces.nsILoadContext));
     xferable.addDataFlavor(flavor);
     this._cb.getData(xferable, this._cb.kGlobalClipboard);
     var data = {};
     try {
       xferable.getTransferData(flavor, data, {});
     } catch (e) {}
     data = data.value || null;
     if (data == null)
       return "";
       
     return data.QueryInterface(Components.interfaces.nsISupportsString).data;
   },
 
-  clipboardCopyString: function(preExpectedVal) {  
+  clipboardCopyString: function(preExpectedVal, doc) {
     var cbHelperSvc = Components.classes["@mozilla.org/widget/clipboardhelper;1"].
                       getService(Components.interfaces.nsIClipboardHelper);
-    cbHelperSvc.copyString(preExpectedVal);
+    cbHelperSvc.copyString(preExpectedVal, doc);
   },
 
   supportsSelectionClipboard: function() {
     if (this._cb == null) {
       this._cb = Components.classes["@mozilla.org/widget/clipboard;1"].
                             getService(Components.interfaces.nsIClipboard);
     }
     return this._cb.supportsSelectionClipboard();
--- a/toolkit/components/console/content/consoleBindings.xml
+++ b/toolkit/components/console/content/consoleBindings.xml
@@ -255,17 +255,17 @@
 
       <method name="copySelectedItem">
         <body><![CDATA[
           if (this.mSelectedItem) try {
             const clipURI = "@mozilla.org/widget/clipboardhelper;1";
             const clipI = Components.interfaces.nsIClipboardHelper;
             var clipboard = Components.classes[clipURI].getService(clipI);
 
-            clipboard.copyString(this.mSelectedItem.toString());
+            clipboard.copyString(this.mSelectedItem.toString(), document);
           } catch (ex) {
             // Unable to copy anything, die quietly
           }
         ]]></body>
       </method>
                   
       <method name="createConsoleRow">
         <body><![CDATA[
--- a/toolkit/components/passwordmgr/content/passwordManager.js
+++ b/toolkit/components/passwordmgr/content/passwordManager.js
@@ -317,17 +317,17 @@ function CopyPassword() {
   // password hasn't been entered.
   if (!showingPasswords && !masterPasswordLogin())
     return;
   // Copy selected signon's password to clipboard
   var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"].
                   getService(Components.interfaces.nsIClipboardHelper);
   var row = document.getElementById("signonsTree").currentIndex;
   var password = signonsTreeView.getCellText(row, {id : "passwordCol" });
-  clipboard.copyString(password);
+  clipboard.copyString(password, document);
 }
 
 function UpdateCopyPassword() {
   var singleSelection = (signonsTreeView.selection.count == 1);
   var menuitem = document.getElementById("context-copypassword");
   if (singleSelection)
     menuitem.removeAttribute("disabled");
   else
--- a/toolkit/components/viewconfig/content/config.js
+++ b/toolkit/components/viewconfig/content/config.js
@@ -538,27 +538,27 @@ function updateContextMenu()
   var toggleSelected = document.getElementById("toggleSelected");
   toggleSelected.setAttribute("disabled", isLocked);
   toggleSelected.hidden = !canToggle;
 }
 
 function copyPref()
 {
   var pref = gPrefView[view.selection.currentIndex];
-  gClipboardHelper.copyString(pref.prefCol + ';' + pref.valueCol);
+  gClipboardHelper.copyString(pref.prefCol + ';' + pref.valueCol, document);
 }
 
 function copyName()
 {
-  gClipboardHelper.copyString(gPrefView[view.selection.currentIndex].prefCol);
+  gClipboardHelper.copyString(gPrefView[view.selection.currentIndex].prefCol, document);
 }
 
 function copyValue()
 {
-  gClipboardHelper.copyString(gPrefView[view.selection.currentIndex].valueCol);
+  gClipboardHelper.copyString(gPrefView[view.selection.currentIndex].valueCol, document);
 }
 
 function ModifySelected()
 {
   if (view.selection.currentIndex >= 0)
     ModifyPref(gPrefView[view.selection.currentIndex]);
 }
 
--- a/toolkit/components/viewsource/content/viewSource.js
+++ b/toolkit/components/viewsource/content/viewSource.js
@@ -750,10 +750,10 @@ function contextMenuShowing() {
 
 function contextMenuCopyLinkOrEmail() {
   if (!gContextMenu.triggerNode)
     return;
 
   var href = gContextMenu.triggerNode.href;
   var clipboard = Cc['@mozilla.org/widget/clipboardhelper;1'].
                   getService(Ci.nsIClipboardHelper);
-  clipboard.copyString(href.substring(href.indexOf(':') + 1));
+  clipboard.copyString(href.substring(href.indexOf(':') + 1), document);
 }
--- a/toolkit/content/aboutSupport.js
+++ b/toolkit/content/aboutSupport.js
@@ -473,29 +473,36 @@ function createElement(tagName, textCont
   return elem;
 }
 
 function appendChildren(parentElem, childNodes) {
   for (let i = 0; i < childNodes.length; i++)
     parentElem.appendChild(childNodes[i]);
 }
 
+function getLoadContext() {
+  return window.QueryInterface(Ci.nsIInterfaceRequestor)
+               .getInterface(Ci.nsIWebNavigation)
+               .QueryInterface(Ci.nsILoadContext);
+}
+
 function copyContentsToClipboard() {
   // Get the HTML and text representations for the important part of the page.
   let contentsDiv = document.getElementById("contents");
   let dataHtml = contentsDiv.innerHTML;
   let dataText = createTextForElement(contentsDiv);
 
   // We can't use plain strings, we have to use nsSupportsString.
   let supportsStringClass = Cc["@mozilla.org/supports-string;1"];
   let ssHtml = supportsStringClass.createInstance(Ci.nsISupportsString);
   let ssText = supportsStringClass.createInstance(Ci.nsISupportsString);
 
   let transferable = Cc["@mozilla.org/widget/transferable;1"]
                        .createInstance(Ci.nsITransferable);
+  transferable.init(getLoadContext());
 
   // Add the HTML flavor.
   transferable.addDataFlavor("text/html");
   ssHtml.data = dataHtml;
   transferable.setTransferData("text/html", ssHtml, dataHtml.length * 2);
 
   // Add the plain text flavor.
   transferable.addDataFlavor("text/unicode");
--- a/toolkit/content/nsDragAndDrop.js
+++ b/toolkit/content/nsDragAndDrop.js
@@ -125,17 +125,19 @@ var nsTransferable = {
    * nsITransferable createTransferable (void) ;
    *
    * Creates and returns a transferable object.
    **/    
   createTransferable: function ()
     {
       const kXferableContractID = "@mozilla.org/widget/transferable;1";
       const kXferableIID = Components.interfaces.nsITransferable;
-      return Components.classes[kXferableContractID].createInstance(kXferableIID);
+      var trans = Components.classes[kXferableContractID].createInstance(kXferableIID);
+      trans.init(null);
+      return trans;
     }
 };  
 
 /** 
  * A FlavourSet is a simple type that represents a collection of Flavour objects.
  * FlavourSet is constructed from an array of Flavours, and stores this list as
  * an array and a hashtable. The rationale for the dual storage is as follows:
  * 
--- a/toolkit/content/tests/chrome/test_autocomplete_delayOnPaste.xul
+++ b/toolkit/content/tests/chrome/test_autocomplete_delayOnPaste.xul
@@ -104,17 +104,17 @@ function runTest() {
     synthesizeKey("v", { accelKey: true });
     is(gAutoComplete.value, SEARCH_STRING, "Value should not be autocompleted immediately");
   }
 
   SimpleTest.waitForClipboard(SEARCH_STRING, function () {
     gACTimer = Date.now();
     Components.classes["@mozilla.org/widget/clipboardhelper;1"]
       .getService(Components.interfaces.nsIClipboardHelper)
-      .copyStringToClipboard(SEARCH_STRING, Components.interfaces.nsIClipboard.kGlobalClipboard);
+      .copyStringToClipboard(SEARCH_STRING, document, Components.interfaces.nsIClipboard.kGlobalClipboard);
   }, cbCallback, cbCallback);
 }
 ]]>
 </script>
 
 <body xmlns="http://www.w3.org/1999/xhtml">
 <p id="display">
 </p>
--- a/toolkit/content/tests/chrome/test_bug253481.xul
+++ b/toolkit/content/tests/chrome/test_bug253481.xul
@@ -64,17 +64,17 @@ var expectedResults = {
 // "stripsurroundingwhitespace" strips all newlines and whitespace around them
 "stripsurroundingwhitespace": testString.replace(/\s*\n\s*/g,'')
 };
 
 // Put a multi-line string in the clipboard
 SimpleTest.waitForClipboard(testString, function() {
   var clip = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
                        .getService(Components.interfaces.nsIClipboardHelper);
-  clip.copyString(testString);
+  clip.copyString(testString, document);
 }, function() {
   for (let [item, expected] in Iterator(expectedResults)) {
      testPaste(item, $(item), expected);
   }
 
   SimpleTest.finish();
 }, function() {
   ok(false, "Could not copy the string to clipboard, giving up");
--- a/toolkit/mozapps/downloads/content/downloads.js
+++ b/toolkit/mozapps/downloads/content/downloads.js
@@ -312,25 +312,25 @@ function copySourceLocation(aDownload)
   var uri = aDownload.getAttribute("uri");
   var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
                   getService(Ci.nsIClipboardHelper);
 
   // Check if we should initialize a callback
   if (gPerformAllCallback === null) {
     let uris = [];
     gPerformAllCallback = function(aURI) aURI ? uris.push(aURI) :
-      clipboard.copyString(uris.join("\n"));
+      clipboard.copyString(uris.join("\n"), document);
   }
 
   // We have a callback to use, so use it to add a uri
   if (typeof gPerformAllCallback == "function")
     gPerformAllCallback(uri);
   else {
     // It's a plain copy source, so copy it
-    clipboard.copyString(uri);
+    clipboard.copyString(uri, document);
   }
 }
 
 /**
  * Remove the currently shown downloads from the download list.
  */
 function clearDownloadList() {
   // Clear the whole list if there's no search
@@ -707,16 +707,17 @@ var gDownloadDNDObserver =
     if (url)
       saveURL(url, name ? name : url, null, true, true);
   }
 }
 
 function pasteHandler() {
   let trans = Cc["@mozilla.org/widget/transferable;1"].
               createInstance(Ci.nsITransferable);
+  trans.init(null);
   let flavors = ["text/x-moz-url", "text/unicode"];
   flavors.forEach(trans.addDataFlavor);
 
   Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard);
 
   // Getting the data or creating the nsIURI might fail
   try {
     let data = {};
--- a/toolkit/mozapps/downloads/tests/chrome/test_multi_select.xul
+++ b/toolkit/mozapps/downloads/tests/chrome/test_multi_select.xul
@@ -78,32 +78,39 @@ function test()
     observe: function(aSubject, aTopic, aData) {
       if (aTopic != DLMGR_UI_DONE)
         return;
 
       SimpleTest.waitForFocus(function () { continueTest(aSubject) }, aSubject);
     }
   };
 
+  function getLoadContext() {
+    return window.QueryInterface(Ci.nsIInterfaceRequestor)
+                 .getInterface(Ci.nsIWebNavigation)
+                 .QueryInterface(Ci.nsILoadContext);
+  }
+
   function continueTest(win) {
     let $ = function(aId) win.document.getElementById(aId);
     let downloadView = $("downloadView");
 
     // Default test/check for invocations
     let invokeCount = 0;
     let counter = function() invokeCount++;
 
     // Accessors for returning a value for various properties
     let getItems = function() downloadView.itemCount;
     let getSelected = function() downloadView.selectedCount;
     let getClipboard = function() {
       let clip = Cc["@mozilla.org/widget/clipboard;1"].
                  getService(Ci.nsIClipboard);
       let trans = Cc["@mozilla.org/widget/transferable;1"].
                   createInstance(Ci.nsITransferable);
+      trans.init(getLoadContext());
       trans.addDataFlavor("text/unicode");
       clip.getData(trans, clip.kGlobalClipboard);
       let str = {};
       let strLen = {};
       trans.getTransferData("text/unicode", str, strLen);
       return str.value.QueryInterface(Ci.nsISupportsString).data.
         substring(0, strLen.value / 2);
     };
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -4640,16 +4640,17 @@ NSEvent* gLastDragMouseDownEvent = nil;
   for (PRUint32 i = 0; i < transferableCount; i++) {
     nsCOMPtr<nsISupports> genericItem;
     gDraggedTransferables->GetElementAt(i, getter_AddRefs(genericItem));
     nsCOMPtr<nsITransferable> item(do_QueryInterface(genericItem));
     if (!item) {
       NS_ERROR("no transferable");
       return nil;
     }
+    item->Init(nsnull);
 
     item->SetTransferData(kFilePromiseDirectoryMime, macLocalFile, sizeof(nsIFile*));
     
     // now request the kFilePromiseMime data, which will invoke the data provider
     // If successful, the returned data is a reference to the resulting file.
     nsCOMPtr<nsISupports> fileDataPrimitive;
     PRUint32 dataSize = 0;
     item->GetTransferData(kFilePromiseMime, getter_AddRefs(fileDataPrimitive), &dataSize);
@@ -4794,16 +4795,17 @@ NSEvent* gLastDragMouseDownEvent = nil;
 
 // Called if the service wants us to replace the current selection.
 - (BOOL)readSelectionFromPasteboard:(NSPasteboard *)pboard
 {
   nsresult rv;
   nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
   if (NS_FAILED(rv))
     return NO;
+  trans->Init(nsnull);
 
   trans->AddDataFlavor(kUnicodeMime);
   trans->AddDataFlavor(kHTMLMime);
 
   rv = nsClipboard::TransferableFromPasteboard(trans, pboard);
   if (NS_FAILED(rv))
     return NO;
 
--- a/widget/nsIClipboardHelper.idl
+++ b/widget/nsIClipboardHelper.idl
@@ -6,33 +6,37 @@
 
 #include "nsISupports.idl"
 #include "nsIClipboard.idl"
 
 %{ C++
 #include "nsString.h" // needed for AString -> nsAString, unfortunately
 %}
 
+interface nsIDOMDocument;
+
 /**
  * helper service for common uses of nsIClipboard.
  */
 
-[scriptable, uuid(44073a98-1dd2-11b2-8600-d0ae854dbe93)]
+[scriptable, uuid(836316a9-6834-45e7-92af-5a4b9bd01a31)]
 interface nsIClipboardHelper : nsISupports
 {
 
   /**
    * copy string to given clipboard
    *
    * @param aString, the string to copy to the clipboard
+   * @param aDoc, the source document for the string, if available
    * @param aClipboardID, the ID of the clipboard to copy to
    *        (eg. kSelectionClipboard -- see nsIClipboard.idl)
    */
-  void copyStringToClipboard(in AString aString, in long aClipboardID);
+  void copyStringToClipboard(in AString aString, [optional] in nsIDOMDocument aDoc, in long aClipboardID);
 
   /**
    * copy string to (default) clipboard
    *
    * @param aString, the string to copy to the clipboard
+   * @param aDoc, the source document for the string, if available
    */
-  void copyString(in AString aString);
+  void copyString(in AString aString, [optional] in nsIDOMDocument aDoc);
 
 };
--- a/widget/nsITransferable.idl
+++ b/widget/nsITransferable.idl
@@ -58,16 +58,17 @@
   * a nsIFlavorDataProvider QI'd to nsISupports, and a data size of 0.
   *
   * When someone calls getTransferData later, if the data size is
   * stored as 0, the nsISupports will be QI'd to nsIFlavorDataProvider,
   * and its getFlavorData called.
   *
   */
 interface nsITransferable;
+interface nsILoadContext;
 
 [scriptable, uuid(7E225E5F-711C-11D7-9FAE-000393636592)]
 interface nsIFlavorDataProvider : nsISupports
 {
 
   /**
     * Retrieve the data from this data provider.
     *
@@ -75,21 +76,31 @@ interface nsIFlavorDataProvider : nsISup
     * @param  aFlavor (in parameter) the flavor of data to retrieve
     * @param  aData the data. Some variant of class in nsISupportsPrimitives.idl
     * @param  aDataLen the length of the data
     */
   void getFlavorData(in nsITransferable aTransferable, in string aFlavor, out nsISupports aData, out unsigned long aDataLen);
 };
 
 
-[scriptable, uuid(8B5314BC-DB01-11d2-96CE-0060B0FB9956)]
+[scriptable, uuid(51fede5f-8d3f-4625-9402-e82c21110541)]
 interface nsITransferable : nsISupports
 {
   const long kFlavorHasDataProvider = 0;
-  
+
+  /**
+   * Initializes a transferable object.  This should be called on alli
+   * transferable objects.  Failure to do so will result in fatal assertions in
+   * debug builds.
+   *
+   * @param aContext the load context associated with the transferable object.
+   *        This can be set to null if a load context is not available.
+   */
+  void init(in nsILoadContext aContext);
+
   /**
     * Computes a list of flavors (mime types as nsISupportsCString) that the transferable 
     * can export, either through intrinsic knowledge or output data converters.
     *
     * @param  aDataFlavorList fills list with supported flavors. This is a copy of
     *          the internal list, so it may be edited w/out affecting the transferable.
     */
   nsISupportsArray flavorsTransferableCanExport ( ) ;
--- a/widget/os2/nsDragService.cpp
+++ b/widget/os2/nsDragService.cpp
@@ -839,16 +839,17 @@ NS_IMETHODIMP nsDragService::NativeDragE
     }
   }
 
   if (NS_SUCCEEDED(rv)) {
     rv = NS_ERROR_FAILURE;
     nsCOMPtr<nsITransferable> trans(
             do_CreateInstance("@mozilla.org/widget/transferable;1", &rv));
     if (trans) {
+      trans->Init(nsnull);
 
       bool isUrl = DrgVerifyType(pditem, "UniformResourceLocator");
       bool isAlt = (WinGetKeyState(HWND_DESKTOP, VK_ALT) & 0x8000);
 
         // if this is a fully-qualified file or the item claims to be
         // a Url, identify it as a Url & also offer it as html
       if ((isFQFile && !isAlt) || isUrl) {
         trans->AddDataFlavor(kURLMime);
--- a/widget/tests/test_bug444800.xul
+++ b/widget/tests/test_bug444800.xul
@@ -34,27 +34,35 @@ function copyImageToClipboard()
   var controller = top.document.commandDispatcher
                    .getControllerForCommand(kCmd);
   ok((controller && controller.isCommandEnabled(kCmd)), "have copy command");
   controller.doCommand(kCmd);
 
   document.popupNode = tmpNode;
 }
 
+function getLoadContext() {
+  const Ci = Components.interfaces;
+  return window.QueryInterface(Ci.nsIInterfaceRequestor)
+               .getInterface(Ci.nsIWebNavigation)
+               .QueryInterface(Ci.nsILoadContext);
+}
+
 function runImageClipboardTests(aCBSvc, aImageType)
 {
   // Verify that hasDataMatchingFlavors() is working correctly.
   var typeArray = [ aImageType ];
   var hasImage = aCBSvc.hasDataMatchingFlavors(typeArray, typeArray.length,
                                                knsIClipboard.kGlobalClipboard);
   ok(hasImage, aImageType + " - hasDataMatchingFlavors()");
 
   // Verify that getData() is working correctly.
   var xfer = Components.classes["@mozilla.org/widget/transferable;1"]
                        .createInstance(Components.interfaces.nsITransferable);
+  xfer.init(getLoadContext());
   xfer.addDataFlavor(aImageType);
   aCBSvc.getData(xfer, knsIClipboard.kGlobalClipboard);
 
   var typeObj = {}, dataObj = {}, lenObj = {};
   xfer.getAnyTransferData(typeObj, dataObj, lenObj);
   var gotValue = (null != dataObj.value);
   ok(gotValue, aImageType + " - getData() returned a value");
   if (gotValue)
--- a/widget/tests/test_bug462106.xul
+++ b/widget/tests/test_bug462106.xul
@@ -24,22 +24,29 @@ https://bugzilla.mozilla.org/show_bug.cg
   /** Test for Bug 462106 **/
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 function copy(str) {
   Cc["@mozilla.org/widget/clipboardhelper;1"].
   getService(Ci.nsIClipboardHelper).
-  copyString(str);
+  copyString(str, document);
+}
+
+function getLoadContext() {
+  return window.QueryInterface(Ci.nsIInterfaceRequestor)
+               .getInterface(Ci.nsIWebNavigation)
+               .QueryInterface(Ci.nsILoadContext);
 }
 
 function paste() {
   let trans = Cc["@mozilla.org/widget/transferable;1"].
               createInstance(Ci.nsITransferable);
+  trans.init(getLoadContext());
   trans.addDataFlavor("text/unicode");
   let clip = Cc["@mozilla.org/widget/clipboard;1"].
              getService(Ci.nsIClipboard);
   clip.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
   let str = {}, length = {};
   try {
     trans.getTransferData("text/unicode", str, length);
   } catch (e) {
--- a/widget/tests/test_bug466599.xul
+++ b/widget/tests/test_bug466599.xul
@@ -18,27 +18,35 @@ https://bugzilla.mozilla.org/show_bug.cg
   </body>
 
   <!-- test code goes here -->
   <script class="testbody" type="application/javascript">
   <![CDATA[
 
   /** Test for Bug 466599 **/
 
+function getLoadContext() {
+  const Ci = Components.interfaces;
+  return window.QueryInterface(Ci.nsIInterfaceRequestor)
+               .getInterface(Ci.nsIWebNavigation)
+               .QueryInterface(Ci.nsILoadContext);
+}
+
 function copyToClipboard(txt)
 {
   var clipid = Components.interfaces.nsIClipboard;
   var clip =
     Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(clipid);
   if (!clip)
     return false;
   var trans =
     Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);
   if (!trans)
     return false;
+  trans.init(getLoadContext());
   trans.addDataFlavor('text/html');
   var str =
     Components.classes['@mozilla.org/supports-string;1'].createInstance(Components.interfaces.nsISupportsString);
   var copytext = txt;
   str.data = copytext;
   trans.setTransferData("text/html",str,copytext.length*2);
   if (!clip)
     return false;
@@ -52,16 +60,17 @@ function readFromClipboard()
   var clip =
     Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(clipid);
   if (!clip)
     return;
   var trans =
     Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);
   if (!trans)
     return;
+  trans.init(getLoadContext());
   trans.addDataFlavor('text/html');
   clip.getData(trans,clipid.kGlobalClipboard);
   var str = new Object();
   var strLength = new Object();
   trans.getTransferData("text/html",str,strLength);
   if (str)
     str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
   if (str)
--- a/widget/tests/test_bug565392.html
+++ b/widget/tests/test_bug565392.html
@@ -23,30 +23,38 @@ https://bugzilla.mozilla.org/show_bug.cg
   const Cc = Components.classes;
   const Ci = Components.interfaces;
   var ds = Cc["@mozilla.org/file/directory_service;1"]
              .getService(Ci.nsIProperties);
   var dir1 = ds.get("ProfD", Ci.nsIFile);
   var clipboard = Cc["@mozilla.org/widget/clipboard;1"]
                     .getService(Ci.nsIClipboard);
   
+  function getLoadContext() {
+    return window.QueryInterface(Ci.nsIInterfaceRequestor)
+                 .getInterface(Ci.nsIWebNavigation)
+                 .QueryInterface(Ci.nsILoadContext);
+  }
+
   function getTransferableFile(file) {
     var transferable = Cc['@mozilla.org/widget/transferable;1']
                          .createInstance(Ci.nsITransferable);
+    transferable.init(getLoadContext());
     transferable.setTransferData("application/x-moz-file", file, 0);
     return transferable;
   }
 
   function setClipboardData(transferable) {
     clipboard.setData(transferable, null, 1);
   }
   
   function getClipboardData(mime) {
     var transferable = Cc['@mozilla.org/widget/transferable;1']
                          .createInstance(Ci.nsITransferable);
+    transferable.init(getLoadContext());
     transferable.addDataFlavor(mime);
     clipboard.getData(transferable, 1);
     var data = {};
     transferable.getTransferData(mime, data, {}) ;
     return data;
   }
 
 setClipboardData(getTransferableFile(dir1))
--- a/widget/tests/test_bug673301.xul
+++ b/widget/tests/test_bug673301.xul
@@ -9,21 +9,29 @@
 <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
 
 <body  xmlns="http://www.w3.org/1999/xhtml">
 <p id="display"></p>
 <div id="content" style="display: none"/>
 </body>
 
 <script type="application/javascript">
+function getLoadContext() {
+  const Ci = Components.interfaces;
+  return window.QueryInterface(Ci.nsIInterfaceRequestor)
+               .getInterface(Ci.nsIWebNavigation)
+               .QueryInterface(Ci.nsILoadContext);
+}
+
 var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
                           .getService(Components.interfaces.nsIClipboard);
 
 var transferable = Components.classes['@mozilla.org/widget/transferable;1']
                              .createInstance(Components.interfaces.nsITransferable);
+transferable.init(getLoadContext());
 
 transferable.addDataFlavor("text/unicode");
 transferable.setTransferData("text/unicode", document, 4);
 
 clipboard.setData(transferable, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
 
 SimpleTest.ok(true, "Didn't crash setting non-text data for text/unicode type");
 </script>
--- a/widget/windows/tests/TestWinDND.cpp
+++ b/widget/windows/tests/TestWinDND.cpp
@@ -162,16 +162,17 @@ nsresult CheckValidUNICODETwo(STGMEDIUM*
 
 nsresult GetTransferableFile(nsCOMPtr<nsITransferable>& pTransferable)
 {
   nsresult rv;
 
   nsCOMPtr<nsISupports> genericWrapper = do_QueryInterface(xferFile);
 
   pTransferable = do_CreateInstance("@mozilla.org/widget/transferable;1");
+  pTransferable->Init(nsnull);
   rv = pTransferable->SetTransferData("application/x-moz-file", genericWrapper,
                                       0);
   return rv;
 }
 
 nsresult GetTransferableText(nsCOMPtr<nsITransferable>& pTransferable)
 {
   nsresult rv;
@@ -179,16 +180,17 @@ nsresult GetTransferableText(nsCOMPtr<ns
   nsCOMPtr<nsISupportsString> xferString =
                                do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
   rv = xferString->SetData(mozString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsISupports> genericWrapper = do_QueryInterface(xferString);
 
   pTransferable = do_CreateInstance("@mozilla.org/widget/transferable;1");
+  pTransferable->Init(nsnull);
   rv = pTransferable->SetTransferData("text/unicode", genericWrapper,
                                       mozString.Length() * sizeof(PRUnichar));
   return rv;
 }
 
 nsresult GetTransferableTextTwo(nsCOMPtr<nsITransferable>& pTransferable)
 {
   nsresult rv;
@@ -196,16 +198,17 @@ nsresult GetTransferableTextTwo(nsCOMPtr
   nsCOMPtr<nsISupportsString> xferString =
                                do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
   rv = xferString->SetData(mozString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsISupports> genericWrapper = do_QueryInterface(xferString);
 
   pTransferable = do_CreateInstance("@mozilla.org/widget/transferable;1");
+  pTransferable->Init(nsnull);
   rv = pTransferable->SetTransferData("text/unicode", genericWrapper,
                                       mozString.Length() * sizeof(PRUnichar));
   return rv;
 }
 
 nsresult GetTransferableURI(nsCOMPtr<nsITransferable>& pTransferable)
 {
   nsresult rv;
@@ -213,16 +216,17 @@ nsresult GetTransferableURI(nsCOMPtr<nsI
   nsCOMPtr<nsIURI> xferURI;
 
   rv = NS_NewURI(getter_AddRefs(xferURI), "http://www.mozilla.org");
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsISupports> genericWrapper = do_QueryInterface(xferURI);
 
   pTransferable = do_CreateInstance("@mozilla.org/widget/transferable;1");
+  pTransferable->Init(nsnull);
   rv = pTransferable->SetTransferData("text/x-moz-url", genericWrapper, 0);
   return rv;
 }
 
 nsresult MakeDataObject(nsISupportsArray* transferableArray,
                         nsRefPtr<IDataObject>& itemToDrag)
 {
   nsresult rv;
--- a/widget/xpwidgets/nsClipboardHelper.cpp
+++ b/widget/xpwidgets/nsClipboardHelper.cpp
@@ -11,16 +11,17 @@
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIServiceManager.h"
 
 // helpers
 #include "nsIClipboard.h"
 #include "nsITransferable.h"
 #include "nsReadableUtils.h"
+#include "nsIDocument.h"
 
 NS_IMPL_ISUPPORTS1(nsClipboardHelper, nsIClipboardHelper)
 
 /*****************************************************************************
  * nsClipboardHelper ctor / dtor
  *****************************************************************************/
 
 nsClipboardHelper::nsClipboardHelper()
@@ -33,16 +34,17 @@ nsClipboardHelper::~nsClipboardHelper()
 }
 
 /*****************************************************************************
  * nsIClipboardHelper methods
  *****************************************************************************/
 
 NS_IMETHODIMP
 nsClipboardHelper::CopyStringToClipboard(const nsAString& aString,
+                                         nsIDOMDocument* aDocument,
                                          PRInt32 aClipboardID)
 {
   nsresult rv;
 
   // get the clipboard
   nsCOMPtr<nsIClipboard>
     clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -59,16 +61,20 @@ nsClipboardHelper::CopyStringToClipboard
   }
 
   // create a transferable for putting data on the clipboard
   nsCOMPtr<nsITransferable>
     trans(do_CreateInstance("@mozilla.org/widget/transferable;1", &rv));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
 
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDocument);
+  nsILoadContext* loadContext = doc ? doc->GetLoadContext() : nsnull;
+  trans->Init(loadContext);
+
   // Add the text data flavor to the transferable
   rv = trans->AddDataFlavor(kUnicodeMime);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // get wStrings to hold clip data
   nsCOMPtr<nsISupportsString>
     data(do_CreateInstance("@mozilla.org/supports-string;1", &rv));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -92,29 +98,29 @@ nsClipboardHelper::CopyStringToClipboard
   // put the transferable on the clipboard
   rv = clipboard->SetData(trans, nsnull, aClipboardID);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsClipboardHelper::CopyString(const nsAString& aString)
+nsClipboardHelper::CopyString(const nsAString& aString, nsIDOMDocument* aDocument)
 {
   nsresult rv;
 
   // copy to the global clipboard. it's bad if this fails in any way.
-  rv = CopyStringToClipboard(aString, nsIClipboard::kGlobalClipboard);
+  rv = CopyStringToClipboard(aString, aDocument, nsIClipboard::kGlobalClipboard);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // unix also needs us to copy to the selection clipboard. this will
   // fail in CopyStringToClipboard if we're not on a platform that
   // supports the selection clipboard. (this could have been #ifdef
   // XP_UNIX, but using the SupportsSelectionClipboard call is the
   // more correct thing to do.
   //
   // if this fails in any way other than "not being unix", we'll get
   // the assertion we need in CopyStringToClipboard, and we needn't
   // assert again here.
-  CopyStringToClipboard(aString, nsIClipboard::kSelectionClipboard);
+  CopyStringToClipboard(aString, aDocument, nsIClipboard::kSelectionClipboard);
 
   return NS_OK;
 }
--- a/widget/xpwidgets/nsClipboardPrivacyHandler.cpp
+++ b/widget/xpwidgets/nsClipboardPrivacyHandler.cpp
@@ -88,16 +88,17 @@ nsClipboardPrivacyHandler::Observe(nsISu
       // We work around the problem by clearing the clipboard using
       // the usual Win32 API.
       NS_ENSURE_TRUE(SUCCEEDED(::OleSetClipboard(NULL)), NS_ERROR_FAILURE);
 #else
       // Empty the native clipboard by copying an empty transferable
       nsCOMPtr<nsITransferable> nullData =
         do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
       NS_ENSURE_SUCCESS(rv, rv);
+      nullData->Init(nsnull);
       rv = clipboard->SetData(nullData, nsnull,
                               nsIClipboard::kGlobalClipboard);
       NS_ENSURE_SUCCESS(rv, rv);
 #endif
     }
   }
 
   return NS_OK;
--- a/widget/xpwidgets/nsTransferable.cpp
+++ b/widget/xpwidgets/nsTransferable.cpp
@@ -27,16 +27,17 @@ Notes to self:
 #include "nsXPIDLString.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsDirectoryService.h"
 #include "nsCRT.h" 
 #include "nsNetUtil.h"
 #include "nsIOutputStream.h"
 #include "nsIInputStream.h"
 #include "nsIFile.h"
+#include "nsILoadContext.h"
 #include "nsAutoPtr.h"
 
 NS_IMPL_ISUPPORTS1(nsTransferable, nsITransferable)
 
 PRUint32 GetDataForFlavor (const nsTArray<DataStruct>& aArray,
                            const char* aDataFlavor)
 {
   for (PRUint32 i = 0 ; i < aArray.Length () ; ++i) {
@@ -212,39 +213,59 @@ DataStruct::ReadCache(nsISupports** aDat
 
 
 //-------------------------------------------------------------------------
 //
 // Transferable constructor
 //
 //-------------------------------------------------------------------------
 nsTransferable::nsTransferable()
+  : mPrivateData(false)
+#ifdef DEBUG
+  , mInitialized(false)
+#endif
 {
 }
 
 //-------------------------------------------------------------------------
 //
 // Transferable destructor
 //
 //-------------------------------------------------------------------------
 nsTransferable::~nsTransferable()
 {
 }
 
 
+NS_IMETHODIMP
+nsTransferable::Init(nsILoadContext* aContext)
+{
+  MOZ_ASSERT(!mInitialized);
+
+  if (aContext) {
+    mPrivateData = aContext->UsePrivateBrowsing();
+  }
+#ifdef DEBUG
+  mInitialized = true;
+#endif
+  return NS_OK;
+}
+
 //
 // GetTransferDataFlavors
 //
 // Returns a copy of the internal list of flavors. This does NOT take into 
 // account any converter that may be registered. This list consists of
 // nsISupportsCString objects so that the flavor list can be accessed from JS.
 //
 nsresult
 nsTransferable::GetTransferDataFlavors(nsISupportsArray ** aDataFlavorList)
 {
+  MOZ_ASSERT(mInitialized);
+
   nsresult rv = NS_NewISupportsArray ( aDataFlavorList );
   if (NS_FAILED(rv)) return rv;
 
   for ( PRUint32 i=0; i<mDataArray.Length(); ++i ) {
     DataStruct& data = mDataArray.ElementAt(i);
     nsCOMPtr<nsISupportsCString> flavorWrapper = do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID);
     if ( flavorWrapper ) {
       flavorWrapper->SetData ( data.GetFlavor() );
@@ -262,16 +283,18 @@ nsTransferable::GetTransferDataFlavors(n
 //
 // Returns the data of the requested flavor, obtained from either having the data on hand or
 // using a converter to get it. The data is wrapped in a nsISupports primitive so that it is
 // accessible from JS.
 //
 NS_IMETHODIMP
 nsTransferable::GetTransferData(const char *aFlavor, nsISupports **aData, PRUint32 *aDataLen)
 {
+  MOZ_ASSERT(mInitialized);
+
   NS_ENSURE_ARG_POINTER(aFlavor && aData && aDataLen);
 
   nsresult rv = NS_OK;
   nsCOMPtr<nsISupports> savedData;
   
   // first look and see if the data is present in one of the intrinsic flavors
   PRUint32 i;
   for (i = 0; i < mDataArray.Length(); ++i ) {
@@ -343,16 +366,18 @@ nsTransferable::GetTransferData(const ch
 // GetAnyTransferData
 //
 // Returns the data of the first flavor found. Caller is responsible for deleting the
 // flavor string.
 // 
 NS_IMETHODIMP
 nsTransferable::GetAnyTransferData(char **aFlavor, nsISupports **aData, PRUint32 *aDataLen)
 {
+  MOZ_ASSERT(mInitialized);
+
   NS_ENSURE_ARG_POINTER(aFlavor && aData && aDataLen);
 
   for ( PRUint32 i=0; i < mDataArray.Length(); ++i ) {
     DataStruct& data = mDataArray.ElementAt(i);
     if (data.IsDataAvailable()) {
       *aFlavor = ToNewCString(data.GetFlavor());
       data.GetData(aData, aDataLen);
       return NS_OK;
@@ -366,16 +391,18 @@ nsTransferable::GetAnyTransferData(char 
 //
 // SetTransferData
 //
 //
 // 
 NS_IMETHODIMP
 nsTransferable::SetTransferData(const char *aFlavor, nsISupports *aData, PRUint32 aDataLen)
 {
+  MOZ_ASSERT(mInitialized);
+
   NS_ENSURE_ARG(aFlavor);
 
   // first check our intrinsic flavors to see if one has been registered.
   PRUint32 i = 0;
   for (i = 0; i < mDataArray.Length(); ++i) {
     DataStruct& data = mDataArray.ElementAt(i);
     if ( data.GetFlavor().Equals(aFlavor) ) {
       data.SetData ( aData, aDataLen );
@@ -412,16 +439,18 @@ nsTransferable::SetTransferData(const ch
 //
 // AddDataFlavor
 //
 // Adds a data flavor to our list with no data. Error if it already exists.
 // 
 NS_IMETHODIMP
 nsTransferable::AddDataFlavor(const char *aDataFlavor)
 {
+  MOZ_ASSERT(mInitialized);
+
   if (GetDataForFlavor (mDataArray, aDataFlavor) != mDataArray.NoIndex)
     return NS_ERROR_FAILURE;
 
   // Create a new "slot" for the data
   mDataArray.AppendElement(DataStruct ( aDataFlavor ));
 
   return NS_OK;
 }
@@ -431,71 +460,81 @@ nsTransferable::AddDataFlavor(const char
 // RemoveDataFlavor
 //
 // Removes a data flavor (and causes the data to be destroyed). Error if
 // the requested flavor is not present.
 //
 NS_IMETHODIMP
 nsTransferable::RemoveDataFlavor(const char *aDataFlavor)
 {
+  MOZ_ASSERT(mInitialized);
+
   PRUint32 idx;
   if ((idx = GetDataForFlavor(mDataArray, aDataFlavor)) != mDataArray.NoIndex) {
     mDataArray.RemoveElementAt (idx);
     return NS_OK;
   }
   return NS_ERROR_FAILURE;
 }
 
 
 /**
   * 
   *
   */
 NS_IMETHODIMP
 nsTransferable::IsLargeDataSet(bool *_retval)
 {
+  MOZ_ASSERT(mInitialized);
+
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = false;
   return NS_OK;
 }
 
 
 /**
   * 
   *
   */
 NS_IMETHODIMP nsTransferable::SetConverter(nsIFormatConverter * aConverter)
 {
+  MOZ_ASSERT(mInitialized);
+
   mFormatConv = aConverter;
   return NS_OK;
 }
 
 
 /**
   * 
   *
   */
 NS_IMETHODIMP nsTransferable::GetConverter(nsIFormatConverter * *aConverter)
 {
+  MOZ_ASSERT(mInitialized);
+
   NS_ENSURE_ARG_POINTER(aConverter);
   *aConverter = mFormatConv;
   NS_IF_ADDREF(*aConverter);
   return NS_OK;
 }
 
 
 //
 // FlavorsTransferableCanImport
 //
 // Computes a list of flavors that the transferable can accept into it, either through
 // intrinsic knowledge or input data converters.
 //
 NS_IMETHODIMP
 nsTransferable::FlavorsTransferableCanImport(nsISupportsArray **_retval)
 {
+  MOZ_ASSERT(mInitialized);
+
   NS_ENSURE_ARG_POINTER(_retval);
   
   // Get the flavor list, and on to the end of it, append the list of flavors we
   // can also get to through a converter. This is so that we can just walk the list
   // in one go, looking for the desired flavor.
   GetTransferDataFlavors(_retval);                        // addrefs
   nsCOMPtr<nsIFormatConverter> converter;
   GetConverter(getter_AddRefs(converter));
@@ -530,16 +569,18 @@ nsTransferable::FlavorsTransferableCanIm
 // FlavorsTransferableCanExport
 //
 // Computes a list of flavors that the transferable can export, either through
 // intrinsic knowledge or output data converters.
 //
 NS_IMETHODIMP
 nsTransferable::FlavorsTransferableCanExport(nsISupportsArray **_retval)
 {
+  MOZ_ASSERT(mInitialized);
+
   NS_ENSURE_ARG_POINTER(_retval);
   
   // Get the flavor list, and on to the end of it, append the list of flavors we
   // can also get to through a converter. This is so that we can just walk the list
   // in one go, looking for the desired flavor.
   GetTransferDataFlavors(_retval);  // addrefs
   nsCOMPtr<nsIFormatConverter> converter;
   GetConverter(getter_AddRefs(converter));
--- a/widget/xpwidgets/nsTransferable.h
+++ b/widget/xpwidgets/nsTransferable.h
@@ -67,12 +67,16 @@ public:
 
 protected:
 
     // get flavors w/out converter
   nsresult GetTransferDataFlavors(nsISupportsArray** aDataFlavorList);
  
   nsTArray<DataStruct> mDataArray;
   nsCOMPtr<nsIFormatConverter> mFormatConv;
+  bool mPrivateData;
+#if DEBUG
+  bool mInitialized;
+#endif
 
 };
 
 #endif // nsTransferable_h__