Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #ifndef mozilla_DOMEventTargetHelper_h_ |
michael@0 | 7 | #define mozilla_DOMEventTargetHelper_h_ |
michael@0 | 8 | |
michael@0 | 9 | #include "nsCOMPtr.h" |
michael@0 | 10 | #include "nsGkAtoms.h" |
michael@0 | 11 | #include "nsCycleCollectionParticipant.h" |
michael@0 | 12 | #include "nsPIDOMWindow.h" |
michael@0 | 13 | #include "nsIScriptGlobalObject.h" |
michael@0 | 14 | #include "nsIScriptContext.h" |
michael@0 | 15 | #include "MainThreadUtils.h" |
michael@0 | 16 | #include "mozilla/Attributes.h" |
michael@0 | 17 | #include "mozilla/EventListenerManager.h" |
michael@0 | 18 | #include "mozilla/dom/EventTarget.h" |
michael@0 | 19 | |
michael@0 | 20 | class JSCompartment; |
michael@0 | 21 | |
michael@0 | 22 | namespace mozilla { |
michael@0 | 23 | |
michael@0 | 24 | class ErrorResult; |
michael@0 | 25 | |
michael@0 | 26 | #define NS_DOMEVENTTARGETHELPER_IID \ |
michael@0 | 27 | { 0xa28385c6, 0x9451, 0x4d7e, \ |
michael@0 | 28 | { 0xa3, 0xdd, 0xf4, 0xb6, 0x87, 0x2f, 0xa4, 0x76 } } |
michael@0 | 29 | |
michael@0 | 30 | class DOMEventTargetHelper : public dom::EventTarget |
michael@0 | 31 | { |
michael@0 | 32 | public: |
michael@0 | 33 | DOMEventTargetHelper() |
michael@0 | 34 | : mParentObject(nullptr) |
michael@0 | 35 | , mOwnerWindow(nullptr) |
michael@0 | 36 | , mHasOrHasHadOwnerWindow(false) |
michael@0 | 37 | { |
michael@0 | 38 | } |
michael@0 | 39 | DOMEventTargetHelper(nsPIDOMWindow* aWindow) |
michael@0 | 40 | : mParentObject(nullptr) |
michael@0 | 41 | , mOwnerWindow(nullptr) |
michael@0 | 42 | , mHasOrHasHadOwnerWindow(false) |
michael@0 | 43 | { |
michael@0 | 44 | BindToOwner(aWindow); |
michael@0 | 45 | // All objects coming through here are WebIDL objects |
michael@0 | 46 | SetIsDOMBinding(); |
michael@0 | 47 | } |
michael@0 | 48 | DOMEventTargetHelper(DOMEventTargetHelper* aOther) |
michael@0 | 49 | : mParentObject(nullptr) |
michael@0 | 50 | , mOwnerWindow(nullptr) |
michael@0 | 51 | , mHasOrHasHadOwnerWindow(false) |
michael@0 | 52 | { |
michael@0 | 53 | BindToOwner(aOther); |
michael@0 | 54 | // All objects coming through here are WebIDL objects |
michael@0 | 55 | SetIsDOMBinding(); |
michael@0 | 56 | } |
michael@0 | 57 | |
michael@0 | 58 | virtual ~DOMEventTargetHelper(); |
michael@0 | 59 | NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
michael@0 | 60 | NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(DOMEventTargetHelper) |
michael@0 | 61 | |
michael@0 | 62 | NS_DECL_NSIDOMEVENTTARGET |
michael@0 | 63 | |
michael@0 | 64 | virtual EventListenerManager* GetExistingListenerManager() const MOZ_OVERRIDE; |
michael@0 | 65 | virtual EventListenerManager* GetOrCreateListenerManager() MOZ_OVERRIDE; |
michael@0 | 66 | |
michael@0 | 67 | using dom::EventTarget::RemoveEventListener; |
michael@0 | 68 | virtual void AddEventListener(const nsAString& aType, |
michael@0 | 69 | dom::EventListener* aListener, |
michael@0 | 70 | bool aCapture, |
michael@0 | 71 | const dom::Nullable<bool>& aWantsUntrusted, |
michael@0 | 72 | ErrorResult& aRv) MOZ_OVERRIDE; |
michael@0 | 73 | |
michael@0 | 74 | NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOMEVENTTARGETHELPER_IID) |
michael@0 | 75 | |
michael@0 | 76 | void GetParentObject(nsIScriptGlobalObject **aParentObject) |
michael@0 | 77 | { |
michael@0 | 78 | if (mParentObject) { |
michael@0 | 79 | CallQueryInterface(mParentObject, aParentObject); |
michael@0 | 80 | } else { |
michael@0 | 81 | *aParentObject = nullptr; |
michael@0 | 82 | } |
michael@0 | 83 | } |
michael@0 | 84 | |
michael@0 | 85 | static DOMEventTargetHelper* FromSupports(nsISupports* aSupports) |
michael@0 | 86 | { |
michael@0 | 87 | dom::EventTarget* target = static_cast<dom::EventTarget*>(aSupports); |
michael@0 | 88 | #ifdef DEBUG |
michael@0 | 89 | { |
michael@0 | 90 | nsCOMPtr<dom::EventTarget> target_qi = do_QueryInterface(aSupports); |
michael@0 | 91 | |
michael@0 | 92 | // If this assertion fires the QI implementation for the object in |
michael@0 | 93 | // question doesn't use the EventTarget pointer as the |
michael@0 | 94 | // nsISupports pointer. That must be fixed, or we'll crash... |
michael@0 | 95 | NS_ASSERTION(target_qi == target, "Uh, fix QI!"); |
michael@0 | 96 | } |
michael@0 | 97 | #endif |
michael@0 | 98 | |
michael@0 | 99 | return static_cast<DOMEventTargetHelper*>(target); |
michael@0 | 100 | } |
michael@0 | 101 | |
michael@0 | 102 | bool HasListenersFor(nsIAtom* aTypeWithOn) |
michael@0 | 103 | { |
michael@0 | 104 | return mListenerManager && mListenerManager->HasListenersFor(aTypeWithOn); |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | nsresult SetEventHandler(nsIAtom* aType, |
michael@0 | 108 | JSContext* aCx, |
michael@0 | 109 | const JS::Value& aValue); |
michael@0 | 110 | using dom::EventTarget::SetEventHandler; |
michael@0 | 111 | void GetEventHandler(nsIAtom* aType, |
michael@0 | 112 | JSContext* aCx, |
michael@0 | 113 | JS::Value* aValue); |
michael@0 | 114 | using dom::EventTarget::GetEventHandler; |
michael@0 | 115 | virtual nsIDOMWindow* GetOwnerGlobal() MOZ_OVERRIDE |
michael@0 | 116 | { |
michael@0 | 117 | return nsPIDOMWindow::GetOuterFromCurrentInner(GetOwner()); |
michael@0 | 118 | } |
michael@0 | 119 | |
michael@0 | 120 | nsresult CheckInnerWindowCorrectness() |
michael@0 | 121 | { |
michael@0 | 122 | NS_ENSURE_STATE(!mHasOrHasHadOwnerWindow || mOwnerWindow); |
michael@0 | 123 | if (mOwnerWindow) { |
michael@0 | 124 | NS_ASSERTION(mOwnerWindow->IsInnerWindow(), "Should have inner window here!\n"); |
michael@0 | 125 | nsPIDOMWindow* outer = mOwnerWindow->GetOuterWindow(); |
michael@0 | 126 | if (!outer || outer->GetCurrentInnerWindow() != mOwnerWindow) { |
michael@0 | 127 | return NS_ERROR_FAILURE; |
michael@0 | 128 | } |
michael@0 | 129 | } |
michael@0 | 130 | return NS_OK; |
michael@0 | 131 | } |
michael@0 | 132 | |
michael@0 | 133 | nsPIDOMWindow* GetOwner() const { return mOwnerWindow; } |
michael@0 | 134 | void BindToOwner(nsIGlobalObject* aOwner); |
michael@0 | 135 | void BindToOwner(nsPIDOMWindow* aOwner); |
michael@0 | 136 | void BindToOwner(DOMEventTargetHelper* aOther); |
michael@0 | 137 | virtual void DisconnectFromOwner(); |
michael@0 | 138 | nsIGlobalObject* GetParentObject() const { return mParentObject; } |
michael@0 | 139 | bool HasOrHasHadOwner() { return mHasOrHasHadOwnerWindow; } |
michael@0 | 140 | |
michael@0 | 141 | virtual void EventListenerAdded(nsIAtom* aType) MOZ_OVERRIDE; |
michael@0 | 142 | virtual void EventListenerRemoved(nsIAtom* aType) MOZ_OVERRIDE; |
michael@0 | 143 | virtual void EventListenerWasAdded(const nsAString& aType, |
michael@0 | 144 | ErrorResult& aRv, |
michael@0 | 145 | JSCompartment* aCompartment = nullptr) {} |
michael@0 | 146 | virtual void EventListenerWasRemoved(const nsAString& aType, |
michael@0 | 147 | ErrorResult& aRv, |
michael@0 | 148 | JSCompartment* aCompartment = nullptr) {} |
michael@0 | 149 | protected: |
michael@0 | 150 | nsresult WantsUntrusted(bool* aRetVal); |
michael@0 | 151 | |
michael@0 | 152 | nsRefPtr<EventListenerManager> mListenerManager; |
michael@0 | 153 | // Dispatch a trusted, non-cancellable and non-bubbling event to |this|. |
michael@0 | 154 | nsresult DispatchTrustedEvent(const nsAString& aEventName); |
michael@0 | 155 | // Make |event| trusted and dispatch |aEvent| to |this|. |
michael@0 | 156 | nsresult DispatchTrustedEvent(nsIDOMEvent* aEvent); |
michael@0 | 157 | |
michael@0 | 158 | virtual void LastRelease() {} |
michael@0 | 159 | private: |
michael@0 | 160 | // Inner window or sandbox. |
michael@0 | 161 | nsIGlobalObject* mParentObject; |
michael@0 | 162 | // mParentObject pre QI-ed and cached |
michael@0 | 163 | // (it is needed for off main thread access) |
michael@0 | 164 | nsPIDOMWindow* mOwnerWindow; |
michael@0 | 165 | bool mHasOrHasHadOwnerWindow; |
michael@0 | 166 | }; |
michael@0 | 167 | |
michael@0 | 168 | NS_DEFINE_STATIC_IID_ACCESSOR(DOMEventTargetHelper, |
michael@0 | 169 | NS_DOMEVENTTARGETHELPER_IID) |
michael@0 | 170 | |
michael@0 | 171 | } // namespace mozilla |
michael@0 | 172 | |
michael@0 | 173 | // XPIDL event handlers |
michael@0 | 174 | #define NS_IMPL_EVENT_HANDLER(_class, _event) \ |
michael@0 | 175 | NS_IMETHODIMP _class::GetOn##_event(JSContext* aCx, \ |
michael@0 | 176 | JS::MutableHandle<JS::Value> aValue) \ |
michael@0 | 177 | { \ |
michael@0 | 178 | GetEventHandler(nsGkAtoms::on##_event, aCx, aValue.address()); \ |
michael@0 | 179 | return NS_OK; \ |
michael@0 | 180 | } \ |
michael@0 | 181 | NS_IMETHODIMP _class::SetOn##_event(JSContext* aCx, \ |
michael@0 | 182 | JS::Handle<JS::Value> aValue) \ |
michael@0 | 183 | { \ |
michael@0 | 184 | return SetEventHandler(nsGkAtoms::on##_event, aCx, aValue); \ |
michael@0 | 185 | } |
michael@0 | 186 | |
michael@0 | 187 | #define NS_IMPL_FORWARD_EVENT_HANDLER(_class, _event, _baseclass) \ |
michael@0 | 188 | NS_IMETHODIMP _class::GetOn##_event(JSContext* aCx, \ |
michael@0 | 189 | JS::MutableHandle<JS::Value> aValue) \ |
michael@0 | 190 | { \ |
michael@0 | 191 | return _baseclass::GetOn##_event(aCx, aValue); \ |
michael@0 | 192 | } \ |
michael@0 | 193 | NS_IMETHODIMP _class::SetOn##_event(JSContext* aCx, \ |
michael@0 | 194 | JS::Handle<JS::Value> aValue) \ |
michael@0 | 195 | { \ |
michael@0 | 196 | return _baseclass::SetOn##_event(aCx, aValue); \ |
michael@0 | 197 | } |
michael@0 | 198 | |
michael@0 | 199 | // WebIDL event handlers |
michael@0 | 200 | #define IMPL_EVENT_HANDLER(_event) \ |
michael@0 | 201 | inline mozilla::dom::EventHandlerNonNull* GetOn##_event() \ |
michael@0 | 202 | { \ |
michael@0 | 203 | if (NS_IsMainThread()) { \ |
michael@0 | 204 | return GetEventHandler(nsGkAtoms::on##_event, EmptyString()); \ |
michael@0 | 205 | } \ |
michael@0 | 206 | return GetEventHandler(nullptr, NS_LITERAL_STRING(#_event)); \ |
michael@0 | 207 | } \ |
michael@0 | 208 | inline void SetOn##_event(mozilla::dom::EventHandlerNonNull* aCallback) \ |
michael@0 | 209 | { \ |
michael@0 | 210 | if (NS_IsMainThread()) { \ |
michael@0 | 211 | SetEventHandler(nsGkAtoms::on##_event, EmptyString(), aCallback); \ |
michael@0 | 212 | } else { \ |
michael@0 | 213 | SetEventHandler(nullptr, NS_LITERAL_STRING(#_event), aCallback); \ |
michael@0 | 214 | } \ |
michael@0 | 215 | } |
michael@0 | 216 | |
michael@0 | 217 | /* Use this macro to declare functions that forward the behavior of this |
michael@0 | 218 | * interface to another object. |
michael@0 | 219 | * This macro doesn't forward PreHandleEvent because sometimes subclasses |
michael@0 | 220 | * want to override it. |
michael@0 | 221 | */ |
michael@0 | 222 | #define NS_FORWARD_NSIDOMEVENTTARGET_NOPREHANDLEEVENT(_to) \ |
michael@0 | 223 | NS_IMETHOD AddEventListener(const nsAString & type, nsIDOMEventListener *listener, bool useCapture, bool wantsUntrusted, uint8_t _argc) { \ |
michael@0 | 224 | return _to AddEventListener(type, listener, useCapture, wantsUntrusted, _argc); \ |
michael@0 | 225 | } \ |
michael@0 | 226 | NS_IMETHOD AddSystemEventListener(const nsAString & type, nsIDOMEventListener *listener, bool aUseCapture, bool aWantsUntrusted, uint8_t _argc) { \ |
michael@0 | 227 | return _to AddSystemEventListener(type, listener, aUseCapture, aWantsUntrusted, _argc); \ |
michael@0 | 228 | } \ |
michael@0 | 229 | NS_IMETHOD RemoveEventListener(const nsAString & type, nsIDOMEventListener *listener, bool useCapture) { \ |
michael@0 | 230 | return _to RemoveEventListener(type, listener, useCapture); \ |
michael@0 | 231 | } \ |
michael@0 | 232 | NS_IMETHOD RemoveSystemEventListener(const nsAString & type, nsIDOMEventListener *listener, bool aUseCapture) { \ |
michael@0 | 233 | return _to RemoveSystemEventListener(type, listener, aUseCapture); \ |
michael@0 | 234 | } \ |
michael@0 | 235 | NS_IMETHOD DispatchEvent(nsIDOMEvent *evt, bool *_retval) { \ |
michael@0 | 236 | return _to DispatchEvent(evt, _retval); \ |
michael@0 | 237 | } \ |
michael@0 | 238 | virtual mozilla::dom::EventTarget* GetTargetForDOMEvent() { \ |
michael@0 | 239 | return _to GetTargetForDOMEvent(); \ |
michael@0 | 240 | } \ |
michael@0 | 241 | virtual mozilla::dom::EventTarget* GetTargetForEventTargetChain() { \ |
michael@0 | 242 | return _to GetTargetForEventTargetChain(); \ |
michael@0 | 243 | } \ |
michael@0 | 244 | virtual nsresult WillHandleEvent( \ |
michael@0 | 245 | mozilla::EventChainPostVisitor & aVisitor) { \ |
michael@0 | 246 | return _to WillHandleEvent(aVisitor); \ |
michael@0 | 247 | } \ |
michael@0 | 248 | virtual nsresult PostHandleEvent( \ |
michael@0 | 249 | mozilla::EventChainPostVisitor & aVisitor) { \ |
michael@0 | 250 | return _to PostHandleEvent(aVisitor); \ |
michael@0 | 251 | } \ |
michael@0 | 252 | virtual nsresult DispatchDOMEvent(mozilla::WidgetEvent* aEvent, nsIDOMEvent* aDOMEvent, nsPresContext* aPresContext, nsEventStatus* aEventStatus) { \ |
michael@0 | 253 | return _to DispatchDOMEvent(aEvent, aDOMEvent, aPresContext, aEventStatus); \ |
michael@0 | 254 | } \ |
michael@0 | 255 | virtual mozilla::EventListenerManager* GetOrCreateListenerManager() { \ |
michael@0 | 256 | return _to GetOrCreateListenerManager(); \ |
michael@0 | 257 | } \ |
michael@0 | 258 | virtual mozilla::EventListenerManager* GetExistingListenerManager() const { \ |
michael@0 | 259 | return _to GetExistingListenerManager(); \ |
michael@0 | 260 | } \ |
michael@0 | 261 | virtual nsIScriptContext * GetContextForEventHandlers(nsresult *aRv) { \ |
michael@0 | 262 | return _to GetContextForEventHandlers(aRv); \ |
michael@0 | 263 | } \ |
michael@0 | 264 | virtual JSContext * GetJSContextForEventHandlers(void) { \ |
michael@0 | 265 | return _to GetJSContextForEventHandlers(); \ |
michael@0 | 266 | } |
michael@0 | 267 | |
michael@0 | 268 | #define NS_REALLY_FORWARD_NSIDOMEVENTTARGET(_class) \ |
michael@0 | 269 | using _class::AddEventListener; \ |
michael@0 | 270 | using _class::RemoveEventListener; \ |
michael@0 | 271 | NS_FORWARD_NSIDOMEVENTTARGET(_class::) \ |
michael@0 | 272 | virtual mozilla::EventListenerManager* \ |
michael@0 | 273 | GetOrCreateListenerManager() { \ |
michael@0 | 274 | return _class::GetOrCreateListenerManager(); \ |
michael@0 | 275 | } \ |
michael@0 | 276 | virtual mozilla::EventListenerManager* \ |
michael@0 | 277 | GetExistingListenerManager() const { \ |
michael@0 | 278 | return _class::GetExistingListenerManager(); \ |
michael@0 | 279 | } |
michael@0 | 280 | |
michael@0 | 281 | #endif // mozilla_DOMEventTargetHelper_h_ |