Bug 407983, add clipboard events constructor, r=smaug

This commit is contained in:
Neil Deakin 2013-03-11 11:49:56 -04:00
Родитель 5624ee6b03
Коммит 9fe80b713b
7 изменённых файлов: 157 добавлений и 12 удалений

Просмотреть файл

@ -7,6 +7,7 @@
#include "nsContentUtils.h"
#include "nsClientRect.h"
#include "nsDOMDataTransfer.h"
#include "DictionaryHelpers.h"
#include "nsDOMClassInfoID.h"
nsDOMClipboardEvent::nsDOMClipboardEvent(mozilla::dom::EventTarget* aOwner,
@ -41,6 +42,45 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
NS_IMPL_ADDREF_INHERITED(nsDOMClipboardEvent, nsDOMEvent)
NS_IMPL_RELEASE_INHERITED(nsDOMClipboardEvent, nsDOMEvent)
nsresult
nsDOMClipboardEvent::InitClipboardEvent(const nsAString & aType, bool aCanBubble, bool aCancelable,
nsIDOMDataTransfer* clipboardData)
{
nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable);
NS_ENSURE_SUCCESS(rv, rv);
nsClipboardEvent* event = static_cast<nsClipboardEvent*>(mEvent);
event->clipboardData = clipboardData;
return NS_OK;
}
nsresult
nsDOMClipboardEvent::InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal)
{
mozilla::idl::ClipboardEventInit d;
nsresult rv = d.Init(aCx, aVal);
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsDOMDataTransfer> clipboardData;
if (mEventIsInternal) {
nsClipboardEvent* event = static_cast<nsClipboardEvent*>(mEvent);
if (event) {
// Always create a clipboardData for the copy event. If this is changed to
// support other types of events, make sure that read/write privileges are
// checked properly within nsDOMDataTransfer.
clipboardData = new nsDOMDataTransfer(NS_COPY, false);
clipboardData->SetData(d.dataType, d.data);
}
}
rv = InitClipboardEvent(aType, d.bubbles, d.cancelable, clipboardData);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
nsDOMClipboardEvent::GetClipboardData(nsIDOMDataTransfer** aClipboardData)
{

Просмотреть файл

@ -24,6 +24,10 @@ public:
// Forward to base class
NS_FORWARD_TO_NSDOMEVENT
nsresult InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal);
};
#endif // nsDOMClipboardEvent_h_

Просмотреть файл

@ -742,7 +742,7 @@ nsEventDispatcher::CreateEvent(mozilla::dom::EventTarget* aOwner,
return NS_NewDOMTextEvent(aDOMEvent, aOwner, aPresContext,
static_cast<nsTextEvent*>(aEvent));
case NS_CLIPBOARD_EVENT:
return NS_NewDOMClipboardEvent(aDOMEvent, aPresContext,
return NS_NewDOMClipboardEvent(aDOMEvent, aOwner, aPresContext,
static_cast<nsClipboardEvent*>(aEvent));
case NS_SVG_EVENT:
return NS_NewDOMSVGEvent(aDOMEvent, aOwner, aPresContext,

Просмотреть файл

@ -1196,6 +1196,7 @@ NS_DEFINE_CONTRACT_CTOR(MozActivity, NS_DOMACTIVITY_CONTRACTID)
NS_DEFINE_EVENT_CTOR(UIEvent)
NS_DEFINE_EVENT_CTOR(MouseEvent)
NS_DEFINE_EVENT_CTOR(WheelEvent)
NS_DEFINE_EVENT_CTOR(ClipboardEvent)
#define MOZ_GENERATED_EVENT_LIST
#define MOZ_GENERATED_EVENT(_event_interface) \
@ -1222,6 +1223,7 @@ static const nsConstructorFuncMapData kConstructorFuncMap[] =
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(UIEvent)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(MouseEvent)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(WheelEvent)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(ClipboardEvent)
#ifdef MOZ_B2G_RIL
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(MozWifiStatusChangeEvent)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(MozWifiConnectionInfoEvent)

Просмотреть файл

@ -13,4 +13,16 @@ interface nsIDOMClipboardEvent : nsIDOMEvent
{
readonly attribute nsIDOMDataTransfer clipboardData;
// The constructor must be used from script to initialize
// clipboard events.
[noscript] void initClipboardEvent(in DOMString typeArg,
in boolean canBubbleArg,
in boolean cancelableArg,
in nsIDOMDataTransfer clipboardData);
};
dictionary ClipboardEventInit : EventInit
{
DOMString data;
DOMString dataType;
};

Просмотреть файл

@ -4,7 +4,7 @@
<title>Test for Clipboard Events</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
@ -12,6 +12,10 @@
<div id="content" style="border: 3px solid black; padding: 3em;">CONTENT TEXT<input id="content-input" value="INPUT TEXT"></div>
<button id="button">Button</button>
<div id="syntheticSpot" oncut="compareSynthetic(event, 'cut')"
oncopy="compareSynthetic(event, 'copy')"
onpaste="compareSynthetic(event, 'paste')">Spot</div>
<pre id="test">
<script class="testbody" type="text/javascript;version=1.7">
@ -64,25 +68,27 @@ window.onfocus = function()
test_input_copypaste_dataTransfer_multiple,
test_input_copy_button_dataTransfer
];
// Run the main tests. This will also populate the delayedTests array
for (let i = 0; i < testFunctions.length; i++) {
// Init clipboard
setClipboardText(clipboardInitialValue);
// Reset value of contentInput.
contentInput.value = "INPUT TEXT";
var func = testFunctions[i];
func();
}
// Finally, check if the cached clipboard data can be accessed or modified
// Check if the cached clipboard data can be accessed or modified
// and whether it modifies the real clipboard
checkCachedDataTransfer(cachedCutData, "cut");
checkCachedDataTransfer(cachedCopyData, "copy");
checkCachedDataTransfer(cachedPasteData, "paste");
checkSyntheticEvents();
SimpleTest.finish();
}
@ -102,7 +108,7 @@ function getClipboardText() {
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);
@ -110,7 +116,7 @@ function getClipboardText() {
var str = new Object();
var strLen = new Object();
try {
trans.getTransferData("text/unicode", str, strLen);
} catch(e) {
@ -124,15 +130,15 @@ function getClipboardText() {
throw e;
}
}
if (!str) return null;
str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
if (!str) return null;
str = str.data.substring(0, strLen.value / 2);
if (!str) return null;
return str;
}
@ -160,6 +166,7 @@ function test_dom_oncopy() {
// handler was called, and the clipboard contents have set to CONTENT TEXT.
// Test firing oncopy event on ctrl-c:
selectContentDiv();
var oncopy_fired = false;
content.oncopy = function() { oncopy_fired = true; };
try {
@ -564,6 +571,85 @@ function test_input_copy_button_dataTransfer() {
}
}
let expectedData = [];
// Check to make that synthetic events do not change the clipboard
function checkSyntheticEvents()
{
let syntheticSpot = document.getElementById("syntheticSpot");
setClipboardText(clipboardInitialValue);
// No dataType specified
let event = new ClipboardEvent("cut", { data: "something" });
expectedData = { type: "cut", data: null }
compareSynthetic(event, "before");
syntheticSpot.dispatchEvent(event);
ok(expectedData.eventFired, "cut event fired");
compareSynthetic(event, "after");
event = new ClipboardEvent("cut", { dataType: "text/plain", data: "something" });
expectedData = { type: "cut", dataType: "text/plain", data: "something" }
compareSynthetic(event, "before");
syntheticSpot.dispatchEvent(event);
ok(expectedData.eventFired, "cut event fired");
compareSynthetic(event, "after");
event = new ClipboardEvent("copy", { dataType: "text/plain", data: "something" });
expectedData = { type: "copy", dataType: "text/plain", data: "something" }
compareSynthetic(event, "before");
syntheticSpot.dispatchEvent(event);
ok(expectedData.eventFired, "copy event fired");
compareSynthetic(event, "after");
event = new ClipboardEvent("copy", { dataType: "text/plain" });
expectedData = { type: "copy", dataType: "text/plain", data: "" }
compareSynthetic(event, "before");
syntheticSpot.dispatchEvent(event);
ok(expectedData.eventFired, "copy event fired");
compareSynthetic(event, "after");
event = new ClipboardEvent("paste", { dataType: "text/plain", data: "something" });
expectedData = { type: "paste", dataType: "text/plain", data: "something" }
compareSynthetic(event, "before");
syntheticSpot.dispatchEvent(event);
ok(expectedData.eventFired, "paste event fired");
compareSynthetic(event, "after");
event = new ClipboardEvent("paste", { dataType: "application/unknown", data: "unknown" });
expectedData = { type: "paste", dataType: "application/unknown", data: "unknown" }
compareSynthetic(event, "before");
syntheticSpot.dispatchEvent(event);
ok(expectedData.eventFired, "paste event fired");
compareSynthetic(event, "after");
}
function compareSynthetic(event, eventtype)
{
let step = (eventtype == "cut" || eventtype == "copy" || eventtype == "paste") ? "during" : eventtype;
if (step == "during") {
is(eventtype, expectedData.type, "synthetic " + eventtype + " event fired");
}
ok(event.clipboardData instanceof DataTransfer, "clipboardData is assigned");
is(event.type, expectedData.type, "synthetic " + eventtype + " event type");
if (expectedData.data === null) {
is(event.clipboardData.mozItemCount, 0, "synthetic " + eventtype + " empty data");
}
else {
is(event.clipboardData.mozItemCount, 1, "synthetic " + eventtype + " item count");
is(event.clipboardData.types.length, 1, "synthetic " + eventtype + " types length");
is(event.clipboardData.getData(expectedData.dataType), expectedData.data,
"synthetic " + eventtype + " data");
}
is(getClipboardText(), "empty", "event does not change the clipboard " + step + " dispatch");
if (step == "during") {
expectedData.eventFired = true;
}
}
function checkCachedDataTransfer(cd, eventtype)
{
var testprefix = "cached " + eventtype + " dataTransfer";

Просмотреть файл

@ -7,6 +7,7 @@ dictionaries = [
[ 'EventInit', 'nsIDOMEvent.idl' ],
[ 'UIEventInit', 'nsIDOMUIEvent.idl' ],
[ 'MouseEventInit', 'nsIDOMMouseEvent.idl' ],
[ 'ClipboardEventInit', 'nsIDOMClipboardEvent.idl' ],
[ 'WheelEventInit', 'nsIDOMWheelEvent.idl' ],
[ 'IDBObjectStoreParameters', 'nsIIDBDatabase.idl' ],
[ 'IDBIndexParameters', 'nsIIDBObjectStore.idl' ],