mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 597784 - The inserthtml command should not use a sanitizing fragment content sink; r=bzbarsky a=blocking-betaN,1.9.2.11,1.9.1.14
This commit is contained in:
parent
7706293fb5
commit
37297d45dc
@ -262,6 +262,22 @@ nsHTMLEditor::InsertHTMLWithContext(const nsAString & aInputString,
|
||||
nsIDOMNode *aDestNode,
|
||||
PRInt32 aDestOffset,
|
||||
PRBool aDeleteSelection)
|
||||
{
|
||||
return DoInsertHTMLWithContext(aInputString, aContextStr, aInfoStr,
|
||||
aFlavor, aSourceDoc, aDestNode, aDestOffset, aDeleteSelection,
|
||||
PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
|
||||
const nsAString & aContextStr,
|
||||
const nsAString & aInfoStr,
|
||||
const nsAString & aFlavor,
|
||||
nsIDOMDocument *aSourceDoc,
|
||||
nsIDOMNode *aDestNode,
|
||||
PRInt32 aDestOffset,
|
||||
PRBool aDeleteSelection,
|
||||
PRBool aTrustedInput)
|
||||
{
|
||||
NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
@ -285,7 +301,8 @@ nsHTMLEditor::InsertHTMLWithContext(const nsAString & aInputString,
|
||||
address_of(streamStartParent),
|
||||
address_of(streamEndParent),
|
||||
&streamStartOffset,
|
||||
&streamEndOffset);
|
||||
&streamEndOffset,
|
||||
aTrustedInput);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> targetNode, tempNode;
|
||||
@ -1301,11 +1318,12 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable
|
||||
if (NS_SUCCEEDED(rv) && !cffragment.IsEmpty())
|
||||
{
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
rv = InsertHTMLWithContext(cffragment,
|
||||
cfcontext, cfselection, flavor,
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection);
|
||||
rv = DoInsertHTMLWithContext(cffragment,
|
||||
cfcontext, cfselection, flavor,
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection,
|
||||
PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1319,11 +1337,12 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable
|
||||
NS_ASSERTION(text.Length() <= (len/2), "Invalid length!");
|
||||
stuffToPaste.Assign(text.get(), len / 2);
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
rv = InsertHTMLWithContext(stuffToPaste,
|
||||
aContextStr, aInfoStr, flavor,
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection);
|
||||
rv = DoInsertHTMLWithContext(stuffToPaste,
|
||||
aContextStr, aInfoStr, flavor,
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection,
|
||||
PR_FALSE);
|
||||
}
|
||||
}
|
||||
else if (0 == nsCRT::strcmp(bestFlavor, kUnicodeMime) ||
|
||||
@ -1389,11 +1408,12 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
|
||||
const nsAFlatString& empty = EmptyString();
|
||||
rv = InsertHTMLWithContext(stuffToPaste,
|
||||
empty, empty, flavor,
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection);
|
||||
rv = DoInsertHTMLWithContext(stuffToPaste,
|
||||
empty, empty, flavor,
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection,
|
||||
PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1418,11 +1438,12 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable
|
||||
AppendUTF8toUTF16(base64, stuffToPaste);
|
||||
stuffToPaste.AppendLiteral("\" alt=\"\" >");
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
rv = InsertHTMLWithContext(stuffToPaste, EmptyString(), EmptyString(),
|
||||
NS_LITERAL_STRING(kFileMime),
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection);
|
||||
rv = DoInsertHTMLWithContext(stuffToPaste, EmptyString(), EmptyString(),
|
||||
NS_LITERAL_STRING(kFileMime),
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection,
|
||||
PR_FALSE);
|
||||
PR_Free(base64);
|
||||
}
|
||||
}
|
||||
@ -2552,7 +2573,8 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(const nsAString &aInputString,
|
||||
nsCOMPtr<nsIDOMNode> *outStartNode,
|
||||
nsCOMPtr<nsIDOMNode> *outEndNode,
|
||||
PRInt32 *outStartOffset,
|
||||
PRInt32 *outEndOffset)
|
||||
PRInt32 *outEndOffset,
|
||||
PRBool aTrustedInput)
|
||||
{
|
||||
NS_ENSURE_TRUE(outFragNode && outStartNode && outEndNode, NS_ERROR_NULL_POINTER);
|
||||
nsCOMPtr<nsIDOMDocumentFragment> docfrag;
|
||||
@ -2571,7 +2593,8 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(const nsAString &aInputString,
|
||||
nsCOMPtr<nsIDOMNode> contextLeaf, junk;
|
||||
if (!aContextStr.IsEmpty())
|
||||
{
|
||||
res = ParseFragment(aContextStr, tagStack, doc, address_of(contextAsNode));
|
||||
res = ParseFragment(aContextStr, tagStack, doc, address_of(contextAsNode),
|
||||
aTrustedInput);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
NS_ENSURE_TRUE(contextAsNode, NS_ERROR_FAILURE);
|
||||
|
||||
@ -2591,7 +2614,7 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(const nsAString &aInputString,
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
// create fragment for pasted html
|
||||
res = ParseFragment(aInputString, tagStack, doc, outFragNode);
|
||||
res = ParseFragment(aInputString, tagStack, doc, outFragNode, aTrustedInput);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
NS_ENSURE_TRUE(*outFragNode, NS_ERROR_FAILURE);
|
||||
|
||||
@ -2651,7 +2674,8 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(const nsAString &aInputString,
|
||||
nsresult nsHTMLEditor::ParseFragment(const nsAString & aFragStr,
|
||||
nsTArray<nsString> &aTagStack,
|
||||
nsIDocument* aTargetDocument,
|
||||
nsCOMPtr<nsIDOMNode> *outNode)
|
||||
nsCOMPtr<nsIDOMNode> *outNode,
|
||||
PRBool aTrustedInput)
|
||||
{
|
||||
// figure out if we are parsing full context or not
|
||||
PRBool bContext = aTagStack.IsEmpty();
|
||||
@ -2664,25 +2688,32 @@ nsresult nsHTMLEditor::ParseFragment(const nsAString & aFragStr,
|
||||
|
||||
// create the html fragment sink
|
||||
nsCOMPtr<nsIContentSink> sink;
|
||||
if (bContext)
|
||||
sink = do_CreateInstance(NS_HTMLPARANOIDFRAGMENTSINK2_CONTRACTID);
|
||||
else
|
||||
sink = do_CreateInstance(NS_HTMLPARANOIDFRAGMENTSINK_CONTRACTID);
|
||||
if (aTrustedInput) {
|
||||
if (bContext)
|
||||
sink = do_CreateInstance(NS_HTMLFRAGMENTSINK2_CONTRACTID);
|
||||
else
|
||||
sink = do_CreateInstance(NS_HTMLFRAGMENTSINK_CONTRACTID);
|
||||
} else {
|
||||
if (bContext)
|
||||
sink = do_CreateInstance(NS_HTMLPARANOIDFRAGMENTSINK2_CONTRACTID);
|
||||
else
|
||||
sink = do_CreateInstance(NS_HTMLPARANOIDFRAGMENTSINK_CONTRACTID);
|
||||
|
||||
nsCOMPtr<nsIParanoidFragmentContentSink> paranoidSink(do_QueryInterface(sink));
|
||||
NS_ASSERTION(paranoidSink, "Our content sink is paranoid");
|
||||
if (bContext) {
|
||||
// Allow comments for the context to catch our placeholder cookie
|
||||
paranoidSink->AllowComments();
|
||||
} else {
|
||||
// Allow style elements and attributes for the actual content
|
||||
paranoidSink->AllowStyles();
|
||||
}
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(sink, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIFragmentContentSink> fragSink(do_QueryInterface(sink));
|
||||
NS_ENSURE_TRUE(fragSink, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIParanoidFragmentContentSink> paranoidSink(do_QueryInterface(sink));
|
||||
NS_ASSERTION(paranoidSink, "Our content sink is paranoid");
|
||||
if (bContext) {
|
||||
// Allow comemnts for the context to catch our placeholder cookie
|
||||
paranoidSink->AllowComments();
|
||||
} else {
|
||||
// Allow style elements and attributes for the actual content
|
||||
paranoidSink->AllowStyles();
|
||||
}
|
||||
|
||||
fragSink->SetTargetDocument(aTargetDocument);
|
||||
|
||||
// parse the fragment
|
||||
|
@ -622,10 +622,12 @@ protected:
|
||||
nsCOMPtr<nsIDOMNode> *outStartNode,
|
||||
nsCOMPtr<nsIDOMNode> *outEndNode,
|
||||
PRInt32 *outStartOffset,
|
||||
PRInt32 *outEndOffset);
|
||||
PRInt32 *outEndOffset,
|
||||
PRBool aTrustedInput);
|
||||
nsresult ParseFragment(const nsAString & aStr, nsTArray<nsString> &aTagStack,
|
||||
nsIDocument* aTargetDoc,
|
||||
nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsCOMPtr<nsIDOMNode> *outNode,
|
||||
PRBool aTrustedInput);
|
||||
nsresult CreateListOfNodesToPaste(nsIDOMNode *aFragmentAsNode,
|
||||
nsCOMArray<nsIDOMNode>& outNodeList,
|
||||
nsIDOMNode *aStartNode,
|
||||
@ -751,6 +753,23 @@ protected:
|
||||
// Whether the outer window of the DOM event target has focus or not.
|
||||
PRBool OurWindowHasFocus();
|
||||
|
||||
// This function is used to insert a string of HTML input optionally with some
|
||||
// context information into the editable field. The HTML input either comes
|
||||
// from a transferable object created as part of a drop/paste operation, or from
|
||||
// the InsertHTML method. We may want the HTML input to be sanitized (for example,
|
||||
// if it's coming from a transferable object), in which case aTrustedInput should
|
||||
// be set to false, otherwise, the caller should set it to true, which means that
|
||||
// the HTML will be inserted in the DOM verbatim.
|
||||
nsresult DoInsertHTMLWithContext(const nsAString& aInputString,
|
||||
const nsAString& aContextStr,
|
||||
const nsAString& aInfoStr,
|
||||
const nsAString& aFlavor,
|
||||
nsIDOMDocument* aSourceDoc,
|
||||
nsIDOMNode* aDestNode,
|
||||
PRInt32 aDestOffset,
|
||||
PRBool aDeleteSelection,
|
||||
PRBool aTrustedInput);
|
||||
|
||||
// Data members
|
||||
protected:
|
||||
|
||||
|
@ -60,6 +60,7 @@ _TEST_FILES = \
|
||||
test_bug537046.html \
|
||||
test_bug550434.html \
|
||||
test_bug592592.html \
|
||||
test_bug597784.html \
|
||||
test_CF_HTML_clipboard.html \
|
||||
test_contenteditable_focus.html \
|
||||
test_contenteditable_text_input_handling.html \
|
||||
|
@ -343,7 +343,7 @@ var tests = [
|
||||
{
|
||||
id: "mm",
|
||||
isIFrame: true,
|
||||
insertHTML: true,
|
||||
indirectPaste: true,
|
||||
payload: invalidStyle7Payload,
|
||||
rootElement: function() document.getElementById("mm").contentDocument.documentElement,
|
||||
checkResult: function(html) {
|
||||
@ -353,7 +353,7 @@ var tests = [
|
||||
},
|
||||
{
|
||||
id: "nn",
|
||||
insertHTML: true,
|
||||
indirectPaste: true,
|
||||
payload: invalidStyle7Payload,
|
||||
rootElement: function() document.getElementById("nn"),
|
||||
checkResult: function(html) {
|
||||
@ -397,26 +397,33 @@ function runTest(test) {
|
||||
} else
|
||||
elem.focus();
|
||||
|
||||
if ("insertHTML" in test) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var trans = Components.classes["@mozilla.org/widget/transferable;1"]
|
||||
.createInstance(Components.interfaces.nsITransferable);
|
||||
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;
|
||||
if ("isIFrame" in test) {
|
||||
elem.contentDocument.execCommand("inserthtml", false, test.payload);
|
||||
win = elem.contentDocument.defaultView;
|
||||
} else {
|
||||
getSelection().collapse(elem, 0);
|
||||
document.execCommand("inserthtml", false, test.payload);
|
||||
win = window;
|
||||
}
|
||||
editor = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsIEditorDocShell)
|
||||
.editor;
|
||||
editor.pasteTransferable(trans);
|
||||
} else {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
|
||||
.getService(Components.interfaces.nsIClipboard);
|
||||
|
||||
var trans = Components.classes["@mozilla.org/widget/transferable;1"]
|
||||
.createInstance(Components.interfaces.nsITransferable);
|
||||
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);
|
||||
clipboard.setData(trans, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
|
||||
|
||||
var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
|
39
editor/libeditor/html/tests/test_bug597784.html
Normal file
39
editor/libeditor/html/tests/test_bug597784.html
Normal file
@ -0,0 +1,39 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=597784
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 597784</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=597784">Mozilla Bug 597784</a>
|
||||
<p id="display"></p>
|
||||
<div id="content"></div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 597784 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(function() {
|
||||
document.designMode = "on";
|
||||
var content = document.getElementById("content");
|
||||
getSelection().collapse(content, 0);
|
||||
var html1 = "<test:tag>test:tag</test:tag>";
|
||||
var html2 = "<a href=\"http://mozilla.org/\" test:attr=\"test:attr\" custom=\"value\">link</a>";
|
||||
document.execCommand("insertHTML", false, html1);
|
||||
document.execCommand("insertHTML", false, html2);
|
||||
is(content.innerHTML, html1 + html2,
|
||||
"The custom tags and attributes should be inserted into the document using the insertHTML command");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user