LCOV - code coverage report
Current view: directory - content/xbl/src - nsXBLPrototypeHandler.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 445 0 0.0 %
Date: 2012-06-02 Functions: 23 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Original Author: David W. Hyatt (hyatt@netscape.com)
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "mozilla/Util.h"
      40                 : 
      41                 : #include "nsCOMPtr.h"
      42                 : #include "nsXBLPrototypeHandler.h"
      43                 : #include "nsXBLPrototypeBinding.h"
      44                 : #include "nsContentUtils.h"
      45                 : #include "nsIContent.h"
      46                 : #include "nsIAtom.h"
      47                 : #include "nsIDOMKeyEvent.h"
      48                 : #include "nsIDOMMouseEvent.h"
      49                 : #include "nsINameSpaceManager.h"
      50                 : #include "nsIScriptContext.h"
      51                 : #include "nsIDocument.h"
      52                 : #include "nsIDOMDocument.h"
      53                 : #include "nsIJSEventListener.h"
      54                 : #include "nsIController.h"
      55                 : #include "nsIControllers.h"
      56                 : #include "nsIDOMXULElement.h"
      57                 : #include "nsIURI.h"
      58                 : #include "nsIDOMHTMLTextAreaElement.h"
      59                 : #include "nsIDOMHTMLInputElement.h"
      60                 : #include "nsFocusManager.h"
      61                 : #include "nsEventListenerManager.h"
      62                 : #include "nsIDOMEventTarget.h"
      63                 : #include "nsIDOMEventListener.h"
      64                 : #include "nsIPrivateDOMEvent.h"
      65                 : #include "nsIDOMNSEvent.h"
      66                 : #include "nsPIDOMWindow.h"
      67                 : #include "nsPIWindowRoot.h"
      68                 : #include "nsIDOMWindow.h"
      69                 : #include "nsIServiceManager.h"
      70                 : #include "nsIScriptError.h"
      71                 : #include "nsXPIDLString.h"
      72                 : #include "nsReadableUtils.h"
      73                 : #include "nsGkAtoms.h"
      74                 : #include "nsGUIEvent.h"
      75                 : #include "nsIXPConnect.h"
      76                 : #include "nsIDOMScriptObjectFactory.h"
      77                 : #include "nsDOMCID.h"
      78                 : #include "nsUnicharUtils.h"
      79                 : #include "nsReadableUtils.h"
      80                 : #include "nsCRT.h"
      81                 : #include "nsXBLEventHandler.h"
      82                 : #include "nsXBLSerialize.h"
      83                 : #include "nsEventDispatcher.h"
      84                 : #include "mozilla/Preferences.h"
      85                 : 
      86                 : using namespace mozilla;
      87                 : 
      88                 : static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
      89                 :                      NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
      90                 : 
      91                 : PRUint32 nsXBLPrototypeHandler::gRefCnt = 0;
      92                 : 
      93                 : PRInt32 nsXBLPrototypeHandler::kMenuAccessKey = -1;
      94                 : PRInt32 nsXBLPrototypeHandler::kAccelKey = -1;
      95                 : 
      96                 : const PRInt32 nsXBLPrototypeHandler::cShift = (1<<0);
      97                 : const PRInt32 nsXBLPrototypeHandler::cAlt = (1<<1);
      98                 : const PRInt32 nsXBLPrototypeHandler::cControl = (1<<2);
      99                 : const PRInt32 nsXBLPrototypeHandler::cMeta = (1<<3);
     100                 : 
     101                 : const PRInt32 nsXBLPrototypeHandler::cShiftMask = (1<<4);
     102                 : const PRInt32 nsXBLPrototypeHandler::cAltMask = (1<<5);
     103                 : const PRInt32 nsXBLPrototypeHandler::cControlMask = (1<<6);
     104                 : const PRInt32 nsXBLPrototypeHandler::cMetaMask = (1<<7);
     105                 : 
     106                 : const PRInt32 nsXBLPrototypeHandler::cAllModifiers = cShiftMask | cAltMask | cControlMask | cMetaMask;
     107                 : 
     108               0 : nsXBLPrototypeHandler::nsXBLPrototypeHandler(const PRUnichar* aEvent,
     109                 :                                              const PRUnichar* aPhase,
     110                 :                                              const PRUnichar* aAction,
     111                 :                                              const PRUnichar* aCommand,
     112                 :                                              const PRUnichar* aKeyCode,
     113                 :                                              const PRUnichar* aCharCode,
     114                 :                                              const PRUnichar* aModifiers,
     115                 :                                              const PRUnichar* aButton,
     116                 :                                              const PRUnichar* aClickCount,
     117                 :                                              const PRUnichar* aGroup,
     118                 :                                              const PRUnichar* aPreventDefault,
     119                 :                                              const PRUnichar* aAllowUntrusted,
     120                 :                                              nsXBLPrototypeBinding* aBinding,
     121                 :                                              PRUint32 aLineNumber)
     122                 :   : mHandlerText(nsnull),
     123                 :     mLineNumber(aLineNumber),
     124                 :     mNextHandler(nsnull),
     125               0 :     mPrototypeBinding(aBinding)
     126                 : {
     127               0 :   Init();
     128                 : 
     129                 :   ConstructPrototype(nsnull, aEvent, aPhase, aAction, aCommand, aKeyCode,
     130                 :                      aCharCode, aModifiers, aButton, aClickCount,
     131               0 :                      aGroup, aPreventDefault, aAllowUntrusted);
     132               0 : }
     133                 : 
     134               0 : nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement)
     135                 :   : mHandlerElement(nsnull),
     136                 :     mLineNumber(0),
     137                 :     mNextHandler(nsnull),
     138               0 :     mPrototypeBinding(nsnull)
     139                 : {
     140               0 :   Init();
     141                 : 
     142                 :   // Make sure our prototype is initialized.
     143               0 :   ConstructPrototype(aHandlerElement);
     144               0 : }
     145                 : 
     146               0 : nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsXBLPrototypeBinding* aBinding)
     147                 :   : mHandlerText(nsnull),
     148                 :     mLineNumber(nsnull),
     149                 :     mNextHandler(nsnull),
     150               0 :     mPrototypeBinding(aBinding)
     151                 : {
     152               0 :   Init();
     153               0 : }
     154                 : 
     155               0 : nsXBLPrototypeHandler::~nsXBLPrototypeHandler()
     156                 : {
     157               0 :   --gRefCnt;
     158               0 :   if (mType & NS_HANDLER_TYPE_XUL) {
     159               0 :     NS_IF_RELEASE(mHandlerElement);
     160               0 :   } else if (mHandlerText) {
     161               0 :     nsMemory::Free(mHandlerText);
     162                 :   }
     163                 : 
     164                 :   // We own the next handler in the chain, so delete it now.
     165               0 :   NS_CONTENT_DELETE_LIST_MEMBER(nsXBLPrototypeHandler, this, mNextHandler);
     166               0 : }
     167                 : 
     168                 : already_AddRefed<nsIContent>
     169               0 : nsXBLPrototypeHandler::GetHandlerElement()
     170                 : {
     171               0 :   if (mType & NS_HANDLER_TYPE_XUL) {
     172               0 :     nsCOMPtr<nsIContent> element = do_QueryReferent(mHandlerElement);
     173               0 :     nsIContent* el = nsnull;
     174               0 :     element.swap(el);
     175               0 :     return el;
     176                 :   }
     177                 : 
     178               0 :   return nsnull;
     179                 : }
     180                 : 
     181                 : void
     182               0 : nsXBLPrototypeHandler::AppendHandlerText(const nsAString& aText) 
     183                 : {
     184               0 :   if (mHandlerText) {
     185                 :     // Append our text to the existing text.
     186               0 :     PRUnichar* temp = mHandlerText;
     187               0 :     mHandlerText = ToNewUnicode(nsDependentString(temp) + aText);
     188               0 :     nsMemory::Free(temp);
     189                 :   }
     190                 :   else {
     191               0 :     mHandlerText = ToNewUnicode(aText);
     192                 :   }
     193               0 : }
     194                 : 
     195                 : /////////////////////////////////////////////////////////////////////////////
     196                 : // Get the menu access key from prefs.
     197                 : // XXX Eventually pick up using CSS3 key-equivalent property or somesuch
     198                 : void
     199               0 : nsXBLPrototypeHandler::InitAccessKeys()
     200                 : {
     201               0 :   if (kAccelKey >= 0 && kMenuAccessKey >= 0)
     202               0 :     return;
     203                 : 
     204                 :   // Compiled-in defaults, in case we can't get the pref --
     205                 :   // mac doesn't have menu shortcuts, other platforms use alt.
     206                 : #ifdef XP_MACOSX
     207                 :   kMenuAccessKey = 0;
     208                 :   kAccelKey = nsIDOMKeyEvent::DOM_VK_META;
     209                 : #else
     210               0 :   kMenuAccessKey = nsIDOMKeyEvent::DOM_VK_ALT;
     211               0 :   kAccelKey = nsIDOMKeyEvent::DOM_VK_CONTROL;
     212                 : #endif
     213                 : 
     214                 :   // Get the menu access key value from prefs, overriding the default:
     215                 :   kMenuAccessKey =
     216               0 :     Preferences::GetInt("ui.key.menuAccessKey", kMenuAccessKey);
     217               0 :   kAccelKey = Preferences::GetInt("ui.key.accelKey", kAccelKey);
     218                 : }
     219                 : 
     220                 : nsresult
     221               0 : nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventTarget* aTarget,
     222                 :                                       nsIDOMEvent* aEvent)
     223                 : {
     224               0 :   nsresult rv = NS_ERROR_FAILURE;
     225                 : 
     226                 :   // Prevent default action?
     227               0 :   if (mType & NS_HANDLER_TYPE_PREVENTDEFAULT) {
     228               0 :     aEvent->PreventDefault();
     229                 :     // If we prevent default, then it's okay for
     230                 :     // mHandlerElement and mHandlerText to be null
     231               0 :     rv = NS_OK;
     232                 :   }
     233                 : 
     234               0 :   if (!mHandlerElement) // This works for both types of handlers.  In both cases, the union's var should be defined.
     235               0 :     return rv;
     236                 : 
     237                 :   // See if our event receiver is a content node (and not us).
     238               0 :   bool isXULKey = !!(mType & NS_HANDLER_TYPE_XUL);
     239               0 :   bool isXBLCommand = !!(mType & NS_HANDLER_TYPE_XBL_COMMAND);
     240               0 :   NS_ASSERTION(!(isXULKey && isXBLCommand),
     241                 :                "can't be both a key and xbl command handler");
     242                 : 
     243                 :   // XUL handlers and commands shouldn't be triggered by non-trusted
     244                 :   // events.
     245               0 :   if (isXULKey || isXBLCommand) {
     246               0 :     nsCOMPtr<nsIDOMNSEvent> domNSEvent = do_QueryInterface(aEvent);
     247               0 :     bool trustedEvent = false;
     248               0 :     if (domNSEvent) {
     249               0 :       domNSEvent->GetIsTrusted(&trustedEvent);
     250                 :     }
     251                 : 
     252               0 :     if (!trustedEvent)
     253               0 :       return NS_OK;
     254                 :   }
     255                 :     
     256               0 :   if (isXBLCommand) {
     257               0 :     return DispatchXBLCommand(aTarget, aEvent);
     258                 :   }
     259                 : 
     260                 :   // If we're executing on a XUL key element, just dispatch a command
     261                 :   // event at the element.  It will take care of retargeting it to its
     262                 :   // command element, if applicable, and executing the event handler.
     263               0 :   if (isXULKey) {
     264               0 :     return DispatchXULKeyCommand(aEvent);
     265                 :   }
     266                 : 
     267                 :   // Look for a compiled handler on the element. 
     268                 :   // Should be compiled and bound with "on" in front of the name.
     269               0 :   nsCOMPtr<nsIAtom> onEventAtom = do_GetAtom(NS_LITERAL_STRING("onxbl") +
     270               0 :                                              nsDependentAtomString(mEventName));
     271                 : 
     272                 :   // Compile the handler and bind it to the element.
     273               0 :   nsCOMPtr<nsIScriptGlobalObject> boundGlobal;
     274               0 :   nsCOMPtr<nsPIWindowRoot> winRoot(do_QueryInterface(aTarget));
     275               0 :   nsCOMPtr<nsPIDOMWindow> window;
     276                 : 
     277               0 :   if (winRoot) {
     278               0 :     window = winRoot->GetWindow();
     279                 :   }
     280                 : 
     281               0 :   if (window) {
     282               0 :     window = window->GetCurrentInnerWindow();
     283               0 :     NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED);
     284                 : 
     285               0 :     boundGlobal = do_QueryInterface(window->GetPrivateRoot());
     286                 :   }
     287               0 :   else boundGlobal = do_QueryInterface(aTarget);
     288                 : 
     289               0 :   if (!boundGlobal) {
     290               0 :     nsCOMPtr<nsIDocument> boundDocument(do_QueryInterface(aTarget));
     291               0 :     if (!boundDocument) {
     292                 :       // We must be an element.
     293               0 :       nsCOMPtr<nsIContent> content(do_QueryInterface(aTarget));
     294               0 :       if (!content)
     295               0 :         return NS_OK;
     296               0 :       boundDocument = content->OwnerDoc();
     297                 :     }
     298                 : 
     299               0 :     boundGlobal = boundDocument->GetScopeObject();
     300                 :   }
     301                 : 
     302               0 :   if (!boundGlobal)
     303               0 :     return NS_OK;
     304                 : 
     305                 :   nsIScriptContext *boundContext =
     306               0 :     boundGlobal->GetScriptContext(nsIProgrammingLanguage::JAVASCRIPT);
     307               0 :   if (!boundContext)
     308               0 :     return NS_OK;
     309                 : 
     310               0 :   nsScriptObjectHolder<JSObject> handler(boundContext);
     311                 :   nsISupports *scriptTarget;
     312                 : 
     313               0 :   if (winRoot) {
     314               0 :     scriptTarget = boundGlobal;
     315                 :   } else {
     316               0 :     scriptTarget = aTarget;
     317                 :   }
     318                 : 
     319               0 :   rv = EnsureEventHandler(boundGlobal, boundContext, onEventAtom, handler);
     320               0 :   NS_ENSURE_SUCCESS(rv, rv);
     321                 : 
     322                 :   // Bind it to the bound element
     323               0 :   JSObject* scope = boundGlobal->GetGlobalJSObject();
     324               0 :   nsScriptObjectHolder<JSObject> boundHandler(boundContext);
     325                 :   rv = boundContext->BindCompiledEventHandler(scriptTarget, scope,
     326               0 :                                               handler.get(), boundHandler);
     327               0 :   NS_ENSURE_SUCCESS(rv, rv);
     328                 : 
     329                 :   // Execute it.
     330               0 :   nsCOMPtr<nsIJSEventListener> eventListener;
     331                 :   rv = NS_NewJSEventListener(boundContext, scope,
     332                 :                              scriptTarget, onEventAtom,
     333                 :                              boundHandler.get(),
     334               0 :                              getter_AddRefs(eventListener));
     335               0 :   NS_ENSURE_SUCCESS(rv, rv);
     336                 : 
     337                 :   // Handle the event.
     338               0 :   eventListener->HandleEvent(aEvent);
     339               0 :   eventListener->Disconnect();
     340               0 :   return NS_OK;
     341                 : }
     342                 : 
     343                 : nsresult
     344               0 : nsXBLPrototypeHandler::EnsureEventHandler(nsIScriptGlobalObject* aGlobal,
     345                 :                                           nsIScriptContext *aBoundContext,
     346                 :                                           nsIAtom *aName,
     347                 :                                           nsScriptObjectHolder<JSObject>& aHandler)
     348                 : {
     349                 :   // Check to see if we've already compiled this
     350               0 :   nsCOMPtr<nsPIDOMWindow> pWindow = do_QueryInterface(aGlobal);
     351               0 :   if (pWindow) {
     352               0 :     JSObject* cachedHandler = pWindow->GetCachedXBLPrototypeHandler(this);
     353               0 :     if (cachedHandler) {
     354               0 :       aHandler.set(cachedHandler);
     355               0 :       return aHandler ? NS_OK : NS_ERROR_FAILURE;
     356                 :     }
     357                 :   }
     358                 : 
     359                 :   // Ensure that we have something to compile
     360               0 :   nsDependentString handlerText(mHandlerText);
     361               0 :   if (handlerText.IsEmpty())
     362               0 :     return NS_ERROR_FAILURE;
     363                 : 
     364               0 :   nsCAutoString bindingURI;
     365               0 :   mPrototypeBinding->DocURI()->GetSpec(bindingURI);
     366                 : 
     367                 :   PRUint32 argCount;
     368                 :   const char **argNames;
     369                 :   nsContentUtils::GetEventArgNames(kNameSpaceID_XBL, aName, &argCount,
     370               0 :                                    &argNames);
     371                 :   nsresult rv = aBoundContext->CompileEventHandler(aName, argCount, argNames,
     372                 :                                                    handlerText,
     373                 :                                                    bindingURI.get(), 
     374                 :                                                    mLineNumber,
     375               0 :                                                    JSVERSION_LATEST, aHandler);
     376               0 :   NS_ENSURE_SUCCESS(rv, rv);
     377                 : 
     378               0 :   if (pWindow) {
     379               0 :     pWindow->CacheXBLPrototypeHandler(this, aHandler);
     380                 :   }
     381                 : 
     382               0 :   return NS_OK;
     383                 : }
     384                 : 
     385                 : nsresult
     386               0 : nsXBLPrototypeHandler::DispatchXBLCommand(nsIDOMEventTarget* aTarget, nsIDOMEvent* aEvent)
     387                 : {
     388                 :   // This is a special-case optimization to make command handling fast.
     389                 :   // It isn't really a part of XBL, but it helps speed things up.
     390                 : 
     391                 :   // See if preventDefault has been set.  If so, don't execute.
     392               0 :   bool preventDefault = false;
     393               0 :   nsCOMPtr<nsIDOMNSEvent> domNSEvent = do_QueryInterface(aEvent);
     394               0 :   if (domNSEvent) {
     395               0 :     domNSEvent->GetPreventDefault(&preventDefault);
     396                 :   }
     397                 : 
     398               0 :   if (preventDefault)
     399               0 :     return NS_OK;
     400                 : 
     401               0 :   nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(aEvent);
     402               0 :   if (privateEvent) {
     403               0 :     bool dispatchStopped = privateEvent->IsDispatchStopped();
     404               0 :     if (dispatchStopped)
     405               0 :       return NS_OK;
     406                 :   }
     407                 : 
     408                 :   // Instead of executing JS, let's get the controller for the bound
     409                 :   // element and call doCommand on it.
     410               0 :   nsCOMPtr<nsIController> controller;
     411                 : 
     412               0 :   nsCOMPtr<nsPIDOMWindow> privateWindow;
     413               0 :   nsCOMPtr<nsPIWindowRoot> windowRoot(do_QueryInterface(aTarget));
     414               0 :   if (windowRoot) {
     415               0 :     privateWindow = windowRoot->GetWindow();
     416                 :   }
     417                 :   else {
     418               0 :     privateWindow = do_QueryInterface(aTarget);
     419               0 :     if (!privateWindow) {
     420               0 :       nsCOMPtr<nsIContent> elt(do_QueryInterface(aTarget));
     421               0 :       nsCOMPtr<nsIDocument> doc;
     422                 :       // XXXbz sXBL/XBL2 issue -- this should be the "scope doc" or
     423                 :       // something... whatever we use when wrapping DOM nodes
     424                 :       // normally.  It's not clear that the owner doc is the right
     425                 :       // thing.
     426               0 :       if (elt)
     427               0 :         doc = elt->OwnerDoc();
     428                 : 
     429               0 :       if (!doc)
     430               0 :         doc = do_QueryInterface(aTarget);
     431                 : 
     432               0 :       if (!doc)
     433               0 :         return NS_ERROR_FAILURE;
     434                 : 
     435               0 :       privateWindow = do_QueryInterface(doc->GetScriptGlobalObject());
     436               0 :       if (!privateWindow)
     437               0 :         return NS_ERROR_FAILURE;
     438                 :     }
     439                 : 
     440               0 :     windowRoot = privateWindow->GetTopWindowRoot();
     441                 :   }
     442                 : 
     443               0 :   NS_LossyConvertUTF16toASCII command(mHandlerText);
     444               0 :   if (windowRoot)
     445               0 :     windowRoot->GetControllerForCommand(command.get(), getter_AddRefs(controller));
     446                 :   else
     447               0 :     controller = GetController(aTarget); // We're attached to the receiver possibly.
     448                 : 
     449               0 :   if (mEventName == nsGkAtoms::keypress &&
     450                 :       mDetail == nsIDOMKeyEvent::DOM_VK_SPACE &&
     451                 :       mMisc == 1) {
     452                 :     // get the focused element so that we can pageDown only at
     453                 :     // certain times.
     454                 : 
     455               0 :     nsCOMPtr<nsPIDOMWindow> windowToCheck;
     456               0 :     if (windowRoot)
     457               0 :       windowToCheck = windowRoot->GetWindow();
     458                 :     else
     459               0 :       windowToCheck = privateWindow->GetPrivateRoot();
     460                 : 
     461               0 :     nsCOMPtr<nsIContent> focusedContent;
     462               0 :     if (windowToCheck) {
     463               0 :       nsCOMPtr<nsPIDOMWindow> focusedWindow;
     464                 :       focusedContent =
     465               0 :         nsFocusManager::GetFocusedDescendant(windowToCheck, true, getter_AddRefs(focusedWindow));
     466                 :     }
     467                 : 
     468               0 :     bool isLink = false;
     469               0 :     nsIContent *content = focusedContent;
     470                 : 
     471                 :     // if the focused element is a link then we do want space to 
     472                 :     // scroll down. The focused element may be an element in a link,
     473                 :     // we need to check the parent node too. Only do this check if an
     474                 :     // element is focused and has a parent.
     475               0 :     if (focusedContent && focusedContent->GetParent()) {
     476               0 :       while (content) {
     477               0 :         if (content->Tag() == nsGkAtoms::a && content->IsHTML()) {
     478               0 :           isLink = true;
     479               0 :           break;
     480                 :         }
     481                 : 
     482               0 :         if (content->HasAttr(kNameSpaceID_XLink, nsGkAtoms::type)) {
     483                 :           isLink = content->AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::type,
     484               0 :                                         nsGkAtoms::simple, eCaseMatters);
     485                 : 
     486               0 :           if (isLink) {
     487               0 :             break;
     488                 :           }
     489                 :         }
     490                 : 
     491               0 :         content = content->GetParent();
     492                 :       }
     493                 : 
     494               0 :       if (!isLink)
     495               0 :         return NS_OK;
     496                 :     }
     497                 :   }
     498                 : 
     499                 :   // We are the default action for this command.
     500                 :   // Stop any other default action from executing.
     501               0 :   aEvent->PreventDefault();
     502                 :   
     503               0 :   if (controller)
     504               0 :     controller->DoCommand(command.get());
     505                 : 
     506               0 :   return NS_OK;
     507                 : }
     508                 : 
     509                 : nsresult
     510               0 : nsXBLPrototypeHandler::DispatchXULKeyCommand(nsIDOMEvent* aEvent)
     511                 : {
     512               0 :   nsCOMPtr<nsIContent> handlerElement = GetHandlerElement();
     513               0 :   NS_ENSURE_STATE(handlerElement);
     514               0 :   if (handlerElement->AttrValueIs(kNameSpaceID_None,
     515                 :                                   nsGkAtoms::disabled,
     516                 :                                   nsGkAtoms::_true,
     517               0 :                                   eCaseMatters)) {
     518                 :     // Don't dispatch command events for disabled keys.
     519               0 :     return NS_OK;
     520                 :   }
     521                 : 
     522               0 :   aEvent->PreventDefault();
     523                 : 
     524                 :   // Copy the modifiers from the key event.
     525               0 :   nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
     526               0 :   if (!keyEvent) {
     527               0 :     NS_ERROR("Trying to execute a key handler for a non-key event!");
     528               0 :     return NS_ERROR_FAILURE;
     529                 :   }
     530                 : 
     531               0 :   bool isAlt = false;
     532               0 :   bool isControl = false;
     533               0 :   bool isShift = false;
     534               0 :   bool isMeta = false;
     535               0 :   keyEvent->GetAltKey(&isAlt);
     536               0 :   keyEvent->GetCtrlKey(&isControl);
     537               0 :   keyEvent->GetShiftKey(&isShift);
     538               0 :   keyEvent->GetMetaKey(&isMeta);
     539                 : 
     540                 :   nsContentUtils::DispatchXULCommand(handlerElement, true,
     541                 :                                      nsnull, nsnull,
     542               0 :                                      isControl, isAlt, isShift, isMeta);
     543               0 :   return NS_OK;
     544                 : }
     545                 : 
     546                 : already_AddRefed<nsIAtom>
     547               0 : nsXBLPrototypeHandler::GetEventName()
     548                 : {
     549               0 :   nsIAtom* eventName = mEventName;
     550               0 :   NS_IF_ADDREF(eventName);
     551               0 :   return eventName;
     552                 : }
     553                 : 
     554                 : already_AddRefed<nsIController>
     555               0 : nsXBLPrototypeHandler::GetController(nsIDOMEventTarget* aTarget)
     556                 : {
     557                 :   // XXX Fix this so there's a generic interface that describes controllers, 
     558                 :   // This code should have no special knowledge of what objects might have controllers.
     559               0 :   nsCOMPtr<nsIControllers> controllers;
     560                 : 
     561               0 :   nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(aTarget));
     562               0 :   if (xulElement)
     563               0 :     xulElement->GetControllers(getter_AddRefs(controllers));
     564                 : 
     565               0 :   if (!controllers) {
     566               0 :     nsCOMPtr<nsIDOMHTMLTextAreaElement> htmlTextArea(do_QueryInterface(aTarget));
     567               0 :     if (htmlTextArea)
     568               0 :       htmlTextArea->GetControllers(getter_AddRefs(controllers));
     569                 :   }
     570                 : 
     571               0 :   if (!controllers) {
     572               0 :     nsCOMPtr<nsIDOMHTMLInputElement> htmlInputElement(do_QueryInterface(aTarget));
     573               0 :     if (htmlInputElement)
     574               0 :       htmlInputElement->GetControllers(getter_AddRefs(controllers));
     575                 :   }
     576                 : 
     577               0 :   if (!controllers) {
     578               0 :     nsCOMPtr<nsIDOMWindow> domWindow(do_QueryInterface(aTarget));
     579               0 :     if (domWindow)
     580               0 :       domWindow->GetControllers(getter_AddRefs(controllers));
     581                 :   }
     582                 : 
     583                 :   // Return the first controller.
     584                 :   // XXX This code should be checking the command name and using supportscommand and
     585                 :   // iscommandenabled.
     586                 :   nsIController* controller;
     587               0 :   if (controllers) {
     588               0 :     controllers->GetControllerAt(0, &controller);  // return reference
     589                 :   }
     590               0 :   else controller = nsnull;
     591                 : 
     592               0 :   return controller;
     593                 : }
     594                 : 
     595                 : bool
     596               0 : nsXBLPrototypeHandler::KeyEventMatched(nsIDOMKeyEvent* aKeyEvent,
     597                 :                                        PRUint32 aCharCode,
     598                 :                                        bool aIgnoreShiftKey)
     599                 : {
     600               0 :   if (mDetail != -1) {
     601                 :     // Get the keycode or charcode of the key event.
     602                 :     PRUint32 code;
     603                 : 
     604               0 :     if (mMisc) {
     605               0 :       if (aCharCode)
     606               0 :         code = aCharCode;
     607                 :       else
     608               0 :         aKeyEvent->GetCharCode(&code);
     609               0 :       if (IS_IN_BMP(code))
     610               0 :         code = ToLowerCase(PRUnichar(code));
     611                 :     }
     612                 :     else
     613               0 :       aKeyEvent->GetKeyCode(&code);
     614                 : 
     615               0 :     if (code != PRUint32(mDetail))
     616               0 :       return false;
     617                 :   }
     618                 : 
     619               0 :   return ModifiersMatchMask(aKeyEvent, aIgnoreShiftKey);
     620                 : }
     621                 : 
     622                 : bool
     623               0 : nsXBLPrototypeHandler::MouseEventMatched(nsIDOMMouseEvent* aMouseEvent)
     624                 : {
     625               0 :   if (mDetail == -1 && mMisc == 0 && (mKeyMask & cAllModifiers) == 0)
     626               0 :     return true; // No filters set up. It's generic.
     627                 : 
     628                 :   PRUint16 button;
     629               0 :   aMouseEvent->GetButton(&button);
     630               0 :   if (mDetail != -1 && (button != mDetail))
     631               0 :     return false;
     632                 : 
     633                 :   PRInt32 clickcount;
     634               0 :   aMouseEvent->GetDetail(&clickcount);
     635               0 :   if (mMisc != 0 && (clickcount != mMisc))
     636               0 :     return false;
     637                 : 
     638               0 :   return ModifiersMatchMask(aMouseEvent);
     639                 : }
     640                 : 
     641                 : struct keyCodeData {
     642                 :   const char* str;
     643                 :   size_t strlength;
     644                 :   PRUint32 keycode;
     645                 : };
     646                 : 
     647                 : // All of these must be uppercase, since the function below does
     648                 : // case-insensitive comparison by converting to uppercase.
     649                 : // XXX: be sure to check this periodically for new symbol additions!
     650                 : static const keyCodeData gKeyCodes[] = {
     651                 : 
     652                 : #define KEYCODE_ENTRY(str) {#str, sizeof(#str) - 1, nsIDOMKeyEvent::DOM_##str}
     653                 : #define KEYCODE_ENTRY2(str, code) {str, sizeof(str) - 1, code}
     654                 : 
     655                 :   KEYCODE_ENTRY(VK_CANCEL),
     656                 :   KEYCODE_ENTRY2("VK_BACK", nsIDOMKeyEvent::DOM_VK_BACK_SPACE),
     657                 :   KEYCODE_ENTRY(VK_TAB),
     658                 :   KEYCODE_ENTRY(VK_CLEAR),
     659                 :   KEYCODE_ENTRY(VK_RETURN),
     660                 :   KEYCODE_ENTRY(VK_ENTER),
     661                 :   KEYCODE_ENTRY(VK_SHIFT),
     662                 :   KEYCODE_ENTRY(VK_CONTROL),
     663                 :   KEYCODE_ENTRY(VK_ALT),
     664                 :   KEYCODE_ENTRY(VK_PAUSE),
     665                 :   KEYCODE_ENTRY(VK_CAPS_LOCK),
     666                 :   KEYCODE_ENTRY(VK_ESCAPE),
     667                 :   KEYCODE_ENTRY(VK_SPACE),
     668                 :   KEYCODE_ENTRY(VK_PAGE_UP),
     669                 :   KEYCODE_ENTRY(VK_PAGE_DOWN),
     670                 :   KEYCODE_ENTRY(VK_END),
     671                 :   KEYCODE_ENTRY(VK_HOME),
     672                 :   KEYCODE_ENTRY(VK_LEFT),
     673                 :   KEYCODE_ENTRY(VK_UP),
     674                 :   KEYCODE_ENTRY(VK_RIGHT),
     675                 :   KEYCODE_ENTRY(VK_DOWN),
     676                 :   KEYCODE_ENTRY(VK_PRINTSCREEN),
     677                 :   KEYCODE_ENTRY(VK_INSERT),
     678                 :   KEYCODE_ENTRY(VK_HELP),
     679                 :   KEYCODE_ENTRY(VK_DELETE),
     680                 :   KEYCODE_ENTRY(VK_0),
     681                 :   KEYCODE_ENTRY(VK_1),
     682                 :   KEYCODE_ENTRY(VK_2),
     683                 :   KEYCODE_ENTRY(VK_3),
     684                 :   KEYCODE_ENTRY(VK_4),
     685                 :   KEYCODE_ENTRY(VK_5),
     686                 :   KEYCODE_ENTRY(VK_6),
     687                 :   KEYCODE_ENTRY(VK_7),
     688                 :   KEYCODE_ENTRY(VK_8),
     689                 :   KEYCODE_ENTRY(VK_9),
     690                 :   KEYCODE_ENTRY(VK_SEMICOLON),
     691                 :   KEYCODE_ENTRY(VK_EQUALS),
     692                 :   KEYCODE_ENTRY(VK_A),
     693                 :   KEYCODE_ENTRY(VK_B),
     694                 :   KEYCODE_ENTRY(VK_C),
     695                 :   KEYCODE_ENTRY(VK_D),
     696                 :   KEYCODE_ENTRY(VK_E),
     697                 :   KEYCODE_ENTRY(VK_F),
     698                 :   KEYCODE_ENTRY(VK_G),
     699                 :   KEYCODE_ENTRY(VK_H),
     700                 :   KEYCODE_ENTRY(VK_I),
     701                 :   KEYCODE_ENTRY(VK_J),
     702                 :   KEYCODE_ENTRY(VK_K),
     703                 :   KEYCODE_ENTRY(VK_L),
     704                 :   KEYCODE_ENTRY(VK_M),
     705                 :   KEYCODE_ENTRY(VK_N),
     706                 :   KEYCODE_ENTRY(VK_O),
     707                 :   KEYCODE_ENTRY(VK_P),
     708                 :   KEYCODE_ENTRY(VK_Q),
     709                 :   KEYCODE_ENTRY(VK_R),
     710                 :   KEYCODE_ENTRY(VK_S),
     711                 :   KEYCODE_ENTRY(VK_T),
     712                 :   KEYCODE_ENTRY(VK_U),
     713                 :   KEYCODE_ENTRY(VK_V),
     714                 :   KEYCODE_ENTRY(VK_W),
     715                 :   KEYCODE_ENTRY(VK_X),
     716                 :   KEYCODE_ENTRY(VK_Y),
     717                 :   KEYCODE_ENTRY(VK_Z),
     718                 :   KEYCODE_ENTRY(VK_NUMPAD0),
     719                 :   KEYCODE_ENTRY(VK_NUMPAD1),
     720                 :   KEYCODE_ENTRY(VK_NUMPAD2),
     721                 :   KEYCODE_ENTRY(VK_NUMPAD3),
     722                 :   KEYCODE_ENTRY(VK_NUMPAD4),
     723                 :   KEYCODE_ENTRY(VK_NUMPAD5),
     724                 :   KEYCODE_ENTRY(VK_NUMPAD6),
     725                 :   KEYCODE_ENTRY(VK_NUMPAD7),
     726                 :   KEYCODE_ENTRY(VK_NUMPAD8),
     727                 :   KEYCODE_ENTRY(VK_NUMPAD9),
     728                 :   KEYCODE_ENTRY(VK_MULTIPLY),
     729                 :   KEYCODE_ENTRY(VK_ADD),
     730                 :   KEYCODE_ENTRY(VK_SEPARATOR),
     731                 :   KEYCODE_ENTRY(VK_SUBTRACT),
     732                 :   KEYCODE_ENTRY(VK_DECIMAL),
     733                 :   KEYCODE_ENTRY(VK_DIVIDE),
     734                 :   KEYCODE_ENTRY(VK_F1),
     735                 :   KEYCODE_ENTRY(VK_F2),
     736                 :   KEYCODE_ENTRY(VK_F3),
     737                 :   KEYCODE_ENTRY(VK_F4),
     738                 :   KEYCODE_ENTRY(VK_F5),
     739                 :   KEYCODE_ENTRY(VK_F6),
     740                 :   KEYCODE_ENTRY(VK_F7),
     741                 :   KEYCODE_ENTRY(VK_F8),
     742                 :   KEYCODE_ENTRY(VK_F9),
     743                 :   KEYCODE_ENTRY(VK_F10),
     744                 :   KEYCODE_ENTRY(VK_F11),
     745                 :   KEYCODE_ENTRY(VK_F12),
     746                 :   KEYCODE_ENTRY(VK_F13),
     747                 :   KEYCODE_ENTRY(VK_F14),
     748                 :   KEYCODE_ENTRY(VK_F15),
     749                 :   KEYCODE_ENTRY(VK_F16),
     750                 :   KEYCODE_ENTRY(VK_F17),
     751                 :   KEYCODE_ENTRY(VK_F18),
     752                 :   KEYCODE_ENTRY(VK_F19),
     753                 :   KEYCODE_ENTRY(VK_F20),
     754                 :   KEYCODE_ENTRY(VK_F21),
     755                 :   KEYCODE_ENTRY(VK_F22),
     756                 :   KEYCODE_ENTRY(VK_F23),
     757                 :   KEYCODE_ENTRY(VK_F24),
     758                 :   KEYCODE_ENTRY(VK_NUM_LOCK),
     759                 :   KEYCODE_ENTRY(VK_SCROLL_LOCK),
     760                 :   KEYCODE_ENTRY(VK_COMMA),
     761                 :   KEYCODE_ENTRY(VK_PERIOD),
     762                 :   KEYCODE_ENTRY(VK_SLASH),
     763                 :   KEYCODE_ENTRY(VK_BACK_QUOTE),
     764                 :   KEYCODE_ENTRY(VK_OPEN_BRACKET),
     765                 :   KEYCODE_ENTRY(VK_BACK_SLASH),
     766                 :   KEYCODE_ENTRY(VK_CLOSE_BRACKET),
     767                 :   KEYCODE_ENTRY(VK_QUOTE)
     768                 : 
     769                 : #undef KEYCODE_ENTRY
     770                 : #undef KEYCODE_ENTRY2
     771                 : 
     772                 : };
     773                 : 
     774               0 : PRInt32 nsXBLPrototypeHandler::GetMatchingKeyCode(const nsAString& aKeyName)
     775                 : {
     776               0 :   nsCAutoString keyName;
     777               0 :   keyName.AssignWithConversion(aKeyName);
     778               0 :   ToUpperCase(keyName); // We want case-insensitive comparison with data
     779                 :                         // stored as uppercase.
     780                 : 
     781               0 :   PRUint32 keyNameLength = keyName.Length();
     782               0 :   const char* keyNameStr = keyName.get();
     783               0 :   for (PRUint16 i = 0; i < (sizeof(gKeyCodes) / sizeof(gKeyCodes[0])); ++i)
     784               0 :     if (keyNameLength == gKeyCodes[i].strlength &&
     785               0 :         !nsCRT::strcmp(gKeyCodes[i].str, keyNameStr))
     786               0 :       return gKeyCodes[i].keycode;
     787                 : 
     788               0 :   return 0;
     789                 : }
     790                 : 
     791               0 : PRInt32 nsXBLPrototypeHandler::KeyToMask(PRInt32 key)
     792                 : {
     793               0 :   switch (key)
     794                 :   {
     795                 :     case nsIDOMKeyEvent::DOM_VK_META:
     796               0 :       return cMeta | cMetaMask;
     797                 :       break;
     798                 : 
     799                 :     case nsIDOMKeyEvent::DOM_VK_ALT:
     800               0 :       return cAlt | cAltMask;
     801                 :       break;
     802                 : 
     803                 :     case nsIDOMKeyEvent::DOM_VK_CONTROL:
     804                 :     default:
     805               0 :       return cControl | cControlMask;
     806                 :   }
     807                 :   return cControl | cControlMask;  // for warning avoidance
     808                 : }
     809                 : 
     810                 : void
     811               0 : nsXBLPrototypeHandler::GetEventType(nsAString& aEvent)
     812                 : {
     813               0 :   nsCOMPtr<nsIContent> handlerElement = GetHandlerElement();
     814               0 :   if (!handlerElement) {
     815               0 :     aEvent.Truncate();
     816                 :     return;
     817                 :   }
     818               0 :   handlerElement->GetAttr(kNameSpaceID_None, nsGkAtoms::event, aEvent);
     819                 :   
     820               0 :   if (aEvent.IsEmpty() && (mType & NS_HANDLER_TYPE_XUL))
     821                 :     // If no type is specified for a XUL <key> element, let's assume that we're "keypress".
     822               0 :     aEvent.AssignLiteral("keypress");
     823                 : }
     824                 : 
     825                 : void
     826               0 : nsXBLPrototypeHandler::ConstructPrototype(nsIContent* aKeyElement, 
     827                 :                                           const PRUnichar* aEvent,
     828                 :                                           const PRUnichar* aPhase,
     829                 :                                           const PRUnichar* aAction,
     830                 :                                           const PRUnichar* aCommand,
     831                 :                                           const PRUnichar* aKeyCode,
     832                 :                                           const PRUnichar* aCharCode,
     833                 :                                           const PRUnichar* aModifiers,
     834                 :                                           const PRUnichar* aButton,
     835                 :                                           const PRUnichar* aClickCount,
     836                 :                                           const PRUnichar* aGroup,
     837                 :                                           const PRUnichar* aPreventDefault,
     838                 :                                           const PRUnichar* aAllowUntrusted)
     839                 : {
     840               0 :   mType = 0;
     841                 : 
     842               0 :   if (aKeyElement) {
     843               0 :     mType |= NS_HANDLER_TYPE_XUL;
     844               0 :     nsCOMPtr<nsIWeakReference> weak = do_GetWeakReference(aKeyElement);
     845               0 :     if (!weak) {
     846                 :       return;
     847                 :     }
     848               0 :     weak.swap(mHandlerElement);
     849                 :   }
     850                 :   else {
     851               0 :     mType |= aCommand ? NS_HANDLER_TYPE_XBL_COMMAND : NS_HANDLER_TYPE_XBL_JS;
     852               0 :     mHandlerText = nsnull;
     853                 :   }
     854                 : 
     855               0 :   mDetail = -1;
     856               0 :   mMisc = 0;
     857               0 :   mKeyMask = 0;
     858               0 :   mPhase = NS_PHASE_BUBBLING;
     859                 : 
     860               0 :   if (aAction)
     861               0 :     mHandlerText = ToNewUnicode(nsDependentString(aAction));
     862               0 :   else if (aCommand)
     863               0 :     mHandlerText = ToNewUnicode(nsDependentString(aCommand));
     864                 : 
     865               0 :   nsAutoString event(aEvent);
     866               0 :   if (event.IsEmpty()) {
     867               0 :     if (mType & NS_HANDLER_TYPE_XUL)
     868               0 :       GetEventType(event);
     869               0 :     if (event.IsEmpty())
     870                 :       return;
     871                 :   }
     872                 : 
     873               0 :   mEventName = do_GetAtom(event);
     874                 : 
     875               0 :   if (aPhase) {
     876               0 :     const nsDependentString phase(aPhase);
     877               0 :     if (phase.EqualsLiteral("capturing"))
     878               0 :       mPhase = NS_PHASE_CAPTURING;
     879               0 :     else if (phase.EqualsLiteral("target"))
     880               0 :       mPhase = NS_PHASE_TARGET;
     881                 :   }
     882                 : 
     883                 :   // Button and clickcount apply only to XBL handlers and don't apply to XUL key
     884                 :   // handlers.  
     885               0 :   if (aButton && *aButton)
     886               0 :     mDetail = *aButton - '0';
     887                 : 
     888               0 :   if (aClickCount && *aClickCount)
     889               0 :     mMisc = *aClickCount - '0';
     890                 : 
     891                 :   // Modifiers are supported by both types of handlers (XUL and XBL).  
     892               0 :   nsAutoString modifiers(aModifiers);
     893               0 :   if (mType & NS_HANDLER_TYPE_XUL)
     894               0 :     aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiers);
     895                 :   
     896               0 :   if (!modifiers.IsEmpty()) {
     897               0 :     mKeyMask = cAllModifiers;
     898               0 :     char* str = ToNewCString(modifiers);
     899                 :     char* newStr;
     900               0 :     char* token = nsCRT::strtok( str, ", \t", &newStr );
     901               0 :     while( token != NULL ) {
     902               0 :       if (PL_strcmp(token, "shift") == 0)
     903               0 :         mKeyMask |= cShift | cShiftMask;
     904               0 :       else if (PL_strcmp(token, "alt") == 0)
     905               0 :         mKeyMask |= cAlt | cAltMask;
     906               0 :       else if (PL_strcmp(token, "meta") == 0)
     907               0 :         mKeyMask |= cMeta | cMetaMask;
     908               0 :       else if (PL_strcmp(token, "control") == 0)
     909               0 :         mKeyMask |= cControl | cControlMask;
     910               0 :       else if (PL_strcmp(token, "accel") == 0)
     911               0 :         mKeyMask |= KeyToMask(kAccelKey);
     912               0 :       else if (PL_strcmp(token, "access") == 0)
     913               0 :         mKeyMask |= KeyToMask(kMenuAccessKey);
     914               0 :       else if (PL_strcmp(token, "any") == 0)
     915               0 :         mKeyMask &= ~(mKeyMask << 4);
     916                 :     
     917               0 :       token = nsCRT::strtok( newStr, ", \t", &newStr );
     918                 :     }
     919                 : 
     920               0 :     nsMemory::Free(str);
     921                 :   }
     922                 : 
     923               0 :   nsAutoString key(aCharCode);
     924               0 :   if (key.IsEmpty()) {
     925               0 :     if (mType & NS_HANDLER_TYPE_XUL) {
     926               0 :       aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::key, key);
     927               0 :       if (key.IsEmpty()) 
     928               0 :         aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::charcode, key);
     929                 :     }
     930                 :   }
     931                 : 
     932               0 :   if (!key.IsEmpty()) {
     933               0 :     if (mKeyMask == 0)
     934               0 :       mKeyMask = cAllModifiers;
     935               0 :     nsContentUtils::ASCIIToLower(key);
     936                 : 
     937                 :     // We have a charcode.
     938               0 :     mMisc = 1;
     939               0 :     mDetail = key[0];
     940               0 :     const PRUint8 GTK2Modifiers = cShift | cControl | cShiftMask | cControlMask;
     941               0 :     if ((mKeyMask & GTK2Modifiers) == GTK2Modifiers &&
     942               0 :         modifiers.First() != PRUnichar(',') && mDetail == 'u')
     943               0 :       ReportKeyConflict(key.get(), modifiers.get(), aKeyElement, "GTK2Conflict");
     944               0 :     const PRUint8 WinModifiers = cControl | cAlt | cControlMask | cAltMask;
     945               0 :     if ((mKeyMask & WinModifiers) == WinModifiers &&
     946               0 :         modifiers.First() != PRUnichar(',') && ('a' <= mDetail && mDetail <= 'z'))
     947               0 :       ReportKeyConflict(key.get(), modifiers.get(), aKeyElement, "WinConflict");
     948                 :   }
     949                 :   else {
     950               0 :     key.Assign(aKeyCode);
     951               0 :     if (mType & NS_HANDLER_TYPE_XUL)
     952               0 :       aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, key);
     953                 :     
     954               0 :     if (!key.IsEmpty()) {
     955               0 :       if (mKeyMask == 0)
     956               0 :         mKeyMask = cAllModifiers;
     957               0 :       mDetail = GetMatchingKeyCode(key);
     958                 :     }
     959                 :   }
     960                 : 
     961               0 :   if (aGroup && nsDependentString(aGroup).EqualsLiteral("system"))
     962               0 :     mType |= NS_HANDLER_TYPE_SYSTEM;
     963                 : 
     964               0 :   if (aPreventDefault &&
     965               0 :       nsDependentString(aPreventDefault).EqualsLiteral("true"))
     966               0 :     mType |= NS_HANDLER_TYPE_PREVENTDEFAULT;
     967                 : 
     968               0 :   if (aAllowUntrusted) {
     969               0 :     mType |= NS_HANDLER_HAS_ALLOW_UNTRUSTED_ATTR;
     970               0 :     if (nsDependentString(aAllowUntrusted).EqualsLiteral("true")) {
     971               0 :       mType |= NS_HANDLER_ALLOW_UNTRUSTED;
     972                 :     } else {
     973               0 :       mType &= ~NS_HANDLER_ALLOW_UNTRUSTED;
     974                 :     }
     975                 :   }
     976                 : }
     977                 : 
     978                 : void
     979               0 : nsXBLPrototypeHandler::ReportKeyConflict(const PRUnichar* aKey, const PRUnichar* aModifiers, nsIContent* aKeyElement, const char *aMessageName)
     980                 : {
     981               0 :   nsCOMPtr<nsIDocument> doc;
     982               0 :   if (mPrototypeBinding) {
     983               0 :     nsXBLDocumentInfo* docInfo = mPrototypeBinding->XBLDocumentInfo();
     984               0 :     if (docInfo) {
     985               0 :       doc = docInfo->GetDocument();
     986                 :     }
     987               0 :   } else if (aKeyElement) {
     988               0 :     doc = aKeyElement->OwnerDoc();
     989                 :   }
     990                 : 
     991               0 :   const PRUnichar* params[] = { aKey, aModifiers };
     992                 :   nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
     993                 :                                   "XBL Prototype Handler", doc,
     994                 :                                   nsContentUtils::eXBL_PROPERTIES,
     995                 :                                   aMessageName,
     996                 :                                   params, ArrayLength(params),
     997               0 :                                   nsnull, EmptyString(), mLineNumber);
     998               0 : }
     999                 : 
    1000                 : bool
    1001               0 : nsXBLPrototypeHandler::ModifiersMatchMask(nsIDOMUIEvent* aEvent,
    1002                 :                                           bool aIgnoreShiftKey)
    1003                 : {
    1004               0 :   nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aEvent));
    1005               0 :   nsCOMPtr<nsIDOMMouseEvent> mouse(do_QueryInterface(aEvent));
    1006                 : 
    1007                 :   bool keyPresent;
    1008               0 :   if (mKeyMask & cMetaMask) {
    1009               0 :     key ? key->GetMetaKey(&keyPresent) : mouse->GetMetaKey(&keyPresent);
    1010               0 :     if (keyPresent != ((mKeyMask & cMeta) != 0))
    1011               0 :       return false;
    1012                 :   }
    1013                 : 
    1014               0 :   if (mKeyMask & cShiftMask && !aIgnoreShiftKey) {
    1015               0 :     key ? key->GetShiftKey(&keyPresent) : mouse->GetShiftKey(&keyPresent);
    1016               0 :     if (keyPresent != ((mKeyMask & cShift) != 0))
    1017               0 :       return false;
    1018                 :   }
    1019                 : 
    1020               0 :   if (mKeyMask & cAltMask) {
    1021               0 :     key ? key->GetAltKey(&keyPresent) : mouse->GetAltKey(&keyPresent);
    1022               0 :     if (keyPresent != ((mKeyMask & cAlt) != 0))
    1023               0 :       return false;
    1024                 :   }
    1025                 : 
    1026               0 :   if (mKeyMask & cControlMask) {
    1027               0 :     key ? key->GetCtrlKey(&keyPresent) : mouse->GetCtrlKey(&keyPresent);
    1028               0 :     if (keyPresent != ((mKeyMask & cControl) != 0))
    1029               0 :       return false;
    1030                 :   }
    1031                 : 
    1032               0 :   return true;
    1033                 : }
    1034                 : 
    1035                 : nsresult
    1036               0 : nsXBLPrototypeHandler::Read(nsIScriptContext* aContext, nsIObjectInputStream* aStream)
    1037                 : {
    1038               0 :   nsresult rv = aStream->Read8(&mPhase);
    1039               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1040               0 :   rv = aStream->Read8(&mKeyMask);
    1041               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1042               0 :   rv = aStream->Read8(&mType);
    1043               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1044               0 :   rv = aStream->Read8(&mMisc);
    1045               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1046                 : 
    1047                 :   PRUint32 detail; 
    1048               0 :   rv = aStream->Read32(&detail);
    1049               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1050               0 :   mDetail = detail;
    1051                 : 
    1052               0 :   nsAutoString name;
    1053               0 :   rv = aStream->ReadString(name);
    1054               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1055               0 :   mEventName = do_GetAtom(name);
    1056                 : 
    1057               0 :   rv = aStream->Read32(&mLineNumber);
    1058               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1059                 : 
    1060               0 :   nsAutoString handlerText;
    1061               0 :   rv = aStream->ReadString(handlerText);
    1062               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1063               0 :   if (!handlerText.IsEmpty())
    1064               0 :     mHandlerText = ToNewUnicode(handlerText);
    1065                 : 
    1066               0 :   return NS_OK;
    1067                 : }
    1068                 : 
    1069                 : nsresult
    1070               0 : nsXBLPrototypeHandler::Write(nsIScriptContext* aContext, nsIObjectOutputStream* aStream)
    1071                 : {
    1072                 :   // Make sure we don't write out NS_HANDLER_TYPE_XUL types, as they are used
    1073                 :   // for <keyset> elements.
    1074               0 :   if ((mType & NS_HANDLER_TYPE_XUL) || !mEventName)
    1075               0 :     return NS_OK;
    1076                 : 
    1077               0 :   XBLBindingSerializeDetails type = XBLBinding_Serialize_Handler;
    1078                 : 
    1079               0 :   nsresult rv = aStream->Write8(type);
    1080               0 :   rv = aStream->Write8(mPhase);
    1081               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1082               0 :   rv = aStream->Write8(mKeyMask);
    1083               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1084               0 :   rv = aStream->Write8(mType);
    1085               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1086               0 :   rv = aStream->Write8(mMisc);
    1087               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1088               0 :   rv = aStream->Write32(mDetail);
    1089               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1090                 : 
    1091               0 :   rv = aStream->WriteWStringZ(nsDependentAtomString(mEventName).get());
    1092               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1093                 : 
    1094               0 :   rv = aStream->Write32(mLineNumber);
    1095               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1096               0 :   return aStream->WriteWStringZ(mHandlerText ? mHandlerText : EmptyString().get());
    1097                 : }

Generated by: LCOV version 1.7