LCOV - code coverage report
Current view: top level - dom/xbl - nsXBLPrototypeHandler.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 171 543 31.5 %
Date: 2017-07-14 16:53:18 Functions: 8 27 29.6 %
Legend: Lines: hit not hit

          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             : }

Generated by: LCOV version 1.13