mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-19 07:26:26 +00:00
Bug 586587 - support kHTMLMime in the Windows clipboard as CF_HTML. r=jimm
This commit is contained in:
parent
f1d99d6f28
commit
ffb1c5dd5b
@ -20,6 +20,10 @@ const base64png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYA" +
|
||||
|
||||
const { base64jpeg } = require("./fixtures");
|
||||
|
||||
const { platform } = require("sdk/system");
|
||||
// For Windows, Mac and Linux, platform returns the following: winnt, darwin and linux.
|
||||
var isWindows = platform.toLowerCase().indexOf("win") == 0;
|
||||
|
||||
const canvasHTML = "data:text/html," + encodeURIComponent(
|
||||
"<html>\
|
||||
<body>\
|
||||
@ -99,6 +103,13 @@ exports["test With No Flavor"] = function(assert) {
|
||||
exports["test With Flavor"] = function(assert) {
|
||||
var contents = "<b>hello there</b>";
|
||||
var contentsText = "hello there";
|
||||
|
||||
// On windows, HTML clipboard includes extra data.
|
||||
// The values are from widget/windows/nsDataObj.cpp.
|
||||
var contentsWindowsHtml = "<html><body>\n<!--StartFragment-->" +
|
||||
contents +
|
||||
"<!--EndFragment-->\n</body>\n</html>";
|
||||
|
||||
var flavor = "html";
|
||||
var fullFlavor = "text/html";
|
||||
var unicodeFlavor = "text";
|
||||
@ -110,8 +121,8 @@ exports["test With Flavor"] = function(assert) {
|
||||
assert.equal(clip.currentFlavors[0], unicodeFlavor);
|
||||
assert.equal(clip.currentFlavors[1], flavor);
|
||||
assert.equal(clip.get(), contentsText);
|
||||
assert.equal(clip.get(flavor), contents);
|
||||
assert.equal(clip.get(fullFlavor), contents);
|
||||
assert.equal(clip.get(flavor), isWindows ? contentsWindowsHtml : contents);
|
||||
assert.equal(clip.get(fullFlavor), isWindows ? contentsWindowsHtml : contents);
|
||||
assert.equal(clip.get(unicodeFlavor), contentsText);
|
||||
assert.equal(clip.get(unicodeFullFlavor), contentsText);
|
||||
};
|
||||
|
@ -14,11 +14,16 @@ add_task(function*() {
|
||||
yield promiseTabLoadEvent(tab, "data:text/html," + escape(testPage));
|
||||
yield SimpleTest.promiseFocus(browser.contentWindowAsCPOW);
|
||||
|
||||
const modifier = (content.navigator.platform.indexOf("Mac") >= 0) ?
|
||||
const modifier = (navigator.platform.indexOf("Mac") >= 0) ?
|
||||
Components.interfaces.nsIDOMWindowUtils.MODIFIER_META :
|
||||
Components.interfaces.nsIDOMWindowUtils.MODIFIER_CONTROL;
|
||||
|
||||
let results = yield ContentTask.spawn(browser, { modifier: modifier },
|
||||
// On windows, HTML clipboard includes extra data.
|
||||
// The values are from widget/windows/nsDataObj.cpp.
|
||||
const htmlPrefix = (navigator.platform.indexOf("Win") >= 0) ? "<html><body>\n<!--StartFragment-->" : "";
|
||||
const htmlPostfix = (navigator.platform.indexOf("Win") >= 0) ? "<!--EndFragment-->\n</body>\n</html>" : "";
|
||||
|
||||
let results = yield ContentTask.spawn(browser, { modifier: modifier, htmlPrefix: htmlPrefix, htmlPostfix: htmlPostfix },
|
||||
function* (arg) {
|
||||
var doc = content.document;
|
||||
var main = doc.getElementById("main");
|
||||
@ -71,7 +76,7 @@ add_task(function*() {
|
||||
is(clipboardData.types.length, 2, "Two types on clipboard");
|
||||
is(clipboardData.types[0], "text/html", "text/html on clipboard");
|
||||
is(clipboardData.types[1], "text/plain", "text/plain on clipboard");
|
||||
is(clipboardData.getData("text/html"), "t <b>Bold</b>", "text/html value");
|
||||
is(clipboardData.getData("text/html"), arg.htmlPrefix + "t <b>Bold</b>" + arg.htmlPostfix, "text/html value");
|
||||
is(clipboardData.getData("text/plain"), "t Bold", "text/plain value");
|
||||
resolve();
|
||||
}, true)
|
||||
@ -106,7 +111,7 @@ add_task(function*() {
|
||||
is(clipboardData.types.length, 2, "Two types on clipboard 2");
|
||||
is(clipboardData.types[0], "text/html", "text/html on clipboard 2");
|
||||
is(clipboardData.types[1], "text/plain", "text/plain on clipboard 2");
|
||||
is(clipboardData.getData("text/html"), "<i>Italic</i> ", "text/html value 2");
|
||||
is(clipboardData.getData("text/html"), arg.htmlPrefix + "<i>Italic</i> " + arg.htmlPostfix, "text/html value 2");
|
||||
is(clipboardData.getData("text/plain"), "Some text", "text/plain value 2");
|
||||
resolve();
|
||||
}, true)
|
||||
@ -140,7 +145,7 @@ add_task(function*() {
|
||||
// Focus the content again
|
||||
yield SimpleTest.promiseFocus(browser.contentWindowAsCPOW);
|
||||
|
||||
let expectedContent = yield ContentTask.spawn(browser, { modifier: modifier },
|
||||
let expectedContent = yield ContentTask.spawn(browser, { modifier: modifier, htmlPrefix: htmlPrefix, htmlPostfix: htmlPostfix },
|
||||
function* (arg) {
|
||||
var doc = content.document;
|
||||
var main = doc.getElementById("main");
|
||||
@ -153,9 +158,10 @@ add_task(function*() {
|
||||
|
||||
// DataTransfer doesn't support the image types yet, so only text/html
|
||||
// will be present.
|
||||
if (clipboardData.getData("text/html") !=
|
||||
'<img id="img" tabindex="1" src="http://example.org/browser/browser/base/content/test/general/moz.png">') {
|
||||
reject();
|
||||
if (clipboardData.getData("text/html") !== arg.htmlPrefix +
|
||||
'<img id="img" tabindex="1" src="http://example.org/browser/browser/base/content/test/general/moz.png">' +
|
||||
arg.htmlPostfix) {
|
||||
reject('Clipboard Data did not contain an image, was ' + clipboardData.getData("text/html"));
|
||||
}
|
||||
resolve();
|
||||
}, true)
|
||||
|
@ -92,6 +92,17 @@ function testCopyPaste (isXHTML) {
|
||||
transferable.getTransferData(mime, data, {}) ;
|
||||
return data;
|
||||
}
|
||||
function testHtmlClipboardValue(mime, expected) {
|
||||
// For Windows, navigator.platform returns "Win32".
|
||||
var expectedValue = expected;
|
||||
if (navigator.platform.indexOf("Win") >= 0) {
|
||||
// Windows has extra content.
|
||||
var expectedValue = "<html><body>\n<!--StartFragment-->" +
|
||||
expected.replace(/\n/g, '\n') +
|
||||
"<!--EndFragment-->\n</body>\n</html>";
|
||||
}
|
||||
testClipboardValue(mime, expectedValue);
|
||||
}
|
||||
function testClipboardValue(mime, expected) {
|
||||
if (suppressHTMLCheck && mime == "text/html")
|
||||
return null;
|
||||
@ -133,37 +144,37 @@ function testCopyPaste (isXHTML) {
|
||||
testSelectionToString("This is a draggable bit of text.");
|
||||
testClipboardValue("text/unicode",
|
||||
"This is a draggable bit of text.");
|
||||
testClipboardValue("text/html",
|
||||
testHtmlClipboardValue("text/html",
|
||||
"<div id=\"draggable\" title=\"title to have a long HTML line\">This is a <em>draggable</em> bit of text.</div>");
|
||||
testPasteText("This is a draggable bit of text.");
|
||||
|
||||
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", "<div id=\"alist\">\n bla\n <ul>\n <li>foo</li>\n \n <li>bar</li>\n </ul>\n </div>");
|
||||
testHtmlClipboardValue("text/html", "<div id=\"alist\">\n bla\n <ul>\n <li>foo</li>\n \n <li>bar</li>\n </ul>\n </div>");
|
||||
testPasteText(" bla\n\n foo\n bar\n\n");
|
||||
|
||||
copyChildrenToClipboard("blist");
|
||||
testSelectionToString(" mozilla\n\n foo\n bar\n\n");
|
||||
testClipboardValue("text/unicode", " mozilla\n\n foo\n bar\n\n");
|
||||
testClipboardValue("text/html", "<div id=\"blist\">\n mozilla\n <ol>\n <li>foo</li>\n \n <li>bar</li>\n </ol>\n </div>");
|
||||
testHtmlClipboardValue("text/html", "<div id=\"blist\">\n mozilla\n <ol>\n <li>foo</li>\n \n <li>bar</li>\n </ol>\n </div>");
|
||||
testPasteText(" mozilla\n\n foo\n bar\n\n");
|
||||
|
||||
copyChildrenToClipboard("clist");
|
||||
testSelectionToString(" mzla\n\n foo\n bazzinga!\n bar\n\n");
|
||||
testClipboardValue("text/unicode", " mzla\n\n foo\n bazzinga!\n bar\n\n");
|
||||
testClipboardValue("text/html", "<div id=\"clist\">\n mzla\n <ul>\n <li>foo<ul>\n <li>bazzinga!</li>\n </ul></li>\n \n <li>bar</li>\n </ul>\n </div>");
|
||||
testHtmlClipboardValue("text/html", "<div id=\"clist\">\n mzla\n <ul>\n <li>foo<ul>\n <li>bazzinga!</li>\n </ul></li>\n \n <li>bar</li>\n </ul>\n </div>");
|
||||
testPasteText(" mzla\n\n foo\n bazzinga!\n bar\n\n");
|
||||
|
||||
copyChildrenToClipboard("div4");
|
||||
testSelectionToString(" Tt t t ");
|
||||
testClipboardValue("text/unicode", " Tt t t ");
|
||||
if (isXHTML) {
|
||||
testClipboardValue("text/html", "<div id=\"div4\">\n T<textarea xmlns=\"http://www.w3.org/1999/xhtml\">t t t</textarea>\n</div>");
|
||||
testHtmlClipboardValue("text/html", "<div id=\"div4\">\n T<textarea xmlns=\"http://www.w3.org/1999/xhtml\">t t t</textarea>\n</div>");
|
||||
testInnerHTML("div4", "\n T<textarea xmlns=\"http://www.w3.org/1999/xhtml\">t t t</textarea>\n");
|
||||
}
|
||||
else {
|
||||
testClipboardValue("text/html", "<div id=\"div4\">\n T<textarea>t t t</textarea>\n</div>");
|
||||
testHtmlClipboardValue("text/html", "<div id=\"div4\">\n T<textarea>t t t</textarea>\n</div>");
|
||||
testInnerHTML("div4", "\n T<textarea>t t t</textarea>\n");
|
||||
}
|
||||
testPasteText(" Tt t t ");
|
||||
@ -172,11 +183,11 @@ function testCopyPaste (isXHTML) {
|
||||
testSelectionToString(" T ");
|
||||
testClipboardValue("text/unicode", " T ");
|
||||
if (isXHTML) {
|
||||
testClipboardValue("text/html", "<div id=\"div5\">\n T<textarea xmlns=\"http://www.w3.org/1999/xhtml\"> </textarea>\n</div>");
|
||||
testHtmlClipboardValue("text/html", "<div id=\"div5\">\n T<textarea xmlns=\"http://www.w3.org/1999/xhtml\"> </textarea>\n</div>");
|
||||
testInnerHTML("div5", "\n T<textarea xmlns=\"http://www.w3.org/1999/xhtml\"> </textarea>\n");
|
||||
}
|
||||
else {
|
||||
testClipboardValue("text/html", "<div id=\"div5\">\n T<textarea> </textarea>\n</div>");
|
||||
testHtmlClipboardValue("text/html", "<div id=\"div5\">\n T<textarea> </textarea>\n</div>");
|
||||
testInnerHTML("div5", "\n T<textarea> </textarea>\n");
|
||||
}
|
||||
testPasteText(" T ");
|
||||
@ -214,7 +225,7 @@ if (false) {
|
||||
copyRangeToClipboard($("div9").childNodes[0],0, $("div9").childNodes[0],4,suppressUnicodeCheckIfHidden);
|
||||
testSelectionToString("div9");
|
||||
testClipboardValue("text/unicode", "div9");
|
||||
testClipboardValue("text/html", "div9");
|
||||
testHtmlClipboardValue("text/html", "div9");
|
||||
testInnerHTML("div9", "div9");
|
||||
|
||||
copyToClipboard($("div10"), suppressUnicodeCheckIfHidden);
|
||||
@ -357,7 +368,7 @@ if (false) {
|
||||
copyChildrenToClipboard("div13");
|
||||
testSelectionToString("__");
|
||||
testClipboardValue("text/unicode", "__");
|
||||
testClipboardValue("text/html", "<div id=\"div13\">__</div>");
|
||||
testHtmlClipboardValue("text/html", "<div id=\"div13\">__</div>");
|
||||
testPasteText("__");
|
||||
|
||||
// ============ converting cell boundaries to tabs in tables
|
||||
@ -370,7 +381,7 @@ if (false) {
|
||||
|
||||
copyRangeToClipboard($("tr2"),0,$("tr3"),0);
|
||||
testClipboardValue("text/unicode", "1\t2\n3\t4\n");
|
||||
testClipboardValue("text/html", '<table><tbody><tr id="tr2"><tr id="tr2"><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr><tr id="tr3"></tr></tr></tbody></table>');
|
||||
testHtmlClipboardValue("text/html", '<table><tbody><tr id="tr2"><tr id="tr2"><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr><tr id="tr3"></tr></tr></tbody></table>');
|
||||
|
||||
// ============ spanning multiple rows in multi-range selection
|
||||
|
||||
@ -379,20 +390,20 @@ if (false) {
|
||||
addRange($("tr3"),0,$("tr3"),2);
|
||||
copySelectionToClipboard();
|
||||
testClipboardValue("text/unicode", "1\t2\n5\t6");
|
||||
testClipboardValue("text/html", '<table><tbody><tr id="tr2"><td>1</td><td>2</td></tr><tr id="tr3"><td>5</td><td>6</td></tr></tbody></table>');
|
||||
testHtmlClipboardValue("text/html", '<table><tbody><tr id="tr2"><td>1</td><td>2</td></tr><tr id="tr3"><td>5</td><td>6</td></tr></tbody></table>');
|
||||
}
|
||||
|
||||
// ============ manipulating Selection in oncopy
|
||||
|
||||
copyRangeToClipboard($("div11").childNodes[0],0, $("div11").childNodes[1],2);
|
||||
testClipboardValue("text/unicode", "Xdiv11");
|
||||
testClipboardValue("text/html", "<div><p>X<span>div</span>11</p></div>");
|
||||
testHtmlClipboardValue("text/html", "<div><p>X<span>div</span>11</p></div>");
|
||||
setTimeout(function(){testSelectionToString("div11")},0);
|
||||
|
||||
setTimeout(function(){
|
||||
copyRangeToClipboard($("div12").childNodes[0],0, $("div12").childNodes[1],2);
|
||||
testClipboardValue("text/unicode", "Xdiv12");
|
||||
testClipboardValue("text/html", "<div><p>X<span>div</span>12</p></div>");
|
||||
testHtmlClipboardValue("text/html", "<div><p>X<span>div</span>12</p></div>");
|
||||
setTimeout(function(){
|
||||
testSelectionToString("div12");
|
||||
setTimeout(SimpleTest.finish,0);
|
||||
|
@ -67,6 +67,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=816298
|
||||
transferable.getTransferData(mime, data, {}) ;
|
||||
return SpecialPowers.wrap(data);
|
||||
}
|
||||
function testHtmlClipboardValue(mime, expected, test) {
|
||||
var expectedValue = expected;
|
||||
// For Windows, navigator.platform returns "Win32".
|
||||
if (navigator.platform.indexOf("Win") >= 0) {
|
||||
expectedValue = "<html><body>\n<!--StartFragment-->" + expected + "<!--EndFragment-->\n</body>\n</html>";
|
||||
}
|
||||
testClipboardValue(mime, expectedValue, test);
|
||||
}
|
||||
function testClipboardValue(mime, expected, test) {
|
||||
var data = getClipboardData(mime);
|
||||
is (data.value == null ? data.value :
|
||||
@ -140,7 +148,7 @@ for (var i = 0; i < originalStrings.length; i++) {
|
||||
var id = 'test' + i;
|
||||
copyChildrenToClipboard(id);
|
||||
is(window.getSelection().toString(), originalStrings[i], id + ' Selection.toString()');
|
||||
testClipboardValue("text/html", clipboardHTML[i], id);
|
||||
testHtmlClipboardValue("text/html", clipboardHTML[i], id);
|
||||
testClipboardValue("text/unicode", clipboardUnicode[i], id);
|
||||
testInnerHTML(id, innerHTMLStrings[i]);
|
||||
testPasteText(textareaStrings[i], id + '.innerHTML');
|
||||
|
@ -71,7 +71,11 @@ function testCopyImage () {
|
||||
// Is the text/uncodie data correct ?
|
||||
testClipboardValue('text/unicode', 'about:logo');
|
||||
// Is the text/html data correct ?
|
||||
testClipboardValue('text/html', '<img id="logo" src="about:logo">');
|
||||
var expected = '<img id="logo" src="about:logo">';
|
||||
if (navigator.platform.indexOf("Win") >= 0) {
|
||||
expected = "<html><body>\n<!--StartFragment-->" + expected + "<!--EndFragment-->\n</body>\n</html>";
|
||||
}
|
||||
testClipboardValue('text/html', expected);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -1361,7 +1361,14 @@ DataTransfer::FillInExternalData(TransferItem& aItem, uint32_t aIndex)
|
||||
variant->SetAsAString(str);
|
||||
}
|
||||
else {
|
||||
variant->SetAsISupports(data);
|
||||
nsCOMPtr<nsISupportsCString> supportscstr = do_QueryInterface(data);
|
||||
if (supportscstr) {
|
||||
nsAutoCString str;
|
||||
supportscstr->GetData(str);
|
||||
variant->SetAsACString(str);
|
||||
} else {
|
||||
variant->SetAsISupports(data);
|
||||
}
|
||||
}
|
||||
|
||||
aItem.mData = variant;
|
||||
|
@ -812,8 +812,7 @@ NS_IMETHODIMP nsHTMLEditor::PrepareTransferable(nsITransferable **transferable)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::PrepareHTMLTransferable(nsITransferable **aTransferable,
|
||||
bool aHavePrivFlavor)
|
||||
nsHTMLEditor::PrepareHTMLTransferable(nsITransferable **aTransferable)
|
||||
{
|
||||
// Create generic Transferable for getting the data
|
||||
nsresult rv = CallCreateInstance("@mozilla.org/widget/transferable;1", aTransferable);
|
||||
@ -831,10 +830,7 @@ nsHTMLEditor::PrepareHTMLTransferable(nsITransferable **aTransferable,
|
||||
// This should only happen in html editors, not plaintext
|
||||
if (!IsPlaintextEditor())
|
||||
{
|
||||
if (!aHavePrivFlavor)
|
||||
{
|
||||
(*aTransferable)->AddDataFlavor(kNativeHTMLMime);
|
||||
}
|
||||
(*aTransferable)->AddDataFlavor(kNativeHTMLMime);
|
||||
(*aTransferable)->AddDataFlavor(kHTMLMime);
|
||||
(*aTransferable)->AddDataFlavor(kFileMime);
|
||||
|
||||
@ -1095,6 +1091,7 @@ nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable,
|
||||
nsIDOMDocument *aSourceDoc,
|
||||
const nsAString & aContextStr,
|
||||
const nsAString & aInfoStr,
|
||||
bool havePrivateHTMLFlavor,
|
||||
nsIDOMNode *aDestinationNode,
|
||||
int32_t aDestOffset,
|
||||
bool aDoDeleteSelection)
|
||||
@ -1134,12 +1131,24 @@ nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable,
|
||||
if (NS_SUCCEEDED(rv) && !cffragment.IsEmpty())
|
||||
{
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
rv = DoInsertHTMLWithContext(cffragment,
|
||||
cfcontext, cfselection, flavor,
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection,
|
||||
isSafe);
|
||||
// If we have our private HTML flavor, we will only use the fragment
|
||||
// from the CF_HTML. The rest comes from the clipboard.
|
||||
if (havePrivateHTMLFlavor) {
|
||||
rv = DoInsertHTMLWithContext(cffragment,
|
||||
aContextStr, aInfoStr, flavor,
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection,
|
||||
isSafe);
|
||||
} else {
|
||||
rv = DoInsertHTMLWithContext(cffragment,
|
||||
cfcontext, cfselection, flavor,
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection,
|
||||
isSafe);
|
||||
|
||||
}
|
||||
} else {
|
||||
// In some platforms (like Linux), the clipboard might return data
|
||||
// requested for unknown flavors (for example:
|
||||
@ -1241,9 +1250,10 @@ nsresult nsHTMLEditor::InsertFromDataTransfer(DataTransfer *aDataTransfer,
|
||||
aSourceDoc, aDestinationNode, aDestOffset, aDoDeleteSelection);
|
||||
}
|
||||
}
|
||||
else if (!hasPrivateHTMLFlavor && type.EqualsLiteral(kNativeHTMLMime)) {
|
||||
else if (type.EqualsLiteral(kNativeHTMLMime)) {
|
||||
// Windows only clipboard parsing.
|
||||
nsAutoString text;
|
||||
GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kNativeHTMLMime), aIndex, text);
|
||||
GetStringFromDataTransfer(aDataTransfer, type, aIndex, text);
|
||||
NS_ConvertUTF16toUTF8 cfhtml(text);
|
||||
|
||||
nsXPIDLString cfcontext, cffragment, cfselection; // cfselection left emtpy for now
|
||||
@ -1252,12 +1262,28 @@ nsresult nsHTMLEditor::InsertFromDataTransfer(DataTransfer *aDataTransfer,
|
||||
if (NS_SUCCEEDED(rv) && !cffragment.IsEmpty())
|
||||
{
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
return DoInsertHTMLWithContext(cffragment,
|
||||
cfcontext, cfselection, type,
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection,
|
||||
isSafe);
|
||||
|
||||
if (hasPrivateHTMLFlavor) {
|
||||
// If we have our private HTML flavor, we will only use the fragment
|
||||
// from the CF_HTML. The rest comes from the clipboard.
|
||||
nsAutoString contextString, infoString;
|
||||
GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), aIndex, contextString);
|
||||
GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), aIndex, infoString);
|
||||
return DoInsertHTMLWithContext(cffragment,
|
||||
contextString, infoString, type,
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection,
|
||||
isSafe);
|
||||
}
|
||||
else {
|
||||
return DoInsertHTMLWithContext(cffragment,
|
||||
cfcontext, cfselection, type,
|
||||
aSourceDoc,
|
||||
aDestinationNode, aDestOffset,
|
||||
aDoDeleteSelection,
|
||||
isSafe);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type.EqualsLiteral(kHTMLMime)) {
|
||||
@ -1321,13 +1347,9 @@ NS_IMETHODIMP nsHTMLEditor::Paste(int32_t aSelectionType)
|
||||
nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// find out if we have our internal html flavor on the clipboard. We don't want to mess
|
||||
// around with cfhtml if we do.
|
||||
bool bHavePrivateHTMLFlavor = HavePrivateHTMLFlavor(clipboard);
|
||||
|
||||
// Get the nsITransferable interface for getting the data from the clipboard
|
||||
nsCOMPtr<nsITransferable> trans;
|
||||
rv = PrepareHTMLTransferable(getter_AddRefs(trans), bHavePrivateHTMLFlavor);
|
||||
rv = PrepareHTMLTransferable(getter_AddRefs(trans));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
|
||||
// Get the Data from the clipboard
|
||||
@ -1340,7 +1362,9 @@ NS_IMETHODIMP nsHTMLEditor::Paste(int32_t aSelectionType)
|
||||
// also get additional html copy hints, if present
|
||||
nsAutoString contextStr, infoStr;
|
||||
|
||||
// also get additional html copy hints, if present
|
||||
// If we have our internal html flavor on the clipboard, there is special
|
||||
// context to use instead of cfhtml context.
|
||||
bool bHavePrivateHTMLFlavor = HavePrivateHTMLFlavor(clipboard);
|
||||
if (bHavePrivateHTMLFlavor)
|
||||
{
|
||||
nsCOMPtr<nsISupports> contextDataObj, infoDataObj;
|
||||
@ -1388,7 +1412,7 @@ NS_IMETHODIMP nsHTMLEditor::Paste(int32_t aSelectionType)
|
||||
if (!nsEditorHookUtils::DoInsertionHook(domdoc, nullptr, trans))
|
||||
return NS_OK;
|
||||
|
||||
return InsertFromTransferable(trans, nullptr, contextStr, infoStr,
|
||||
return InsertFromTransferable(trans, nullptr, contextStr, infoStr, bHavePrivateHTMLFlavor,
|
||||
nullptr, 0, true);
|
||||
}
|
||||
|
||||
@ -1406,7 +1430,7 @@ NS_IMETHODIMP nsHTMLEditor::PasteTransferable(nsITransferable *aTransferable)
|
||||
return NS_OK;
|
||||
|
||||
nsAutoString contextStr, infoStr;
|
||||
return InsertFromTransferable(aTransferable, nullptr, contextStr, infoStr,
|
||||
return InsertFromTransferable(aTransferable, nullptr, contextStr, infoStr, false,
|
||||
nullptr, 0, true);
|
||||
}
|
||||
|
||||
@ -1436,7 +1460,7 @@ NS_IMETHODIMP nsHTMLEditor::PasteNoFormatting(int32_t aSelectionType)
|
||||
if (NS_SUCCEEDED(clipboard->GetData(trans, aSelectionType)) && IsModifiable())
|
||||
{
|
||||
const nsAFlatString& empty = EmptyString();
|
||||
rv = InsertFromTransferable(trans, nullptr, empty, empty, nullptr, 0,
|
||||
rv = InsertFromTransferable(trans, nullptr, empty, empty, false, nullptr, 0,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
@ -552,11 +552,12 @@ protected:
|
||||
|
||||
// factored methods for handling insertion of data from transferables (drag&drop or clipboard)
|
||||
NS_IMETHOD PrepareTransferable(nsITransferable **transferable) override;
|
||||
nsresult PrepareHTMLTransferable(nsITransferable **transferable, bool havePrivFlavor);
|
||||
nsresult PrepareHTMLTransferable(nsITransferable **transferable);
|
||||
nsresult InsertFromTransferable(nsITransferable *transferable,
|
||||
nsIDOMDocument *aSourceDoc,
|
||||
const nsAString & aContextStr,
|
||||
const nsAString & aInfoStr,
|
||||
bool havePrivateHTMLFlavor,
|
||||
nsIDOMNode *aDestinationNode,
|
||||
int32_t aDestinationOffset,
|
||||
bool aDoDeleteSelection);
|
||||
|
@ -26,7 +26,13 @@ function runTest() {
|
||||
function verifyContent(s) {
|
||||
var e = document.getElementById('i1');
|
||||
var doc = e.contentDocument;
|
||||
is(doc.body.innerHTML, s, "");
|
||||
if (navigator.platform.indexOf("Win") >= 0) {
|
||||
// On Windows ignore \n which got left over from the removal of the fragment tags
|
||||
// <html><body>\n<!--StartFragment--> and <!--EndFragment-->\n</body>\n</html>.
|
||||
is(doc.body.innerHTML.replace(/\n/g, ""), s, "");
|
||||
} else {
|
||||
is(doc.body.innerHTML, s, "");
|
||||
}
|
||||
}
|
||||
|
||||
function pasteInto(trans, html, target_id) {
|
||||
|
@ -79,6 +79,40 @@ nsPrimitiveHelpers :: CreatePrimitiveForData ( const char* aFlavor, const void*
|
||||
|
||||
} // CreatePrimitiveForData
|
||||
|
||||
//
|
||||
// CreatePrimitiveForCFHTML
|
||||
//
|
||||
// Platform specific CreatePrimitive, windows CF_HTML.
|
||||
//
|
||||
void
|
||||
nsPrimitiveHelpers :: CreatePrimitiveForCFHTML ( const void* aDataBuff,
|
||||
uint32_t* aDataLen, nsISupports** aPrimitive )
|
||||
{
|
||||
if (!aPrimitive)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsISupportsString> primitive =
|
||||
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
|
||||
if (!primitive)
|
||||
return;
|
||||
|
||||
// We need to duplicate the input buffer, since the removal of linebreaks
|
||||
// might reallocte it.
|
||||
void* utf8 = moz_xmalloc(*aDataLen);
|
||||
if (!utf8)
|
||||
return;
|
||||
memcpy(utf8, aDataBuff, *aDataLen);
|
||||
int32_t signedLen = static_cast<int32_t>(*aDataLen);
|
||||
nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(kTextMime, &utf8, &signedLen);
|
||||
*aDataLen = signedLen;
|
||||
|
||||
nsAutoString str(NS_ConvertUTF8toUTF16(reinterpret_cast<const char*>(utf8), *aDataLen));
|
||||
free(utf8);
|
||||
*aDataLen = str.Length() * sizeof(char16_t);
|
||||
primitive->SetData(str);
|
||||
NS_ADDREF(*aPrimitive = primitive);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// CreateDataFromPrimitive
|
||||
|
@ -23,6 +23,10 @@ public:
|
||||
static void CreatePrimitiveForData ( const char* aFlavor, const void* aDataBuff,
|
||||
uint32_t aDataLen, nsISupports** aPrimitive ) ;
|
||||
|
||||
// A specific case of CreatePrimitive for windows CF_HTML handling in DataTransfer
|
||||
static void CreatePrimitiveForCFHTML ( const void* aDataBuff,
|
||||
uint32_t* aDataLen, nsISupports** aPrimitive ) ;
|
||||
|
||||
// Given a nsISupports* primitive and the flavor it represents, creates a new data
|
||||
// buffer with the data in it. This data will be null terminated, but the length
|
||||
// parameter does not reflect that.
|
||||
|
@ -102,7 +102,8 @@ UINT nsClipboard::GetFormat(const char* aMimeStr)
|
||||
else if (strcmp(aMimeStr, kFileMime) == 0 ||
|
||||
strcmp(aMimeStr, kFilePromiseMime) == 0)
|
||||
format = CF_HDROP;
|
||||
else if (strcmp(aMimeStr, kNativeHTMLMime) == 0)
|
||||
else if (strcmp(aMimeStr, kNativeHTMLMime) == 0 ||
|
||||
strcmp(aMimeStr, kHTMLMime) == 0)
|
||||
format = CF_HTML;
|
||||
else
|
||||
format = ::RegisterClipboardFormatW(NS_ConvertASCIItoUTF16(aMimeStr).get());
|
||||
@ -624,11 +625,12 @@ nsresult nsClipboard::GetDataFromDataObject(IDataObject * aDataObject,
|
||||
genericDataWrapper = do_QueryInterface(file);
|
||||
free(data);
|
||||
}
|
||||
else if ( strcmp(flavorStr, kNativeHTMLMime) == 0) {
|
||||
else if ( strcmp(flavorStr, kNativeHTMLMime) == 0 ) {
|
||||
uint32_t dummy;
|
||||
// the editor folks want CF_HTML exactly as it's on the clipboard, no conversions,
|
||||
// no fancy stuff. Pull it off the clipboard, stuff it into a wrapper and hand
|
||||
// it back to them.
|
||||
if ( FindPlatformHTML(aDataObject, anIndex, &data, &dataLen) )
|
||||
if ( FindPlatformHTML(aDataObject, anIndex, &data, &dummy, &dataLen) )
|
||||
nsPrimitiveHelpers::CreatePrimitiveForData ( flavorStr, data, dataLen, getter_AddRefs(genericDataWrapper) );
|
||||
else
|
||||
{
|
||||
@ -637,6 +639,23 @@ nsresult nsClipboard::GetDataFromDataObject(IDataObject * aDataObject,
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
else if ( strcmp(flavorStr, kHTMLMime) == 0 ) {
|
||||
uint32_t startOfData = 0;
|
||||
// The JS folks want CF_HTML exactly as it is on the clipboard, but
|
||||
// minus the CF_HTML header index information.
|
||||
// It also needs to be converted to UTF16 and have linebreaks changed.
|
||||
if ( FindPlatformHTML(aDataObject, anIndex, &data, &startOfData, &dataLen) ) {
|
||||
dataLen -= startOfData;
|
||||
nsPrimitiveHelpers::CreatePrimitiveForCFHTML ( static_cast<char*>(data) + startOfData,
|
||||
&dataLen, getter_AddRefs(genericDataWrapper) );
|
||||
}
|
||||
else
|
||||
{
|
||||
free(data);
|
||||
continue; // something wrong with this flavor, keep looking for other data
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
else if ( strcmp(flavorStr, kJPEGImageMime) == 0 ||
|
||||
strcmp(flavorStr, kJPGImageMime) == 0 ||
|
||||
strcmp(flavorStr, kPNGImageMime) == 0) {
|
||||
@ -678,7 +697,9 @@ nsresult nsClipboard::GetDataFromDataObject(IDataObject * aDataObject,
|
||||
// Someone asked for the OS CF_HTML flavor. We give it back to them exactly as-is.
|
||||
//
|
||||
bool
|
||||
nsClipboard :: FindPlatformHTML ( IDataObject* inDataObject, UINT inIndex, void** outData, uint32_t* outDataLen )
|
||||
nsClipboard :: FindPlatformHTML ( IDataObject* inDataObject, UINT inIndex,
|
||||
void** outData, uint32_t* outStartOfData,
|
||||
uint32_t* outDataLen )
|
||||
{
|
||||
// Reference: MSDN doc entitled "HTML Clipboard Format"
|
||||
// http://msdn.microsoft.com/en-us/library/aa767917(VS.85).aspx#unknown_854
|
||||
@ -721,6 +742,10 @@ nsClipboard :: FindPlatformHTML ( IDataObject* inDataObject, UINT inIndex, void*
|
||||
// We want to return the buffer not offset by startOfData because it will be
|
||||
// parsed out later (probably by nsHTMLEditor::ParseCFHTML) when it is still
|
||||
// in CF_HTML format.
|
||||
|
||||
// We return the byte offset from the start of the data buffer to where the
|
||||
// HTML data starts. The caller might want to extract the HTML only.
|
||||
*outStartOfData = startOfData;
|
||||
*outDataLen = endOfData;
|
||||
return true;
|
||||
}
|
||||
|
@ -63,7 +63,8 @@ protected:
|
||||
static bool FindURLFromLocalFile ( IDataObject* inDataObject, UINT inIndex, void** outData, uint32_t* outDataLen ) ;
|
||||
static bool FindURLFromNativeURL ( IDataObject* inDataObject, UINT inIndex, void** outData, uint32_t* outDataLen ) ;
|
||||
static bool FindUnicodeFromPlainText ( IDataObject* inDataObject, UINT inIndex, void** outData, uint32_t* outDataLen ) ;
|
||||
static bool FindPlatformHTML ( IDataObject* inDataObject, UINT inIndex, void** outData, uint32_t* outDataLen );
|
||||
static bool FindPlatformHTML ( IDataObject* inDataObject, UINT inIndex, void** outData,
|
||||
uint32_t* outStartOfData, uint32_t* outDataLen );
|
||||
static void ResolveShortcut ( nsIFile* inFileName, nsACString& outURL ) ;
|
||||
|
||||
nsIWidget * mWindow;
|
||||
|
@ -539,6 +539,14 @@ nsDragService::IsDataFlavorSupported(const char *aDataFlavor, bool *_retval)
|
||||
if (mDataObject->QueryGetData(&fe) == S_OK)
|
||||
*_retval = true; // found it!
|
||||
}
|
||||
else if (strcmp(aDataFlavor, kHTMLMime) == 0) {
|
||||
// If the client wants html, maybe it's in "HTML Format".
|
||||
format = nsClipboard::GetFormat(kHTMLMime);
|
||||
SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1,
|
||||
TYMED_HGLOBAL);
|
||||
if (mDataObject->QueryGetData(&fe) == S_OK)
|
||||
*_retval = true; // found it!
|
||||
}
|
||||
} // else try again
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user