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: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #include "nsPresContext.h" |
michael@0 | 8 | #include "nsContentUtils.h" |
michael@0 | 9 | #include "nsError.h" |
michael@0 | 10 | #include <new> |
michael@0 | 11 | #include "nsIContent.h" |
michael@0 | 12 | #include "nsIDocument.h" |
michael@0 | 13 | #include "nsINode.h" |
michael@0 | 14 | #include "nsPIDOMWindow.h" |
michael@0 | 15 | #include "GeckoProfiler.h" |
michael@0 | 16 | #include "GeneratedEvents.h" |
michael@0 | 17 | #include "mozilla/ContentEvents.h" |
michael@0 | 18 | #include "mozilla/dom/EventTarget.h" |
michael@0 | 19 | #include "mozilla/dom/TouchEvent.h" |
michael@0 | 20 | #include "mozilla/EventDispatcher.h" |
michael@0 | 21 | #include "mozilla/EventListenerManager.h" |
michael@0 | 22 | #include "mozilla/InternalMutationEvent.h" |
michael@0 | 23 | #include "mozilla/MiscEvents.h" |
michael@0 | 24 | #include "mozilla/MouseEvents.h" |
michael@0 | 25 | #include "mozilla/TextEvents.h" |
michael@0 | 26 | #include "mozilla/TouchEvents.h" |
michael@0 | 27 | #include "mozilla/unused.h" |
michael@0 | 28 | |
michael@0 | 29 | namespace mozilla { |
michael@0 | 30 | |
michael@0 | 31 | using namespace dom; |
michael@0 | 32 | |
michael@0 | 33 | class ELMCreationDetector |
michael@0 | 34 | { |
michael@0 | 35 | public: |
michael@0 | 36 | ELMCreationDetector() |
michael@0 | 37 | // We can do this optimization only in the main thread. |
michael@0 | 38 | : mNonMainThread(!NS_IsMainThread()) |
michael@0 | 39 | , mInitialCount(mNonMainThread ? |
michael@0 | 40 | 0 : EventListenerManager::sMainThreadCreatedCount) |
michael@0 | 41 | { |
michael@0 | 42 | } |
michael@0 | 43 | |
michael@0 | 44 | bool MayHaveNewListenerManager() |
michael@0 | 45 | { |
michael@0 | 46 | return mNonMainThread || |
michael@0 | 47 | mInitialCount != EventListenerManager::sMainThreadCreatedCount; |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | bool IsMainThread() |
michael@0 | 51 | { |
michael@0 | 52 | return !mNonMainThread; |
michael@0 | 53 | } |
michael@0 | 54 | |
michael@0 | 55 | private: |
michael@0 | 56 | bool mNonMainThread; |
michael@0 | 57 | uint32_t mInitialCount; |
michael@0 | 58 | }; |
michael@0 | 59 | |
michael@0 | 60 | #define NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH (1 << 0) |
michael@0 | 61 | #define NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT (1 << 1) |
michael@0 | 62 | #define NS_TARGET_CHAIN_MAY_HAVE_MANAGER (1 << 2) |
michael@0 | 63 | |
michael@0 | 64 | // EventTargetChainItem represents a single item in the event target chain. |
michael@0 | 65 | class EventTargetChainItem |
michael@0 | 66 | { |
michael@0 | 67 | private: |
michael@0 | 68 | EventTargetChainItem(EventTarget* aTarget); |
michael@0 | 69 | public: |
michael@0 | 70 | EventTargetChainItem() |
michael@0 | 71 | : mFlags(0) |
michael@0 | 72 | , mItemFlags(0) |
michael@0 | 73 | { |
michael@0 | 74 | } |
michael@0 | 75 | |
michael@0 | 76 | static EventTargetChainItem* Create(nsTArray<EventTargetChainItem>& aChain, |
michael@0 | 77 | EventTarget* aTarget, |
michael@0 | 78 | EventTargetChainItem* aChild = nullptr) |
michael@0 | 79 | { |
michael@0 | 80 | MOZ_ASSERT(!aChild || &aChain.ElementAt(aChain.Length() - 1) == aChild); |
michael@0 | 81 | return new (aChain.AppendElement()) EventTargetChainItem(aTarget); |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | static void DestroyLast(nsTArray<EventTargetChainItem>& aChain, |
michael@0 | 85 | EventTargetChainItem* aItem) |
michael@0 | 86 | { |
michael@0 | 87 | uint32_t lastIndex = aChain.Length() - 1; |
michael@0 | 88 | MOZ_ASSERT(&aChain[lastIndex] == aItem); |
michael@0 | 89 | aChain.RemoveElementAt(lastIndex); |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | bool IsValid() |
michael@0 | 93 | { |
michael@0 | 94 | NS_WARN_IF_FALSE(!!(mTarget), "Event target is not valid!"); |
michael@0 | 95 | return !!(mTarget); |
michael@0 | 96 | } |
michael@0 | 97 | |
michael@0 | 98 | EventTarget* GetNewTarget() |
michael@0 | 99 | { |
michael@0 | 100 | return mNewTarget; |
michael@0 | 101 | } |
michael@0 | 102 | |
michael@0 | 103 | void SetNewTarget(EventTarget* aNewTarget) |
michael@0 | 104 | { |
michael@0 | 105 | mNewTarget = aNewTarget; |
michael@0 | 106 | } |
michael@0 | 107 | |
michael@0 | 108 | void SetForceContentDispatch(bool aForce) |
michael@0 | 109 | { |
michael@0 | 110 | if (aForce) { |
michael@0 | 111 | mFlags |= NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH; |
michael@0 | 112 | } else { |
michael@0 | 113 | mFlags &= ~NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH; |
michael@0 | 114 | } |
michael@0 | 115 | } |
michael@0 | 116 | |
michael@0 | 117 | bool ForceContentDispatch() |
michael@0 | 118 | { |
michael@0 | 119 | return !!(mFlags & NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH); |
michael@0 | 120 | } |
michael@0 | 121 | |
michael@0 | 122 | void SetWantsWillHandleEvent(bool aWants) |
michael@0 | 123 | { |
michael@0 | 124 | if (aWants) { |
michael@0 | 125 | mFlags |= NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT; |
michael@0 | 126 | } else { |
michael@0 | 127 | mFlags &= ~NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT; |
michael@0 | 128 | } |
michael@0 | 129 | } |
michael@0 | 130 | |
michael@0 | 131 | bool WantsWillHandleEvent() |
michael@0 | 132 | { |
michael@0 | 133 | return !!(mFlags & NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT); |
michael@0 | 134 | } |
michael@0 | 135 | |
michael@0 | 136 | void SetMayHaveListenerManager(bool aMayHave) |
michael@0 | 137 | { |
michael@0 | 138 | if (aMayHave) { |
michael@0 | 139 | mFlags |= NS_TARGET_CHAIN_MAY_HAVE_MANAGER; |
michael@0 | 140 | } else { |
michael@0 | 141 | mFlags &= ~NS_TARGET_CHAIN_MAY_HAVE_MANAGER; |
michael@0 | 142 | } |
michael@0 | 143 | } |
michael@0 | 144 | |
michael@0 | 145 | bool MayHaveListenerManager() |
michael@0 | 146 | { |
michael@0 | 147 | return !!(mFlags & NS_TARGET_CHAIN_MAY_HAVE_MANAGER); |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | EventTarget* CurrentTarget() |
michael@0 | 151 | { |
michael@0 | 152 | return mTarget; |
michael@0 | 153 | } |
michael@0 | 154 | |
michael@0 | 155 | /** |
michael@0 | 156 | * Dispatches event through the event target chain. |
michael@0 | 157 | * Handles capture, target and bubble phases both in default |
michael@0 | 158 | * and system event group and calls also PostHandleEvent for each |
michael@0 | 159 | * item in the chain. |
michael@0 | 160 | */ |
michael@0 | 161 | static void HandleEventTargetChain(nsTArray<EventTargetChainItem>& aChain, |
michael@0 | 162 | EventChainPostVisitor& aVisitor, |
michael@0 | 163 | EventDispatchingCallback* aCallback, |
michael@0 | 164 | ELMCreationDetector& aCd); |
michael@0 | 165 | |
michael@0 | 166 | /** |
michael@0 | 167 | * Resets aVisitor object and calls PreHandleEvent. |
michael@0 | 168 | * Copies mItemFlags and mItemData to the current EventTargetChainItem. |
michael@0 | 169 | */ |
michael@0 | 170 | void PreHandleEvent(EventChainPreVisitor& aVisitor); |
michael@0 | 171 | |
michael@0 | 172 | /** |
michael@0 | 173 | * If the current item in the event target chain has an event listener |
michael@0 | 174 | * manager, this method calls EventListenerManager::HandleEvent(). |
michael@0 | 175 | */ |
michael@0 | 176 | void HandleEvent(EventChainPostVisitor& aVisitor, |
michael@0 | 177 | ELMCreationDetector& aCd) |
michael@0 | 178 | { |
michael@0 | 179 | if (WantsWillHandleEvent()) { |
michael@0 | 180 | mTarget->WillHandleEvent(aVisitor); |
michael@0 | 181 | } |
michael@0 | 182 | if (aVisitor.mEvent->mFlags.mPropagationStopped) { |
michael@0 | 183 | return; |
michael@0 | 184 | } |
michael@0 | 185 | if (!mManager) { |
michael@0 | 186 | if (!MayHaveListenerManager() && !aCd.MayHaveNewListenerManager()) { |
michael@0 | 187 | return; |
michael@0 | 188 | } |
michael@0 | 189 | mManager = mTarget->GetExistingListenerManager(); |
michael@0 | 190 | } |
michael@0 | 191 | if (mManager) { |
michael@0 | 192 | NS_ASSERTION(aVisitor.mEvent->currentTarget == nullptr, |
michael@0 | 193 | "CurrentTarget should be null!"); |
michael@0 | 194 | mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent, |
michael@0 | 195 | &aVisitor.mDOMEvent, |
michael@0 | 196 | CurrentTarget(), |
michael@0 | 197 | &aVisitor.mEventStatus); |
michael@0 | 198 | NS_ASSERTION(aVisitor.mEvent->currentTarget == nullptr, |
michael@0 | 199 | "CurrentTarget should be null!"); |
michael@0 | 200 | } |
michael@0 | 201 | } |
michael@0 | 202 | |
michael@0 | 203 | /** |
michael@0 | 204 | * Copies mItemFlags and mItemData to aVisitor and calls PostHandleEvent. |
michael@0 | 205 | */ |
michael@0 | 206 | void PostHandleEvent(EventChainPostVisitor& aVisitor); |
michael@0 | 207 | |
michael@0 | 208 | nsCOMPtr<EventTarget> mTarget; |
michael@0 | 209 | uint16_t mFlags; |
michael@0 | 210 | uint16_t mItemFlags; |
michael@0 | 211 | nsCOMPtr<nsISupports> mItemData; |
michael@0 | 212 | // Event retargeting must happen whenever mNewTarget is non-null. |
michael@0 | 213 | nsCOMPtr<EventTarget> mNewTarget; |
michael@0 | 214 | // Cache mTarget's event listener manager. |
michael@0 | 215 | nsRefPtr<EventListenerManager> mManager; |
michael@0 | 216 | }; |
michael@0 | 217 | |
michael@0 | 218 | EventTargetChainItem::EventTargetChainItem(EventTarget* aTarget) |
michael@0 | 219 | : mTarget(aTarget) |
michael@0 | 220 | , mFlags(0) |
michael@0 | 221 | , mItemFlags(0) |
michael@0 | 222 | { |
michael@0 | 223 | MOZ_ASSERT(!aTarget || mTarget == aTarget->GetTargetForEventTargetChain()); |
michael@0 | 224 | } |
michael@0 | 225 | |
michael@0 | 226 | void |
michael@0 | 227 | EventTargetChainItem::PreHandleEvent(EventChainPreVisitor& aVisitor) |
michael@0 | 228 | { |
michael@0 | 229 | aVisitor.Reset(); |
michael@0 | 230 | unused << mTarget->PreHandleEvent(aVisitor); |
michael@0 | 231 | SetForceContentDispatch(aVisitor.mForceContentDispatch); |
michael@0 | 232 | SetWantsWillHandleEvent(aVisitor.mWantsWillHandleEvent); |
michael@0 | 233 | SetMayHaveListenerManager(aVisitor.mMayHaveListenerManager); |
michael@0 | 234 | mItemFlags = aVisitor.mItemFlags; |
michael@0 | 235 | mItemData = aVisitor.mItemData; |
michael@0 | 236 | } |
michael@0 | 237 | |
michael@0 | 238 | void |
michael@0 | 239 | EventTargetChainItem::PostHandleEvent(EventChainPostVisitor& aVisitor) |
michael@0 | 240 | { |
michael@0 | 241 | aVisitor.mItemFlags = mItemFlags; |
michael@0 | 242 | aVisitor.mItemData = mItemData; |
michael@0 | 243 | mTarget->PostHandleEvent(aVisitor); |
michael@0 | 244 | } |
michael@0 | 245 | |
michael@0 | 246 | void |
michael@0 | 247 | EventTargetChainItem::HandleEventTargetChain( |
michael@0 | 248 | nsTArray<EventTargetChainItem>& aChain, |
michael@0 | 249 | EventChainPostVisitor& aVisitor, |
michael@0 | 250 | EventDispatchingCallback* aCallback, |
michael@0 | 251 | ELMCreationDetector& aCd) |
michael@0 | 252 | { |
michael@0 | 253 | // Save the target so that it can be restored later. |
michael@0 | 254 | nsCOMPtr<EventTarget> firstTarget = aVisitor.mEvent->target; |
michael@0 | 255 | uint32_t chainLength = aChain.Length(); |
michael@0 | 256 | |
michael@0 | 257 | // Capture |
michael@0 | 258 | aVisitor.mEvent->mFlags.mInCapturePhase = true; |
michael@0 | 259 | aVisitor.mEvent->mFlags.mInBubblingPhase = false; |
michael@0 | 260 | for (uint32_t i = chainLength - 1; i > 0; --i) { |
michael@0 | 261 | EventTargetChainItem& item = aChain[i]; |
michael@0 | 262 | if ((!aVisitor.mEvent->mFlags.mNoContentDispatch || |
michael@0 | 263 | item.ForceContentDispatch()) && |
michael@0 | 264 | !aVisitor.mEvent->mFlags.mPropagationStopped) { |
michael@0 | 265 | item.HandleEvent(aVisitor, aCd); |
michael@0 | 266 | } |
michael@0 | 267 | |
michael@0 | 268 | if (item.GetNewTarget()) { |
michael@0 | 269 | // item is at anonymous boundary. Need to retarget for the child items. |
michael@0 | 270 | for (uint32_t j = i; j > 0; --j) { |
michael@0 | 271 | uint32_t childIndex = j - 1; |
michael@0 | 272 | EventTarget* newTarget = aChain[childIndex].GetNewTarget(); |
michael@0 | 273 | if (newTarget) { |
michael@0 | 274 | aVisitor.mEvent->target = newTarget; |
michael@0 | 275 | break; |
michael@0 | 276 | } |
michael@0 | 277 | } |
michael@0 | 278 | } |
michael@0 | 279 | } |
michael@0 | 280 | |
michael@0 | 281 | // Target |
michael@0 | 282 | aVisitor.mEvent->mFlags.mInBubblingPhase = true; |
michael@0 | 283 | EventTargetChainItem& targetItem = aChain[0]; |
michael@0 | 284 | if (!aVisitor.mEvent->mFlags.mPropagationStopped && |
michael@0 | 285 | (!aVisitor.mEvent->mFlags.mNoContentDispatch || |
michael@0 | 286 | targetItem.ForceContentDispatch())) { |
michael@0 | 287 | targetItem.HandleEvent(aVisitor, aCd); |
michael@0 | 288 | } |
michael@0 | 289 | if (aVisitor.mEvent->mFlags.mInSystemGroup) { |
michael@0 | 290 | targetItem.PostHandleEvent(aVisitor); |
michael@0 | 291 | } |
michael@0 | 292 | |
michael@0 | 293 | // Bubble |
michael@0 | 294 | aVisitor.mEvent->mFlags.mInCapturePhase = false; |
michael@0 | 295 | for (uint32_t i = 1; i < chainLength; ++i) { |
michael@0 | 296 | EventTargetChainItem& item = aChain[i]; |
michael@0 | 297 | EventTarget* newTarget = item.GetNewTarget(); |
michael@0 | 298 | if (newTarget) { |
michael@0 | 299 | // Item is at anonymous boundary. Need to retarget for the current item |
michael@0 | 300 | // and for parent items. |
michael@0 | 301 | aVisitor.mEvent->target = newTarget; |
michael@0 | 302 | } |
michael@0 | 303 | |
michael@0 | 304 | if (aVisitor.mEvent->mFlags.mBubbles || newTarget) { |
michael@0 | 305 | if ((!aVisitor.mEvent->mFlags.mNoContentDispatch || |
michael@0 | 306 | item.ForceContentDispatch()) && |
michael@0 | 307 | !aVisitor.mEvent->mFlags.mPropagationStopped) { |
michael@0 | 308 | item.HandleEvent(aVisitor, aCd); |
michael@0 | 309 | } |
michael@0 | 310 | if (aVisitor.mEvent->mFlags.mInSystemGroup) { |
michael@0 | 311 | item.PostHandleEvent(aVisitor); |
michael@0 | 312 | } |
michael@0 | 313 | } |
michael@0 | 314 | } |
michael@0 | 315 | aVisitor.mEvent->mFlags.mInBubblingPhase = false; |
michael@0 | 316 | |
michael@0 | 317 | if (!aVisitor.mEvent->mFlags.mInSystemGroup) { |
michael@0 | 318 | // Dispatch to the system event group. Make sure to clear the |
michael@0 | 319 | // STOP_DISPATCH flag since this resets for each event group. |
michael@0 | 320 | aVisitor.mEvent->mFlags.mPropagationStopped = false; |
michael@0 | 321 | aVisitor.mEvent->mFlags.mImmediatePropagationStopped = false; |
michael@0 | 322 | |
michael@0 | 323 | // Setting back the original target of the event. |
michael@0 | 324 | aVisitor.mEvent->target = aVisitor.mEvent->originalTarget; |
michael@0 | 325 | |
michael@0 | 326 | // Special handling if PresShell (or some other caller) |
michael@0 | 327 | // used a callback object. |
michael@0 | 328 | if (aCallback) { |
michael@0 | 329 | aCallback->HandleEvent(aVisitor); |
michael@0 | 330 | } |
michael@0 | 331 | |
michael@0 | 332 | // Retarget for system event group (which does the default handling too). |
michael@0 | 333 | // Setting back the target which was used also for default event group. |
michael@0 | 334 | aVisitor.mEvent->target = firstTarget; |
michael@0 | 335 | aVisitor.mEvent->mFlags.mInSystemGroup = true; |
michael@0 | 336 | HandleEventTargetChain(aChain, |
michael@0 | 337 | aVisitor, |
michael@0 | 338 | aCallback, |
michael@0 | 339 | aCd); |
michael@0 | 340 | aVisitor.mEvent->mFlags.mInSystemGroup = false; |
michael@0 | 341 | |
michael@0 | 342 | // After dispatch, clear all the propagation flags so that |
michael@0 | 343 | // system group listeners don't affect to the event. |
michael@0 | 344 | aVisitor.mEvent->mFlags.mPropagationStopped = false; |
michael@0 | 345 | aVisitor.mEvent->mFlags.mImmediatePropagationStopped = false; |
michael@0 | 346 | } |
michael@0 | 347 | } |
michael@0 | 348 | |
michael@0 | 349 | static nsTArray<EventTargetChainItem>* sCachedMainThreadChain = nullptr; |
michael@0 | 350 | |
michael@0 | 351 | /* static */ void |
michael@0 | 352 | EventDispatcher::Shutdown() |
michael@0 | 353 | { |
michael@0 | 354 | delete sCachedMainThreadChain; |
michael@0 | 355 | sCachedMainThreadChain = nullptr; |
michael@0 | 356 | } |
michael@0 | 357 | |
michael@0 | 358 | EventTargetChainItem* |
michael@0 | 359 | EventTargetChainItemForChromeTarget(nsTArray<EventTargetChainItem>& aChain, |
michael@0 | 360 | nsINode* aNode, |
michael@0 | 361 | EventTargetChainItem* aChild = nullptr) |
michael@0 | 362 | { |
michael@0 | 363 | if (!aNode->IsInDoc()) { |
michael@0 | 364 | return nullptr; |
michael@0 | 365 | } |
michael@0 | 366 | nsPIDOMWindow* win = aNode->OwnerDoc()->GetInnerWindow(); |
michael@0 | 367 | EventTarget* piTarget = win ? win->GetParentTarget() : nullptr; |
michael@0 | 368 | NS_ENSURE_TRUE(piTarget, nullptr); |
michael@0 | 369 | |
michael@0 | 370 | EventTargetChainItem* etci = |
michael@0 | 371 | EventTargetChainItem::Create(aChain, |
michael@0 | 372 | piTarget->GetTargetForEventTargetChain(), |
michael@0 | 373 | aChild); |
michael@0 | 374 | if (!etci->IsValid()) { |
michael@0 | 375 | EventTargetChainItem::DestroyLast(aChain, etci); |
michael@0 | 376 | return nullptr; |
michael@0 | 377 | } |
michael@0 | 378 | return etci; |
michael@0 | 379 | } |
michael@0 | 380 | |
michael@0 | 381 | /* static */ nsresult |
michael@0 | 382 | EventDispatcher::Dispatch(nsISupports* aTarget, |
michael@0 | 383 | nsPresContext* aPresContext, |
michael@0 | 384 | WidgetEvent* aEvent, |
michael@0 | 385 | nsIDOMEvent* aDOMEvent, |
michael@0 | 386 | nsEventStatus* aEventStatus, |
michael@0 | 387 | EventDispatchingCallback* aCallback, |
michael@0 | 388 | nsCOMArray<EventTarget>* aTargets) |
michael@0 | 389 | { |
michael@0 | 390 | PROFILER_LABEL("EventDispatcher", "Dispatch"); |
michael@0 | 391 | NS_ASSERTION(aEvent, "Trying to dispatch without WidgetEvent!"); |
michael@0 | 392 | NS_ENSURE_TRUE(!aEvent->mFlags.mIsBeingDispatched, |
michael@0 | 393 | NS_ERROR_DOM_INVALID_STATE_ERR); |
michael@0 | 394 | NS_ASSERTION(!aTargets || !aEvent->message, "Wrong parameters!"); |
michael@0 | 395 | |
michael@0 | 396 | // If we're dispatching an already created DOMEvent object, make |
michael@0 | 397 | // sure it is initialized! |
michael@0 | 398 | // If aTargets is non-null, the event isn't going to be dispatched. |
michael@0 | 399 | NS_ENSURE_TRUE(aEvent->message || !aDOMEvent || aTargets, |
michael@0 | 400 | NS_ERROR_DOM_INVALID_STATE_ERR); |
michael@0 | 401 | |
michael@0 | 402 | nsCOMPtr<EventTarget> target = do_QueryInterface(aTarget); |
michael@0 | 403 | |
michael@0 | 404 | bool retargeted = false; |
michael@0 | 405 | |
michael@0 | 406 | if (aEvent->mFlags.mRetargetToNonNativeAnonymous) { |
michael@0 | 407 | nsCOMPtr<nsIContent> content = do_QueryInterface(target); |
michael@0 | 408 | if (content && content->IsInNativeAnonymousSubtree()) { |
michael@0 | 409 | nsCOMPtr<EventTarget> newTarget = |
michael@0 | 410 | do_QueryInterface(content->FindFirstNonChromeOnlyAccessContent()); |
michael@0 | 411 | NS_ENSURE_STATE(newTarget); |
michael@0 | 412 | |
michael@0 | 413 | aEvent->originalTarget = target; |
michael@0 | 414 | target = newTarget; |
michael@0 | 415 | retargeted = true; |
michael@0 | 416 | } |
michael@0 | 417 | } |
michael@0 | 418 | |
michael@0 | 419 | if (aEvent->mFlags.mOnlyChromeDispatch) { |
michael@0 | 420 | nsCOMPtr<nsINode> node = do_QueryInterface(aTarget); |
michael@0 | 421 | if (!node) { |
michael@0 | 422 | nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aTarget); |
michael@0 | 423 | if (win) { |
michael@0 | 424 | node = win->GetExtantDoc(); |
michael@0 | 425 | } |
michael@0 | 426 | } |
michael@0 | 427 | |
michael@0 | 428 | NS_ENSURE_STATE(node); |
michael@0 | 429 | nsIDocument* doc = node->OwnerDoc(); |
michael@0 | 430 | if (!nsContentUtils::IsChromeDoc(doc)) { |
michael@0 | 431 | nsPIDOMWindow* win = doc ? doc->GetInnerWindow() : nullptr; |
michael@0 | 432 | // If we can't dispatch the event to chrome, do nothing. |
michael@0 | 433 | EventTarget* piTarget = win ? win->GetParentTarget() : nullptr; |
michael@0 | 434 | NS_ENSURE_TRUE(piTarget, NS_OK); |
michael@0 | 435 | |
michael@0 | 436 | // Set the target to be the original dispatch target, |
michael@0 | 437 | aEvent->target = target; |
michael@0 | 438 | // but use chrome event handler or TabChildGlobal for event target chain. |
michael@0 | 439 | target = piTarget; |
michael@0 | 440 | } |
michael@0 | 441 | } |
michael@0 | 442 | |
michael@0 | 443 | #ifdef DEBUG |
michael@0 | 444 | if (!nsContentUtils::IsSafeToRunScript()) { |
michael@0 | 445 | nsresult rv = NS_ERROR_FAILURE; |
michael@0 | 446 | if (target->GetContextForEventHandlers(&rv) || |
michael@0 | 447 | NS_FAILED(rv)) { |
michael@0 | 448 | nsCOMPtr<nsINode> node = do_QueryInterface(target); |
michael@0 | 449 | if (node && nsContentUtils::IsChromeDoc(node->OwnerDoc())) { |
michael@0 | 450 | NS_WARNING("Fix the caller!"); |
michael@0 | 451 | } else { |
michael@0 | 452 | NS_ERROR("This is unsafe! Fix the caller!"); |
michael@0 | 453 | } |
michael@0 | 454 | } |
michael@0 | 455 | } |
michael@0 | 456 | |
michael@0 | 457 | if (aDOMEvent) { |
michael@0 | 458 | WidgetEvent* innerEvent = aDOMEvent->GetInternalNSEvent(); |
michael@0 | 459 | NS_ASSERTION(innerEvent == aEvent, |
michael@0 | 460 | "The inner event of aDOMEvent is not the same as aEvent!"); |
michael@0 | 461 | } |
michael@0 | 462 | #endif |
michael@0 | 463 | |
michael@0 | 464 | nsresult rv = NS_OK; |
michael@0 | 465 | bool externalDOMEvent = !!(aDOMEvent); |
michael@0 | 466 | |
michael@0 | 467 | // If we have a PresContext, make sure it doesn't die before |
michael@0 | 468 | // event dispatching is finished. |
michael@0 | 469 | nsRefPtr<nsPresContext> kungFuDeathGrip(aPresContext); |
michael@0 | 470 | |
michael@0 | 471 | ELMCreationDetector cd; |
michael@0 | 472 | nsTArray<EventTargetChainItem> chain; |
michael@0 | 473 | if (cd.IsMainThread()) { |
michael@0 | 474 | if (!sCachedMainThreadChain) { |
michael@0 | 475 | sCachedMainThreadChain = new nsTArray<EventTargetChainItem>(); |
michael@0 | 476 | } |
michael@0 | 477 | chain.SwapElements(*sCachedMainThreadChain); |
michael@0 | 478 | chain.SetCapacity(128); |
michael@0 | 479 | } |
michael@0 | 480 | |
michael@0 | 481 | // Create the event target chain item for the event target. |
michael@0 | 482 | EventTargetChainItem* targetEtci = |
michael@0 | 483 | EventTargetChainItem::Create(chain, target->GetTargetForEventTargetChain()); |
michael@0 | 484 | MOZ_ASSERT(&chain[0] == targetEtci); |
michael@0 | 485 | if (!targetEtci->IsValid()) { |
michael@0 | 486 | EventTargetChainItem::DestroyLast(chain, targetEtci); |
michael@0 | 487 | return NS_ERROR_FAILURE; |
michael@0 | 488 | } |
michael@0 | 489 | |
michael@0 | 490 | // Make sure that nsIDOMEvent::target and nsIDOMEvent::originalTarget |
michael@0 | 491 | // point to the last item in the chain. |
michael@0 | 492 | if (!aEvent->target) { |
michael@0 | 493 | // Note, CurrentTarget() points always to the object returned by |
michael@0 | 494 | // GetTargetForEventTargetChain(). |
michael@0 | 495 | aEvent->target = targetEtci->CurrentTarget(); |
michael@0 | 496 | } else { |
michael@0 | 497 | // XXX But if the target is already set, use that. This is a hack |
michael@0 | 498 | // for the 'load', 'beforeunload' and 'unload' events, |
michael@0 | 499 | // which are dispatched to |window| but have document as their target. |
michael@0 | 500 | // |
michael@0 | 501 | // Make sure that the event target points to the right object. |
michael@0 | 502 | aEvent->target = aEvent->target->GetTargetForEventTargetChain(); |
michael@0 | 503 | NS_ENSURE_STATE(aEvent->target); |
michael@0 | 504 | } |
michael@0 | 505 | |
michael@0 | 506 | if (retargeted) { |
michael@0 | 507 | aEvent->originalTarget = |
michael@0 | 508 | aEvent->originalTarget->GetTargetForEventTargetChain(); |
michael@0 | 509 | NS_ENSURE_STATE(aEvent->originalTarget); |
michael@0 | 510 | } |
michael@0 | 511 | else { |
michael@0 | 512 | aEvent->originalTarget = aEvent->target; |
michael@0 | 513 | } |
michael@0 | 514 | |
michael@0 | 515 | nsCOMPtr<nsIContent> content = do_QueryInterface(aEvent->originalTarget); |
michael@0 | 516 | bool isInAnon = (content && content->IsInAnonymousSubtree()); |
michael@0 | 517 | |
michael@0 | 518 | aEvent->mFlags.mIsBeingDispatched = true; |
michael@0 | 519 | |
michael@0 | 520 | // Create visitor object and start event dispatching. |
michael@0 | 521 | // PreHandleEvent for the original target. |
michael@0 | 522 | nsEventStatus status = aEventStatus ? *aEventStatus : nsEventStatus_eIgnore; |
michael@0 | 523 | EventChainPreVisitor preVisitor(aPresContext, aEvent, aDOMEvent, status, |
michael@0 | 524 | isInAnon); |
michael@0 | 525 | targetEtci->PreHandleEvent(preVisitor); |
michael@0 | 526 | |
michael@0 | 527 | if (!preVisitor.mCanHandle && preVisitor.mAutomaticChromeDispatch && content) { |
michael@0 | 528 | // Event target couldn't handle the event. Try to propagate to chrome. |
michael@0 | 529 | EventTargetChainItem::DestroyLast(chain, targetEtci); |
michael@0 | 530 | targetEtci = EventTargetChainItemForChromeTarget(chain, content); |
michael@0 | 531 | NS_ENSURE_STATE(targetEtci); |
michael@0 | 532 | MOZ_ASSERT(&chain[0] == targetEtci); |
michael@0 | 533 | targetEtci->PreHandleEvent(preVisitor); |
michael@0 | 534 | } |
michael@0 | 535 | if (preVisitor.mCanHandle) { |
michael@0 | 536 | // At least the original target can handle the event. |
michael@0 | 537 | // Setting the retarget to the |target| simplifies retargeting code. |
michael@0 | 538 | nsCOMPtr<EventTarget> t = do_QueryInterface(aEvent->target); |
michael@0 | 539 | targetEtci->SetNewTarget(t); |
michael@0 | 540 | EventTargetChainItem* topEtci = targetEtci; |
michael@0 | 541 | targetEtci = nullptr; |
michael@0 | 542 | while (preVisitor.mParentTarget) { |
michael@0 | 543 | EventTarget* parentTarget = preVisitor.mParentTarget; |
michael@0 | 544 | EventTargetChainItem* parentEtci = |
michael@0 | 545 | EventTargetChainItem::Create(chain, preVisitor.mParentTarget, topEtci); |
michael@0 | 546 | if (!parentEtci->IsValid()) { |
michael@0 | 547 | EventTargetChainItem::DestroyLast(chain, parentEtci); |
michael@0 | 548 | rv = NS_ERROR_FAILURE; |
michael@0 | 549 | break; |
michael@0 | 550 | } |
michael@0 | 551 | |
michael@0 | 552 | // Item needs event retargetting. |
michael@0 | 553 | if (preVisitor.mEventTargetAtParent) { |
michael@0 | 554 | // Need to set the target of the event |
michael@0 | 555 | // so that also the next retargeting works. |
michael@0 | 556 | preVisitor.mEvent->target = preVisitor.mEventTargetAtParent; |
michael@0 | 557 | parentEtci->SetNewTarget(preVisitor.mEventTargetAtParent); |
michael@0 | 558 | } |
michael@0 | 559 | |
michael@0 | 560 | parentEtci->PreHandleEvent(preVisitor); |
michael@0 | 561 | if (preVisitor.mCanHandle) { |
michael@0 | 562 | topEtci = parentEtci; |
michael@0 | 563 | } else { |
michael@0 | 564 | EventTargetChainItem::DestroyLast(chain, parentEtci); |
michael@0 | 565 | parentEtci = nullptr; |
michael@0 | 566 | if (preVisitor.mAutomaticChromeDispatch && content) { |
michael@0 | 567 | // Even if the current target can't handle the event, try to |
michael@0 | 568 | // propagate to chrome. |
michael@0 | 569 | nsCOMPtr<nsINode> disabledTarget = do_QueryInterface(parentTarget); |
michael@0 | 570 | if (disabledTarget) { |
michael@0 | 571 | parentEtci = EventTargetChainItemForChromeTarget(chain, |
michael@0 | 572 | disabledTarget, |
michael@0 | 573 | topEtci); |
michael@0 | 574 | if (parentEtci) { |
michael@0 | 575 | parentEtci->PreHandleEvent(preVisitor); |
michael@0 | 576 | if (preVisitor.mCanHandle) { |
michael@0 | 577 | chain[0].SetNewTarget(parentTarget); |
michael@0 | 578 | topEtci = parentEtci; |
michael@0 | 579 | continue; |
michael@0 | 580 | } |
michael@0 | 581 | } |
michael@0 | 582 | } |
michael@0 | 583 | } |
michael@0 | 584 | break; |
michael@0 | 585 | } |
michael@0 | 586 | } |
michael@0 | 587 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 588 | if (aTargets) { |
michael@0 | 589 | aTargets->Clear(); |
michael@0 | 590 | aTargets->SetCapacity(chain.Length()); |
michael@0 | 591 | for (uint32_t i = 0; i < chain.Length(); ++i) { |
michael@0 | 592 | aTargets->AppendObject(chain[i].CurrentTarget()->GetTargetForDOMEvent()); |
michael@0 | 593 | } |
michael@0 | 594 | } else { |
michael@0 | 595 | // Event target chain is created. Handle the chain. |
michael@0 | 596 | EventChainPostVisitor postVisitor(preVisitor); |
michael@0 | 597 | EventTargetChainItem::HandleEventTargetChain(chain, postVisitor, |
michael@0 | 598 | aCallback, cd); |
michael@0 | 599 | |
michael@0 | 600 | preVisitor.mEventStatus = postVisitor.mEventStatus; |
michael@0 | 601 | // If the DOM event was created during event flow. |
michael@0 | 602 | if (!preVisitor.mDOMEvent && postVisitor.mDOMEvent) { |
michael@0 | 603 | preVisitor.mDOMEvent = postVisitor.mDOMEvent; |
michael@0 | 604 | } |
michael@0 | 605 | } |
michael@0 | 606 | } |
michael@0 | 607 | } |
michael@0 | 608 | |
michael@0 | 609 | // Note, EventTargetChainItem objects are deleted when the chain goes out of |
michael@0 | 610 | // the scope. |
michael@0 | 611 | |
michael@0 | 612 | aEvent->mFlags.mIsBeingDispatched = false; |
michael@0 | 613 | aEvent->mFlags.mDispatchedAtLeastOnce = true; |
michael@0 | 614 | |
michael@0 | 615 | if (!externalDOMEvent && preVisitor.mDOMEvent) { |
michael@0 | 616 | // An dom::Event was created while dispatching the event. |
michael@0 | 617 | // Duplicate private data if someone holds a pointer to it. |
michael@0 | 618 | nsrefcnt rc = 0; |
michael@0 | 619 | NS_RELEASE2(preVisitor.mDOMEvent, rc); |
michael@0 | 620 | if (preVisitor.mDOMEvent) { |
michael@0 | 621 | preVisitor.mDOMEvent->DuplicatePrivateData(); |
michael@0 | 622 | } |
michael@0 | 623 | } |
michael@0 | 624 | |
michael@0 | 625 | if (aEventStatus) { |
michael@0 | 626 | *aEventStatus = preVisitor.mEventStatus; |
michael@0 | 627 | } |
michael@0 | 628 | |
michael@0 | 629 | if (cd.IsMainThread() && chain.Capacity() == 128 && sCachedMainThreadChain) { |
michael@0 | 630 | chain.ClearAndRetainStorage(); |
michael@0 | 631 | chain.SwapElements(*sCachedMainThreadChain); |
michael@0 | 632 | } |
michael@0 | 633 | |
michael@0 | 634 | return rv; |
michael@0 | 635 | } |
michael@0 | 636 | |
michael@0 | 637 | /* static */ nsresult |
michael@0 | 638 | EventDispatcher::DispatchDOMEvent(nsISupports* aTarget, |
michael@0 | 639 | WidgetEvent* aEvent, |
michael@0 | 640 | nsIDOMEvent* aDOMEvent, |
michael@0 | 641 | nsPresContext* aPresContext, |
michael@0 | 642 | nsEventStatus* aEventStatus) |
michael@0 | 643 | { |
michael@0 | 644 | if (aDOMEvent) { |
michael@0 | 645 | WidgetEvent* innerEvent = aDOMEvent->GetInternalNSEvent(); |
michael@0 | 646 | NS_ENSURE_TRUE(innerEvent, NS_ERROR_ILLEGAL_VALUE); |
michael@0 | 647 | |
michael@0 | 648 | bool dontResetTrusted = false; |
michael@0 | 649 | if (innerEvent->mFlags.mDispatchedAtLeastOnce) { |
michael@0 | 650 | innerEvent->target = nullptr; |
michael@0 | 651 | innerEvent->originalTarget = nullptr; |
michael@0 | 652 | } else { |
michael@0 | 653 | aDOMEvent->GetIsTrusted(&dontResetTrusted); |
michael@0 | 654 | } |
michael@0 | 655 | |
michael@0 | 656 | if (!dontResetTrusted) { |
michael@0 | 657 | //Check security state to determine if dispatcher is trusted |
michael@0 | 658 | aDOMEvent->SetTrusted(nsContentUtils::ThreadsafeIsCallerChrome()); |
michael@0 | 659 | } |
michael@0 | 660 | |
michael@0 | 661 | return EventDispatcher::Dispatch(aTarget, aPresContext, innerEvent, |
michael@0 | 662 | aDOMEvent, aEventStatus); |
michael@0 | 663 | } else if (aEvent) { |
michael@0 | 664 | return EventDispatcher::Dispatch(aTarget, aPresContext, aEvent, |
michael@0 | 665 | aDOMEvent, aEventStatus); |
michael@0 | 666 | } |
michael@0 | 667 | return NS_ERROR_ILLEGAL_VALUE; |
michael@0 | 668 | } |
michael@0 | 669 | |
michael@0 | 670 | /* static */ nsresult |
michael@0 | 671 | EventDispatcher::CreateEvent(EventTarget* aOwner, |
michael@0 | 672 | nsPresContext* aPresContext, |
michael@0 | 673 | WidgetEvent* aEvent, |
michael@0 | 674 | const nsAString& aEventType, |
michael@0 | 675 | nsIDOMEvent** aDOMEvent) |
michael@0 | 676 | { |
michael@0 | 677 | *aDOMEvent = nullptr; |
michael@0 | 678 | |
michael@0 | 679 | if (aEvent) { |
michael@0 | 680 | switch(aEvent->eventStructType) { |
michael@0 | 681 | case NS_MUTATION_EVENT: |
michael@0 | 682 | return NS_NewDOMMutationEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 683 | aEvent->AsMutationEvent()); |
michael@0 | 684 | case NS_GUI_EVENT: |
michael@0 | 685 | case NS_SCROLLPORT_EVENT: |
michael@0 | 686 | case NS_UI_EVENT: |
michael@0 | 687 | return NS_NewDOMUIEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 688 | aEvent->AsGUIEvent()); |
michael@0 | 689 | case NS_SCROLLAREA_EVENT: |
michael@0 | 690 | return NS_NewDOMScrollAreaEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 691 | aEvent->AsScrollAreaEvent()); |
michael@0 | 692 | case NS_KEY_EVENT: |
michael@0 | 693 | return NS_NewDOMKeyboardEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 694 | aEvent->AsKeyboardEvent()); |
michael@0 | 695 | case NS_COMPOSITION_EVENT: |
michael@0 | 696 | return NS_NewDOMCompositionEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 697 | aEvent->AsCompositionEvent()); |
michael@0 | 698 | case NS_MOUSE_EVENT: |
michael@0 | 699 | return NS_NewDOMMouseEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 700 | aEvent->AsMouseEvent()); |
michael@0 | 701 | case NS_FOCUS_EVENT: |
michael@0 | 702 | return NS_NewDOMFocusEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 703 | aEvent->AsFocusEvent()); |
michael@0 | 704 | case NS_MOUSE_SCROLL_EVENT: |
michael@0 | 705 | return NS_NewDOMMouseScrollEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 706 | aEvent->AsMouseScrollEvent()); |
michael@0 | 707 | case NS_WHEEL_EVENT: |
michael@0 | 708 | return NS_NewDOMWheelEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 709 | aEvent->AsWheelEvent()); |
michael@0 | 710 | case NS_EDITOR_INPUT_EVENT: |
michael@0 | 711 | return NS_NewDOMInputEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 712 | aEvent->AsEditorInputEvent()); |
michael@0 | 713 | case NS_DRAG_EVENT: |
michael@0 | 714 | return NS_NewDOMDragEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 715 | aEvent->AsDragEvent()); |
michael@0 | 716 | case NS_TEXT_EVENT: |
michael@0 | 717 | return NS_NewDOMUIEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 718 | aEvent->AsTextEvent()); |
michael@0 | 719 | case NS_CLIPBOARD_EVENT: |
michael@0 | 720 | return NS_NewDOMClipboardEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 721 | aEvent->AsClipboardEvent()); |
michael@0 | 722 | case NS_SVGZOOM_EVENT: |
michael@0 | 723 | return NS_NewDOMSVGZoomEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 724 | aEvent->AsGUIEvent()); |
michael@0 | 725 | case NS_SMIL_TIME_EVENT: |
michael@0 | 726 | return NS_NewDOMTimeEvent(aDOMEvent, aOwner, aPresContext, aEvent); |
michael@0 | 727 | |
michael@0 | 728 | case NS_COMMAND_EVENT: |
michael@0 | 729 | return NS_NewDOMCommandEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 730 | aEvent->AsCommandEvent()); |
michael@0 | 731 | case NS_SIMPLE_GESTURE_EVENT: |
michael@0 | 732 | return NS_NewDOMSimpleGestureEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 733 | aEvent->AsSimpleGestureEvent()); |
michael@0 | 734 | case NS_POINTER_EVENT: |
michael@0 | 735 | return NS_NewDOMPointerEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 736 | aEvent->AsPointerEvent()); |
michael@0 | 737 | case NS_TOUCH_EVENT: |
michael@0 | 738 | return NS_NewDOMTouchEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 739 | aEvent->AsTouchEvent()); |
michael@0 | 740 | case NS_TRANSITION_EVENT: |
michael@0 | 741 | return NS_NewDOMTransitionEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 742 | aEvent->AsTransitionEvent()); |
michael@0 | 743 | case NS_ANIMATION_EVENT: |
michael@0 | 744 | return NS_NewDOMAnimationEvent(aDOMEvent, aOwner, aPresContext, |
michael@0 | 745 | aEvent->AsAnimationEvent()); |
michael@0 | 746 | default: |
michael@0 | 747 | // For all other types of events, create a vanilla event object. |
michael@0 | 748 | return NS_NewDOMEvent(aDOMEvent, aOwner, aPresContext, aEvent); |
michael@0 | 749 | } |
michael@0 | 750 | } |
michael@0 | 751 | |
michael@0 | 752 | // And if we didn't get an event, check the type argument. |
michael@0 | 753 | |
michael@0 | 754 | if (aEventType.LowerCaseEqualsLiteral("mouseevent") || |
michael@0 | 755 | aEventType.LowerCaseEqualsLiteral("mouseevents") || |
michael@0 | 756 | aEventType.LowerCaseEqualsLiteral("popupevents")) |
michael@0 | 757 | return NS_NewDOMMouseEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 758 | if (aEventType.LowerCaseEqualsLiteral("mousescrollevents")) |
michael@0 | 759 | return NS_NewDOMMouseScrollEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 760 | if (aEventType.LowerCaseEqualsLiteral("dragevent") || |
michael@0 | 761 | aEventType.LowerCaseEqualsLiteral("dragevents")) |
michael@0 | 762 | return NS_NewDOMDragEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 763 | if (aEventType.LowerCaseEqualsLiteral("keyboardevent") || |
michael@0 | 764 | aEventType.LowerCaseEqualsLiteral("keyevents")) |
michael@0 | 765 | return NS_NewDOMKeyboardEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 766 | if (aEventType.LowerCaseEqualsLiteral("compositionevent")) |
michael@0 | 767 | return NS_NewDOMCompositionEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 768 | if (aEventType.LowerCaseEqualsLiteral("mutationevent") || |
michael@0 | 769 | aEventType.LowerCaseEqualsLiteral("mutationevents")) |
michael@0 | 770 | return NS_NewDOMMutationEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 771 | if (aEventType.LowerCaseEqualsLiteral("textevent") || |
michael@0 | 772 | aEventType.LowerCaseEqualsLiteral("textevents")) |
michael@0 | 773 | return NS_NewDOMUIEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 774 | if (aEventType.LowerCaseEqualsLiteral("popupblockedevents")) |
michael@0 | 775 | return NS_NewDOMPopupBlockedEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 776 | if (aEventType.LowerCaseEqualsLiteral("deviceorientationevent")) |
michael@0 | 777 | return NS_NewDOMDeviceOrientationEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 778 | if (aEventType.LowerCaseEqualsLiteral("devicemotionevent")) |
michael@0 | 779 | return NS_NewDOMDeviceMotionEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 780 | if (aEventType.LowerCaseEqualsLiteral("uievent") || |
michael@0 | 781 | aEventType.LowerCaseEqualsLiteral("uievents")) |
michael@0 | 782 | return NS_NewDOMUIEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 783 | if (aEventType.LowerCaseEqualsLiteral("event") || |
michael@0 | 784 | aEventType.LowerCaseEqualsLiteral("events") || |
michael@0 | 785 | aEventType.LowerCaseEqualsLiteral("htmlevents") || |
michael@0 | 786 | aEventType.LowerCaseEqualsLiteral("svgevent") || |
michael@0 | 787 | aEventType.LowerCaseEqualsLiteral("svgevents")) |
michael@0 | 788 | return NS_NewDOMEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 789 | if (aEventType.LowerCaseEqualsLiteral("svgzoomevent") || |
michael@0 | 790 | aEventType.LowerCaseEqualsLiteral("svgzoomevents")) |
michael@0 | 791 | return NS_NewDOMSVGZoomEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 792 | if (aEventType.LowerCaseEqualsLiteral("timeevent") || |
michael@0 | 793 | aEventType.LowerCaseEqualsLiteral("timeevents")) |
michael@0 | 794 | return NS_NewDOMTimeEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 795 | if (aEventType.LowerCaseEqualsLiteral("xulcommandevent") || |
michael@0 | 796 | aEventType.LowerCaseEqualsLiteral("xulcommandevents")) |
michael@0 | 797 | return NS_NewDOMXULCommandEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 798 | if (aEventType.LowerCaseEqualsLiteral("commandevent") || |
michael@0 | 799 | aEventType.LowerCaseEqualsLiteral("commandevents")) |
michael@0 | 800 | return NS_NewDOMCommandEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 801 | if (aEventType.LowerCaseEqualsLiteral("elementreplace")) |
michael@0 | 802 | return NS_NewDOMElementReplaceEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 803 | if (aEventType.LowerCaseEqualsLiteral("datacontainerevent") || |
michael@0 | 804 | aEventType.LowerCaseEqualsLiteral("datacontainerevents")) |
michael@0 | 805 | return NS_NewDOMDataContainerEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 806 | if (aEventType.LowerCaseEqualsLiteral("messageevent")) |
michael@0 | 807 | return NS_NewDOMMessageEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 808 | if (aEventType.LowerCaseEqualsLiteral("notifypaintevent")) |
michael@0 | 809 | return NS_NewDOMNotifyPaintEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 810 | if (aEventType.LowerCaseEqualsLiteral("simplegestureevent")) |
michael@0 | 811 | return NS_NewDOMSimpleGestureEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 812 | if (aEventType.LowerCaseEqualsLiteral("beforeunloadevent")) |
michael@0 | 813 | return NS_NewDOMBeforeUnloadEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 814 | if (aEventType.LowerCaseEqualsLiteral("pagetransition")) |
michael@0 | 815 | return NS_NewDOMPageTransitionEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 816 | if (aEventType.LowerCaseEqualsLiteral("domtransaction")) |
michael@0 | 817 | return NS_NewDOMDOMTransactionEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 818 | if (aEventType.LowerCaseEqualsLiteral("scrollareaevent")) |
michael@0 | 819 | return NS_NewDOMScrollAreaEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 820 | if (aEventType.LowerCaseEqualsLiteral("popstateevent")) |
michael@0 | 821 | return NS_NewDOMPopStateEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 822 | if (aEventType.LowerCaseEqualsLiteral("closeevent")) |
michael@0 | 823 | return NS_NewDOMCloseEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 824 | if (aEventType.LowerCaseEqualsLiteral("touchevent") && |
michael@0 | 825 | TouchEvent::PrefEnabled()) |
michael@0 | 826 | return NS_NewDOMTouchEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 827 | if (aEventType.LowerCaseEqualsLiteral("hashchangeevent")) |
michael@0 | 828 | return NS_NewDOMHashChangeEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 829 | if (aEventType.LowerCaseEqualsLiteral("customevent")) |
michael@0 | 830 | return NS_NewDOMCustomEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 831 | if (aEventType.LowerCaseEqualsLiteral("mozsmsevent")) |
michael@0 | 832 | return NS_NewDOMMozSmsEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 833 | if (aEventType.LowerCaseEqualsLiteral("mozmmsevent")) |
michael@0 | 834 | return NS_NewDOMMozMmsEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 835 | if (aEventType.LowerCaseEqualsLiteral("storageevent")) { |
michael@0 | 836 | return NS_NewDOMStorageEvent(aDOMEvent, aOwner, aPresContext, nullptr); |
michael@0 | 837 | } |
michael@0 | 838 | // NEW EVENT TYPES SHOULD NOT BE ADDED HERE; THEY SHOULD USE ONLY EVENT |
michael@0 | 839 | // CONSTRUCTORS |
michael@0 | 840 | |
michael@0 | 841 | return NS_ERROR_DOM_NOT_SUPPORTED_ERR; |
michael@0 | 842 | } |
michael@0 | 843 | |
michael@0 | 844 | } // namespace mozilla |