Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "mozilla/ArrayUtils.h"
8 :
9 : #include "nsCOMPtr.h"
10 : #include "nsQueryObject.h"
11 : #include "nsXBLPrototypeHandler.h"
12 : #include "nsXBLPrototypeBinding.h"
13 : #include "nsContentUtils.h"
14 : #include "nsGlobalWindow.h"
15 : #include "nsGlobalWindowCommands.h"
16 : #include "nsIContent.h"
17 : #include "nsIAtom.h"
18 : #include "nsIDOMKeyEvent.h"
19 : #include "nsIDOMMouseEvent.h"
20 : #include "nsNameSpaceManager.h"
21 : #include "nsIDocument.h"
22 : #include "nsIController.h"
23 : #include "nsIControllers.h"
24 : #include "nsXULElement.h"
25 : #include "nsIURI.h"
26 : #include "nsIDOMHTMLTextAreaElement.h"
27 : #include "nsIDOMHTMLInputElement.h"
28 : #include "nsFocusManager.h"
29 : #include "nsIFormControl.h"
30 : #include "nsIDOMEventListener.h"
31 : #include "nsPIDOMWindow.h"
32 : #include "nsPIWindowRoot.h"
33 : #include "nsIDOMWindow.h"
34 : #include "nsIServiceManager.h"
35 : #include "nsIScriptError.h"
36 : #include "nsXPIDLString.h"
37 : #include "nsReadableUtils.h"
38 : #include "nsGkAtoms.h"
39 : #include "nsIXPConnect.h"
40 : #include "mozilla/AddonPathService.h"
41 : #include "nsDOMCID.h"
42 : #include "nsUnicharUtils.h"
43 : #include "nsCRT.h"
44 : #include "nsXBLEventHandler.h"
45 : #include "nsXBLSerialize.h"
46 : #include "nsJSUtils.h"
47 : #include "mozilla/BasicEvents.h"
48 : #include "mozilla/JSEventHandler.h"
49 : #include "mozilla/Preferences.h"
50 : #include "mozilla/TextEvents.h"
51 : #include "mozilla/dom/Element.h"
52 : #include "mozilla/dom/EventHandlerBinding.h"
53 : #include "mozilla/dom/ScriptSettings.h"
54 : #include "mozilla/layers/KeyboardMap.h"
55 : #include "xpcpublic.h"
56 :
57 : using namespace mozilla;
58 : using namespace mozilla::dom;
59 : using namespace mozilla::layers;
60 :
61 : uint32_t nsXBLPrototypeHandler::gRefCnt = 0;
62 :
63 : int32_t nsXBLPrototypeHandler::kMenuAccessKey = -1;
64 :
65 : const int32_t nsXBLPrototypeHandler::cShift = (1<<0);
66 : const int32_t nsXBLPrototypeHandler::cAlt = (1<<1);
67 : const int32_t nsXBLPrototypeHandler::cControl = (1<<2);
68 : const int32_t nsXBLPrototypeHandler::cMeta = (1<<3);
69 : const int32_t nsXBLPrototypeHandler::cOS = (1<<4);
70 :
71 : const int32_t nsXBLPrototypeHandler::cShiftMask = (1<<5);
72 : const int32_t nsXBLPrototypeHandler::cAltMask = (1<<6);
73 : const int32_t nsXBLPrototypeHandler::cControlMask = (1<<7);
74 : const int32_t nsXBLPrototypeHandler::cMetaMask = (1<<8);
75 : const int32_t nsXBLPrototypeHandler::cOSMask = (1<<9);
76 :
77 : const int32_t nsXBLPrototypeHandler::cAllModifiers =
78 : cShiftMask | cAltMask | cControlMask | cMetaMask | cOSMask;
79 :
80 4 : nsXBLPrototypeHandler::nsXBLPrototypeHandler(const char16_t* aEvent,
81 : const char16_t* aPhase,
82 : const char16_t* aAction,
83 : const char16_t* aCommand,
84 : const char16_t* aKeyCode,
85 : const char16_t* aCharCode,
86 : const char16_t* aModifiers,
87 : const char16_t* aButton,
88 : const char16_t* aClickCount,
89 : const char16_t* aGroup,
90 : const char16_t* aPreventDefault,
91 : const char16_t* aAllowUntrusted,
92 : nsXBLPrototypeBinding* aBinding,
93 4 : uint32_t aLineNumber)
94 : : mHandlerText(nullptr),
95 : mLineNumber(aLineNumber),
96 : mReserved(false),
97 : mNextHandler(nullptr),
98 4 : mPrototypeBinding(aBinding)
99 : {
100 4 : Init();
101 :
102 : ConstructPrototype(nullptr, aEvent, aPhase, aAction, aCommand, aKeyCode,
103 : aCharCode, aModifiers, aButton, aClickCount,
104 4 : aGroup, aPreventDefault, aAllowUntrusted);
105 4 : }
106 :
107 0 : nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement, bool aReserved)
108 : : mHandlerElement(nullptr),
109 : mLineNumber(0),
110 : mReserved(aReserved),
111 : mNextHandler(nullptr),
112 0 : mPrototypeBinding(nullptr)
113 : {
114 0 : Init();
115 :
116 : // Make sure our prototype is initialized.
117 0 : ConstructPrototype(aHandlerElement);
118 0 : }
119 :
120 280 : nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsXBLPrototypeBinding* aBinding)
121 : : mHandlerText(nullptr),
122 : mLineNumber(0),
123 : mReserved(false),
124 : mNextHandler(nullptr),
125 280 : mPrototypeBinding(aBinding)
126 : {
127 280 : Init();
128 280 : }
129 :
130 0 : nsXBLPrototypeHandler::~nsXBLPrototypeHandler()
131 : {
132 0 : --gRefCnt;
133 0 : if (mType & NS_HANDLER_TYPE_XUL) {
134 0 : NS_IF_RELEASE(mHandlerElement);
135 0 : } else if (mHandlerText) {
136 0 : free(mHandlerText);
137 : }
138 :
139 : // We own the next handler in the chain, so delete it now.
140 0 : NS_CONTENT_DELETE_LIST_MEMBER(nsXBLPrototypeHandler, this, mNextHandler);
141 0 : }
142 :
143 : bool
144 0 : nsXBLPrototypeHandler::TryConvertToKeyboardShortcut(
145 : KeyboardShortcut* aOut) const
146 : {
147 : // Convert the event type
148 : KeyboardInput::KeyboardEventType eventType;
149 :
150 0 : if (mEventName == nsGkAtoms::keydown) {
151 0 : eventType = KeyboardInput::KEY_DOWN;
152 0 : } else if (mEventName == nsGkAtoms::keypress) {
153 0 : eventType = KeyboardInput::KEY_PRESS;
154 0 : } else if (mEventName == nsGkAtoms::keyup) {
155 0 : eventType = KeyboardInput::KEY_UP;
156 : } else {
157 0 : return false;
158 : }
159 :
160 : // Convert the modifiers
161 0 : Modifiers modifiersMask = GetModifiers();
162 0 : Modifiers modifiers = GetModifiersMask();
163 :
164 : // Mask away any bits that won't be compared
165 0 : modifiers &= modifiersMask;
166 :
167 : // Convert the keyCode or charCode
168 : uint32_t keyCode;
169 : uint32_t charCode;
170 :
171 0 : if (mMisc) {
172 0 : keyCode = 0;
173 0 : charCode = static_cast<uint32_t>(mDetail);
174 : } else {
175 0 : keyCode = static_cast<uint32_t>(mDetail);
176 0 : charCode = 0;
177 : }
178 :
179 0 : NS_LossyConvertUTF16toASCII commandText(mHandlerText);
180 0 : KeyboardScrollAction action;
181 0 : if (!nsGlobalWindowCommands::FindScrollCommand(commandText.get(), &action)) {
182 : // This action doesn't represent a scroll so we need to create a dispatch
183 : // to content keyboard shortcut so APZ handles this command correctly
184 0 : *aOut = KeyboardShortcut(eventType,
185 : keyCode,
186 : charCode,
187 : modifiers,
188 0 : modifiersMask);
189 0 : return true;
190 : }
191 :
192 : // This prototype is a command which represents a scroll action, so create
193 : // a keyboard shortcut to handle it
194 0 : *aOut = KeyboardShortcut(eventType,
195 : keyCode,
196 : charCode,
197 : modifiers,
198 : modifiersMask,
199 0 : action);
200 0 : return true;
201 : }
202 :
203 : already_AddRefed<nsIContent>
204 0 : nsXBLPrototypeHandler::GetHandlerElement()
205 : {
206 0 : if (mType & NS_HANDLER_TYPE_XUL) {
207 0 : nsCOMPtr<nsIContent> element = do_QueryReferent(mHandlerElement);
208 0 : return element.forget();
209 : }
210 :
211 0 : return nullptr;
212 : }
213 :
214 : void
215 0 : nsXBLPrototypeHandler::AppendHandlerText(const nsAString& aText)
216 : {
217 0 : if (mHandlerText) {
218 : // Append our text to the existing text.
219 0 : char16_t* temp = mHandlerText;
220 0 : mHandlerText = ToNewUnicode(nsDependentString(temp) + aText);
221 0 : free(temp);
222 : }
223 : else {
224 0 : mHandlerText = ToNewUnicode(aText);
225 : }
226 0 : }
227 :
228 : /////////////////////////////////////////////////////////////////////////////
229 : // Get the menu access key from prefs.
230 : // XXX Eventually pick up using CSS3 key-equivalent property or somesuch
231 : void
232 2 : nsXBLPrototypeHandler::InitAccessKeys()
233 : {
234 2 : if (kMenuAccessKey >= 0) {
235 0 : return;
236 : }
237 :
238 : // Compiled-in defaults, in case we can't get the pref --
239 : // mac doesn't have menu shortcuts, other platforms use alt.
240 : #ifdef XP_MACOSX
241 : kMenuAccessKey = 0;
242 : #else
243 2 : kMenuAccessKey = nsIDOMKeyEvent::DOM_VK_ALT;
244 : #endif
245 :
246 : // Get the menu access key value from prefs, overriding the default:
247 2 : kMenuAccessKey =
248 2 : Preferences::GetInt("ui.key.menuAccessKey", kMenuAccessKey);
249 : }
250 :
251 : nsresult
252 6 : nsXBLPrototypeHandler::ExecuteHandler(EventTarget* aTarget,
253 : nsIDOMEvent* aEvent)
254 : {
255 6 : nsresult rv = NS_ERROR_FAILURE;
256 :
257 : // Prevent default action?
258 6 : if (mType & NS_HANDLER_TYPE_PREVENTDEFAULT) {
259 0 : aEvent->PreventDefault();
260 : // If we prevent default, then it's okay for
261 : // mHandlerElement and mHandlerText to be null
262 0 : rv = NS_OK;
263 : }
264 :
265 6 : if (!mHandlerElement) // This works for both types of handlers. In both cases, the union's var should be defined.
266 0 : return rv;
267 :
268 : // See if our event receiver is a content node (and not us).
269 6 : bool isXULKey = !!(mType & NS_HANDLER_TYPE_XUL);
270 6 : bool isXBLCommand = !!(mType & NS_HANDLER_TYPE_XBL_COMMAND);
271 6 : NS_ASSERTION(!(isXULKey && isXBLCommand),
272 : "can't be both a key and xbl command handler");
273 :
274 : // XUL handlers and commands shouldn't be triggered by non-trusted
275 : // events.
276 6 : if (isXULKey || isXBLCommand) {
277 0 : bool trustedEvent = false;
278 0 : aEvent->GetIsTrusted(&trustedEvent);
279 :
280 0 : if (!trustedEvent)
281 0 : return NS_OK;
282 : }
283 :
284 6 : if (isXBLCommand) {
285 0 : return DispatchXBLCommand(aTarget, aEvent);
286 : }
287 :
288 : // If we're executing on a XUL key element, just dispatch a command
289 : // event at the element. It will take care of retargeting it to its
290 : // command element, if applicable, and executing the event handler.
291 6 : if (isXULKey) {
292 0 : return DispatchXULKeyCommand(aEvent);
293 : }
294 :
295 : // Look for a compiled handler on the element.
296 : // Should be compiled and bound with "on" in front of the name.
297 18 : nsCOMPtr<nsIAtom> onEventAtom = NS_Atomize(NS_LITERAL_STRING("onxbl") +
298 30 : nsDependentAtomString(mEventName));
299 :
300 : // Compile the handler and bind it to the element.
301 12 : nsCOMPtr<nsIScriptGlobalObject> boundGlobal;
302 12 : nsCOMPtr<nsPIWindowRoot> winRoot = do_QueryInterface(aTarget);
303 6 : if (winRoot) {
304 0 : if (nsCOMPtr<nsPIDOMWindowOuter> window = winRoot->GetWindow()) {
305 0 : nsPIDOMWindowInner* innerWindow = window->GetCurrentInnerWindow();
306 0 : NS_ENSURE_TRUE(innerWindow, NS_ERROR_UNEXPECTED);
307 :
308 0 : boundGlobal = do_QueryInterface(innerWindow->GetPrivateRoot());
309 : }
310 : }
311 6 : else boundGlobal = do_QueryInterface(aTarget);
312 :
313 6 : if (!boundGlobal) {
314 12 : nsCOMPtr<nsIDocument> boundDocument(do_QueryInterface(aTarget));
315 6 : if (!boundDocument) {
316 : // We must be an element.
317 12 : nsCOMPtr<nsIContent> content(do_QueryInterface(aTarget));
318 6 : if (!content)
319 0 : return NS_OK;
320 6 : boundDocument = content->OwnerDoc();
321 : }
322 :
323 6 : boundGlobal = do_QueryInterface(boundDocument->GetScopeObject());
324 : }
325 :
326 6 : if (!boundGlobal)
327 0 : return NS_OK;
328 :
329 : nsISupports *scriptTarget;
330 :
331 6 : if (winRoot) {
332 0 : scriptTarget = boundGlobal;
333 : } else {
334 6 : scriptTarget = aTarget;
335 : }
336 :
337 : // We're about to create a new JSEventHandler, which means that we need to
338 : // Initiatize an AutoJSAPI with aTarget's bound global to make sure any errors
339 : // are reported to the correct place.
340 12 : AutoJSAPI jsapi;
341 6 : if (NS_WARN_IF(!jsapi.Init(boundGlobal))) {
342 0 : return NS_OK;
343 : }
344 6 : JSContext* cx = jsapi.cx();
345 12 : JS::Rooted<JSObject*> handler(cx);
346 :
347 6 : rv = EnsureEventHandler(jsapi, onEventAtom, &handler);
348 6 : NS_ENSURE_SUCCESS(rv, rv);
349 :
350 6 : JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI());
351 :
352 12 : JS::Rooted<JSObject*> globalObject(cx, boundGlobal->GetGlobalJSObject());
353 12 : JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, addonId));
354 6 : NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
355 :
356 : // Bind it to the bound element. Note that if we're using a separate XBL scope,
357 : // we'll actually be binding the event handler to a cross-compartment wrapper
358 : // to the bound element's reflector.
359 :
360 : // First, enter our XBL scope. This is where the generic handler should have
361 : // been compiled, above.
362 12 : JSAutoCompartment ac(cx, scopeObject);
363 12 : JS::Rooted<JSObject*> genericHandler(cx, handler.get());
364 6 : bool ok = JS_WrapObject(cx, &genericHandler);
365 6 : NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
366 6 : MOZ_ASSERT(!js::IsCrossCompartmentWrapper(genericHandler));
367 :
368 : // Build a scope chain in the XBL scope.
369 12 : RefPtr<Element> targetElement = do_QueryObject(scriptTarget);
370 12 : JS::AutoObjectVector scopeChain(cx);
371 6 : ok = nsJSUtils::GetScopeChainForElement(cx, targetElement, scopeChain);
372 6 : NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
373 :
374 : // Next, clone the generic handler with our desired scope chain.
375 12 : JS::Rooted<JSObject*> bound(cx, JS::CloneFunctionObject(cx, genericHandler,
376 12 : scopeChain));
377 6 : NS_ENSURE_TRUE(bound, NS_ERROR_FAILURE);
378 :
379 : RefPtr<EventHandlerNonNull> handlerCallback =
380 18 : new EventHandlerNonNull(nullptr, bound, /* aIncumbentGlobal = */ nullptr);
381 :
382 12 : TypedEventHandler typedHandler(handlerCallback);
383 :
384 : // Execute it.
385 12 : nsCOMPtr<JSEventHandler> jsEventHandler;
386 6 : rv = NS_NewJSEventHandler(scriptTarget, onEventAtom,
387 : typedHandler,
388 12 : getter_AddRefs(jsEventHandler));
389 6 : NS_ENSURE_SUCCESS(rv, rv);
390 :
391 : // Handle the event.
392 6 : jsEventHandler->HandleEvent(aEvent);
393 6 : jsEventHandler->Disconnect();
394 6 : return NS_OK;
395 : }
396 :
397 : nsresult
398 6 : nsXBLPrototypeHandler::EnsureEventHandler(AutoJSAPI& jsapi, nsIAtom* aName,
399 : JS::MutableHandle<JSObject*> aHandler)
400 : {
401 6 : JSContext* cx = jsapi.cx();
402 :
403 : // Check to see if we've already compiled this
404 12 : JS::Rooted<JSObject*> globalObject(cx, JS::CurrentGlobalOrNull(cx));
405 12 : nsCOMPtr<nsPIDOMWindowInner> pWindow = xpc::WindowOrNull(globalObject)->AsInner();
406 6 : if (pWindow) {
407 10 : JS::Rooted<JSObject*> cachedHandler(cx, pWindow->GetCachedXBLPrototypeHandler(this));
408 6 : if (cachedHandler) {
409 2 : JS::ExposeObjectToActiveJS(cachedHandler);
410 2 : aHandler.set(cachedHandler);
411 2 : NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE);
412 2 : return NS_OK;
413 : }
414 : }
415 :
416 : // Ensure that we have something to compile
417 8 : nsDependentString handlerText(mHandlerText);
418 4 : NS_ENSURE_TRUE(!handlerText.IsEmpty(), NS_ERROR_FAILURE);
419 :
420 4 : JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI());
421 :
422 8 : JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, addonId));
423 4 : NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
424 :
425 8 : nsAutoCString bindingURI;
426 4 : nsresult rv = mPrototypeBinding->DocURI()->GetSpec(bindingURI);
427 4 : NS_ENSURE_SUCCESS(rv, rv);
428 :
429 : uint32_t argCount;
430 : const char **argNames;
431 : nsContentUtils::GetEventArgNames(kNameSpaceID_XBL, aName, false, &argCount,
432 4 : &argNames);
433 :
434 : // Compile the event handler in the xbl scope.
435 8 : JSAutoCompartment ac(cx, scopeObject);
436 8 : JS::CompileOptions options(cx);
437 4 : options.setFileAndLine(bindingURI.get(), mLineNumber)
438 4 : .setVersion(JSVERSION_LATEST);
439 :
440 8 : JS::Rooted<JSObject*> handlerFun(cx);
441 8 : JS::AutoObjectVector emptyVector(cx);
442 4 : rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options,
443 8 : nsAtomCString(aName), argCount,
444 : argNames, handlerText,
445 4 : handlerFun.address());
446 4 : NS_ENSURE_SUCCESS(rv, rv);
447 4 : NS_ENSURE_TRUE(handlerFun, NS_ERROR_FAILURE);
448 :
449 : // Wrap the handler into the content scope, since we're about to stash it
450 : // on the DOM window and such.
451 8 : JSAutoCompartment ac2(cx, globalObject);
452 4 : bool ok = JS_WrapObject(cx, &handlerFun);
453 4 : NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
454 4 : aHandler.set(handlerFun);
455 4 : NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE);
456 :
457 4 : if (pWindow) {
458 4 : pWindow->CacheXBLPrototypeHandler(this, aHandler);
459 : }
460 :
461 4 : return NS_OK;
462 : }
463 :
464 : nsresult
465 0 : nsXBLPrototypeHandler::DispatchXBLCommand(EventTarget* aTarget, nsIDOMEvent* aEvent)
466 : {
467 : // This is a special-case optimization to make command handling fast.
468 : // It isn't really a part of XBL, but it helps speed things up.
469 :
470 0 : if (aEvent) {
471 : // See if preventDefault has been set. If so, don't execute.
472 0 : bool preventDefault = false;
473 0 : aEvent->GetDefaultPrevented(&preventDefault);
474 0 : if (preventDefault) {
475 0 : return NS_OK;
476 : }
477 0 : bool dispatchStopped = aEvent->IsDispatchStopped();
478 0 : if (dispatchStopped) {
479 0 : return NS_OK;
480 : }
481 : }
482 :
483 : // Instead of executing JS, let's get the controller for the bound
484 : // element and call doCommand on it.
485 0 : nsCOMPtr<nsIController> controller;
486 :
487 0 : nsCOMPtr<nsPIDOMWindowOuter> privateWindow;
488 0 : nsCOMPtr<nsPIWindowRoot> windowRoot = do_QueryInterface(aTarget);
489 0 : if (windowRoot) {
490 0 : privateWindow = windowRoot->GetWindow();
491 : }
492 : else {
493 0 : privateWindow = do_QueryInterface(aTarget);
494 0 : if (!privateWindow) {
495 0 : nsCOMPtr<nsIContent> elt(do_QueryInterface(aTarget));
496 0 : nsCOMPtr<nsIDocument> doc;
497 : // XXXbz sXBL/XBL2 issue -- this should be the "scope doc" or
498 : // something... whatever we use when wrapping DOM nodes
499 : // normally. It's not clear that the owner doc is the right
500 : // thing.
501 0 : if (elt)
502 0 : doc = elt->OwnerDoc();
503 :
504 0 : if (!doc)
505 0 : doc = do_QueryInterface(aTarget);
506 :
507 0 : if (!doc)
508 0 : return NS_ERROR_FAILURE;
509 :
510 0 : privateWindow = doc->GetWindow();
511 0 : if (!privateWindow)
512 0 : return NS_ERROR_FAILURE;
513 : }
514 :
515 0 : windowRoot = privateWindow->GetTopWindowRoot();
516 : }
517 :
518 0 : NS_LossyConvertUTF16toASCII command(mHandlerText);
519 0 : if (windowRoot)
520 0 : windowRoot->GetControllerForCommand(command.get(), getter_AddRefs(controller));
521 : else
522 0 : controller = GetController(aTarget); // We're attached to the receiver possibly.
523 :
524 : // We are the default action for this command.
525 : // Stop any other default action from executing.
526 0 : aEvent->PreventDefault();
527 :
528 0 : if (mEventName == nsGkAtoms::keypress &&
529 0 : mDetail == nsIDOMKeyEvent::DOM_VK_SPACE &&
530 0 : mMisc == 1) {
531 : // get the focused element so that we can pageDown only at
532 : // certain times.
533 :
534 0 : nsCOMPtr<nsPIDOMWindowOuter> windowToCheck;
535 0 : if (windowRoot)
536 0 : windowToCheck = windowRoot->GetWindow();
537 : else
538 0 : windowToCheck = privateWindow->GetPrivateRoot();
539 :
540 0 : nsCOMPtr<nsIContent> focusedContent;
541 0 : if (windowToCheck) {
542 0 : nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
543 : focusedContent =
544 0 : nsFocusManager::GetFocusedDescendant(windowToCheck, true, getter_AddRefs(focusedWindow));
545 : }
546 :
547 : // If the focus is in an editable region, don't scroll.
548 0 : if (focusedContent && focusedContent->IsEditable()) {
549 0 : return NS_OK;
550 : }
551 :
552 : // If the focus is in a form control, don't scroll.
553 0 : for (nsIContent* c = focusedContent; c; c = c->GetParent()) {
554 0 : nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(c);
555 0 : if (formControl) {
556 0 : return NS_OK;
557 : }
558 : }
559 : }
560 :
561 0 : if (controller)
562 0 : controller->DoCommand(command.get());
563 :
564 0 : return NS_OK;
565 : }
566 :
567 : nsresult
568 0 : nsXBLPrototypeHandler::DispatchXULKeyCommand(nsIDOMEvent* aEvent)
569 : {
570 0 : nsCOMPtr<nsIContent> handlerElement = GetHandlerElement();
571 0 : NS_ENSURE_STATE(handlerElement);
572 0 : if (handlerElement->AttrValueIs(kNameSpaceID_None,
573 : nsGkAtoms::disabled,
574 : nsGkAtoms::_true,
575 : eCaseMatters)) {
576 : // Don't dispatch command events for disabled keys.
577 0 : return NS_OK;
578 : }
579 :
580 0 : aEvent->PreventDefault();
581 :
582 : // Copy the modifiers from the key event.
583 0 : nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
584 0 : if (!keyEvent) {
585 0 : NS_ERROR("Trying to execute a key handler for a non-key event!");
586 0 : return NS_ERROR_FAILURE;
587 : }
588 :
589 : // XXX We should use mozilla::Modifiers for supporting all modifiers.
590 :
591 0 : bool isAlt = false;
592 0 : bool isControl = false;
593 0 : bool isShift = false;
594 0 : bool isMeta = false;
595 0 : keyEvent->GetAltKey(&isAlt);
596 0 : keyEvent->GetCtrlKey(&isControl);
597 0 : keyEvent->GetShiftKey(&isShift);
598 0 : keyEvent->GetMetaKey(&isMeta);
599 :
600 0 : nsContentUtils::DispatchXULCommand(handlerElement, true,
601 : nullptr, nullptr,
602 0 : isControl, isAlt, isShift, isMeta);
603 0 : return NS_OK;
604 : }
605 :
606 : Modifiers
607 0 : nsXBLPrototypeHandler::GetModifiers() const
608 : {
609 0 : Modifiers modifiers = 0;
610 :
611 0 : if (mKeyMask & cMeta) {
612 0 : modifiers |= MODIFIER_META;
613 : }
614 0 : if (mKeyMask & cOS) {
615 0 : modifiers |= MODIFIER_OS;
616 : }
617 0 : if (mKeyMask & cShift) {
618 0 : modifiers |= MODIFIER_SHIFT;
619 : }
620 0 : if (mKeyMask & cAlt) {
621 0 : modifiers |= MODIFIER_ALT;
622 : }
623 0 : if (mKeyMask & cControl) {
624 0 : modifiers |= MODIFIER_CONTROL;
625 : }
626 :
627 0 : return modifiers;
628 : }
629 :
630 : Modifiers
631 0 : nsXBLPrototypeHandler::GetModifiersMask() const
632 : {
633 0 : Modifiers modifiersMask = 0;
634 :
635 0 : if (mKeyMask & cMetaMask) {
636 0 : modifiersMask |= MODIFIER_META;
637 : }
638 0 : if (mKeyMask & cOSMask) {
639 0 : modifiersMask |= MODIFIER_OS;
640 : }
641 0 : if (mKeyMask & cShiftMask) {
642 0 : modifiersMask |= MODIFIER_SHIFT;
643 : }
644 0 : if (mKeyMask & cAltMask) {
645 0 : modifiersMask |= MODIFIER_ALT;
646 : }
647 0 : if (mKeyMask & cControlMask) {
648 0 : modifiersMask |= MODIFIER_CONTROL;
649 : }
650 :
651 0 : return modifiersMask;
652 : }
653 :
654 : already_AddRefed<nsIAtom>
655 725 : nsXBLPrototypeHandler::GetEventName()
656 : {
657 1450 : nsCOMPtr<nsIAtom> eventName = mEventName;
658 1450 : return eventName.forget();
659 : }
660 :
661 : already_AddRefed<nsIController>
662 0 : nsXBLPrototypeHandler::GetController(EventTarget* aTarget)
663 : {
664 : // XXX Fix this so there's a generic interface that describes controllers,
665 : // This code should have no special knowledge of what objects might have controllers.
666 0 : nsCOMPtr<nsIControllers> controllers;
667 :
668 0 : nsCOMPtr<nsIContent> targetContent(do_QueryInterface(aTarget));
669 : RefPtr<nsXULElement> xulElement =
670 0 : nsXULElement::FromContentOrNull(targetContent);
671 0 : if (xulElement) {
672 0 : IgnoredErrorResult rv;
673 0 : controllers = xulElement->GetControllers(rv);
674 : }
675 :
676 0 : if (!controllers) {
677 0 : nsCOMPtr<nsIDOMHTMLTextAreaElement> htmlTextArea(do_QueryInterface(aTarget));
678 0 : if (htmlTextArea)
679 0 : htmlTextArea->GetControllers(getter_AddRefs(controllers));
680 : }
681 :
682 0 : if (!controllers) {
683 0 : nsCOMPtr<nsIDOMHTMLInputElement> htmlInputElement(do_QueryInterface(aTarget));
684 0 : if (htmlInputElement)
685 0 : htmlInputElement->GetControllers(getter_AddRefs(controllers));
686 : }
687 :
688 0 : if (!controllers) {
689 0 : nsCOMPtr<nsPIDOMWindowOuter> domWindow(do_QueryInterface(aTarget));
690 0 : if (domWindow) {
691 0 : domWindow->GetControllers(getter_AddRefs(controllers));
692 : }
693 : }
694 :
695 : // Return the first controller.
696 : // XXX This code should be checking the command name and using supportscommand and
697 : // iscommandenabled.
698 0 : nsCOMPtr<nsIController> controller;
699 0 : if (controllers) {
700 0 : controllers->GetControllerAt(0, getter_AddRefs(controller));
701 : }
702 :
703 0 : return controller.forget();
704 : }
705 :
706 : bool
707 0 : nsXBLPrototypeHandler::KeyEventMatched(
708 : nsIDOMKeyEvent* aKeyEvent,
709 : uint32_t aCharCode,
710 : const IgnoreModifierState& aIgnoreModifierState)
711 : {
712 0 : if (mDetail != -1) {
713 : // Get the keycode or charcode of the key event.
714 : uint32_t code;
715 :
716 0 : if (mMisc) {
717 0 : if (aCharCode)
718 0 : code = aCharCode;
719 : else
720 0 : aKeyEvent->GetCharCode(&code);
721 0 : if (IS_IN_BMP(code))
722 0 : code = ToLowerCase(char16_t(code));
723 : }
724 : else
725 0 : aKeyEvent->GetKeyCode(&code);
726 :
727 0 : if (code != uint32_t(mDetail))
728 0 : return false;
729 : }
730 :
731 0 : return ModifiersMatchMask(aKeyEvent, aIgnoreModifierState);
732 : }
733 :
734 : bool
735 0 : nsXBLPrototypeHandler::MouseEventMatched(nsIDOMMouseEvent* aMouseEvent)
736 : {
737 0 : if (mDetail == -1 && mMisc == 0 && (mKeyMask & cAllModifiers) == 0)
738 0 : return true; // No filters set up. It's generic.
739 :
740 : int16_t button;
741 0 : aMouseEvent->GetButton(&button);
742 0 : if (mDetail != -1 && (button != mDetail))
743 0 : return false;
744 :
745 : int32_t clickcount;
746 0 : aMouseEvent->GetDetail(&clickcount);
747 0 : if (mMisc != 0 && (clickcount != mMisc))
748 0 : return false;
749 :
750 0 : return ModifiersMatchMask(aMouseEvent, IgnoreModifierState());
751 : }
752 :
753 : struct keyCodeData {
754 : const char* str;
755 : uint16_t strlength;
756 : uint16_t keycode;
757 : };
758 :
759 : // All of these must be uppercase, since the function below does
760 : // case-insensitive comparison by converting to uppercase.
761 : // XXX: be sure to check this periodically for new symbol additions!
762 : static const keyCodeData gKeyCodes[] = {
763 :
764 : #define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) \
765 : { #aDOMKeyName, sizeof(#aDOMKeyName) - 1, aDOMKeyCode },
766 : #include "mozilla/VirtualKeyCodeList.h"
767 : #undef NS_DEFINE_VK
768 :
769 : { nullptr, 0, 0 }
770 : };
771 :
772 0 : int32_t nsXBLPrototypeHandler::GetMatchingKeyCode(const nsAString& aKeyName)
773 : {
774 0 : nsAutoCString keyName;
775 0 : keyName.AssignWithConversion(aKeyName);
776 0 : ToUpperCase(keyName); // We want case-insensitive comparison with data
777 : // stored as uppercase.
778 :
779 0 : uint32_t keyNameLength = keyName.Length();
780 0 : const char* keyNameStr = keyName.get();
781 0 : for (uint16_t i = 0; i < ArrayLength(gKeyCodes) - 1; ++i) {
782 0 : if (keyNameLength == gKeyCodes[i].strlength &&
783 0 : !nsCRT::strcmp(gKeyCodes[i].str, keyNameStr)) {
784 0 : return gKeyCodes[i].keycode;
785 : }
786 : }
787 :
788 0 : return 0;
789 : }
790 :
791 0 : int32_t nsXBLPrototypeHandler::KeyToMask(int32_t key)
792 : {
793 0 : switch (key)
794 : {
795 : case nsIDOMKeyEvent::DOM_VK_META:
796 0 : return cMeta | cMetaMask;
797 :
798 : case nsIDOMKeyEvent::DOM_VK_WIN:
799 0 : return cOS | cOSMask;
800 :
801 : case nsIDOMKeyEvent::DOM_VK_ALT:
802 0 : return cAlt | cAltMask;
803 :
804 : case nsIDOMKeyEvent::DOM_VK_CONTROL:
805 : default:
806 0 : return cControl | cControlMask;
807 : }
808 : return cControl | cControlMask; // for warning avoidance
809 : }
810 :
811 : // static
812 : int32_t
813 0 : nsXBLPrototypeHandler::AccelKeyMask()
814 : {
815 0 : switch (WidgetInputEvent::AccelModifier()) {
816 : case MODIFIER_ALT:
817 0 : return KeyToMask(nsIDOMKeyEvent::DOM_VK_ALT);
818 : case MODIFIER_CONTROL:
819 0 : return KeyToMask(nsIDOMKeyEvent::DOM_VK_CONTROL);
820 : case MODIFIER_META:
821 0 : return KeyToMask(nsIDOMKeyEvent::DOM_VK_META);
822 : case MODIFIER_OS:
823 0 : return KeyToMask(nsIDOMKeyEvent::DOM_VK_WIN);
824 : default:
825 0 : MOZ_CRASH("Handle the new result of WidgetInputEvent::AccelModifier()");
826 : return 0;
827 : }
828 : }
829 :
830 : void
831 0 : nsXBLPrototypeHandler::GetEventType(nsAString& aEvent)
832 : {
833 0 : nsCOMPtr<nsIContent> handlerElement = GetHandlerElement();
834 0 : if (!handlerElement) {
835 0 : aEvent.Truncate();
836 0 : return;
837 : }
838 0 : handlerElement->GetAttr(kNameSpaceID_None, nsGkAtoms::event, aEvent);
839 :
840 0 : if (aEvent.IsEmpty() && (mType & NS_HANDLER_TYPE_XUL))
841 : // If no type is specified for a XUL <key> element, let's assume that we're "keypress".
842 0 : aEvent.AssignLiteral("keypress");
843 : }
844 :
845 : void
846 4 : nsXBLPrototypeHandler::ConstructPrototype(nsIContent* aKeyElement,
847 : const char16_t* aEvent,
848 : const char16_t* aPhase,
849 : const char16_t* aAction,
850 : const char16_t* aCommand,
851 : const char16_t* aKeyCode,
852 : const char16_t* aCharCode,
853 : const char16_t* aModifiers,
854 : const char16_t* aButton,
855 : const char16_t* aClickCount,
856 : const char16_t* aGroup,
857 : const char16_t* aPreventDefault,
858 : const char16_t* aAllowUntrusted)
859 : {
860 4 : mType = 0;
861 :
862 4 : if (aKeyElement) {
863 0 : mType |= NS_HANDLER_TYPE_XUL;
864 0 : MOZ_ASSERT(!mPrototypeBinding);
865 0 : nsCOMPtr<nsIWeakReference> weak = do_GetWeakReference(aKeyElement);
866 0 : if (!weak) {
867 0 : return;
868 : }
869 0 : weak.swap(mHandlerElement);
870 : }
871 : else {
872 4 : mType |= aCommand ? NS_HANDLER_TYPE_XBL_COMMAND : NS_HANDLER_TYPE_XBL_JS;
873 4 : mHandlerText = nullptr;
874 : }
875 :
876 4 : mDetail = -1;
877 4 : mMisc = 0;
878 4 : mKeyMask = 0;
879 4 : mPhase = NS_PHASE_BUBBLING;
880 :
881 4 : if (aAction)
882 4 : mHandlerText = ToNewUnicode(nsDependentString(aAction));
883 0 : else if (aCommand)
884 0 : mHandlerText = ToNewUnicode(nsDependentString(aCommand));
885 :
886 8 : nsAutoString event(aEvent);
887 4 : if (event.IsEmpty()) {
888 0 : if (mType & NS_HANDLER_TYPE_XUL)
889 0 : GetEventType(event);
890 0 : if (event.IsEmpty())
891 0 : return;
892 : }
893 :
894 4 : mEventName = NS_Atomize(event);
895 :
896 4 : if (aPhase) {
897 0 : const nsDependentString phase(aPhase);
898 0 : if (phase.EqualsLiteral("capturing"))
899 0 : mPhase = NS_PHASE_CAPTURING;
900 0 : else if (phase.EqualsLiteral("target"))
901 0 : mPhase = NS_PHASE_TARGET;
902 : }
903 :
904 : // Button and clickcount apply only to XBL handlers and don't apply to XUL key
905 : // handlers.
906 4 : if (aButton && *aButton)
907 0 : mDetail = *aButton - '0';
908 :
909 4 : if (aClickCount && *aClickCount)
910 0 : mMisc = *aClickCount - '0';
911 :
912 : // Modifiers are supported by both types of handlers (XUL and XBL).
913 8 : nsAutoString modifiers(aModifiers);
914 4 : if (mType & NS_HANDLER_TYPE_XUL)
915 0 : aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiers);
916 :
917 4 : if (!modifiers.IsEmpty()) {
918 0 : mKeyMask = cAllModifiers;
919 0 : char* str = ToNewCString(modifiers);
920 : char* newStr;
921 0 : char* token = nsCRT::strtok( str, ", \t", &newStr );
922 0 : while( token != nullptr ) {
923 0 : if (PL_strcmp(token, "shift") == 0)
924 0 : mKeyMask |= cShift | cShiftMask;
925 0 : else if (PL_strcmp(token, "alt") == 0)
926 0 : mKeyMask |= cAlt | cAltMask;
927 0 : else if (PL_strcmp(token, "meta") == 0)
928 0 : mKeyMask |= cMeta | cMetaMask;
929 0 : else if (PL_strcmp(token, "os") == 0)
930 0 : mKeyMask |= cOS | cOSMask;
931 0 : else if (PL_strcmp(token, "control") == 0)
932 0 : mKeyMask |= cControl | cControlMask;
933 0 : else if (PL_strcmp(token, "accel") == 0)
934 0 : mKeyMask |= AccelKeyMask();
935 0 : else if (PL_strcmp(token, "access") == 0)
936 0 : mKeyMask |= KeyToMask(kMenuAccessKey);
937 0 : else if (PL_strcmp(token, "any") == 0)
938 0 : mKeyMask &= ~(mKeyMask << 5);
939 :
940 0 : token = nsCRT::strtok( newStr, ", \t", &newStr );
941 : }
942 :
943 0 : free(str);
944 : }
945 :
946 8 : nsAutoString key(aCharCode);
947 4 : if (key.IsEmpty()) {
948 4 : if (mType & NS_HANDLER_TYPE_XUL) {
949 0 : aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::key, key);
950 0 : if (key.IsEmpty())
951 0 : aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::charcode, key);
952 : }
953 : }
954 :
955 4 : if (!key.IsEmpty()) {
956 0 : if (mKeyMask == 0)
957 0 : mKeyMask = cAllModifiers;
958 0 : ToLowerCase(key);
959 :
960 : // We have a charcode.
961 0 : mMisc = 1;
962 0 : mDetail = key[0];
963 0 : const uint8_t GTK2Modifiers = cShift | cControl | cShiftMask | cControlMask;
964 0 : if ((mType & NS_HANDLER_TYPE_XUL) &&
965 0 : (mKeyMask & GTK2Modifiers) == GTK2Modifiers &&
966 0 : modifiers.First() != char16_t(',') &&
967 0 : (mDetail == 'u' || mDetail == 'U'))
968 0 : ReportKeyConflict(key.get(), modifiers.get(), aKeyElement, "GTK2Conflict2");
969 0 : const uint8_t WinModifiers = cControl | cAlt | cControlMask | cAltMask;
970 0 : if ((mType & NS_HANDLER_TYPE_XUL) &&
971 0 : (mKeyMask & WinModifiers) == WinModifiers &&
972 0 : modifiers.First() != char16_t(',') &&
973 0 : (('A' <= mDetail && mDetail <= 'Z') ||
974 0 : ('a' <= mDetail && mDetail <= 'z')))
975 0 : ReportKeyConflict(key.get(), modifiers.get(), aKeyElement, "WinConflict2");
976 : }
977 : else {
978 4 : key.Assign(aKeyCode);
979 4 : if (mType & NS_HANDLER_TYPE_XUL)
980 0 : aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, key);
981 :
982 4 : if (!key.IsEmpty()) {
983 0 : if (mKeyMask == 0)
984 0 : mKeyMask = cAllModifiers;
985 0 : mDetail = GetMatchingKeyCode(key);
986 : }
987 : }
988 :
989 4 : if (aGroup && nsDependentString(aGroup).EqualsLiteral("system"))
990 0 : mType |= NS_HANDLER_TYPE_SYSTEM;
991 :
992 14 : if (aPreventDefault &&
993 10 : nsDependentString(aPreventDefault).EqualsLiteral("true"))
994 2 : mType |= NS_HANDLER_TYPE_PREVENTDEFAULT;
995 :
996 4 : if (aAllowUntrusted) {
997 0 : mType |= NS_HANDLER_HAS_ALLOW_UNTRUSTED_ATTR;
998 0 : if (nsDependentString(aAllowUntrusted).EqualsLiteral("true")) {
999 0 : mType |= NS_HANDLER_ALLOW_UNTRUSTED;
1000 : } else {
1001 0 : mType &= ~NS_HANDLER_ALLOW_UNTRUSTED;
1002 : }
1003 : }
1004 : }
1005 :
1006 : void
1007 0 : nsXBLPrototypeHandler::ReportKeyConflict(const char16_t* aKey, const char16_t* aModifiers, nsIContent* aKeyElement, const char *aMessageName)
1008 : {
1009 0 : nsCOMPtr<nsIDocument> doc;
1010 0 : if (mPrototypeBinding) {
1011 0 : nsXBLDocumentInfo* docInfo = mPrototypeBinding->XBLDocumentInfo();
1012 0 : if (docInfo) {
1013 0 : doc = docInfo->GetDocument();
1014 : }
1015 : } else {
1016 0 : doc = aKeyElement->OwnerDoc();
1017 : }
1018 :
1019 0 : nsAutoString id;
1020 0 : aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
1021 0 : const char16_t* params[] = { aKey, aModifiers, id.get() };
1022 0 : nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
1023 0 : NS_LITERAL_CSTRING("XBL Prototype Handler"), doc,
1024 : nsContentUtils::eXBL_PROPERTIES,
1025 : aMessageName,
1026 0 : params, ArrayLength(params),
1027 0 : nullptr, EmptyString(), mLineNumber);
1028 0 : }
1029 :
1030 : bool
1031 0 : nsXBLPrototypeHandler::ModifiersMatchMask(
1032 : nsIDOMUIEvent* aEvent,
1033 : const IgnoreModifierState& aIgnoreModifierState)
1034 : {
1035 0 : WidgetInputEvent* inputEvent = aEvent->AsEvent()->WidgetEventPtr()->AsInputEvent();
1036 0 : NS_ENSURE_TRUE(inputEvent, false);
1037 :
1038 0 : if (mKeyMask & cMetaMask) {
1039 0 : if (inputEvent->IsMeta() != ((mKeyMask & cMeta) != 0)) {
1040 0 : return false;
1041 : }
1042 : }
1043 :
1044 0 : if ((mKeyMask & cOSMask) && !aIgnoreModifierState.mOS) {
1045 0 : if (inputEvent->IsOS() != ((mKeyMask & cOS) != 0)) {
1046 0 : return false;
1047 : }
1048 : }
1049 :
1050 0 : if (mKeyMask & cShiftMask && !aIgnoreModifierState.mShift) {
1051 0 : if (inputEvent->IsShift() != ((mKeyMask & cShift) != 0)) {
1052 0 : return false;
1053 : }
1054 : }
1055 :
1056 0 : if (mKeyMask & cAltMask) {
1057 0 : if (inputEvent->IsAlt() != ((mKeyMask & cAlt) != 0)) {
1058 0 : return false;
1059 : }
1060 : }
1061 :
1062 0 : if (mKeyMask & cControlMask) {
1063 0 : if (inputEvent->IsControl() != ((mKeyMask & cControl) != 0)) {
1064 0 : return false;
1065 : }
1066 : }
1067 :
1068 0 : return true;
1069 : }
1070 :
1071 : nsresult
1072 280 : nsXBLPrototypeHandler::Read(nsIObjectInputStream* aStream)
1073 : {
1074 280 : AssertInCompilationScope();
1075 280 : nsresult rv = aStream->Read8(&mPhase);
1076 280 : NS_ENSURE_SUCCESS(rv, rv);
1077 280 : rv = aStream->Read8(&mType);
1078 280 : NS_ENSURE_SUCCESS(rv, rv);
1079 280 : rv = aStream->Read8(&mMisc);
1080 280 : NS_ENSURE_SUCCESS(rv, rv);
1081 :
1082 280 : rv = aStream->Read32(reinterpret_cast<uint32_t*>(&mKeyMask));
1083 280 : NS_ENSURE_SUCCESS(rv, rv);
1084 : uint32_t detail;
1085 280 : rv = aStream->Read32(&detail);
1086 280 : NS_ENSURE_SUCCESS(rv, rv);
1087 280 : mDetail = detail;
1088 :
1089 560 : nsAutoString name;
1090 280 : rv = aStream->ReadString(name);
1091 280 : NS_ENSURE_SUCCESS(rv, rv);
1092 280 : mEventName = NS_Atomize(name);
1093 :
1094 280 : rv = aStream->Read32(&mLineNumber);
1095 280 : NS_ENSURE_SUCCESS(rv, rv);
1096 :
1097 560 : nsAutoString handlerText;
1098 280 : rv = aStream->ReadString(handlerText);
1099 280 : NS_ENSURE_SUCCESS(rv, rv);
1100 280 : if (!handlerText.IsEmpty())
1101 280 : mHandlerText = ToNewUnicode(handlerText);
1102 :
1103 280 : return NS_OK;
1104 : }
1105 :
1106 : nsresult
1107 0 : nsXBLPrototypeHandler::Write(nsIObjectOutputStream* aStream)
1108 : {
1109 0 : AssertInCompilationScope();
1110 : // Make sure we don't write out NS_HANDLER_TYPE_XUL types, as they are used
1111 : // for <keyset> elements.
1112 0 : if ((mType & NS_HANDLER_TYPE_XUL) || !mEventName)
1113 0 : return NS_OK;
1114 :
1115 0 : XBLBindingSerializeDetails type = XBLBinding_Serialize_Handler;
1116 :
1117 0 : nsresult rv = aStream->Write8(type);
1118 0 : rv = aStream->Write8(mPhase);
1119 0 : NS_ENSURE_SUCCESS(rv, rv);
1120 0 : rv = aStream->Write8(mType);
1121 0 : NS_ENSURE_SUCCESS(rv, rv);
1122 0 : rv = aStream->Write8(mMisc);
1123 0 : NS_ENSURE_SUCCESS(rv, rv);
1124 0 : rv = aStream->Write32(static_cast<uint32_t>(mKeyMask));
1125 0 : NS_ENSURE_SUCCESS(rv, rv);
1126 0 : rv = aStream->Write32(mDetail);
1127 0 : NS_ENSURE_SUCCESS(rv, rv);
1128 :
1129 0 : rv = aStream->WriteWStringZ(nsDependentAtomString(mEventName).get());
1130 0 : NS_ENSURE_SUCCESS(rv, rv);
1131 :
1132 0 : rv = aStream->Write32(mLineNumber);
1133 0 : NS_ENSURE_SUCCESS(rv, rv);
1134 0 : return aStream->WriteWStringZ(mHandlerText ? mHandlerText : u"");
1135 : }
|