Bug 989198, Patch 2: Implementation of BeforeAfterKeyboardEvent, sr=smaug, r=masayuki.

This commit is contained in:
Gina Yeh 2014-11-03 15:05:32 +08:00
parent 805eb76c01
commit 6b989e71ac
11 changed files with 261 additions and 51 deletions

View File

@ -0,0 +1,92 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "mozilla/dom/BeforeAfterKeyboardEvent.h"
#include "mozilla/TextEvents.h"
#include "prtime.h"
namespace mozilla {
namespace dom {
BeforeAfterKeyboardEvent::BeforeAfterKeyboardEvent(
EventTarget* aOwner,
nsPresContext* aPresContext,
InternalBeforeAfterKeyboardEvent* aEvent)
: KeyboardEvent(aOwner, aPresContext,
aEvent ? aEvent :
new InternalBeforeAfterKeyboardEvent(false, 0,
nullptr))
{
MOZ_ASSERT(mEvent->mClass == eBeforeAfterKeyboardEventClass,
"event type mismatch eBeforeAfterKeyboardEventClass");
if (!aEvent) {
mEventIsInternal = true;
mEvent->time = PR_Now();
}
}
// static
already_AddRefed<BeforeAfterKeyboardEvent>
BeforeAfterKeyboardEvent::Constructor(
EventTarget* aOwner,
const nsAString& aType,
const BeforeAfterKeyboardEventInit& aParam)
{
nsRefPtr<BeforeAfterKeyboardEvent> event =
new BeforeAfterKeyboardEvent(aOwner, nullptr, nullptr);
ErrorResult rv;
event->InitWithKeyboardEventInit(aOwner, aType, aParam, rv);
NS_WARN_IF(rv.Failed());
event->mEvent->AsBeforeAfterKeyboardEvent()->mEmbeddedCancelled =
aParam.mEmbeddedCancelled;
return event.forget();
}
// static
already_AddRefed<BeforeAfterKeyboardEvent>
BeforeAfterKeyboardEvent::Constructor(
const GlobalObject& aGlobal,
const nsAString& aType,
const BeforeAfterKeyboardEventInit& aParam,
ErrorResult& aRv)
{
nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports());
return Constructor(owner, aType, aParam);
}
Nullable<bool>
BeforeAfterKeyboardEvent::GetEmbeddedCancelled()
{
nsAutoString type;
GetType(type);
if (type.EqualsLiteral("mozbrowserafterkeydown") ||
type.EqualsLiteral("mozbrowserafterkeyup")) {
return mEvent->AsBeforeAfterKeyboardEvent()->mEmbeddedCancelled;
}
return Nullable<bool>();
}
} // namespace dom
} // namespace mozilla
using namespace mozilla;
using namespace mozilla::dom;
nsresult
NS_NewDOMBeforeAfterKeyboardEvent(nsIDOMEvent** aInstancePtrResult,
EventTarget* aOwner,
nsPresContext* aPresContext,
InternalBeforeAfterKeyboardEvent* aEvent)
{
BeforeAfterKeyboardEvent* it =
new BeforeAfterKeyboardEvent(aOwner, aPresContext, aEvent);
NS_ADDREF(it);
*aInstancePtrResult = static_cast<Event*>(it);
return NS_OK;
}

View File

@ -0,0 +1,45 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef mozilla_dom_BeforeAfterKeyboardEvent_h_
#define mozilla_dom_BeforeAfterKeyboardEvent_h_
#include "mozilla/dom/KeyboardEvent.h"
#include "mozilla/dom/BeforeAfterKeyboardEventBinding.h"
namespace mozilla {
namespace dom {
class BeforeAfterKeyboardEvent : public KeyboardEvent
{
public:
BeforeAfterKeyboardEvent(EventTarget* aOwner,
nsPresContext* aPresContext,
InternalBeforeAfterKeyboardEvent* aEvent);
virtual JSObject* WrapObjectInternal(JSContext* aCx) MOZ_OVERRIDE
{
return BeforeAfterKeyboardEventBinding::Wrap(aCx, this);
}
static already_AddRefed<BeforeAfterKeyboardEvent>
Constructor(const GlobalObject& aGlobal,
const nsAString& aType,
const BeforeAfterKeyboardEventInit& aParam,
ErrorResult& aRv);
static already_AddRefed<BeforeAfterKeyboardEvent>
Constructor(EventTarget* aOwner, const nsAString& aType,
const BeforeAfterKeyboardEventInit& aEventInitDict);
// This function returns a boolean value when event typs is either
// "mozbrowserafterkeydown" or "mozbrowserafterkeyup".
Nullable<bool> GetEmbeddedCancelled();
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_BeforeAfterKeyboardEvent_h_

View File

@ -701,6 +701,9 @@ EventDispatcher::CreateEvent(EventTarget* aOwner,
case eKeyboardEventClass:
return NS_NewDOMKeyboardEvent(aDOMEvent, aOwner, aPresContext,
aEvent->AsKeyboardEvent());
case eBeforeAfterKeyboardEventClass:
return NS_NewDOMBeforeAfterKeyboardEvent(aDOMEvent, aOwner, aPresContext,
aEvent->AsBeforeAfterKeyboardEvent());
case eCompositionEventClass:
return NS_NewDOMCompositionEvent(aDOMEvent, aOwner, aPresContext,
aEvent->AsCompositionEvent());

View File

@ -17,10 +17,8 @@ KeyboardEvent::KeyboardEvent(EventTarget* aOwner,
: UIEvent(aOwner, aPresContext,
aEvent ? aEvent : new WidgetKeyboardEvent(false, 0, nullptr))
, mInitializedByCtor(false)
, mInitialzedWhichValue(0)
, mInitializedWhichValue(0)
{
NS_ASSERTION(mEvent->mClass == eKeyboardEventClass, "event type mismatch");
if (aEvent) {
mEventIsInternal = false;
}
@ -257,8 +255,12 @@ KeyboardEvent::CharCode()
}
switch (mEvent->message) {
case NS_KEY_UP:
case NS_KEY_BEFORE_DOWN:
case NS_KEY_DOWN:
case NS_KEY_AFTER_DOWN:
case NS_KEY_BEFORE_UP:
case NS_KEY_UP:
case NS_KEY_AFTER_UP:
return 0;
case NS_KEY_PRESS:
return mEvent->AsKeyboardEvent()->charCode;
@ -282,10 +284,7 @@ KeyboardEvent::KeyCode()
return mEvent->AsKeyboardEvent()->keyCode;
}
switch (mEvent->message) {
case NS_KEY_UP:
case NS_KEY_PRESS:
case NS_KEY_DOWN:
if (mEvent->HasKeyEventMessage()) {
return mEvent->AsKeyboardEvent()->keyCode;
}
return 0;
@ -296,12 +295,16 @@ KeyboardEvent::Which()
{
// If this event is initialized with ctor, which can have independent value.
if (mInitializedByCtor) {
return mInitialzedWhichValue;
return mInitializedWhichValue;
}
switch (mEvent->message) {
case NS_KEY_UP:
case NS_KEY_BEFORE_DOWN:
case NS_KEY_DOWN:
case NS_KEY_AFTER_DOWN:
case NS_KEY_BEFORE_UP:
case NS_KEY_UP:
case NS_KEY_AFTER_UP:
return KeyCode();
case NS_KEY_PRESS:
//Special case for 4xp bug 62878. Try to make value of which
@ -343,26 +346,35 @@ KeyboardEvent::Constructor(const GlobalObject& aGlobal,
nsCOMPtr<EventTarget> target = do_QueryInterface(aGlobal.GetAsSupports());
nsRefPtr<KeyboardEvent> newEvent =
new KeyboardEvent(target, nullptr, nullptr);
bool trusted = newEvent->Init(target);
aRv = newEvent->InitKeyEvent(aType, aParam.mBubbles, aParam.mCancelable,
aParam.mView, aParam.mCtrlKey, aParam.mAltKey,
aParam.mShiftKey, aParam.mMetaKey,
aParam.mKeyCode, aParam.mCharCode);
newEvent->SetTrusted(trusted);
newEvent->mDetail = aParam.mDetail;
newEvent->mInitializedByCtor = true;
newEvent->mInitialzedWhichValue = aParam.mWhich;
newEvent->InitWithKeyboardEventInit(target, aType, aParam, aRv);
WidgetKeyboardEvent* internalEvent = newEvent->mEvent->AsKeyboardEvent();
return newEvent.forget();
}
void
KeyboardEvent::InitWithKeyboardEventInit(EventTarget* aOwner,
const nsAString& aType,
const KeyboardEventInit& aParam,
ErrorResult& aRv)
{
bool trusted = Init(aOwner);
aRv = InitKeyEvent(aType, aParam.mBubbles, aParam.mCancelable,
aParam.mView, aParam.mCtrlKey, aParam.mAltKey,
aParam.mShiftKey, aParam.mMetaKey,
aParam.mKeyCode, aParam.mCharCode);
SetTrusted(trusted);
mDetail = aParam.mDetail;
mInitializedByCtor = true;
mInitializedWhichValue = aParam.mWhich;
WidgetKeyboardEvent* internalEvent = mEvent->AsKeyboardEvent();
internalEvent->location = aParam.mLocation;
internalEvent->mIsRepeat = aParam.mRepeat;
internalEvent->mIsComposing = aParam.mIsComposing;
internalEvent->mKeyNameIndex = KEY_NAME_INDEX_USE_STRING;
internalEvent->mKeyValue = aParam.mKey;
internalEvent->mCodeNameIndex = CODE_NAME_INDEX_USE_STRING;
internalEvent->mKeyValue = aParam.mKey;
internalEvent->mCodeValue = aParam.mCode;
return newEvent.forget();
}
NS_IMETHODIMP

View File

@ -74,13 +74,19 @@ public:
protected:
~KeyboardEvent() {}
void InitWithKeyboardEventInit(EventTarget* aOwner,
const nsAString& aType,
const KeyboardEventInit& aParam,
ErrorResult& aRv);
private:
// True, if the instance is created with Constructor().
bool mInitializedByCtor;
// If the instance is created with Constructor(), which may have independent
// value. mInitializedWhichValue stores it. I.e., this is invalid when
// mInitializedByCtor is false.
uint32_t mInitialzedWhichValue;
uint32_t mInitializedWhichValue;
};
} // namespace dom

View File

@ -32,6 +32,7 @@ EXPORTS.mozilla += [
EXPORTS.mozilla.dom += [
'AnimationEvent.h',
'BeforeAfterKeyboardEvent.h',
'BeforeUnloadEvent.h',
'ClipboardEvent.h',
'CommandEvent.h',
@ -71,6 +72,7 @@ if CONFIG['MOZ_WEBSPEECH']:
UNIFIED_SOURCES += [
'AnimationEvent.cpp',
'AsyncEventDispatcher.cpp',
'BeforeAfterKeyboardEvent.cpp',
'BeforeUnloadEvent.cpp',
'ClipboardEvent.cpp',
'CommandEvent.cpp',

View File

@ -34,6 +34,10 @@ const kEventConstructors = {
},
AudioProcessingEvent: { create: null, // Cannot create untrusted event from JS.
},
BeforeAfterKeyboardEvent: { create: function (aName, aProps) {
return new BeforeAfterKeyboardEvent(aName, aProps);
},
},
BeforeUnloadEvent: { create: function (aName, aProps) {
var e = document.createEvent("beforeunloadevent");
e.initEvent(aName, aProps.bubbles, aProps.cancelable);

View File

@ -272,6 +272,13 @@ NS_NewDOMKeyboardEvent(nsIDOMEvent** aInstancePtrResult,
mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext,
mozilla::WidgetKeyboardEvent* aEvent);
nsresult
NS_NewDOMBeforeAfterKeyboardEvent(nsIDOMEvent** aInstancePtrResult,
mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext,
mozilla::InternalBeforeAfterKeyboardEvent* aEvent);
nsresult
NS_NewDOMCompositionEvent(nsIDOMEvent** aInstancePtrResult,
mozilla::dom::EventTarget* aOwner,

View File

@ -172,6 +172,10 @@ var interfaceNamesInGlobalScope =
"BarProp",
// IMPORTANT: Do not change this list without review from a DOM peer!
"BatteryManager",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BeforeAfterKeyboardEvent", b2g: true,
pref: "dom.beforeAfterKeyboardEvent.enabled",
permission: ["embed-apps", "before-after-keyboard-event"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
"BeforeUnloadEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -181,18 +185,18 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"BlobEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothAdapter", b2g: true, permission: "bluetooth"},
{name: "BluetoothAdapter", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothDevice", b2g: true, permission: "bluetooth"},
{name: "BluetoothDevice", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothDeviceEvent", b2g: true, permission: "bluetooth"},
{name: "BluetoothDeviceEvent", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothDiscoveryStateChangedEvent", b2g: true,
permission: "bluetooth"},
permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothManager", b2g: true, permission: "bluetooth"},
{name: "BluetoothManager", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothStatusChangedEvent", b2g: true, permission: "bluetooth"},
{name: "BluetoothStatusChangedEvent", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BoxObject", xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -756,7 +760,7 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"MozSettingsEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozSettingsTransactionEvent", permission: "settings-api-read"},
{name: "MozSettingsTransactionEvent", permission: ["settings-api-read"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
"MozSmsEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -776,23 +780,23 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWakeLock", b2g: true, pref: "dom.wakelock.enabled"},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiCapabilities", b2g: true, permission: "wifi-manage"},
{name: "MozWifiCapabilities", b2g: true, permission: ["wifi-manage"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiConnectionInfoEvent", b2g: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiStationInfoEvent", b2g: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiManager", b2g: true, permission: "wifi-manage"},
{name: "MozWifiManager", b2g: true, permission: ["wifi-manage"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiNetwork", b2g: true, permission: "wifi-manage"},
{name: "MozWifiNetwork", b2g: true, permission: ["wifi-manage"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiStatusChangeEvent", b2g: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiP2pGroupOwner", b2g: true, permission: "wifi-manage"},
{name: "MozWifiP2pGroupOwner", b2g: true, permission: ["wifi-manage"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiP2pManager", b2g: true, permission: "wifi-manage"},
{name: "MozWifiP2pManager", b2g: true, permission: ["wifi-manage"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiP2pStatusChangeEvent", b2g: true, permission: "wifi-manage"},
{name: "MozWifiP2pStatusChangeEvent", b2g: true, permission: ["wifi-manage"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
"MutationEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -850,9 +854,9 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"PeriodicWave",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "PermissionSettings", b2g: true, permission: "permissions"},
{name: "PermissionSettings", b2g: true, permission: ["permissions"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "PhoneNumberService", permission: "phonenumberservice"},
{name: "PhoneNumberService", permission: ["phonenumberservice"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
"Plugin",
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -1236,25 +1240,31 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "TVChannel", b2g: true, pref: "dom.tv.enabled", permission: "tv"},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "TVCurrentChannelChangedEvent", b2g: true, pref: "dom.tv.enabled", permission: "tv"},
{name: "TVCurrentChannelChangedEvent", b2g: true, pref: "dom.tv.enabled",
permission: "tv"},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "TVCurrentSourceChangedEvent", b2g: true, pref: "dom.tv.enabled", permission: "tv"},
{name: "TVCurrentSourceChangedEvent", b2g: true, pref: "dom.tv.enabled",
permission: "tv"},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "TVEITBroadcastedEvent", b2g: true, pref: "dom.tv.enabled", permission: "tv"},
{name: "TVEITBroadcastedEvent", b2g: true, pref: "dom.tv.enabled",
permission: ["tv"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "TVManager", b2g: true, pref: "dom.tv.enabled", permission: "tv"},
{name: "TVManager", b2g: true, pref: "dom.tv.enabled", permission: ["tv"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "TVProgram", b2g: true, pref: "dom.tv.enabled", permission: "tv"},
{name: "TVProgram", b2g: true, pref: "dom.tv.enabled", permission: ["tv"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "TVScanningStateChangedEvent", b2g: true, pref: "dom.tv.enabled", permission: "tv"},
{name: "TVScanningStateChangedEvent", b2g: true, pref: "dom.tv.enabled",
permission: ["tv"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "TVSource", b2g: true, pref: "dom.tv.enabled", permission: "tv"},
{name: "TVSource", b2g: true, pref: "dom.tv.enabled", permission: ["tv"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "TVTuner", b2g: true, pref: "dom.tv.enabled", permission: "tv"},
{name: "TVTuner", b2g: true, pref: "dom.tv.enabled", permission: ["tv"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "UDPMessageEvent", pref: "dom.udpsocket.enabled", permission: "udp-socket"},
{name: "UDPMessageEvent", pref: "dom.udpsocket.enabled",
permission: ["udp-socket"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "UDPSocket", pref: "dom.udpsocket.enabled", permission: "udp-socket"},
{name: "UDPSocket", pref: "dom.udpsocket.enabled",
permission: ["udp-socket"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
"UIEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -1360,8 +1370,12 @@ function createInterfaceMap(isXBLScope) {
var isRelease = !version.contains("a");
var isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
var isB2G = !isDesktop && !navigator.userAgent.contains("Android");
var hasPermission = function (aPermission) {
return SpecialPowers.hasPermission(aPermission, window.document);
var hasPermission = function (aPermissions) {
var result = false;
for (var p of aPermissions) {
result = result || SpecialPowers.hasPermission(p, window.document);
}
return result;
};
var interfaceMap = {};

View File

@ -0,0 +1,24 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*/
[Constructor(DOMString typeArg,
optional BeforeAfterKeyboardEventInit eventInitDict),
CheckPermissions="embed-apps before-after-keyboard-event",
Pref="dom.beforeAfterKeyboardEvent.enabled"]
interface BeforeAfterKeyboardEvent : KeyboardEvent
{
// The valid value of embeddedCancelled is:
// - "mozbrowserbeforekeydown": null
// - "mozbrowserbeforekeyup": null
// - "mozbrowserafterkeydown": true/false
// - "mozbrowserafterkeyup": true/false
readonly attribute boolean? embeddedCancelled;
};
dictionary BeforeAfterKeyboardEventInit : KeyboardEventInit
{
boolean? embeddedCancelled = null;
};

View File

@ -50,6 +50,7 @@ WEBIDL_FILES = [
'AutocompleteInfo.webidl',
'BarProp.webidl',
'BatteryManager.webidl',
'BeforeAfterKeyboardEvent.webidl',
'BeforeUnloadEvent.webidl',
'BiquadFilterNode.webidl',
'Blob.webidl',