dom/events/JSEventHandler.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/events/JSEventHandler.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,277 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef mozilla_JSEventHandler_h_
    1.10 +#define mozilla_JSEventHandler_h_
    1.11 +
    1.12 +#include "mozilla/Attributes.h"
    1.13 +#include "mozilla/MemoryReporting.h"
    1.14 +#include "mozilla/dom/EventHandlerBinding.h"
    1.15 +#include "nsCOMPtr.h"
    1.16 +#include "nsCycleCollectionParticipant.h"
    1.17 +#include "nsIAtom.h"
    1.18 +#include "nsIDOMKeyEvent.h"
    1.19 +#include "nsIDOMEventListener.h"
    1.20 +#include "nsIScriptContext.h"
    1.21 +
    1.22 +namespace mozilla {
    1.23 +
    1.24 +class TypedEventHandler
    1.25 +{
    1.26 +public:
    1.27 +  enum HandlerType
    1.28 +  {
    1.29 +    eUnset = 0,
    1.30 +    eNormal = 0x1,
    1.31 +    eOnError = 0x2,
    1.32 +    eOnBeforeUnload = 0x3,
    1.33 +    eTypeBits = 0x3
    1.34 +  };
    1.35 +
    1.36 +  TypedEventHandler()
    1.37 +    : mBits(0)
    1.38 +  {
    1.39 +  }
    1.40 +
    1.41 +  TypedEventHandler(dom::EventHandlerNonNull* aHandler)
    1.42 +  {
    1.43 +    Assign(aHandler, eNormal);
    1.44 +  }
    1.45 +
    1.46 +  TypedEventHandler(dom::OnErrorEventHandlerNonNull* aHandler)
    1.47 +  {
    1.48 +    Assign(aHandler, eOnError);
    1.49 +  }
    1.50 +
    1.51 +  TypedEventHandler(dom::OnBeforeUnloadEventHandlerNonNull* aHandler)
    1.52 +  {
    1.53 +    Assign(aHandler, eOnBeforeUnload);
    1.54 +  }
    1.55 +
    1.56 +  TypedEventHandler(const TypedEventHandler& aOther)
    1.57 +  {
    1.58 +    if (aOther.HasEventHandler()) {
    1.59 +      // Have to make sure we take our own ref
    1.60 +      Assign(aOther.Ptr(), aOther.Type());
    1.61 +    } else {
    1.62 +      mBits = 0;
    1.63 +    }
    1.64 +  }
    1.65 +
    1.66 +  ~TypedEventHandler()
    1.67 +  {
    1.68 +    ReleaseHandler();
    1.69 +  }
    1.70 +
    1.71 +  HandlerType Type() const
    1.72 +  {
    1.73 +    return HandlerType(mBits & eTypeBits);
    1.74 +  }
    1.75 +
    1.76 +  bool HasEventHandler() const
    1.77 +  {
    1.78 +    return !!Ptr();
    1.79 +  }
    1.80 +
    1.81 +  void SetHandler(const TypedEventHandler& aHandler)
    1.82 +  {
    1.83 +    if (aHandler.HasEventHandler()) {
    1.84 +      ReleaseHandler();
    1.85 +      Assign(aHandler.Ptr(), aHandler.Type());
    1.86 +    } else {
    1.87 +      ForgetHandler();
    1.88 +    }
    1.89 +  }
    1.90 +
    1.91 +  dom::EventHandlerNonNull* NormalEventHandler() const
    1.92 +  {
    1.93 +    MOZ_ASSERT(Type() == eNormal && Ptr());
    1.94 +    return reinterpret_cast<dom::EventHandlerNonNull*>(Ptr());
    1.95 +  }
    1.96 +
    1.97 +  void SetHandler(dom::EventHandlerNonNull* aHandler)
    1.98 +  {
    1.99 +    ReleaseHandler();
   1.100 +    Assign(aHandler, eNormal);
   1.101 +  }
   1.102 +
   1.103 +  dom::OnBeforeUnloadEventHandlerNonNull* OnBeforeUnloadEventHandler() const
   1.104 +  {
   1.105 +    MOZ_ASSERT(Type() == eOnBeforeUnload);
   1.106 +    return reinterpret_cast<dom::OnBeforeUnloadEventHandlerNonNull*>(Ptr());
   1.107 +  }
   1.108 +
   1.109 +  void SetHandler(dom::OnBeforeUnloadEventHandlerNonNull* aHandler)
   1.110 +  {
   1.111 +    ReleaseHandler();
   1.112 +    Assign(aHandler, eOnBeforeUnload);
   1.113 +  }
   1.114 +
   1.115 +  dom::OnErrorEventHandlerNonNull* OnErrorEventHandler() const
   1.116 +  {
   1.117 +    MOZ_ASSERT(Type() == eOnError);
   1.118 +    return reinterpret_cast<dom::OnErrorEventHandlerNonNull*>(Ptr());
   1.119 +  }
   1.120 +
   1.121 +  void SetHandler(dom::OnErrorEventHandlerNonNull* aHandler)
   1.122 +  {
   1.123 +    ReleaseHandler();
   1.124 +    Assign(aHandler, eOnError);
   1.125 +  }
   1.126 +
   1.127 +  dom::CallbackFunction* Ptr() const
   1.128 +  {
   1.129 +    // Have to cast eTypeBits so we don't have to worry about
   1.130 +    // promotion issues after the bitflip.
   1.131 +    return reinterpret_cast<dom::CallbackFunction*>(mBits &
   1.132 +                                                      ~uintptr_t(eTypeBits));
   1.133 +  }
   1.134 +
   1.135 +  void ForgetHandler()
   1.136 +  {
   1.137 +    ReleaseHandler();
   1.138 +    mBits = 0;
   1.139 +  }
   1.140 +
   1.141 +  bool operator==(const TypedEventHandler& aOther) const
   1.142 +  {
   1.143 +    return
   1.144 +      Ptr() && aOther.Ptr() &&
   1.145 +      Ptr()->CallbackPreserveColor() == aOther.Ptr()->CallbackPreserveColor();
   1.146 +  }
   1.147 +
   1.148 +private:
   1.149 +  void operator=(const TypedEventHandler&) MOZ_DELETE;
   1.150 +
   1.151 +  void ReleaseHandler()
   1.152 +  {
   1.153 +    nsISupports* ptr = Ptr();
   1.154 +    NS_IF_RELEASE(ptr);
   1.155 +  }
   1.156 +
   1.157 +  void Assign(nsISupports* aHandler, HandlerType aType)
   1.158 +  {
   1.159 +    MOZ_ASSERT(aHandler, "Must have handler");
   1.160 +    NS_ADDREF(aHandler);
   1.161 +    mBits = uintptr_t(aHandler) | uintptr_t(aType);
   1.162 +  }
   1.163 +
   1.164 +  uintptr_t mBits;
   1.165 +};
   1.166 +
   1.167 +/**
   1.168 + * Implemented by script event listeners. Used to retrieve the script object
   1.169 + * corresponding to the event target and the handler itself.
   1.170 + *
   1.171 + * Note, mTarget is a raw pointer and the owner of the JSEventHandler object
   1.172 + * is expected to call Disconnect()!
   1.173 + */
   1.174 +
   1.175 +#define NS_JSEVENTHANDLER_IID \
   1.176 +{ 0x4f486881, 0x1956, 0x4079, \
   1.177 +  { 0x8c, 0xa0, 0xf3, 0xbd, 0x60, 0x5c, 0xc2, 0x79 } }
   1.178 +
   1.179 +class JSEventHandler : public nsIDOMEventListener
   1.180 +{
   1.181 +public:
   1.182 +  NS_DECLARE_STATIC_IID_ACCESSOR(NS_JSEVENTHANDLER_IID)
   1.183 +
   1.184 +  JSEventHandler(nsISupports* aTarget, nsIAtom* aType,
   1.185 +                 const TypedEventHandler& aTypedHandler);
   1.186 +
   1.187 +  virtual ~JSEventHandler();
   1.188 +
   1.189 +  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   1.190 +
   1.191 +  // nsIDOMEventListener interface
   1.192 +  NS_DECL_NSIDOMEVENTLISTENER
   1.193 +
   1.194 +  nsISupports* GetEventTarget() const
   1.195 +  {
   1.196 +    return mTarget;
   1.197 +  }
   1.198 +
   1.199 +  void Disconnect()
   1.200 +  {
   1.201 +    mTarget = nullptr;
   1.202 +  }
   1.203 +
   1.204 +  const TypedEventHandler& GetTypedEventHandler() const
   1.205 +  {
   1.206 +    return mTypedHandler;
   1.207 +  }
   1.208 +
   1.209 +  void ForgetHandler()
   1.210 +  {
   1.211 +    mTypedHandler.ForgetHandler();
   1.212 +  }
   1.213 +
   1.214 +  nsIAtom* EventName() const
   1.215 +  {
   1.216 +    return mEventName;
   1.217 +  }
   1.218 +
   1.219 +  // Set a handler for this event listener.  The handler must already
   1.220 +  // be bound to the right target.
   1.221 +  void SetHandler(const TypedEventHandler& aTypedHandler)
   1.222 +  {
   1.223 +    mTypedHandler.SetHandler(aTypedHandler);
   1.224 +  }
   1.225 +  void SetHandler(dom::EventHandlerNonNull* aHandler)
   1.226 +  {
   1.227 +    mTypedHandler.SetHandler(aHandler);
   1.228 +  }
   1.229 +  void SetHandler(dom::OnBeforeUnloadEventHandlerNonNull* aHandler)
   1.230 +  {
   1.231 +    mTypedHandler.SetHandler(aHandler);
   1.232 +  }
   1.233 +  void SetHandler(dom::OnErrorEventHandlerNonNull* aHandler)
   1.234 +  {
   1.235 +    mTypedHandler.SetHandler(aHandler);
   1.236 +  }
   1.237 +
   1.238 +  size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
   1.239 +  {
   1.240 +    return 0;
   1.241 +
   1.242 +    // Measurement of the following members may be added later if DMD finds it
   1.243 +    // is worthwhile:
   1.244 +    // - mTarget
   1.245 +    //
   1.246 +    // The following members are not measured:
   1.247 +    // - mTypedHandler: may be shared with others
   1.248 +    // - mEventName: shared with others
   1.249 +  }
   1.250 +
   1.251 +  size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
   1.252 +  {
   1.253 +    return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   1.254 +  }
   1.255 +
   1.256 +  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS(JSEventHandler)
   1.257 +
   1.258 +  bool IsBlackForCC();
   1.259 +
   1.260 +protected:
   1.261 +  nsISupports* mTarget;
   1.262 +  nsCOMPtr<nsIAtom> mEventName;
   1.263 +  TypedEventHandler mTypedHandler;
   1.264 +};
   1.265 +
   1.266 +NS_DEFINE_STATIC_IID_ACCESSOR(JSEventHandler, NS_JSEVENTHANDLER_IID)
   1.267 +
   1.268 +} // namespace mozilla
   1.269 +
   1.270 +/**
   1.271 + * Factory function.  aHandler must already be bound to aTarget.
   1.272 + * aContext is allowed to be null if aHandler is already set up.
   1.273 + */
   1.274 +nsresult NS_NewJSEventHandler(nsISupports* aTarget,
   1.275 +                              nsIAtom* aType,
   1.276 +                              const mozilla::TypedEventHandler& aTypedHandler,
   1.277 +                              mozilla::JSEventHandler** aReturn);
   1.278 +
   1.279 +#endif // mozilla_JSEventHandler_h_
   1.280 +

mercurial