From fe08c8398adeb66193a7efc973485c2f6cff8689 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Tue, 25 May 2010 01:24:15 +0200 Subject: [PATCH] Bug 39098 - Elements with visibility:hidden, visibility:collapse, or display:none get copied to the clipboard. r=dbaron --- content/base/public/nsIDocumentEncoder.idl | 9 +- content/base/src/nsContentAreaDragDrop.cpp | 154 ++++++-------- content/base/src/nsCopySupport.cpp | 9 +- content/base/src/nsDocumentEncoder.cpp | 78 +++++-- content/base/test/test_copypaste.html | 233 ++++++++++++++------- layout/generic/nsSelection.cpp | 4 +- 6 files changed, 310 insertions(+), 177 deletions(-) diff --git a/content/base/public/nsIDocumentEncoder.idl b/content/base/public/nsIDocumentEncoder.idl index f639f280cdc..018b7245262 100644 --- a/content/base/public/nsIDocumentEncoder.idl +++ b/content/base/public/nsIDocumentEncoder.idl @@ -61,7 +61,7 @@ interface nsIDocumentEncoderNodeFixup : nsISupports nsIDOMNode fixupNode(in nsIDOMNode aNode, out boolean aSerializeCloneKids); }; -[scriptable, uuid(f85c5a20-258d-11db-a98b-0800200c9a66)] +[scriptable, uuid(196a3aee-006e-4f8f-a420-e1c1b0958a26)] interface nsIDocumentEncoder : nsISupports { // Output methods flag bits. There are a frightening number of these, @@ -215,6 +215,13 @@ interface nsIDocumentEncoder : nsISupports */ const unsigned long OutputDontRewriteEncodingDeclaration = (1 << 18); + /** + * When using the HTML or XHTML serializer, skip elements that are not + * visible when this flag is set. Elements are not visible when they + * have CSS style display:none or visibility:collapse, for example. + */ + const unsigned long SkipInvisibleContent = (1 << 19); + /** * Initialize with a pointer to the document and the mime type. * @param aDocument Document to encode. diff --git a/content/base/src/nsContentAreaDragDrop.cpp b/content/base/src/nsContentAreaDragDrop.cpp index 1e53ebbbc61..36318bb9bc6 100644 --- a/content/base/src/nsContentAreaDragDrop.cpp +++ b/content/base/src/nsContentAreaDragDrop.cpp @@ -45,7 +45,7 @@ #include "nsString.h" // Interfaces needed to be included -#include "nsIVariant.h" +#include "nsCopySupport.h" #include "nsIDOMNSUIEvent.h" #include "nsIDOMUIEvent.h" #include "nsISelection.h" @@ -59,9 +59,7 @@ #include "nsIDOMDocument.h" #include "nsIDOMDocumentRange.h" #include "nsIDOMRange.h" -#include "nsIDocumentEncoder.h" #include "nsIFormControl.h" -#include "nsISelectionPrivate.h" #include "nsIDOMHTMLAreaElement.h" #include "nsIDOMHTMLAnchorElement.h" #include "nsITransferable.h" @@ -75,14 +73,12 @@ #include "nsIDocShell.h" #include "nsIContent.h" #include "nsIImageLoadingContent.h" -#include "nsINameSpaceManager.h" #include "nsUnicharUtils.h" #include "nsIURL.h" #include "nsIDocument.h" #include "nsIScriptSecurityManager.h" #include "nsIPrincipal.h" #include "nsIDocShellTreeItem.h" -#include "nsIFrame.h" #include "nsRange.h" #include "nsIWebBrowserPersist.h" #include "nsEscape.h" @@ -90,18 +86,50 @@ #include "nsIMIMEService.h" #include "imgIContainer.h" #include "imgIRequest.h" -#include "nsContentCID.h" #include "nsDOMDataTransfer.h" -#include "nsISelectionController.h" -#include "nsFrameSelection.h" -#include "nsWidgetsCID.h" - -static NS_DEFINE_CID(kHTMLConverterCID, NS_HTMLFORMATCONVERTER_CID); // private clipboard data flavors for html copy, used by editor when pasting #define kHTMLContext "text/_moz_htmlcontext" #define kHTMLInfo "text/_moz_htmlinfo" +nsresult NS_NewDomSelection(nsISelection **aDomSelection); + +// if inNode is null, use the selection from the window +static nsresult +GetTransferableForNodeOrSelection(nsIDOMWindow* aWindow, + nsIContent* aNode, + nsITransferable** aTransferable) +{ + NS_ENSURE_ARG_POINTER(aWindow); + + nsCOMPtr domDoc; + aWindow->GetDocument(getter_AddRefs(domDoc)); + NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE); + nsCOMPtr doc = do_QueryInterface(domDoc); + + nsresult rv; + nsCOMPtr selection; + nsCOMPtr node = do_QueryInterface(aNode); + if (node) { + // Make a temporary selection with this node in a single range. + rv = NS_NewDomSelection(getter_AddRefs(selection)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr range; + rv = NS_NewRange(getter_AddRefs(range)); + NS_ENSURE_SUCCESS(rv, rv); + rv = range->SelectNode(node); + NS_ENSURE_SUCCESS(rv, rv); + rv = selection->AddRange(range); + NS_ENSURE_SUCCESS(rv, rv); + } else { + aWindow->GetSelection(getter_AddRefs(selection)); + } + + rv = nsCopySupport::GetTransferableForSelection(selection, doc, + aTransferable); + NS_ENSURE_SUCCESS(rv, rv); + return rv; +} class NS_STACK_CLASS DragDataProducer { @@ -134,13 +162,6 @@ private: static void GetSelectedLink(nsISelection* inSelection, nsIContent **outLinkNode); - // if inNode is null, use the selection from the window - static nsresult SerializeNodeOrSelection(nsIDOMWindow* inWindow, - nsIContent* inNode, - nsAString& outResultString, - nsAString& outHTMLContext, - nsAString& outHTMLInfo); - nsCOMPtr mWindow; nsCOMPtr mTarget; nsCOMPtr mSelectionTargetNode; @@ -417,6 +438,7 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer, *aDragNode = nsnull; + nsresult rv; nsIContent* dragNode = nsnull; // find the selection to see what we could be dragging and if @@ -663,24 +685,31 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer, nodeToSerialize = nsnull; } - SerializeNodeOrSelection(mWindow, nodeToSerialize, - mHtmlString, mContextString, mInfoString); - - nsCOMPtr htmlConverter = - do_CreateInstance(kHTMLConverterCID); - NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE); - - nsCOMPtr html = - do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID); - NS_ENSURE_TRUE(html, NS_ERROR_FAILURE); - html->SetData(mHtmlString); - - nsCOMPtr text; - PRUint32 textLen; - htmlConverter->Convert(kHTMLMime, html, mHtmlString.Length() * 2, - kUnicodeMime, getter_AddRefs(text), &textLen); - NS_ENSURE_TRUE(text, NS_ERROR_FAILURE); - text->GetData(mTitleString); + mHtmlString.Truncate(); + mContextString.Truncate(); + mInfoString.Truncate(); + mTitleString.Truncate(); + nsCOMPtr transferable; + rv = ::GetTransferableForNodeOrSelection(mWindow, nodeToSerialize, + getter_AddRefs(transferable)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr data; + PRUint32 dataSize; + rv = transferable->GetTransferData(kHTMLMime, getter_AddRefs(data), &dataSize); + if (NS_SUCCEEDED(rv)) { + data->GetData(mHtmlString); + } + rv = transferable->GetTransferData(kHTMLContext, getter_AddRefs(data), &dataSize); + if (NS_SUCCEEDED(rv)) { + data->GetData(mContextString); + } + rv = transferable->GetTransferData(kHTMLInfo, getter_AddRefs(data), &dataSize); + if (NS_SUCCEEDED(rv)) { + data->GetData(mInfoString); + } + rv = transferable->GetTransferData(kUnicodeMime, getter_AddRefs(data), &dataSize); + NS_ENSURE_SUCCESS(rv, rv); // require plain text at a minimum + data->GetData(mTitleString); } // default text value is the URL @@ -694,8 +723,8 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer, // if there is no drag node, which will be the case for a selection, just // use the selection target node. - nsresult rv = AddStringsToDataTransfer( - dragNode ? dragNode : mSelectionTargetNode.get(), aDataTransfer); + rv = AddStringsToDataTransfer( + dragNode ? dragNode : mSelectionTargetNode.get(), aDataTransfer); NS_ENSURE_SUCCESS(rv, rv); NS_IF_ADDREF(*aDragNode = dragNode); @@ -982,52 +1011,3 @@ DragDataProducer::GetSelectedLink(nsISelection* inSelection, return; } - -// static -nsresult -DragDataProducer::SerializeNodeOrSelection(nsIDOMWindow* inWindow, - nsIContent* inNode, - nsAString& outResultString, - nsAString& outContext, - nsAString& outInfo) -{ - NS_ENSURE_ARG_POINTER(inWindow); - - nsresult rv; - nsCOMPtr encoder = - do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID); - NS_ENSURE_TRUE(encoder, NS_ERROR_FAILURE); - - nsCOMPtr domDoc; - inWindow->GetDocument(getter_AddRefs(domDoc)); - NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE); - - PRUint32 flags = nsIDocumentEncoder::OutputAbsoluteLinks | - nsIDocumentEncoder::OutputEncodeHTMLEntities | - nsIDocumentEncoder::OutputRaw; - nsCOMPtr range; - nsCOMPtr selection; - nsCOMPtr node = do_QueryInterface(inNode); - if (node) { - // make a range around this node - rv = NS_NewRange(getter_AddRefs(range)); - NS_ENSURE_SUCCESS(rv, rv); - rv = range->SelectNode(node); - NS_ENSURE_SUCCESS(rv, rv); - } else { - inWindow->GetSelection(getter_AddRefs(selection)); - flags |= nsIDocumentEncoder::OutputSelectionOnly; - } - - rv = encoder->Init(domDoc, NS_LITERAL_STRING(kHTMLMime), flags); - NS_ENSURE_SUCCESS(rv, rv); - - if (range) { - encoder->SetRange(range); - } else if (selection) { - encoder->SetSelection(selection); - } - - return encoder->EncodeToStringWithContext(outContext, outInfo, - outResultString); -} diff --git a/content/base/src/nsCopySupport.cpp b/content/base/src/nsCopySupport.cpp index 185c5f3a1f0..98a1439a6b6 100644 --- a/content/base/src/nsCopySupport.cpp +++ b/content/base/src/nsCopySupport.cpp @@ -22,6 +22,7 @@ * Contributor(s): * Kathleen Brade * David Gardiner + * Mats Palmgren * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -134,7 +135,9 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc, // we want preformatted for the case where the selection is inside input/textarea // and we don't want pretty printing for others cases, to not have additionnal // line breaks which are then converted into spaces by the htmlConverter (see bug #524975) - PRUint32 flags = nsIDocumentEncoder::OutputPreformatted | nsIDocumentEncoder::OutputRaw; + PRUint32 flags = nsIDocumentEncoder::OutputPreformatted + | nsIDocumentEncoder::OutputRaw + | nsIDocumentEncoder::SkipInvisibleContent; nsCOMPtr domDoc = do_QueryInterface(aDoc); NS_ASSERTION(domDoc, "Need a document"); @@ -175,7 +178,7 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc, mimeType.AssignLiteral(kHTMLMime); - flags = 0; + flags = nsIDocumentEncoder::SkipInvisibleContent; rv = docEncoder->Init(domDoc, mimeType, flags); NS_ENSURE_SUCCESS(rv, rv); @@ -420,7 +423,7 @@ nsCopySupport::GetContents(const nsACString& aMimeType, PRUint32 aFlags, nsISele docEncoder = do_CreateInstance(encoderContractID.get()); NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE); - PRUint32 flags = aFlags; + PRUint32 flags = aFlags | nsIDocumentEncoder::SkipInvisibleContent; if (aMimeType.Equals("text/plain")) flags |= nsIDocumentEncoder::OutputPreformatted; diff --git a/content/base/src/nsDocumentEncoder.cpp b/content/base/src/nsDocumentEncoder.cpp index 88669ed3e37..3969f915f23 100644 --- a/content/base/src/nsDocumentEncoder.cpp +++ b/content/base/src/nsDocumentEncoder.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Pierre Phaneuf + * Mats Palmgren * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -50,7 +51,6 @@ #include "nsIServiceManager.h" #include "nsIDocument.h" #include "nsIHTMLDocument.h" -#include "nsISelection.h" #include "nsCOMPtr.h" #include "nsIContentSerializer.h" #include "nsIUnicodeEncoder.h" @@ -69,11 +69,13 @@ #include "nsGkAtoms.h" #include "nsIContent.h" #include "nsIEnumerator.h" -#include "nsISelectionPrivate.h" #include "nsIParserService.h" #include "nsIScriptContext.h" #include "nsIScriptGlobalObject.h" #include "nsIScriptSecurityManager.h" +#include "nsISelection.h" +#include "nsISelectionPrivate.h" +#include "nsITransferable.h" // for kUnicodeMime #include "nsContentUtils.h" #include "nsUnicharUtils.h" #include "nsReadableUtils.h" @@ -119,6 +121,29 @@ protected: nsresult FlushText(nsAString& aString, PRBool aForce); + PRBool IsVisibleNode(nsINode* aNode) + { + NS_PRECONDITION(aNode, ""); + + if (mFlags & SkipInvisibleContent) { + nsCOMPtr content = do_QueryInterface(aNode); + if (content) { + nsIFrame* frame = content->GetPrimaryFrame(); + if (!frame) { + if (aNode->IsNodeOfType(nsINode::eTEXT)) { + // We have already checked that our parent is visible. + return PR_TRUE; + } + return PR_FALSE; + } + PRBool isVisible = frame->GetStyleVisibility()->IsVisible(); + if (!isVisible && aNode->IsNodeOfType(nsINode::eTEXT)) + return PR_FALSE; + } + } + return PR_TRUE; + } + static PRBool IsTag(nsIContent* aContent, nsIAtom* aAtom); virtual PRBool IncludeInContext(nsINode *aNode); @@ -269,8 +294,9 @@ nsDocumentEncoder::SerializeNodeStart(nsINode* aNode, nsAString& aStr, nsINode* aOriginalNode) { - PRUint16 type; - + if (!IsVisibleNode(aNode)) + return NS_OK; + nsINode* node = nsnull; nsCOMPtr fixedNodeKungfuDeathGrip; @@ -292,6 +318,7 @@ nsDocumentEncoder::SerializeNodeStart(nsINode* aNode, if (!node) node = aNode; + PRUint16 type; node->GetNodeType(&type); switch (type) { case nsIDOMNode::ELEMENT_NODE: @@ -341,6 +368,9 @@ nsresult nsDocumentEncoder::SerializeNodeEnd(nsINode* aNode, nsAString& aStr) { + if (!IsVisibleNode(aNode)) + return NS_OK; + if (aNode->IsElement()) { mSerializer->AppendElementEnd(static_cast(aNode), aStr); } @@ -352,6 +382,9 @@ nsDocumentEncoder::SerializeToStringRecursive(nsINode* aNode, nsAString& aStr, PRBool aDontSerializeRoot) { + if (!IsVisibleNode(aNode)) + return NS_OK; + nsresult rv = NS_OK; PRBool serializeClonedChildren = PR_FALSE; nsINode* maybeFixedNode = nsnull; @@ -656,19 +689,24 @@ nsDocumentEncoder::SerializeRangeNodes(nsIRange* aRange, nsCOMPtr content = do_QueryInterface(aNode); NS_ENSURE_TRUE(content, NS_ERROR_FAILURE); - nsresult rv=NS_OK; - + if (!IsVisibleNode(aNode)) + return NS_OK; + + nsresult rv = NS_OK; + // get start and end nodes for this recursion level nsCOMPtr startNode, endNode; - PRInt32 start = mStartRootIndex - aDepth; - if (start >= 0 && (PRUint32)start <= mStartNodes.Length()) - startNode = mStartNodes[start]; + { + PRInt32 start = mStartRootIndex - aDepth; + if (start >= 0 && (PRUint32)start <= mStartNodes.Length()) + startNode = mStartNodes[start]; - PRInt32 end = mEndRootIndex - aDepth; - if (end >= 0 && (PRUint32)end <= mEndNodes.Length()) - endNode = mEndNodes[end]; + PRInt32 end = mEndRootIndex - aDepth; + if (end >= 0 && (PRUint32)end <= mEndNodes.Length()) + endNode = mEndNodes[end]; + } - if ((startNode != content) && (endNode != content)) + if (startNode != content && endNode != content) { // node is completely contained in range. Serialize the whole subtree // rooted by this node. @@ -858,6 +896,16 @@ nsDocumentEncoder::SerializeRangeToString(nsIRange *aRange, if ((startParent == endParent) && IsTextNode(startParent)) { + if (mFlags & SkipInvisibleContent) { + // Check that the parent is visible if we don't a frame. + // IsVisibleNode() will do it when there's a frame. + nsCOMPtr content = do_QueryInterface(startParent); + if (content && !content->GetPrimaryFrame()) { + nsIContent* parent = content->GetParent(); + if (!parent || !IsVisibleNode(parent)) + return NS_OK; + } + } rv = SerializeNodeStart(startParent, startOffset, endOffset, aOutputString); NS_ENSURE_SUCCESS(rv, rv); } @@ -1080,7 +1128,7 @@ nsHTMLCopyEncoder::~nsHTMLCopyEncoder() NS_IMETHODIMP nsHTMLCopyEncoder::Init(nsIDOMDocument* aDocument, - const nsAString& aMimetype, + const nsAString& aMimeType, PRUint32 aFlags) { if (!aDocument) @@ -1094,7 +1142,7 @@ nsHTMLCopyEncoder::Init(nsIDOMDocument* aDocument, NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE); mMimeType.AssignLiteral("text/html"); - + // Make all links absolute when copying // (see related bugs #57296, #41924, #58646, #32768) mFlags = aFlags | OutputAbsoluteLinks; diff --git a/content/base/test/test_copypaste.html b/content/base/test/test_copypaste.html index d29e5823d1c..337a8604fa9 100644 --- a/content/base/test/test_copypaste.html +++ b/content/base/test/test_copypaste.html @@ -30,89 +30,155 @@ function testCopyPaste () { var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"] .getService(Components.interfaces.nsIClipboard); - var transferable, node; - var data = {}; var textarea = document.getElementById('input'); - // ============ copy paste test from a simple text content to a textarea + function copySelectionToClipboard() { + documentViewer.copySelection(); + is(clipboard.hasDataMatchingFlavors(["text/unicode"], 1,1), true); + is(clipboard.hasDataMatchingFlavors(["text/html"], 1,1), true); + } + function copyToClipboard(node) { + textarea.blur(); + clipboard.emptyClipboard(1); + var sel = window.getSelection(); + sel.removeAllRanges(); + var r = document.createRange(); + r.selectNode(node); + window.getSelection().addRange(r); + copySelectionToClipboard(); + } + function copyRangeToClipboard(startNode,startIndex,endNode,endIndex) { + textarea.blur(); + clipboard.emptyClipboard(1); + var sel = window.getSelection(); + sel.removeAllRanges(); + var r = document.createRange(); + r.setStart(startNode,startIndex) + r.setEnd(endNode,endIndex) + window.getSelection().addRange(r); + copySelectionToClipboard(); + } + function copyChildrenToClipboard(id) { + 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.addDataFlavor(mime); + clipboard.getData(transferable, 1); + var data = {}; + transferable.getTransferData(mime, data, {}) ; + return data; + } + function testClipboardValue(mime, expected) { + var data = getClipboardData(mime); + is (data.value == null ? data.value : + data.value.QueryInterface(Components.interfaces.nsISupportsString).data, + expected, + mime + " value in the clipboard"); + return data.value; + } + function testPasteText(expected) { + textarea.value=""; + textarea.focus(); + textarea.QueryInterface(Components.interfaces.nsIDOMNSEditableElement) + .editor.paste(1); + is(textarea.value, expected, "value of the textarea after the paste"); + } + function testSelectionToString(expected) { + is(window.getSelection().toString().replace(/\r\n/g,"\n"), expected, "Selection.toString"); + } + function testInnerHTML(id, expected) { + var value = document.getElementById(id).innerHTML; + is(value, expected, id + ".innerHTML"); + } + function testEmptyChildren(id) { + copyChildrenToClipboard(id); + testSelectionToString(""); + testClipboardValue("text/unicode", null); + testClipboardValue("text/html", null); + testPasteText(""); + } - // selection of the node - node = document.getElementById('draggable'); - window.getSelection().selectAllChildren(node); + copyChildrenToClipboard("draggable"); + testSelectionToString("This is a draggable bit of text."); + testClipboardValue("text/unicode", + "This is a draggable bit of text."); + testClipboardValue("text/html", + "
This is a draggable bit of text.
"); + testPasteText("This is a draggable bit of text."); - // let's copy the selection - documentViewer.copySelection(); + copyChildrenToClipboard("alist"); + testSelectionToString("bla\n\n * foo\n * bar\n\n"); + testClipboardValue("text/unicode", " bla\n\n * foo\n * bar\n\n"); + testClipboardValue("text/html", "
\n bla\n
    \n
  • foo
  • \n \n
  • bar
  • \n
\n
"); + testPasteText(" bla\n\n * foo\n * bar\n\n"); - is(clipboard.hasDataMatchingFlavors(["text/unicode"], 1,1), true); - is(clipboard.hasDataMatchingFlavors(["text/html"], 1,1), true); + copyChildrenToClipboard("div4"); + testSelectionToString("Tt t t "); + testClipboardValue("text/unicode", " Tt t t "); + testClipboardValue("text/html", "
\n T\n
"); + testInnerHTML("div4", "\n T\n"); + testPasteText(" Tt t t "); - // is the clipboard contain a text/unicode data ? - transferable = Components.classes['@mozilla.org/widget/transferable;1'] - .createInstance(Components.interfaces.nsITransferable); - transferable.addDataFlavor("text/unicode"); - clipboard.getData(transferable, 1); + copyChildrenToClipboard("div5"); + testSelectionToString("T "); + testClipboardValue("text/unicode", " T "); + testClipboardValue("text/html", "
\n T\n
"); + testInnerHTML("div5", "\n T\n"); + testPasteText(" T "); - transferable.getTransferData ("text/unicode", data, {} ) ; - is (data.value.QueryInterface(Components.interfaces.nsISupportsString).data, - "This is a draggable bit of text.", - "text/unicode value in the clipboard"); - - // is the clipboard contain a text/html data ? - transferable = Components.classes['@mozilla.org/widget/transferable;1'] - .createInstance(Components.interfaces.nsITransferable); - transferable.addDataFlavor("text/html"); - clipboard.getData(transferable, 1); + copyRangeToClipboard($("div6").childNodes[0],0, $("div6").childNodes[1],1); + testSelectionToString(""); +// START Disabled due to bug 564688 +if (false) { + testClipboardValue("text/unicode", ""); + testClipboardValue("text/html", ""); +} +// END Disabled due to bug 564688 + testInnerHTML("div6", "div6"); - transferable.getTransferData ("text/html", data, {} ) ; - is (data.value.QueryInterface(Components.interfaces.nsISupportsString).data, - "
This is a draggable bit of text.
", - "text/html value in the clipboard"); - - // let's paste now in the textarea and verify its content - textarea.focus(); - textarea.QueryInterface(Components.interfaces.nsIDOMNSEditableElement) - .editor.paste(1); - is(textarea.value, "This is a draggable bit of text.", "value of the textarea after the paste"); + copyRangeToClipboard($("div7").childNodes[0],0, $("div7").childNodes[0],4); + testSelectionToString(""); +// START Disabled due to bug 564688 +if (false) { + testClipboardValue("text/unicode", ""); + testClipboardValue("text/html", ""); +} +// END Disabled due to bug 564688 + testInnerHTML("div7", "div7"); + copyRangeToClipboard($("div8").childNodes[0],0, $("div8").childNodes[0],4); + testSelectionToString(""); +// START Disabled due to bug 564688 +if (false) { + testClipboardValue("text/unicode", ""); + testClipboardValue("text/html", ""); +} +// END Disabled due to bug 564688 + testInnerHTML("div8", "div8"); - // ============ copy paste test from a piece of HTML to a textarea - textarea.blur(); - node = document.getElementById('alist'); - window.getSelection().selectAllChildren(node); - documentViewer.copySelection(); + copyRangeToClipboard($("div9").childNodes[0],0, $("div9").childNodes[0],4); + testSelectionToString("div9"); + testClipboardValue("text/unicode", "div9"); + testClipboardValue("text/html", "div9"); + testInnerHTML("div9", "div9"); - is(clipboard.hasDataMatchingFlavors(["text/unicode"], 1,1), true); - is(clipboard.hasDataMatchingFlavors(["text/html"], 1,1), true); + copyToClipboard($("div10")); + testSelectionToString(""); + testInnerHTML("div10", "div10"); - // let's verify the clipboard content for the text/unicode flavor - transferable = Components.classes['@mozilla.org/widget/transferable;1'] - .createInstance(Components.interfaces.nsITransferable); - transferable.addDataFlavor("text/unicode"); - clipboard.getData(transferable, 1); - data = {}; - transferable.getTransferData ("text/unicode", data, {} ) ; - is (data.value.QueryInterface(Components.interfaces.nsISupportsString).data, - " bla\n\n * foo\n * bar\n\n", - "text/unicode value in the clipboard (html piece)"); + copyToClipboard($("div10").firstChild); + testSelectionToString(""); - // let's verify the clipboard content for the text/html flavor - transferable = Components.classes['@mozilla.org/widget/transferable;1'] - .createInstance(Components.interfaces.nsITransferable); - transferable.addDataFlavor("text/html"); - clipboard.getData(transferable, 1); - data = {}; - transferable.getTransferData ("text/html", data, {} ) ; - is (data.value.QueryInterface(Components.interfaces.nsISupportsString).data, - "
\n bla\n
    \n
  • foo
  • \n
  • bar
  • \n
\n
", - "text/html value in the clipboard (html piece)"); - - // let's paste now in the textarea and verify its content - textarea.value=""; - textarea.focus(); - textarea.QueryInterface(Components.interfaces.nsIDOMNSEditableElement) - .editor.paste(1); - is(textarea.value, " bla\n\n * foo\n * bar\n\n", "value of the textarea after the paste (html piece)"); - + copyRangeToClipboard($("div10").childNodes[0],0, $("div10").childNodes[0],1); + testSelectionToString(""); + + copyRangeToClipboard($("div10").childNodes[1],0, $("div10").childNodes[1],1); + testSelectionToString(""); // ============ copy/paste test from/to a textarea @@ -145,10 +211,37 @@ addLoadEvent(testCopyPaste); bla
  • foo
  • +
  • baz
  • bar
+
+ T +
+ +
+ T +
+ + + + + + +
div9
+
+ + + diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index 5958a823eb1..38faede944e 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -1301,7 +1301,9 @@ nsFrameSelection::MoveCaret(PRUint32 aKeycode, NS_IMETHODIMP nsTypedSelection::ToString(PRUnichar **aReturn) { - return ToStringWithFormat("text/plain", 0, 0, aReturn); + return ToStringWithFormat("text/plain", + nsIDocumentEncoder::SkipInvisibleContent, + 0, aReturn); }