mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-07-20 05:59:28 +00:00
21c98793d3
- Bug 1244883 - Add Nightly-/Aurora-only crash for AsyncTransactionWaiter timeouts - r=nical (132b2ceff9) - Bug 1148978 - Trigger paints when moving plugin windows around on the browser main thread. r=mattwoodrow (c75ce5ec09) - Dedent some functions. (bug 1254899 part 1, r=jrmuizel) (c84fb419c7) - Refactor acceleration pref initialization. (bug 1254899 part 2, r=jrmuizel) (29a164c70e) - Remove NS_NATIVE_GRAPHIC on Windows. (bug 1266536, r=jimm) (84011349d1) - Bug 1267253 - Delete gfxWindowsPlatform::RenderMode and replace it with a check against the default backend. r=bas (93cb6e503e) - Introduce gfxConfig, a manager for graphics feature settings. (bug 1254899 part 3, r=milan) (97498ca46a) - Bug 1262187: Allow D3D9 if D3D11 failed, behind the pref, but on by default. r=bas (8163e28b26) - Bug 1178376 - Optionally fade in new progressively painted tiles r=nical (777bf1799d) - Bug 1178376 - Allow progressive painting when low-precision tiles are disabled r=BenWa (3b8d84e19c) - Bug 1178376 - Put progressive paint status in tile updates r=nical (935d3b46ed) - Bug 1251778: Attempt to avoid presenting when the window is still resizing. r=jrmuizel (32b194a6f7) - Hoist mWidget into the Compositor base class. (bug 1264545 part 1, r=nical) (aca26ec343) - Lift compositor-accessed methods from nsIWidget into CompositorWidgetProxy. (bug 1264545 part 2, r=jimm) (609a23157a) - Rename FeatureStatus::Crashed to CrashedInHandler. (bug 1254899 part 4, r=milan) (0eae23a3fd) - Move DeviceInitData from gfxWindowsPlatform to gfxPlatforn. (bug 1254899 part 5, r=milan) (e31540ba18) - Merge gfxWindowsPlatform::mAcceleration into gfxConfig. (bug 1254899 part 6, r=milan) (9d45cc8b87) - Add another feature state for blacklisting and environment decisions. (bug 1254899 part 7, r=milan) (e7eee53cfb) - Give FeatureState a public interface. (bug 1254899 part 8, r=milan) (52d8e7f355) - Replace gfxWindowsPlatform::mD3D11Status with gfxConfig. (bug 1254899 part 9, r=jrmuizel) (90dc658b53) - Replace gfxWindowsPlatform::mD2D1Status with gfxConfig. (bug 1254899 part 10, r=milan) (eb9474f309) - Fix assertion failure in gfxConfig. (bug 1269565, r=milan) (0eb738ce66) - Add gfxConfig to nsIGfxInfo, for about:support access. (bug 1254899 part 11, r=jrmuizel) (e770240152) - Change Compositor::GetWidget to return a CompositorWidgetProxy. (bug 1264545 part 3, r=jimm) (fdf1d96255) - Bug 1251778 - Followup: Remove unreferenced local variable. r=bustage (27579f5542) - Use CompositorWidgetProxy in place of nsIWidget in the compositor. (bug 1264545 part 4, r=jimm) (80def1c2eb) - Use CompositorWidgetProxy in place of nsIWidget in CompositorBridgeParent. (bug 1264545 part 5, r=jimm,kats) (67d0e1ef7d) - Move CompositorWidgetProxy inheritance out of nsIWidget. (bug 1264545 part 6, r=jimm) (61075722c5) - Bug 1251894 - In CompositorD3D11::CreateTexture, copy as much as the render target allows. r=bas (bf5fc6baa2) - Bug 1266444: It is OK for us not to have texture sharing. r=jrmuizel (0b1885f89d) - Bug 1266396 - Make TextureClient more robust against racy shutdown situations. r=Bas (b1d7f54643) - Fix test bustage due to platform line-endings. Bug 1222624 (10b8cf3592) - More test bustage from bug 1222624 (763c4c0bb9) - Backed out 4 changesets (bug 1222624) to fix bug 1249572 (7ba3d433d0) - Bug 1268230 - RunTime.cpp and ScriptLoader do not have to use MainThreadStopSyncLoopRunnable, r=khuey (88499a3982) - Bug 1037725 - Add warning message in the console when worker spawn over limit. r=khuey (8af94dbc1d) - Bug 1047663 - Disabling the cache in a tab should also disable it for all workers in that tab;r=khuey (5411d81682) - Bug 1253793 Update ScriptLoader assertion to handle cancelation case. r=khuey (18c78d5651) - Bug 1245768 - Implement a test for the correct error management when worker imports 3rd party scripts, r=bz (c1d3f290a9) - Bug 1249673. Muted errors should be turned into NetworkError DOMExceptions when returning from importScripts on workers, instead of becoming NS_ERROR_FAILURE. r=baku (0358282cbe) - Bug 1265405 - Add a dictionary to specify how PeriodicWave should be normalized (or not); r=smaug …normalized (or not); r=smaugu (201213146c) - Bug 1251082. Restore comments in PageTransitionEvent.webidl that got lost when nsIDOMPageTransitionEvent.idl was migrated to webidl. r=bz The mentioned migration happened in http://hg.mozilla.org/mozilla-central/rev/e6377ca32f3d from bug 1031051. (2dfa309056) - Bug 1266178 Make ServiceWorkerClient not assert if the document doesn't have an outer window. r=ehsan (eafb169c91) - Bug 1259164 - Set ServiceWorkerMessageEvent.origin correctly when calling ServiceWorkerClient.postMessage(); r=bkelly (caeb65d10e) - Bug 1246319 P1 Dedupe service worker registrar entries. r=baku (b76deef941) - Bug 1246319 P2 Verify entries are deduped from the ServiceWorkerRegistrar. r=baku (8a4e348d6e) - Bug 1246319 P3 Fix service worker registry value update. r=bz (14abf6b6ce) - Bug 1247970 - Remove principal spec from service worker registrar file. r=baku (3c30130700) - Bug 1249438 P1 Move guts of RegisterServiceWorker() into a protected method that can be tested in gtest. r=baku (488243196d) - Bug 1249438 P2 Modify existing gtest to use RegisterServiceWorkerInternal. r=baku (e86c66891d) - Bug 1249438 P3 Add a gtest that registers duplicate service worker registrations. r=baku (35e269f9af) - Bug 1226443 P6 Ignore update() called during top level service worker script evaluation. r=ehsan (dcb9d02553) - Bug 1241725 - about:serviceworkers "Active Cache Name" UUID should not contain null bytes, r=bkelly (4cddea6a67) - Bug 1221852 - SharedWorker.port should be always not null, r=smaug (a9800274dc) - Bug 1261428: Clean up a bit more. r=bz (4977e3d7a5) - Bug 890284. Stop splitting textnodes in the XML content sink. r=peterv (a46dfca1cf) - Bug 1211708 Allow themes to specify XBL bindings even in unprivileged documents r=sicking (82cf1a4023) - Bug 915962 - Part 1: Allow pressing space to scroll the document if an editable element or form control is not focused; r=roc (cdb934af03) - Bug 915962 - Part 2: Add a test case for pressing space when a tabindex=-1 and a button element is focused; r=roc (17dcf5cfd0) - Bug 915962 - Part 3: Do not crash when pressing the space bar without having an element focused; r=roc (2161e62bc3) - Bug 1180761, cancel the event earlier so that space doesn't trigger checkbox change and scroll, r=neil (2425cb76ad) - Bug 1259182 - Shrink keyCodeData. r=bz. (737204af84) - Bug 1193567 - Check result of ReadID in nsXBLPrototypeBinding::Read(). r=wchen (c9b1c35bf3) - Bug 1173344 - Remove an intermediary root from nsXBLProtoImplField's FieldGetterImpl; r=jandem (5f42dd2e48) - Bug 1207494 - Part 14: Remove use of expression closure from dom/xbl/. r=bz (21c7d3825f) - align tests (fe34b613d3) - Bug 1223702 - Fix some errors about wifi direct. r=hchang (568d86054a) - Bug 1166274 - Part 1: Handle the callback and IPC message of setStaticIpMode correctly. r=vchang (8fb8d7f3b7) - Bug 1133665 - [Flame][Wifi] The SSID that has set to be binded with MAC address is not hightlighted when user taps it. r=hchang (3165471d13) - Bug 1207494 - Part 13: Remove use of expression closure from dom/wifi/. r=henry (dd9ad23a8a) - Bug 1251856 - Disable U2F in all releases (fix for 1231681). r=baku (24ada10566) - align tests (dae9ecd0ee) - var-let (11a3cb0878) - Bug 1184822 - Use classId to get provider. r=fabrice (1288eccd06) - Bug 1247410 - "test for _nomap ids does not work correctly". r=dougt (f736a04f08) - Bug 1035097 - Changed the type from 'radio' to 'radioType'. r=jdm (f9a0079152) - Bug 1177871 - Add a timeout to XHR request of WifiGeoPositionProvider. r=jdm (2f6aa87c20) - align code to 978593 with POST and location structure (d8ba75a759) - Bug 1230685 - Replace function declarations with add_task statements in test_storage_value_array.js and test_unicode.js. r=mak (9822bf2215) - Bug 1230683 - Replace try/catch with Assert.throws in test_storage_connection.js. r=mak (1c993fc37e) - Bug 655722 - Rewrite _buildGUIDMap in the sync bookmark engine to use PlacesUtils.promiseBookmarksTree. r=mak (3795d26af0) - Bug 1251057 - enable debug logging for rest.js requests and responses. r=adw (1062bcd113) - Bug 503515 - Try and ensure exported certificates include an extension by default. r=keeler (505967ab7f) - Bug 1017616 - Filter out some more unnecessary characters when exporting certs. r=keeler (e95838e362) - Bug 1241614 - don't overflow:auto the container, use em to size the dialog to avoid hidpi visibility issues, r=dolske,ttaubert (8bd6c2b35b) - Bug 1266851. Make <xmp> and <listing> use HTMLPreElement as their primary interface, per <whatwg/html#1015>. r=peterv (6be7f9d6e9) - Bug 1262184 - Block embed content loading when child of media element; r=bz (a297eeb378) - Bug 1263696 - Block embed content loading when ancestor of object element with content; r=bz (89c143cbfe) - Bug 1266077. Fix <base> href getter to follow the spec; it should be using the fallback base URI to resolve against, not the document URI. r=bkelly (e757b23a14) - Bug 1168079 nsTextEditRules::CollapseSelectionToTrailingBRIfNeeded() should ensure that there is a selection before calling nsEditor::GetStartNodeAndOffset() r=ehsan (6c283bf3a7) - Bug 898321 - Return success from nsTableEditor::GetCellAt if frame not found; r=ehsan (0d09143b95) - Bug 387687 - wrap quotes in plain text replies to window. r=masayuki (ca51437018) - Bug 1247483 - Only replace nodes in nsHTMLEditor::ReplaceOrphanedStructure if all nodes in node list are descendants of replacement node. r=ehsan (8416037da2) - bug 1266496 - fire some selection events for proxied accessibles r=davidb (8806de7dd9) - bug 1266518 - add a new event message for AccSelChangeEvents r=davidb (46af183cab) - Bug 953265: Adjust Opus bitrate in WebRTC to pass >8KHz audio, and comment r=bwc (b0be6a326e) - Bug 1221473: Do not treat answer as authoritative wrt payload types. r=drno (d27409209e) - Bug 1241321 - No RTCP stats for audio streams. r=rjesup (ec0222694e) - bug 1250492 - use tl::Max instead of std::max to get rid of a static constructor r=jesup (3cebbc8969) - Bug 1254187: Fix maxBitrate to respect simulcast. r=jesup (e569e54b57) - Bug 1158931 - Fix static assertion compilation error; r=snorp (eb27881746) - No bug, fix WebrtcMediaCodecVP8VideoCodec.cpp warnings (a983544581) - Bug 1252737 - use size_t instead of uint32_t for InitEncode(). r=jesup (57c3abc9fa) - Bug 1208371 - Never send more than one disabled frame in a row to the WebRTC encoder. r=jesup (ec0c28822b) - Bug 1208371 - Do image format conversion async in MediaPipeline. r=jesup (032efec783) - Bug 1266685 - Don't pass too many frames to the MediaPipelineTransmit VideoFrameConverter. r=jesup (21774a8d25) - Bug 1266644 - Rename StreamBuffer to StreamTracks. r=jesup r=pehrsons (21906fe1f7) - Bug 1208371 - Don't treat audio chunks as mutable in MediaPipeline. r=padenot (3878ef4332) - Bug 1246310 - Let MediaPipelineReceive tracks start at 0. r=jesup (b468ff8d48) - Bug 1266644 - Rename DOMMediaStream:: CreateXXXStream to DOMMediaStream:: CreateXXXStreamAsInput. r=jesup r=pehrsons (fe4b6d70bc) - Bug 1234578: Add an assertion. r=drno, a=abillings (f1a2c8d841) - bug 1250492 - include sstream in SdpMediaSection.h instead of iostream r=jesup (110b5c2eca) - Bug 1264470 - a=identity is a long attribute, r=bwc (5848194fe9) - Bug 1256750: Remove unnecessary sscanf_s parameter on windows, and fix format string everywhere else. r=jesup (371c0db476) - Bug 1204082 - try strtoull instead. r=mt (a0313aa87c) - Bug 1113443 - reject each media type with approriate default. r=bwc (a72ff312d1) - Bug 1095793 - use mid if provided to place candidate in msection. r=bwc (2c29b21fac) - Bug 1252699 - Set WEBRTC_DETECT_ARM_NEON when optional neon is requested. r=jesup (722e2043a5) - Bug 1229475 - webrtc: Call opus tonality_analysis_init. r=jesup (1cf8cc2cd7) - Bug 1254876: assert windows recording is shut down r=pkerr (1f2cb69073) - Bug 1227481 - added a memset on aec. r=jesup (532026ce20) - Bug 1254507 - Fix leak in WebRTC DesktopApplication class. r=jesup (54da72aeb4) - Bug 1196542 - share only windows with non-zero area. r=pkerr (94595ec463) - Bug 1202087 - Filter out non-shareable application for win8 or greater. r=jesup (d989956802) - Bug 1216529 - WebRTC: Request camera permission before accessing camera APIs. r=gcp (24b6699226) - Bug 1237630 - Part 1: Video freeze from WebRTC sender. r=rjesup (02daa8b5b7) - Bug 1237630 - Part 2: remove LOG statement generating a now defunct error condition. r=rjesup (c6002ef12f) - Bug 1248335: avoid using SvcInternal structure entirely, as system-vpx may not have it r=pkerr (ef9b21f20c) - Bug 1234571: unregister encoded-frame callback when releasing codec databases r=pkerr (321bd5166b) - Bug 820972 - Comment out colorTable[] because we don't need it. r=jesup. (60b10803d5) - cleanup and missing test stuff (e2be0331d9) - Merge remote-tracking branch 'upstream/dev' into winbuild (3a3bb0b315) - layout/media: fix export symbol list, fix build bustage (f9f5bfe14c)
1010 lines
31 KiB
C++
1010 lines
31 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* 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/ArrayUtils.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
#include "nsQueryObject.h"
|
|
#include "nsXBLPrototypeHandler.h"
|
|
#include "nsXBLPrototypeBinding.h"
|
|
#include "nsContentUtils.h"
|
|
#include "nsGlobalWindow.h"
|
|
#include "nsIContent.h"
|
|
#include "nsIAtom.h"
|
|
#include "nsIDOMKeyEvent.h"
|
|
#include "nsIDOMMouseEvent.h"
|
|
#include "nsNameSpaceManager.h"
|
|
#include "nsIDocument.h"
|
|
#include "nsIController.h"
|
|
#include "nsIControllers.h"
|
|
#include "nsIDOMXULElement.h"
|
|
#include "nsIURI.h"
|
|
#include "nsIDOMHTMLTextAreaElement.h"
|
|
#include "nsIDOMHTMLInputElement.h"
|
|
#include "nsFocusManager.h"
|
|
#include "nsIFormControl.h"
|
|
#include "nsIDOMEventListener.h"
|
|
#include "nsPIDOMWindow.h"
|
|
#include "nsPIWindowRoot.h"
|
|
#include "nsIDOMWindow.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsIScriptError.h"
|
|
#include "nsXPIDLString.h"
|
|
#include "nsReadableUtils.h"
|
|
#include "nsGkAtoms.h"
|
|
#include "nsIXPConnect.h"
|
|
#include "mozilla/AddonPathService.h"
|
|
#include "nsDOMCID.h"
|
|
#include "nsUnicharUtils.h"
|
|
#include "nsCRT.h"
|
|
#include "nsXBLEventHandler.h"
|
|
#include "nsXBLSerialize.h"
|
|
#include "nsJSUtils.h"
|
|
#include "mozilla/BasicEvents.h"
|
|
#include "mozilla/JSEventHandler.h"
|
|
#include "mozilla/Preferences.h"
|
|
#include "mozilla/dom/Element.h"
|
|
#include "mozilla/dom/EventHandlerBinding.h"
|
|
#include "mozilla/dom/ScriptSettings.h"
|
|
#include "xpcpublic.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::dom;
|
|
|
|
uint32_t nsXBLPrototypeHandler::gRefCnt = 0;
|
|
|
|
int32_t nsXBLPrototypeHandler::kMenuAccessKey = -1;
|
|
|
|
const int32_t nsXBLPrototypeHandler::cShift = (1<<0);
|
|
const int32_t nsXBLPrototypeHandler::cAlt = (1<<1);
|
|
const int32_t nsXBLPrototypeHandler::cControl = (1<<2);
|
|
const int32_t nsXBLPrototypeHandler::cMeta = (1<<3);
|
|
const int32_t nsXBLPrototypeHandler::cOS = (1<<4);
|
|
|
|
const int32_t nsXBLPrototypeHandler::cShiftMask = (1<<5);
|
|
const int32_t nsXBLPrototypeHandler::cAltMask = (1<<6);
|
|
const int32_t nsXBLPrototypeHandler::cControlMask = (1<<7);
|
|
const int32_t nsXBLPrototypeHandler::cMetaMask = (1<<8);
|
|
const int32_t nsXBLPrototypeHandler::cOSMask = (1<<9);
|
|
|
|
const int32_t nsXBLPrototypeHandler::cAllModifiers =
|
|
cShiftMask | cAltMask | cControlMask | cMetaMask | cOSMask;
|
|
|
|
nsXBLPrototypeHandler::nsXBLPrototypeHandler(const char16_t* aEvent,
|
|
const char16_t* aPhase,
|
|
const char16_t* aAction,
|
|
const char16_t* aCommand,
|
|
const char16_t* aKeyCode,
|
|
const char16_t* aCharCode,
|
|
const char16_t* aModifiers,
|
|
const char16_t* aButton,
|
|
const char16_t* aClickCount,
|
|
const char16_t* aGroup,
|
|
const char16_t* aPreventDefault,
|
|
const char16_t* aAllowUntrusted,
|
|
nsXBLPrototypeBinding* aBinding,
|
|
uint32_t aLineNumber)
|
|
: mHandlerText(nullptr),
|
|
mLineNumber(aLineNumber),
|
|
mNextHandler(nullptr),
|
|
mPrototypeBinding(aBinding)
|
|
{
|
|
Init();
|
|
|
|
ConstructPrototype(nullptr, aEvent, aPhase, aAction, aCommand, aKeyCode,
|
|
aCharCode, aModifiers, aButton, aClickCount,
|
|
aGroup, aPreventDefault, aAllowUntrusted);
|
|
}
|
|
|
|
nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement)
|
|
: mHandlerElement(nullptr),
|
|
mLineNumber(0),
|
|
mNextHandler(nullptr),
|
|
mPrototypeBinding(nullptr)
|
|
{
|
|
Init();
|
|
|
|
// Make sure our prototype is initialized.
|
|
ConstructPrototype(aHandlerElement);
|
|
}
|
|
|
|
nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsXBLPrototypeBinding* aBinding)
|
|
: mHandlerText(nullptr),
|
|
mLineNumber(0),
|
|
mNextHandler(nullptr),
|
|
mPrototypeBinding(aBinding)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
nsXBLPrototypeHandler::~nsXBLPrototypeHandler()
|
|
{
|
|
--gRefCnt;
|
|
if (mType & NS_HANDLER_TYPE_XUL) {
|
|
NS_IF_RELEASE(mHandlerElement);
|
|
} else if (mHandlerText) {
|
|
free(mHandlerText);
|
|
}
|
|
|
|
// We own the next handler in the chain, so delete it now.
|
|
NS_CONTENT_DELETE_LIST_MEMBER(nsXBLPrototypeHandler, this, mNextHandler);
|
|
}
|
|
|
|
already_AddRefed<nsIContent>
|
|
nsXBLPrototypeHandler::GetHandlerElement()
|
|
{
|
|
if (mType & NS_HANDLER_TYPE_XUL) {
|
|
nsCOMPtr<nsIContent> element = do_QueryReferent(mHandlerElement);
|
|
return element.forget();
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void
|
|
nsXBLPrototypeHandler::AppendHandlerText(const nsAString& aText)
|
|
{
|
|
if (mHandlerText) {
|
|
// Append our text to the existing text.
|
|
char16_t* temp = mHandlerText;
|
|
mHandlerText = ToNewUnicode(nsDependentString(temp) + aText);
|
|
free(temp);
|
|
}
|
|
else {
|
|
mHandlerText = ToNewUnicode(aText);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Get the menu access key from prefs.
|
|
// XXX Eventually pick up using CSS3 key-equivalent property or somesuch
|
|
void
|
|
nsXBLPrototypeHandler::InitAccessKeys()
|
|
{
|
|
if (kMenuAccessKey >= 0) {
|
|
return;
|
|
}
|
|
|
|
// Compiled-in defaults, in case we can't get the pref --
|
|
// mac doesn't have menu shortcuts, other platforms use alt.
|
|
#ifdef XP_MACOSX
|
|
kMenuAccessKey = 0;
|
|
#else
|
|
kMenuAccessKey = nsIDOMKeyEvent::DOM_VK_ALT;
|
|
#endif
|
|
|
|
// Get the menu access key value from prefs, overriding the default:
|
|
kMenuAccessKey =
|
|
Preferences::GetInt("ui.key.menuAccessKey", kMenuAccessKey);
|
|
}
|
|
|
|
nsresult
|
|
nsXBLPrototypeHandler::ExecuteHandler(EventTarget* aTarget,
|
|
nsIDOMEvent* aEvent)
|
|
{
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
// Prevent default action?
|
|
if (mType & NS_HANDLER_TYPE_PREVENTDEFAULT) {
|
|
aEvent->PreventDefault();
|
|
// If we prevent default, then it's okay for
|
|
// mHandlerElement and mHandlerText to be null
|
|
rv = NS_OK;
|
|
}
|
|
|
|
if (!mHandlerElement) // This works for both types of handlers. In both cases, the union's var should be defined.
|
|
return rv;
|
|
|
|
// See if our event receiver is a content node (and not us).
|
|
bool isXULKey = !!(mType & NS_HANDLER_TYPE_XUL);
|
|
bool isXBLCommand = !!(mType & NS_HANDLER_TYPE_XBL_COMMAND);
|
|
NS_ASSERTION(!(isXULKey && isXBLCommand),
|
|
"can't be both a key and xbl command handler");
|
|
|
|
// XUL handlers and commands shouldn't be triggered by non-trusted
|
|
// events.
|
|
if (isXULKey || isXBLCommand) {
|
|
bool trustedEvent = false;
|
|
aEvent->GetIsTrusted(&trustedEvent);
|
|
|
|
if (!trustedEvent)
|
|
return NS_OK;
|
|
}
|
|
|
|
if (isXBLCommand) {
|
|
return DispatchXBLCommand(aTarget, aEvent);
|
|
}
|
|
|
|
// If we're executing on a XUL key element, just dispatch a command
|
|
// event at the element. It will take care of retargeting it to its
|
|
// command element, if applicable, and executing the event handler.
|
|
if (isXULKey) {
|
|
return DispatchXULKeyCommand(aEvent);
|
|
}
|
|
|
|
// Look for a compiled handler on the element.
|
|
// Should be compiled and bound with "on" in front of the name.
|
|
nsCOMPtr<nsIAtom> onEventAtom = NS_Atomize(NS_LITERAL_STRING("onxbl") +
|
|
nsDependentAtomString(mEventName));
|
|
|
|
// Compile the handler and bind it to the element.
|
|
nsCOMPtr<nsIScriptGlobalObject> boundGlobal;
|
|
nsCOMPtr<nsPIWindowRoot> winRoot(do_QueryInterface(aTarget));
|
|
nsCOMPtr<nsPIDOMWindow> window;
|
|
|
|
if (winRoot) {
|
|
window = winRoot->GetWindow();
|
|
}
|
|
|
|
if (window) {
|
|
window = window->GetCurrentInnerWindow();
|
|
NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED);
|
|
|
|
boundGlobal = do_QueryInterface(window->GetPrivateRoot());
|
|
}
|
|
else boundGlobal = do_QueryInterface(aTarget);
|
|
|
|
if (!boundGlobal) {
|
|
nsCOMPtr<nsIDocument> boundDocument(do_QueryInterface(aTarget));
|
|
if (!boundDocument) {
|
|
// We must be an element.
|
|
nsCOMPtr<nsIContent> content(do_QueryInterface(aTarget));
|
|
if (!content)
|
|
return NS_OK;
|
|
boundDocument = content->OwnerDoc();
|
|
}
|
|
|
|
boundGlobal = do_QueryInterface(boundDocument->GetScopeObject());
|
|
}
|
|
|
|
if (!boundGlobal)
|
|
return NS_OK;
|
|
|
|
nsISupports *scriptTarget;
|
|
|
|
if (winRoot) {
|
|
scriptTarget = boundGlobal;
|
|
} else {
|
|
scriptTarget = aTarget;
|
|
}
|
|
|
|
// We're about to create a new JSEventHandler, which means that we need to
|
|
// Initiatize an AutoJSAPI with aTarget's bound global to make sure any errors
|
|
// are reported to the correct place.
|
|
AutoJSAPI jsapi;
|
|
if (NS_WARN_IF(!jsapi.Init(boundGlobal))) {
|
|
return NS_OK;
|
|
}
|
|
JSContext* cx = jsapi.cx();
|
|
JS::Rooted<JSObject*> handler(cx);
|
|
|
|
rv = EnsureEventHandler(jsapi, onEventAtom, &handler);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI());
|
|
|
|
JS::Rooted<JSObject*> globalObject(cx, boundGlobal->GetGlobalJSObject());
|
|
JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, addonId));
|
|
NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
// Bind it to the bound element. Note that if we're using a separate XBL scope,
|
|
// we'll actually be binding the event handler to a cross-compartment wrapper
|
|
// to the bound element's reflector.
|
|
|
|
// First, enter our XBL scope. This is where the generic handler should have
|
|
// been compiled, above.
|
|
JSAutoCompartment ac(cx, scopeObject);
|
|
JS::Rooted<JSObject*> genericHandler(cx, handler.get());
|
|
bool ok = JS_WrapObject(cx, &genericHandler);
|
|
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
|
|
MOZ_ASSERT(!js::IsCrossCompartmentWrapper(genericHandler));
|
|
|
|
// Build a scope chain in the XBL scope.
|
|
RefPtr<Element> targetElement = do_QueryObject(scriptTarget);
|
|
JS::AutoObjectVector scopeChain(cx);
|
|
ok = nsJSUtils::GetScopeChainForElement(cx, targetElement, scopeChain);
|
|
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
// Next, clone the generic handler with our desired scope chain.
|
|
JS::Rooted<JSObject*> bound(cx, JS::CloneFunctionObject(cx, genericHandler,
|
|
scopeChain));
|
|
NS_ENSURE_TRUE(bound, NS_ERROR_FAILURE);
|
|
|
|
RefPtr<EventHandlerNonNull> handlerCallback =
|
|
new EventHandlerNonNull(nullptr, bound, /* aIncumbentGlobal = */ nullptr);
|
|
|
|
TypedEventHandler typedHandler(handlerCallback);
|
|
|
|
// Execute it.
|
|
nsCOMPtr<JSEventHandler> jsEventHandler;
|
|
rv = NS_NewJSEventHandler(scriptTarget, onEventAtom,
|
|
typedHandler,
|
|
getter_AddRefs(jsEventHandler));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Handle the event.
|
|
jsEventHandler->HandleEvent(aEvent);
|
|
jsEventHandler->Disconnect();
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsXBLPrototypeHandler::EnsureEventHandler(AutoJSAPI& jsapi, nsIAtom* aName,
|
|
JS::MutableHandle<JSObject*> aHandler)
|
|
{
|
|
JSContext* cx = jsapi.cx();
|
|
|
|
// Check to see if we've already compiled this
|
|
JS::Rooted<JSObject*> globalObject(cx, JS::CurrentGlobalOrNull(cx));
|
|
nsCOMPtr<nsPIDOMWindow> pWindow = xpc::WindowOrNull(globalObject);
|
|
if (pWindow) {
|
|
JS::Rooted<JSObject*> cachedHandler(cx, pWindow->GetCachedXBLPrototypeHandler(this));
|
|
if (cachedHandler) {
|
|
JS::ExposeObjectToActiveJS(cachedHandler);
|
|
aHandler.set(cachedHandler);
|
|
NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE);
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
// Ensure that we have something to compile
|
|
nsDependentString handlerText(mHandlerText);
|
|
NS_ENSURE_TRUE(!handlerText.IsEmpty(), NS_ERROR_FAILURE);
|
|
|
|
JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI());
|
|
|
|
JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, addonId));
|
|
NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
nsAutoCString bindingURI;
|
|
mPrototypeBinding->DocURI()->GetSpec(bindingURI);
|
|
|
|
uint32_t argCount;
|
|
const char **argNames;
|
|
nsContentUtils::GetEventArgNames(kNameSpaceID_XBL, aName, false, &argCount,
|
|
&argNames);
|
|
|
|
// Compile the event handler in the xbl scope.
|
|
JSAutoCompartment ac(cx, scopeObject);
|
|
JS::CompileOptions options(cx);
|
|
options.setFileAndLine(bindingURI.get(), mLineNumber)
|
|
.setVersion(JSVERSION_LATEST);
|
|
|
|
JS::Rooted<JSObject*> handlerFun(cx);
|
|
JS::AutoObjectVector emptyVector(cx);
|
|
nsresult rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options,
|
|
nsAtomCString(aName), argCount,
|
|
argNames, handlerText,
|
|
handlerFun.address());
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
NS_ENSURE_TRUE(handlerFun, NS_ERROR_FAILURE);
|
|
|
|
// Wrap the handler into the content scope, since we're about to stash it
|
|
// on the DOM window and such.
|
|
JSAutoCompartment ac2(cx, globalObject);
|
|
bool ok = JS_WrapObject(cx, &handlerFun);
|
|
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
|
|
aHandler.set(handlerFun);
|
|
NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE);
|
|
|
|
if (pWindow) {
|
|
pWindow->CacheXBLPrototypeHandler(this, aHandler);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsXBLPrototypeHandler::DispatchXBLCommand(EventTarget* aTarget, nsIDOMEvent* aEvent)
|
|
{
|
|
// This is a special-case optimization to make command handling fast.
|
|
// It isn't really a part of XBL, but it helps speed things up.
|
|
|
|
if (aEvent) {
|
|
// See if preventDefault has been set. If so, don't execute.
|
|
bool preventDefault = false;
|
|
aEvent->GetDefaultPrevented(&preventDefault);
|
|
if (preventDefault) {
|
|
return NS_OK;
|
|
}
|
|
bool dispatchStopped = aEvent->IsDispatchStopped();
|
|
if (dispatchStopped) {
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
// Instead of executing JS, let's get the controller for the bound
|
|
// element and call doCommand on it.
|
|
nsCOMPtr<nsIController> controller;
|
|
|
|
nsCOMPtr<nsPIDOMWindow> privateWindow;
|
|
nsCOMPtr<nsPIWindowRoot> windowRoot(do_QueryInterface(aTarget));
|
|
if (windowRoot) {
|
|
privateWindow = windowRoot->GetWindow();
|
|
}
|
|
else {
|
|
privateWindow = do_QueryInterface(aTarget);
|
|
if (!privateWindow) {
|
|
nsCOMPtr<nsIContent> elt(do_QueryInterface(aTarget));
|
|
nsCOMPtr<nsIDocument> doc;
|
|
// XXXbz sXBL/XBL2 issue -- this should be the "scope doc" or
|
|
// something... whatever we use when wrapping DOM nodes
|
|
// normally. It's not clear that the owner doc is the right
|
|
// thing.
|
|
if (elt)
|
|
doc = elt->OwnerDoc();
|
|
|
|
if (!doc)
|
|
doc = do_QueryInterface(aTarget);
|
|
|
|
if (!doc)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
privateWindow = doc->GetWindow();
|
|
if (!privateWindow)
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
windowRoot = privateWindow->GetTopWindowRoot();
|
|
}
|
|
|
|
NS_LossyConvertUTF16toASCII command(mHandlerText);
|
|
if (windowRoot)
|
|
windowRoot->GetControllerForCommand(command.get(), getter_AddRefs(controller));
|
|
else
|
|
controller = GetController(aTarget); // We're attached to the receiver possibly.
|
|
|
|
// We are the default action for this command.
|
|
// Stop any other default action from executing.
|
|
aEvent->PreventDefault();
|
|
|
|
if (mEventName == nsGkAtoms::keypress &&
|
|
mDetail == nsIDOMKeyEvent::DOM_VK_SPACE &&
|
|
mMisc == 1) {
|
|
// get the focused element so that we can pageDown only at
|
|
// certain times.
|
|
|
|
nsCOMPtr<nsPIDOMWindow> windowToCheck;
|
|
if (windowRoot)
|
|
windowToCheck = windowRoot->GetWindow();
|
|
else
|
|
windowToCheck = privateWindow->GetPrivateRoot();
|
|
|
|
nsCOMPtr<nsIContent> focusedContent;
|
|
if (windowToCheck) {
|
|
nsCOMPtr<nsPIDOMWindow> focusedWindow;
|
|
focusedContent =
|
|
nsFocusManager::GetFocusedDescendant(windowToCheck, true, getter_AddRefs(focusedWindow));
|
|
}
|
|
|
|
// If the focus is in an editable region, don't scroll.
|
|
if (focusedContent && focusedContent->IsEditable()) {
|
|
return NS_OK;
|
|
}
|
|
|
|
// If the focus is in a form control, don't scroll.
|
|
for (nsIContent* c = focusedContent; c; c = c->GetParent()) {
|
|
nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(c);
|
|
if (formControl) {
|
|
return NS_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (controller)
|
|
controller->DoCommand(command.get());
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsXBLPrototypeHandler::DispatchXULKeyCommand(nsIDOMEvent* aEvent)
|
|
{
|
|
nsCOMPtr<nsIContent> handlerElement = GetHandlerElement();
|
|
NS_ENSURE_STATE(handlerElement);
|
|
if (handlerElement->AttrValueIs(kNameSpaceID_None,
|
|
nsGkAtoms::disabled,
|
|
nsGkAtoms::_true,
|
|
eCaseMatters)) {
|
|
// Don't dispatch command events for disabled keys.
|
|
return NS_OK;
|
|
}
|
|
|
|
aEvent->PreventDefault();
|
|
|
|
// Copy the modifiers from the key event.
|
|
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
|
|
if (!keyEvent) {
|
|
NS_ERROR("Trying to execute a key handler for a non-key event!");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// XXX We should use mozilla::Modifiers for supporting all modifiers.
|
|
|
|
bool isAlt = false;
|
|
bool isControl = false;
|
|
bool isShift = false;
|
|
bool isMeta = false;
|
|
keyEvent->GetAltKey(&isAlt);
|
|
keyEvent->GetCtrlKey(&isControl);
|
|
keyEvent->GetShiftKey(&isShift);
|
|
keyEvent->GetMetaKey(&isMeta);
|
|
|
|
nsContentUtils::DispatchXULCommand(handlerElement, true,
|
|
nullptr, nullptr,
|
|
isControl, isAlt, isShift, isMeta);
|
|
return NS_OK;
|
|
}
|
|
|
|
already_AddRefed<nsIAtom>
|
|
nsXBLPrototypeHandler::GetEventName()
|
|
{
|
|
nsCOMPtr<nsIAtom> eventName = mEventName;
|
|
return eventName.forget();
|
|
}
|
|
|
|
already_AddRefed<nsIController>
|
|
nsXBLPrototypeHandler::GetController(EventTarget* aTarget)
|
|
{
|
|
// XXX Fix this so there's a generic interface that describes controllers,
|
|
// This code should have no special knowledge of what objects might have controllers.
|
|
nsCOMPtr<nsIControllers> controllers;
|
|
|
|
nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(aTarget));
|
|
if (xulElement)
|
|
xulElement->GetControllers(getter_AddRefs(controllers));
|
|
|
|
if (!controllers) {
|
|
nsCOMPtr<nsIDOMHTMLTextAreaElement> htmlTextArea(do_QueryInterface(aTarget));
|
|
if (htmlTextArea)
|
|
htmlTextArea->GetControllers(getter_AddRefs(controllers));
|
|
}
|
|
|
|
if (!controllers) {
|
|
nsCOMPtr<nsIDOMHTMLInputElement> htmlInputElement(do_QueryInterface(aTarget));
|
|
if (htmlInputElement)
|
|
htmlInputElement->GetControllers(getter_AddRefs(controllers));
|
|
}
|
|
|
|
if (!controllers) {
|
|
nsCOMPtr<nsIDOMWindow> domWindow(do_QueryInterface(aTarget));
|
|
if (domWindow)
|
|
domWindow->GetControllers(getter_AddRefs(controllers));
|
|
}
|
|
|
|
// Return the first controller.
|
|
// XXX This code should be checking the command name and using supportscommand and
|
|
// iscommandenabled.
|
|
nsCOMPtr<nsIController> controller;
|
|
if (controllers) {
|
|
controllers->GetControllerAt(0, getter_AddRefs(controller));
|
|
}
|
|
|
|
return controller.forget();
|
|
}
|
|
|
|
bool
|
|
nsXBLPrototypeHandler::KeyEventMatched(
|
|
nsIDOMKeyEvent* aKeyEvent,
|
|
uint32_t aCharCode,
|
|
const IgnoreModifierState& aIgnoreModifierState)
|
|
{
|
|
if (mDetail != -1) {
|
|
// Get the keycode or charcode of the key event.
|
|
uint32_t code;
|
|
|
|
if (mMisc) {
|
|
if (aCharCode)
|
|
code = aCharCode;
|
|
else
|
|
aKeyEvent->GetCharCode(&code);
|
|
if (IS_IN_BMP(code))
|
|
code = ToLowerCase(char16_t(code));
|
|
}
|
|
else
|
|
aKeyEvent->GetKeyCode(&code);
|
|
|
|
if (code != uint32_t(mDetail))
|
|
return false;
|
|
}
|
|
|
|
return ModifiersMatchMask(aKeyEvent, aIgnoreModifierState);
|
|
}
|
|
|
|
bool
|
|
nsXBLPrototypeHandler::MouseEventMatched(nsIDOMMouseEvent* aMouseEvent)
|
|
{
|
|
if (mDetail == -1 && mMisc == 0 && (mKeyMask & cAllModifiers) == 0)
|
|
return true; // No filters set up. It's generic.
|
|
|
|
int16_t button;
|
|
aMouseEvent->GetButton(&button);
|
|
if (mDetail != -1 && (button != mDetail))
|
|
return false;
|
|
|
|
int32_t clickcount;
|
|
aMouseEvent->GetDetail(&clickcount);
|
|
if (mMisc != 0 && (clickcount != mMisc))
|
|
return false;
|
|
|
|
return ModifiersMatchMask(aMouseEvent, IgnoreModifierState());
|
|
}
|
|
|
|
struct keyCodeData {
|
|
const char* str;
|
|
uint16_t strlength;
|
|
uint16_t keycode;
|
|
};
|
|
|
|
// All of these must be uppercase, since the function below does
|
|
// case-insensitive comparison by converting to uppercase.
|
|
// XXX: be sure to check this periodically for new symbol additions!
|
|
static const keyCodeData gKeyCodes[] = {
|
|
|
|
#define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) \
|
|
{ #aDOMKeyName, sizeof(#aDOMKeyName) - 1, aDOMKeyCode }
|
|
#include "mozilla/VirtualKeyCodeList.h"
|
|
#undef NS_DEFINE_VK
|
|
};
|
|
|
|
int32_t nsXBLPrototypeHandler::GetMatchingKeyCode(const nsAString& aKeyName)
|
|
{
|
|
nsAutoCString keyName;
|
|
keyName.AssignWithConversion(aKeyName);
|
|
ToUpperCase(keyName); // We want case-insensitive comparison with data
|
|
// stored as uppercase.
|
|
|
|
uint32_t keyNameLength = keyName.Length();
|
|
const char* keyNameStr = keyName.get();
|
|
for (uint16_t i = 0; i < (sizeof(gKeyCodes) / sizeof(gKeyCodes[0])); ++i)
|
|
if (keyNameLength == gKeyCodes[i].strlength &&
|
|
!nsCRT::strcmp(gKeyCodes[i].str, keyNameStr))
|
|
return gKeyCodes[i].keycode;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t nsXBLPrototypeHandler::KeyToMask(int32_t key)
|
|
{
|
|
switch (key)
|
|
{
|
|
case nsIDOMKeyEvent::DOM_VK_META:
|
|
return cMeta | cMetaMask;
|
|
|
|
case nsIDOMKeyEvent::DOM_VK_WIN:
|
|
return cOS | cOSMask;
|
|
|
|
case nsIDOMKeyEvent::DOM_VK_ALT:
|
|
return cAlt | cAltMask;
|
|
|
|
case nsIDOMKeyEvent::DOM_VK_CONTROL:
|
|
default:
|
|
return cControl | cControlMask;
|
|
}
|
|
return cControl | cControlMask; // for warning avoidance
|
|
}
|
|
|
|
// static
|
|
int32_t
|
|
nsXBLPrototypeHandler::AccelKeyMask()
|
|
{
|
|
switch (WidgetInputEvent::AccelModifier()) {
|
|
case MODIFIER_ALT:
|
|
return KeyToMask(nsIDOMKeyEvent::DOM_VK_ALT);
|
|
case MODIFIER_CONTROL:
|
|
return KeyToMask(nsIDOMKeyEvent::DOM_VK_CONTROL);
|
|
case MODIFIER_META:
|
|
return KeyToMask(nsIDOMKeyEvent::DOM_VK_META);
|
|
case MODIFIER_OS:
|
|
return KeyToMask(nsIDOMKeyEvent::DOM_VK_WIN);
|
|
default:
|
|
MOZ_CRASH("Handle the new result of WidgetInputEvent::AccelModifier()");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
nsXBLPrototypeHandler::GetEventType(nsAString& aEvent)
|
|
{
|
|
nsCOMPtr<nsIContent> handlerElement = GetHandlerElement();
|
|
if (!handlerElement) {
|
|
aEvent.Truncate();
|
|
return;
|
|
}
|
|
handlerElement->GetAttr(kNameSpaceID_None, nsGkAtoms::event, aEvent);
|
|
|
|
if (aEvent.IsEmpty() && (mType & NS_HANDLER_TYPE_XUL))
|
|
// If no type is specified for a XUL <key> element, let's assume that we're "keypress".
|
|
aEvent.AssignLiteral("keypress");
|
|
}
|
|
|
|
void
|
|
nsXBLPrototypeHandler::ConstructPrototype(nsIContent* aKeyElement,
|
|
const char16_t* aEvent,
|
|
const char16_t* aPhase,
|
|
const char16_t* aAction,
|
|
const char16_t* aCommand,
|
|
const char16_t* aKeyCode,
|
|
const char16_t* aCharCode,
|
|
const char16_t* aModifiers,
|
|
const char16_t* aButton,
|
|
const char16_t* aClickCount,
|
|
const char16_t* aGroup,
|
|
const char16_t* aPreventDefault,
|
|
const char16_t* aAllowUntrusted)
|
|
{
|
|
mType = 0;
|
|
|
|
if (aKeyElement) {
|
|
mType |= NS_HANDLER_TYPE_XUL;
|
|
nsCOMPtr<nsIWeakReference> weak = do_GetWeakReference(aKeyElement);
|
|
if (!weak) {
|
|
return;
|
|
}
|
|
weak.swap(mHandlerElement);
|
|
}
|
|
else {
|
|
mType |= aCommand ? NS_HANDLER_TYPE_XBL_COMMAND : NS_HANDLER_TYPE_XBL_JS;
|
|
mHandlerText = nullptr;
|
|
}
|
|
|
|
mDetail = -1;
|
|
mMisc = 0;
|
|
mKeyMask = 0;
|
|
mPhase = NS_PHASE_BUBBLING;
|
|
|
|
if (aAction)
|
|
mHandlerText = ToNewUnicode(nsDependentString(aAction));
|
|
else if (aCommand)
|
|
mHandlerText = ToNewUnicode(nsDependentString(aCommand));
|
|
|
|
nsAutoString event(aEvent);
|
|
if (event.IsEmpty()) {
|
|
if (mType & NS_HANDLER_TYPE_XUL)
|
|
GetEventType(event);
|
|
if (event.IsEmpty())
|
|
return;
|
|
}
|
|
|
|
mEventName = NS_Atomize(event);
|
|
|
|
if (aPhase) {
|
|
const nsDependentString phase(aPhase);
|
|
if (phase.EqualsLiteral("capturing"))
|
|
mPhase = NS_PHASE_CAPTURING;
|
|
else if (phase.EqualsLiteral("target"))
|
|
mPhase = NS_PHASE_TARGET;
|
|
}
|
|
|
|
// Button and clickcount apply only to XBL handlers and don't apply to XUL key
|
|
// handlers.
|
|
if (aButton && *aButton)
|
|
mDetail = *aButton - '0';
|
|
|
|
if (aClickCount && *aClickCount)
|
|
mMisc = *aClickCount - '0';
|
|
|
|
// Modifiers are supported by both types of handlers (XUL and XBL).
|
|
nsAutoString modifiers(aModifiers);
|
|
if (mType & NS_HANDLER_TYPE_XUL)
|
|
aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiers);
|
|
|
|
if (!modifiers.IsEmpty()) {
|
|
mKeyMask = cAllModifiers;
|
|
char* str = ToNewCString(modifiers);
|
|
char* newStr;
|
|
char* token = nsCRT::strtok( str, ", \t", &newStr );
|
|
while( token != nullptr ) {
|
|
if (PL_strcmp(token, "shift") == 0)
|
|
mKeyMask |= cShift | cShiftMask;
|
|
else if (PL_strcmp(token, "alt") == 0)
|
|
mKeyMask |= cAlt | cAltMask;
|
|
else if (PL_strcmp(token, "meta") == 0)
|
|
mKeyMask |= cMeta | cMetaMask;
|
|
else if (PL_strcmp(token, "os") == 0)
|
|
mKeyMask |= cOS | cOSMask;
|
|
else if (PL_strcmp(token, "control") == 0)
|
|
mKeyMask |= cControl | cControlMask;
|
|
else if (PL_strcmp(token, "accel") == 0)
|
|
mKeyMask |= AccelKeyMask();
|
|
else if (PL_strcmp(token, "access") == 0)
|
|
mKeyMask |= KeyToMask(kMenuAccessKey);
|
|
else if (PL_strcmp(token, "any") == 0)
|
|
mKeyMask &= ~(mKeyMask << 5);
|
|
|
|
token = nsCRT::strtok( newStr, ", \t", &newStr );
|
|
}
|
|
|
|
free(str);
|
|
}
|
|
|
|
nsAutoString key(aCharCode);
|
|
if (key.IsEmpty()) {
|
|
if (mType & NS_HANDLER_TYPE_XUL) {
|
|
aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::key, key);
|
|
if (key.IsEmpty())
|
|
aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::charcode, key);
|
|
}
|
|
}
|
|
|
|
if (!key.IsEmpty()) {
|
|
if (mKeyMask == 0)
|
|
mKeyMask = cAllModifiers;
|
|
ToLowerCase(key);
|
|
|
|
// We have a charcode.
|
|
mMisc = 1;
|
|
mDetail = key[0];
|
|
const uint8_t GTK2Modifiers = cShift | cControl | cShiftMask | cControlMask;
|
|
if ((mKeyMask & GTK2Modifiers) == GTK2Modifiers &&
|
|
modifiers.First() != char16_t(',') &&
|
|
(mDetail == 'u' || mDetail == 'U'))
|
|
ReportKeyConflict(key.get(), modifiers.get(), aKeyElement, "GTK2Conflict");
|
|
const uint8_t WinModifiers = cControl | cAlt | cControlMask | cAltMask;
|
|
if ((mKeyMask & WinModifiers) == WinModifiers &&
|
|
modifiers.First() != char16_t(',') &&
|
|
(('A' <= mDetail && mDetail <= 'Z') ||
|
|
('a' <= mDetail && mDetail <= 'z')))
|
|
ReportKeyConflict(key.get(), modifiers.get(), aKeyElement, "WinConflict");
|
|
}
|
|
else {
|
|
key.Assign(aKeyCode);
|
|
if (mType & NS_HANDLER_TYPE_XUL)
|
|
aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, key);
|
|
|
|
if (!key.IsEmpty()) {
|
|
if (mKeyMask == 0)
|
|
mKeyMask = cAllModifiers;
|
|
mDetail = GetMatchingKeyCode(key);
|
|
}
|
|
}
|
|
|
|
if (aGroup && nsDependentString(aGroup).EqualsLiteral("system"))
|
|
mType |= NS_HANDLER_TYPE_SYSTEM;
|
|
|
|
if (aPreventDefault &&
|
|
nsDependentString(aPreventDefault).EqualsLiteral("true"))
|
|
mType |= NS_HANDLER_TYPE_PREVENTDEFAULT;
|
|
|
|
if (aAllowUntrusted) {
|
|
mType |= NS_HANDLER_HAS_ALLOW_UNTRUSTED_ATTR;
|
|
if (nsDependentString(aAllowUntrusted).EqualsLiteral("true")) {
|
|
mType |= NS_HANDLER_ALLOW_UNTRUSTED;
|
|
} else {
|
|
mType &= ~NS_HANDLER_ALLOW_UNTRUSTED;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
nsXBLPrototypeHandler::ReportKeyConflict(const char16_t* aKey, const char16_t* aModifiers, nsIContent* aKeyElement, const char *aMessageName)
|
|
{
|
|
nsCOMPtr<nsIDocument> doc;
|
|
if (mPrototypeBinding) {
|
|
nsXBLDocumentInfo* docInfo = mPrototypeBinding->XBLDocumentInfo();
|
|
if (docInfo) {
|
|
doc = docInfo->GetDocument();
|
|
}
|
|
} else if (aKeyElement) {
|
|
doc = aKeyElement->OwnerDoc();
|
|
}
|
|
|
|
const char16_t* params[] = { aKey, aModifiers };
|
|
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
|
NS_LITERAL_CSTRING("XBL Prototype Handler"), doc,
|
|
nsContentUtils::eXBL_PROPERTIES,
|
|
aMessageName,
|
|
params, ArrayLength(params),
|
|
nullptr, EmptyString(), mLineNumber);
|
|
}
|
|
|
|
bool
|
|
nsXBLPrototypeHandler::ModifiersMatchMask(
|
|
nsIDOMUIEvent* aEvent,
|
|
const IgnoreModifierState& aIgnoreModifierState)
|
|
{
|
|
WidgetInputEvent* inputEvent = aEvent->AsEvent()->WidgetEventPtr()->AsInputEvent();
|
|
NS_ENSURE_TRUE(inputEvent, false);
|
|
|
|
if (mKeyMask & cMetaMask) {
|
|
if (inputEvent->IsMeta() != ((mKeyMask & cMeta) != 0)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ((mKeyMask & cOSMask) && !aIgnoreModifierState.mOS) {
|
|
if (inputEvent->IsOS() != ((mKeyMask & cOS) != 0)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (mKeyMask & cShiftMask && !aIgnoreModifierState.mShift) {
|
|
if (inputEvent->IsShift() != ((mKeyMask & cShift) != 0)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (mKeyMask & cAltMask) {
|
|
if (inputEvent->IsAlt() != ((mKeyMask & cAlt) != 0)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (mKeyMask & cControlMask) {
|
|
if (inputEvent->IsControl() != ((mKeyMask & cControl) != 0)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
nsresult
|
|
nsXBLPrototypeHandler::Read(nsIObjectInputStream* aStream)
|
|
{
|
|
AssertInCompilationScope();
|
|
nsresult rv = aStream->Read8(&mPhase);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aStream->Read8(&mType);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aStream->Read8(&mMisc);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = aStream->Read32(reinterpret_cast<uint32_t*>(&mKeyMask));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
uint32_t detail;
|
|
rv = aStream->Read32(&detail);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
mDetail = detail;
|
|
|
|
nsAutoString name;
|
|
rv = aStream->ReadString(name);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
mEventName = NS_Atomize(name);
|
|
|
|
rv = aStream->Read32(&mLineNumber);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoString handlerText;
|
|
rv = aStream->ReadString(handlerText);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (!handlerText.IsEmpty())
|
|
mHandlerText = ToNewUnicode(handlerText);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsXBLPrototypeHandler::Write(nsIObjectOutputStream* aStream)
|
|
{
|
|
AssertInCompilationScope();
|
|
// Make sure we don't write out NS_HANDLER_TYPE_XUL types, as they are used
|
|
// for <keyset> elements.
|
|
if ((mType & NS_HANDLER_TYPE_XUL) || !mEventName)
|
|
return NS_OK;
|
|
|
|
XBLBindingSerializeDetails type = XBLBinding_Serialize_Handler;
|
|
|
|
nsresult rv = aStream->Write8(type);
|
|
rv = aStream->Write8(mPhase);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aStream->Write8(mType);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aStream->Write8(mMisc);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aStream->Write32(static_cast<uint32_t>(mKeyMask));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aStream->Write32(mDetail);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = aStream->WriteWStringZ(nsDependentAtomString(mEventName).get());
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = aStream->Write32(mLineNumber);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return aStream->WriteWStringZ(mHandlerText ? mHandlerText : MOZ_UTF16(""));
|
|
}
|