dom/events/Event.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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 #include "AccessCheck.h"
michael@0 7 #include "base/basictypes.h"
michael@0 8 #include "ipc/IPCMessageUtils.h"
michael@0 9 #include "mozilla/dom/Event.h"
michael@0 10 #include "mozilla/ContentEvents.h"
michael@0 11 #include "mozilla/DOMEventTargetHelper.h"
michael@0 12 #include "mozilla/EventStateManager.h"
michael@0 13 #include "mozilla/InternalMutationEvent.h"
michael@0 14 #include "mozilla/MiscEvents.h"
michael@0 15 #include "mozilla/MouseEvents.h"
michael@0 16 #include "mozilla/Preferences.h"
michael@0 17 #include "mozilla/TextEvents.h"
michael@0 18 #include "mozilla/TouchEvents.h"
michael@0 19 #include "nsContentUtils.h"
michael@0 20 #include "nsCOMPtr.h"
michael@0 21 #include "nsDeviceContext.h"
michael@0 22 #include "nsError.h"
michael@0 23 #include "nsGlobalWindow.h"
michael@0 24 #include "nsIFrame.h"
michael@0 25 #include "nsIContent.h"
michael@0 26 #include "nsIDocument.h"
michael@0 27 #include "nsIPresShell.h"
michael@0 28 #include "nsIScrollableFrame.h"
michael@0 29 #include "nsJSEnvironment.h"
michael@0 30 #include "nsLayoutUtils.h"
michael@0 31 #include "nsPIWindowRoot.h"
michael@0 32
michael@0 33 namespace mozilla {
michael@0 34 namespace dom {
michael@0 35
michael@0 36 namespace workers {
michael@0 37 extern bool IsCurrentThreadRunningChromeWorker();
michael@0 38 } // namespace workers
michael@0 39
michael@0 40 static char *sPopupAllowedEvents;
michael@0 41
michael@0 42 Event::Event(EventTarget* aOwner,
michael@0 43 nsPresContext* aPresContext,
michael@0 44 WidgetEvent* aEvent)
michael@0 45 {
michael@0 46 ConstructorInit(aOwner, aPresContext, aEvent);
michael@0 47 }
michael@0 48
michael@0 49 Event::Event(nsPIDOMWindow* aParent)
michael@0 50 {
michael@0 51 ConstructorInit(static_cast<nsGlobalWindow *>(aParent), nullptr, nullptr);
michael@0 52 }
michael@0 53
michael@0 54 void
michael@0 55 Event::ConstructorInit(EventTarget* aOwner,
michael@0 56 nsPresContext* aPresContext,
michael@0 57 WidgetEvent* aEvent)
michael@0 58 {
michael@0 59 SetIsDOMBinding();
michael@0 60 SetOwner(aOwner);
michael@0 61 mIsMainThreadEvent = mOwner || NS_IsMainThread();
michael@0 62 if (mIsMainThreadEvent) {
michael@0 63 nsJSContext::LikelyShortLivingObjectCreated();
michael@0 64 }
michael@0 65
michael@0 66 mPrivateDataDuplicated = false;
michael@0 67
michael@0 68 if (aEvent) {
michael@0 69 mEvent = aEvent;
michael@0 70 mEventIsInternal = false;
michael@0 71 }
michael@0 72 else {
michael@0 73 mEventIsInternal = true;
michael@0 74 /*
michael@0 75 A derived class might want to allocate its own type of aEvent
michael@0 76 (derived from WidgetEvent). To do this, it should take care to pass
michael@0 77 a non-nullptr aEvent to this ctor, e.g.:
michael@0 78
michael@0 79 FooEvent::FooEvent(..., WidgetEvent* aEvent)
michael@0 80 : Event(..., aEvent ? aEvent : new WidgetEvent())
michael@0 81
michael@0 82 Then, to override the mEventIsInternal assignments done by the
michael@0 83 base ctor, it should do this in its own ctor:
michael@0 84
michael@0 85 FooEvent::FooEvent(..., WidgetEvent* aEvent)
michael@0 86 ...
michael@0 87 {
michael@0 88 ...
michael@0 89 if (aEvent) {
michael@0 90 mEventIsInternal = false;
michael@0 91 }
michael@0 92 else {
michael@0 93 mEventIsInternal = true;
michael@0 94 }
michael@0 95 ...
michael@0 96 }
michael@0 97 */
michael@0 98 mEvent = new WidgetEvent(false, 0);
michael@0 99 mEvent->time = PR_Now();
michael@0 100 }
michael@0 101
michael@0 102 InitPresContextData(aPresContext);
michael@0 103 }
michael@0 104
michael@0 105 void
michael@0 106 Event::InitPresContextData(nsPresContext* aPresContext)
michael@0 107 {
michael@0 108 mPresContext = aPresContext;
michael@0 109 // Get the explicit original target (if it's anonymous make it null)
michael@0 110 {
michael@0 111 nsCOMPtr<nsIContent> content = GetTargetFromFrame();
michael@0 112 mExplicitOriginalTarget = content;
michael@0 113 if (content && content->IsInAnonymousSubtree()) {
michael@0 114 mExplicitOriginalTarget = nullptr;
michael@0 115 }
michael@0 116 }
michael@0 117 }
michael@0 118
michael@0 119 Event::~Event()
michael@0 120 {
michael@0 121 NS_ASSERT_OWNINGTHREAD(Event);
michael@0 122
michael@0 123 if (mEventIsInternal && mEvent) {
michael@0 124 delete mEvent;
michael@0 125 }
michael@0 126 }
michael@0 127
michael@0 128 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Event)
michael@0 129 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
michael@0 130 NS_INTERFACE_MAP_ENTRY(nsISupports)
michael@0 131 NS_INTERFACE_MAP_ENTRY(nsIDOMEvent)
michael@0 132 NS_INTERFACE_MAP_END
michael@0 133
michael@0 134 NS_IMPL_CYCLE_COLLECTING_ADDREF(Event)
michael@0 135 NS_IMPL_CYCLE_COLLECTING_RELEASE(Event)
michael@0 136
michael@0 137 NS_IMPL_CYCLE_COLLECTION_CLASS(Event)
michael@0 138
michael@0 139 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Event)
michael@0 140 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
michael@0 141 NS_IMPL_CYCLE_COLLECTION_TRACE_END
michael@0 142
michael@0 143 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Event)
michael@0 144 if (tmp->mEventIsInternal) {
michael@0 145 tmp->mEvent->target = nullptr;
michael@0 146 tmp->mEvent->currentTarget = nullptr;
michael@0 147 tmp->mEvent->originalTarget = nullptr;
michael@0 148 switch (tmp->mEvent->eventStructType) {
michael@0 149 case NS_MOUSE_EVENT:
michael@0 150 case NS_MOUSE_SCROLL_EVENT:
michael@0 151 case NS_WHEEL_EVENT:
michael@0 152 case NS_SIMPLE_GESTURE_EVENT:
michael@0 153 case NS_POINTER_EVENT:
michael@0 154 tmp->mEvent->AsMouseEventBase()->relatedTarget = nullptr;
michael@0 155 break;
michael@0 156 case NS_DRAG_EVENT: {
michael@0 157 WidgetDragEvent* dragEvent = tmp->mEvent->AsDragEvent();
michael@0 158 dragEvent->dataTransfer = nullptr;
michael@0 159 dragEvent->relatedTarget = nullptr;
michael@0 160 break;
michael@0 161 }
michael@0 162 case NS_CLIPBOARD_EVENT:
michael@0 163 tmp->mEvent->AsClipboardEvent()->clipboardData = nullptr;
michael@0 164 break;
michael@0 165 case NS_MUTATION_EVENT:
michael@0 166 tmp->mEvent->AsMutationEvent()->mRelatedNode = nullptr;
michael@0 167 break;
michael@0 168 case NS_FOCUS_EVENT:
michael@0 169 tmp->mEvent->AsFocusEvent()->relatedTarget = nullptr;
michael@0 170 break;
michael@0 171 default:
michael@0 172 break;
michael@0 173 }
michael@0 174 }
michael@0 175 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPresContext);
michael@0 176 NS_IMPL_CYCLE_COLLECTION_UNLINK(mExplicitOriginalTarget);
michael@0 177 NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner);
michael@0 178 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
michael@0 179 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
michael@0 180
michael@0 181 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Event)
michael@0 182 if (tmp->mEventIsInternal) {
michael@0 183 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent->target)
michael@0 184 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent->currentTarget)
michael@0 185 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent->originalTarget)
michael@0 186 switch (tmp->mEvent->eventStructType) {
michael@0 187 case NS_MOUSE_EVENT:
michael@0 188 case NS_MOUSE_SCROLL_EVENT:
michael@0 189 case NS_WHEEL_EVENT:
michael@0 190 case NS_SIMPLE_GESTURE_EVENT:
michael@0 191 case NS_POINTER_EVENT:
michael@0 192 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->relatedTarget");
michael@0 193 cb.NoteXPCOMChild(tmp->mEvent->AsMouseEventBase()->relatedTarget);
michael@0 194 break;
michael@0 195 case NS_DRAG_EVENT: {
michael@0 196 WidgetDragEvent* dragEvent = tmp->mEvent->AsDragEvent();
michael@0 197 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->dataTransfer");
michael@0 198 cb.NoteXPCOMChild(dragEvent->dataTransfer);
michael@0 199 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->relatedTarget");
michael@0 200 cb.NoteXPCOMChild(dragEvent->relatedTarget);
michael@0 201 break;
michael@0 202 }
michael@0 203 case NS_CLIPBOARD_EVENT:
michael@0 204 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->clipboardData");
michael@0 205 cb.NoteXPCOMChild(tmp->mEvent->AsClipboardEvent()->clipboardData);
michael@0 206 break;
michael@0 207 case NS_MUTATION_EVENT:
michael@0 208 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->mRelatedNode");
michael@0 209 cb.NoteXPCOMChild(tmp->mEvent->AsMutationEvent()->mRelatedNode);
michael@0 210 break;
michael@0 211 case NS_FOCUS_EVENT:
michael@0 212 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->relatedTarget");
michael@0 213 cb.NoteXPCOMChild(tmp->mEvent->AsFocusEvent()->relatedTarget);
michael@0 214 break;
michael@0 215 default:
michael@0 216 break;
michael@0 217 }
michael@0 218 }
michael@0 219 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresContext)
michael@0 220 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExplicitOriginalTarget)
michael@0 221 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
michael@0 222 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
michael@0 223 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
michael@0 224
michael@0 225 bool
michael@0 226 Event::IsChrome(JSContext* aCx) const
michael@0 227 {
michael@0 228 return mIsMainThreadEvent ?
michael@0 229 xpc::AccessCheck::isChrome(js::GetContextCompartment(aCx)) :
michael@0 230 mozilla::dom::workers::IsCurrentThreadRunningChromeWorker();
michael@0 231 }
michael@0 232
michael@0 233 // nsIDOMEventInterface
michael@0 234 NS_METHOD
michael@0 235 Event::GetType(nsAString& aType)
michael@0 236 {
michael@0 237 if (!mIsMainThreadEvent || !mEvent->typeString.IsEmpty()) {
michael@0 238 aType = mEvent->typeString;
michael@0 239 return NS_OK;
michael@0 240 }
michael@0 241 const char* name = GetEventName(mEvent->message);
michael@0 242
michael@0 243 if (name) {
michael@0 244 CopyASCIItoUTF16(name, aType);
michael@0 245 return NS_OK;
michael@0 246 } else if (mEvent->message == NS_USER_DEFINED_EVENT && mEvent->userType) {
michael@0 247 aType = Substring(nsDependentAtomString(mEvent->userType), 2); // Remove "on"
michael@0 248 mEvent->typeString = aType;
michael@0 249 return NS_OK;
michael@0 250 }
michael@0 251
michael@0 252 aType.Truncate();
michael@0 253 return NS_OK;
michael@0 254 }
michael@0 255
michael@0 256 static EventTarget*
michael@0 257 GetDOMEventTarget(nsIDOMEventTarget* aTarget)
michael@0 258 {
michael@0 259 return aTarget ? aTarget->GetTargetForDOMEvent() : nullptr;
michael@0 260 }
michael@0 261
michael@0 262 EventTarget*
michael@0 263 Event::GetTarget() const
michael@0 264 {
michael@0 265 return GetDOMEventTarget(mEvent->target);
michael@0 266 }
michael@0 267
michael@0 268 NS_METHOD
michael@0 269 Event::GetTarget(nsIDOMEventTarget** aTarget)
michael@0 270 {
michael@0 271 NS_IF_ADDREF(*aTarget = GetTarget());
michael@0 272 return NS_OK;
michael@0 273 }
michael@0 274
michael@0 275 EventTarget*
michael@0 276 Event::GetCurrentTarget() const
michael@0 277 {
michael@0 278 return GetDOMEventTarget(mEvent->currentTarget);
michael@0 279 }
michael@0 280
michael@0 281 NS_IMETHODIMP
michael@0 282 Event::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget)
michael@0 283 {
michael@0 284 NS_IF_ADDREF(*aCurrentTarget = GetCurrentTarget());
michael@0 285 return NS_OK;
michael@0 286 }
michael@0 287
michael@0 288 //
michael@0 289 // Get the actual event target node (may have been retargeted for mouse events)
michael@0 290 //
michael@0 291 already_AddRefed<nsIContent>
michael@0 292 Event::GetTargetFromFrame()
michael@0 293 {
michael@0 294 if (!mPresContext) { return nullptr; }
michael@0 295
michael@0 296 // Get the target frame (have to get the ESM first)
michael@0 297 nsIFrame* targetFrame = mPresContext->EventStateManager()->GetEventTarget();
michael@0 298 if (!targetFrame) { return nullptr; }
michael@0 299
michael@0 300 // get the real content
michael@0 301 nsCOMPtr<nsIContent> realEventContent;
michael@0 302 targetFrame->GetContentForEvent(mEvent, getter_AddRefs(realEventContent));
michael@0 303 return realEventContent.forget();
michael@0 304 }
michael@0 305
michael@0 306 EventTarget*
michael@0 307 Event::GetExplicitOriginalTarget() const
michael@0 308 {
michael@0 309 if (mExplicitOriginalTarget) {
michael@0 310 return mExplicitOriginalTarget;
michael@0 311 }
michael@0 312 return GetTarget();
michael@0 313 }
michael@0 314
michael@0 315 NS_IMETHODIMP
michael@0 316 Event::GetExplicitOriginalTarget(nsIDOMEventTarget** aRealEventTarget)
michael@0 317 {
michael@0 318 NS_IF_ADDREF(*aRealEventTarget = GetExplicitOriginalTarget());
michael@0 319 return NS_OK;
michael@0 320 }
michael@0 321
michael@0 322 EventTarget*
michael@0 323 Event::GetOriginalTarget() const
michael@0 324 {
michael@0 325 if (mEvent->originalTarget) {
michael@0 326 return GetDOMEventTarget(mEvent->originalTarget);
michael@0 327 }
michael@0 328
michael@0 329 return GetTarget();
michael@0 330 }
michael@0 331
michael@0 332 NS_IMETHODIMP
michael@0 333 Event::GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget)
michael@0 334 {
michael@0 335 NS_IF_ADDREF(*aOriginalTarget = GetOriginalTarget());
michael@0 336 return NS_OK;
michael@0 337 }
michael@0 338
michael@0 339 NS_IMETHODIMP_(void)
michael@0 340 Event::SetTrusted(bool aTrusted)
michael@0 341 {
michael@0 342 mEvent->mFlags.mIsTrusted = aTrusted;
michael@0 343 }
michael@0 344
michael@0 345 bool
michael@0 346 Event::Init(mozilla::dom::EventTarget* aGlobal)
michael@0 347 {
michael@0 348 if (!mIsMainThreadEvent) {
michael@0 349 return nsContentUtils::ThreadsafeIsCallerChrome();
michael@0 350 }
michael@0 351 bool trusted = false;
michael@0 352 nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal);
michael@0 353 if (w) {
michael@0 354 nsCOMPtr<nsIDocument> d = w->GetExtantDoc();
michael@0 355 if (d) {
michael@0 356 trusted = nsContentUtils::IsChromeDoc(d);
michael@0 357 nsIPresShell* s = d->GetShell();
michael@0 358 if (s) {
michael@0 359 InitPresContextData(s->GetPresContext());
michael@0 360 }
michael@0 361 }
michael@0 362 }
michael@0 363 return trusted;
michael@0 364 }
michael@0 365
michael@0 366 // static
michael@0 367 already_AddRefed<Event>
michael@0 368 Event::Constructor(const GlobalObject& aGlobal,
michael@0 369 const nsAString& aType,
michael@0 370 const EventInit& aParam,
michael@0 371 ErrorResult& aRv)
michael@0 372 {
michael@0 373 nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
michael@0 374 nsRefPtr<Event> e = new Event(t, nullptr, nullptr);
michael@0 375 bool trusted = e->Init(t);
michael@0 376 aRv = e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
michael@0 377 e->SetTrusted(trusted);
michael@0 378 return e.forget();
michael@0 379 }
michael@0 380
michael@0 381 uint16_t
michael@0 382 Event::EventPhase() const
michael@0 383 {
michael@0 384 // Note, remember to check that this works also
michael@0 385 // if or when Bug 235441 is fixed.
michael@0 386 if ((mEvent->currentTarget &&
michael@0 387 mEvent->currentTarget == mEvent->target) ||
michael@0 388 mEvent->mFlags.InTargetPhase()) {
michael@0 389 return nsIDOMEvent::AT_TARGET;
michael@0 390 }
michael@0 391 if (mEvent->mFlags.mInCapturePhase) {
michael@0 392 return nsIDOMEvent::CAPTURING_PHASE;
michael@0 393 }
michael@0 394 if (mEvent->mFlags.mInBubblingPhase) {
michael@0 395 return nsIDOMEvent::BUBBLING_PHASE;
michael@0 396 }
michael@0 397 return nsIDOMEvent::NONE;
michael@0 398 }
michael@0 399
michael@0 400 NS_IMETHODIMP
michael@0 401 Event::GetEventPhase(uint16_t* aEventPhase)
michael@0 402 {
michael@0 403 *aEventPhase = EventPhase();
michael@0 404 return NS_OK;
michael@0 405 }
michael@0 406
michael@0 407 NS_IMETHODIMP
michael@0 408 Event::GetBubbles(bool* aBubbles)
michael@0 409 {
michael@0 410 *aBubbles = Bubbles();
michael@0 411 return NS_OK;
michael@0 412 }
michael@0 413
michael@0 414 NS_IMETHODIMP
michael@0 415 Event::GetCancelable(bool* aCancelable)
michael@0 416 {
michael@0 417 *aCancelable = Cancelable();
michael@0 418 return NS_OK;
michael@0 419 }
michael@0 420
michael@0 421 NS_IMETHODIMP
michael@0 422 Event::GetTimeStamp(uint64_t* aTimeStamp)
michael@0 423 {
michael@0 424 *aTimeStamp = TimeStamp();
michael@0 425 return NS_OK;
michael@0 426 }
michael@0 427
michael@0 428 NS_IMETHODIMP
michael@0 429 Event::StopPropagation()
michael@0 430 {
michael@0 431 mEvent->mFlags.mPropagationStopped = true;
michael@0 432 return NS_OK;
michael@0 433 }
michael@0 434
michael@0 435 NS_IMETHODIMP
michael@0 436 Event::StopImmediatePropagation()
michael@0 437 {
michael@0 438 mEvent->mFlags.mPropagationStopped = true;
michael@0 439 mEvent->mFlags.mImmediatePropagationStopped = true;
michael@0 440 return NS_OK;
michael@0 441 }
michael@0 442
michael@0 443 NS_IMETHODIMP
michael@0 444 Event::GetIsTrusted(bool* aIsTrusted)
michael@0 445 {
michael@0 446 *aIsTrusted = IsTrusted();
michael@0 447 return NS_OK;
michael@0 448 }
michael@0 449
michael@0 450 NS_IMETHODIMP
michael@0 451 Event::PreventDefault()
michael@0 452 {
michael@0 453 // This method is called only from C++ code which must handle default action
michael@0 454 // of this event. So, pass true always.
michael@0 455 PreventDefaultInternal(true);
michael@0 456 return NS_OK;
michael@0 457 }
michael@0 458
michael@0 459 void
michael@0 460 Event::PreventDefault(JSContext* aCx)
michael@0 461 {
michael@0 462 MOZ_ASSERT(aCx, "JS context must be specified");
michael@0 463
michael@0 464 // Note that at handling default action, another event may be dispatched.
michael@0 465 // Then, JS in content mey be call preventDefault()
michael@0 466 // even in the event is in system event group. Therefore, don't refer
michael@0 467 // mInSystemGroup here.
michael@0 468 PreventDefaultInternal(IsChrome(aCx));
michael@0 469 }
michael@0 470
michael@0 471 void
michael@0 472 Event::PreventDefaultInternal(bool aCalledByDefaultHandler)
michael@0 473 {
michael@0 474 if (!mEvent->mFlags.mCancelable) {
michael@0 475 return;
michael@0 476 }
michael@0 477
michael@0 478 mEvent->mFlags.mDefaultPrevented = true;
michael@0 479
michael@0 480 // Note that even if preventDefault() has already been called by chrome,
michael@0 481 // a call of preventDefault() by content needs to overwrite
michael@0 482 // mDefaultPreventedByContent to true because in such case, defaultPrevented
michael@0 483 // must be true when web apps check it after they call preventDefault().
michael@0 484 if (!aCalledByDefaultHandler) {
michael@0 485 mEvent->mFlags.mDefaultPreventedByContent = true;
michael@0 486 }
michael@0 487
michael@0 488 if (!IsTrusted()) {
michael@0 489 return;
michael@0 490 }
michael@0 491
michael@0 492 WidgetDragEvent* dragEvent = mEvent->AsDragEvent();
michael@0 493 if (!dragEvent) {
michael@0 494 return;
michael@0 495 }
michael@0 496
michael@0 497 nsCOMPtr<nsINode> node = do_QueryInterface(mEvent->currentTarget);
michael@0 498 if (!node) {
michael@0 499 nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mEvent->currentTarget);
michael@0 500 if (!win) {
michael@0 501 return;
michael@0 502 }
michael@0 503 node = win->GetExtantDoc();
michael@0 504 }
michael@0 505 if (!nsContentUtils::IsChromeDoc(node->OwnerDoc())) {
michael@0 506 dragEvent->mDefaultPreventedOnContent = true;
michael@0 507 }
michael@0 508 }
michael@0 509
michael@0 510 void
michael@0 511 Event::SetEventType(const nsAString& aEventTypeArg)
michael@0 512 {
michael@0 513 if (mIsMainThreadEvent) {
michael@0 514 mEvent->userType =
michael@0 515 nsContentUtils::GetEventIdAndAtom(aEventTypeArg, mEvent->eventStructType,
michael@0 516 &(mEvent->message));
michael@0 517 } else {
michael@0 518 mEvent->userType = nullptr;
michael@0 519 mEvent->message = NS_USER_DEFINED_EVENT;
michael@0 520 mEvent->typeString = aEventTypeArg;
michael@0 521 }
michael@0 522 }
michael@0 523
michael@0 524 NS_IMETHODIMP
michael@0 525 Event::InitEvent(const nsAString& aEventTypeArg,
michael@0 526 bool aCanBubbleArg,
michael@0 527 bool aCancelableArg)
michael@0 528 {
michael@0 529 // Make sure this event isn't already being dispatched.
michael@0 530 NS_ENSURE_TRUE(!mEvent->mFlags.mIsBeingDispatched, NS_OK);
michael@0 531
michael@0 532 if (IsTrusted()) {
michael@0 533 // Ensure the caller is permitted to dispatch trusted DOM events.
michael@0 534 if (!nsContentUtils::ThreadsafeIsCallerChrome()) {
michael@0 535 SetTrusted(false);
michael@0 536 }
michael@0 537 }
michael@0 538
michael@0 539 SetEventType(aEventTypeArg);
michael@0 540
michael@0 541 mEvent->mFlags.mBubbles = aCanBubbleArg;
michael@0 542 mEvent->mFlags.mCancelable = aCancelableArg;
michael@0 543
michael@0 544 mEvent->mFlags.mDefaultPrevented = false;
michael@0 545
michael@0 546 // Clearing the old targets, so that the event is targeted correctly when
michael@0 547 // re-dispatching it.
michael@0 548 mEvent->target = nullptr;
michael@0 549 mEvent->originalTarget = nullptr;
michael@0 550 return NS_OK;
michael@0 551 }
michael@0 552
michael@0 553 NS_IMETHODIMP
michael@0 554 Event::DuplicatePrivateData()
michael@0 555 {
michael@0 556 NS_ASSERTION(mEvent, "No WidgetEvent for Event duplication!");
michael@0 557 if (mEventIsInternal) {
michael@0 558 return NS_OK;
michael@0 559 }
michael@0 560
michael@0 561 mEvent = mEvent->Duplicate();
michael@0 562 mPresContext = nullptr;
michael@0 563 mEventIsInternal = true;
michael@0 564 mPrivateDataDuplicated = true;
michael@0 565
michael@0 566 return NS_OK;
michael@0 567 }
michael@0 568
michael@0 569 NS_IMETHODIMP
michael@0 570 Event::SetTarget(nsIDOMEventTarget* aTarget)
michael@0 571 {
michael@0 572 #ifdef DEBUG
michael@0 573 {
michael@0 574 nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aTarget);
michael@0 575
michael@0 576 NS_ASSERTION(!win || !win->IsInnerWindow(),
michael@0 577 "Uh, inner window set as event target!");
michael@0 578 }
michael@0 579 #endif
michael@0 580
michael@0 581 mEvent->target = do_QueryInterface(aTarget);
michael@0 582 return NS_OK;
michael@0 583 }
michael@0 584
michael@0 585 NS_IMETHODIMP_(bool)
michael@0 586 Event::IsDispatchStopped()
michael@0 587 {
michael@0 588 return mEvent->mFlags.mPropagationStopped;
michael@0 589 }
michael@0 590
michael@0 591 NS_IMETHODIMP_(WidgetEvent*)
michael@0 592 Event::GetInternalNSEvent()
michael@0 593 {
michael@0 594 return mEvent;
michael@0 595 }
michael@0 596
michael@0 597 NS_IMETHODIMP_(Event*)
michael@0 598 Event::InternalDOMEvent()
michael@0 599 {
michael@0 600 return this;
michael@0 601 }
michael@0 602
michael@0 603 // return true if eventName is contained within events, delimited by
michael@0 604 // spaces
michael@0 605 static bool
michael@0 606 PopupAllowedForEvent(const char *eventName)
michael@0 607 {
michael@0 608 if (!sPopupAllowedEvents) {
michael@0 609 Event::PopupAllowedEventsChanged();
michael@0 610
michael@0 611 if (!sPopupAllowedEvents) {
michael@0 612 return false;
michael@0 613 }
michael@0 614 }
michael@0 615
michael@0 616 nsDependentCString events(sPopupAllowedEvents);
michael@0 617
michael@0 618 nsAFlatCString::const_iterator start, end;
michael@0 619 nsAFlatCString::const_iterator startiter(events.BeginReading(start));
michael@0 620 events.EndReading(end);
michael@0 621
michael@0 622 while (startiter != end) {
michael@0 623 nsAFlatCString::const_iterator enditer(end);
michael@0 624
michael@0 625 if (!FindInReadable(nsDependentCString(eventName), startiter, enditer))
michael@0 626 return false;
michael@0 627
michael@0 628 // the match is surrounded by spaces, or at a string boundary
michael@0 629 if ((startiter == start || *--startiter == ' ') &&
michael@0 630 (enditer == end || *enditer == ' ')) {
michael@0 631 return true;
michael@0 632 }
michael@0 633
michael@0 634 // Move on and see if there are other matches. (The delimitation
michael@0 635 // requirement makes it pointless to begin the next search before
michael@0 636 // the end of the invalid match just found.)
michael@0 637 startiter = enditer;
michael@0 638 }
michael@0 639
michael@0 640 return false;
michael@0 641 }
michael@0 642
michael@0 643 // static
michael@0 644 PopupControlState
michael@0 645 Event::GetEventPopupControlState(WidgetEvent* aEvent)
michael@0 646 {
michael@0 647 // generally if an event handler is running, new windows are disallowed.
michael@0 648 // check for exceptions:
michael@0 649 PopupControlState abuse = openAbused;
michael@0 650
michael@0 651 switch(aEvent->eventStructType) {
michael@0 652 case NS_EVENT :
michael@0 653 // For these following events only allow popups if they're
michael@0 654 // triggered while handling user input. See
michael@0 655 // nsPresShell::HandleEventInternal() for details.
michael@0 656 if (EventStateManager::IsHandlingUserInput()) {
michael@0 657 switch(aEvent->message) {
michael@0 658 case NS_FORM_SELECTED :
michael@0 659 if (PopupAllowedForEvent("select")) {
michael@0 660 abuse = openControlled;
michael@0 661 }
michael@0 662 break;
michael@0 663 case NS_FORM_CHANGE :
michael@0 664 if (PopupAllowedForEvent("change")) {
michael@0 665 abuse = openControlled;
michael@0 666 }
michael@0 667 break;
michael@0 668 }
michael@0 669 }
michael@0 670 break;
michael@0 671 case NS_EDITOR_INPUT_EVENT :
michael@0 672 // For this following event only allow popups if it's triggered
michael@0 673 // while handling user input. See
michael@0 674 // nsPresShell::HandleEventInternal() for details.
michael@0 675 if (EventStateManager::IsHandlingUserInput()) {
michael@0 676 switch(aEvent->message) {
michael@0 677 case NS_EDITOR_INPUT:
michael@0 678 if (PopupAllowedForEvent("input")) {
michael@0 679 abuse = openControlled;
michael@0 680 }
michael@0 681 break;
michael@0 682 }
michael@0 683 }
michael@0 684 break;
michael@0 685 case NS_INPUT_EVENT :
michael@0 686 // For this following event only allow popups if it's triggered
michael@0 687 // while handling user input. See
michael@0 688 // nsPresShell::HandleEventInternal() for details.
michael@0 689 if (EventStateManager::IsHandlingUserInput()) {
michael@0 690 switch(aEvent->message) {
michael@0 691 case NS_FORM_CHANGE :
michael@0 692 if (PopupAllowedForEvent("change")) {
michael@0 693 abuse = openControlled;
michael@0 694 }
michael@0 695 break;
michael@0 696 case NS_XUL_COMMAND:
michael@0 697 abuse = openControlled;
michael@0 698 break;
michael@0 699 }
michael@0 700 }
michael@0 701 break;
michael@0 702 case NS_KEY_EVENT :
michael@0 703 if (aEvent->mFlags.mIsTrusted) {
michael@0 704 uint32_t key = aEvent->AsKeyboardEvent()->keyCode;
michael@0 705 switch(aEvent->message) {
michael@0 706 case NS_KEY_PRESS :
michael@0 707 // return key on focused button. see note at NS_MOUSE_CLICK.
michael@0 708 if (key == nsIDOMKeyEvent::DOM_VK_RETURN) {
michael@0 709 abuse = openAllowed;
michael@0 710 } else if (PopupAllowedForEvent("keypress")) {
michael@0 711 abuse = openControlled;
michael@0 712 }
michael@0 713 break;
michael@0 714 case NS_KEY_UP :
michael@0 715 // space key on focused button. see note at NS_MOUSE_CLICK.
michael@0 716 if (key == nsIDOMKeyEvent::DOM_VK_SPACE) {
michael@0 717 abuse = openAllowed;
michael@0 718 } else if (PopupAllowedForEvent("keyup")) {
michael@0 719 abuse = openControlled;
michael@0 720 }
michael@0 721 break;
michael@0 722 case NS_KEY_DOWN :
michael@0 723 if (PopupAllowedForEvent("keydown")) {
michael@0 724 abuse = openControlled;
michael@0 725 }
michael@0 726 break;
michael@0 727 }
michael@0 728 }
michael@0 729 break;
michael@0 730 case NS_TOUCH_EVENT :
michael@0 731 if (aEvent->mFlags.mIsTrusted) {
michael@0 732 switch (aEvent->message) {
michael@0 733 case NS_TOUCH_START :
michael@0 734 if (PopupAllowedForEvent("touchstart")) {
michael@0 735 abuse = openControlled;
michael@0 736 }
michael@0 737 break;
michael@0 738 case NS_TOUCH_END :
michael@0 739 if (PopupAllowedForEvent("touchend")) {
michael@0 740 abuse = openControlled;
michael@0 741 }
michael@0 742 break;
michael@0 743 }
michael@0 744 }
michael@0 745 break;
michael@0 746 case NS_MOUSE_EVENT :
michael@0 747 if (aEvent->mFlags.mIsTrusted &&
michael@0 748 aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
michael@0 749 switch(aEvent->message) {
michael@0 750 case NS_MOUSE_BUTTON_UP :
michael@0 751 if (PopupAllowedForEvent("mouseup")) {
michael@0 752 abuse = openControlled;
michael@0 753 }
michael@0 754 break;
michael@0 755 case NS_MOUSE_BUTTON_DOWN :
michael@0 756 if (PopupAllowedForEvent("mousedown")) {
michael@0 757 abuse = openControlled;
michael@0 758 }
michael@0 759 break;
michael@0 760 case NS_MOUSE_CLICK :
michael@0 761 /* Click events get special treatment because of their
michael@0 762 historical status as a more legitimate event handler. If
michael@0 763 click popups are enabled in the prefs, clear the popup
michael@0 764 status completely. */
michael@0 765 if (PopupAllowedForEvent("click")) {
michael@0 766 abuse = openAllowed;
michael@0 767 }
michael@0 768 break;
michael@0 769 case NS_MOUSE_DOUBLECLICK :
michael@0 770 if (PopupAllowedForEvent("dblclick")) {
michael@0 771 abuse = openControlled;
michael@0 772 }
michael@0 773 break;
michael@0 774 }
michael@0 775 }
michael@0 776 break;
michael@0 777 case NS_FORM_EVENT :
michael@0 778 // For these following events only allow popups if they're
michael@0 779 // triggered while handling user input. See
michael@0 780 // nsPresShell::HandleEventInternal() for details.
michael@0 781 if (EventStateManager::IsHandlingUserInput()) {
michael@0 782 switch(aEvent->message) {
michael@0 783 case NS_FORM_SUBMIT :
michael@0 784 if (PopupAllowedForEvent("submit")) {
michael@0 785 abuse = openControlled;
michael@0 786 }
michael@0 787 break;
michael@0 788 case NS_FORM_RESET :
michael@0 789 if (PopupAllowedForEvent("reset")) {
michael@0 790 abuse = openControlled;
michael@0 791 }
michael@0 792 break;
michael@0 793 }
michael@0 794 }
michael@0 795 break;
michael@0 796 default:
michael@0 797 break;
michael@0 798 }
michael@0 799
michael@0 800 return abuse;
michael@0 801 }
michael@0 802
michael@0 803 // static
michael@0 804 void
michael@0 805 Event::PopupAllowedEventsChanged()
michael@0 806 {
michael@0 807 if (sPopupAllowedEvents) {
michael@0 808 nsMemory::Free(sPopupAllowedEvents);
michael@0 809 }
michael@0 810
michael@0 811 nsAdoptingCString str = Preferences::GetCString("dom.popup_allowed_events");
michael@0 812
michael@0 813 // We'll want to do this even if str is empty to avoid looking up
michael@0 814 // this pref all the time if it's not set.
michael@0 815 sPopupAllowedEvents = ToNewCString(str);
michael@0 816 }
michael@0 817
michael@0 818 // static
michael@0 819 void
michael@0 820 Event::Shutdown()
michael@0 821 {
michael@0 822 if (sPopupAllowedEvents) {
michael@0 823 nsMemory::Free(sPopupAllowedEvents);
michael@0 824 }
michael@0 825 }
michael@0 826
michael@0 827 nsIntPoint
michael@0 828 Event::GetScreenCoords(nsPresContext* aPresContext,
michael@0 829 WidgetEvent* aEvent,
michael@0 830 LayoutDeviceIntPoint aPoint)
michael@0 831 {
michael@0 832 if (!nsContentUtils::IsCallerChrome()) {
michael@0 833 // For non-chrome callers, return client coordinates instead.
michael@0 834 // For some events, the result will be zero; specifically, for dragend
michael@0 835 // events (there is no widget associated with dragend events, which
michael@0 836 // causes GetClientX() to return zero). Since dragend is for the drag
michael@0 837 // originator and not for the receiver, it is probably not widely used
michael@0 838 // (receivers get a drop event). Therefore, returning 0 should not break
michael@0 839 // many web pages. Also, a few years ago Firefox returned 0.
michael@0 840 // See: https://bugzilla.mozilla.org/show_bug.cgi?id=466379
michael@0 841 CSSIntPoint clientCoords = GetClientCoords(aPresContext, aEvent, aPoint, CSSIntPoint(0, 0));
michael@0 842 return nsIntPoint(clientCoords.x, clientCoords.y);
michael@0 843 }
michael@0 844
michael@0 845 if (EventStateManager::sIsPointerLocked) {
michael@0 846 return EventStateManager::sLastScreenPoint;
michael@0 847 }
michael@0 848
michael@0 849 if (!aEvent ||
michael@0 850 (aEvent->eventStructType != NS_MOUSE_EVENT &&
michael@0 851 aEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
michael@0 852 aEvent->eventStructType != NS_WHEEL_EVENT &&
michael@0 853 aEvent->eventStructType != NS_POINTER_EVENT &&
michael@0 854 aEvent->eventStructType != NS_TOUCH_EVENT &&
michael@0 855 aEvent->eventStructType != NS_DRAG_EVENT &&
michael@0 856 aEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT)) {
michael@0 857 return nsIntPoint(0, 0);
michael@0 858 }
michael@0 859
michael@0 860 WidgetGUIEvent* guiEvent = aEvent->AsGUIEvent();
michael@0 861 if (!guiEvent->widget) {
michael@0 862 return LayoutDeviceIntPoint::ToUntyped(aPoint);
michael@0 863 }
michael@0 864
michael@0 865 LayoutDeviceIntPoint offset = aPoint +
michael@0 866 LayoutDeviceIntPoint::FromUntyped(guiEvent->widget->WidgetToScreenOffset());
michael@0 867 nscoord factor = aPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel();
michael@0 868 return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(offset.x * factor),
michael@0 869 nsPresContext::AppUnitsToIntCSSPixels(offset.y * factor));
michael@0 870 }
michael@0 871
michael@0 872 // static
michael@0 873 CSSIntPoint
michael@0 874 Event::GetPageCoords(nsPresContext* aPresContext,
michael@0 875 WidgetEvent* aEvent,
michael@0 876 LayoutDeviceIntPoint aPoint,
michael@0 877 CSSIntPoint aDefaultPoint)
michael@0 878 {
michael@0 879 CSSIntPoint pagePoint =
michael@0 880 Event::GetClientCoords(aPresContext, aEvent, aPoint, aDefaultPoint);
michael@0 881
michael@0 882 // If there is some scrolling, add scroll info to client point.
michael@0 883 if (aPresContext && aPresContext->GetPresShell()) {
michael@0 884 nsIPresShell* shell = aPresContext->GetPresShell();
michael@0 885 nsIScrollableFrame* scrollframe = shell->GetRootScrollFrameAsScrollable();
michael@0 886 if (scrollframe) {
michael@0 887 pagePoint += CSSIntPoint::FromAppUnitsRounded(scrollframe->GetScrollPosition());
michael@0 888 }
michael@0 889 }
michael@0 890
michael@0 891 return pagePoint;
michael@0 892 }
michael@0 893
michael@0 894 // static
michael@0 895 CSSIntPoint
michael@0 896 Event::GetClientCoords(nsPresContext* aPresContext,
michael@0 897 WidgetEvent* aEvent,
michael@0 898 LayoutDeviceIntPoint aPoint,
michael@0 899 CSSIntPoint aDefaultPoint)
michael@0 900 {
michael@0 901 if (EventStateManager::sIsPointerLocked) {
michael@0 902 return EventStateManager::sLastClientPoint;
michael@0 903 }
michael@0 904
michael@0 905 if (!aEvent ||
michael@0 906 (aEvent->eventStructType != NS_MOUSE_EVENT &&
michael@0 907 aEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
michael@0 908 aEvent->eventStructType != NS_WHEEL_EVENT &&
michael@0 909 aEvent->eventStructType != NS_TOUCH_EVENT &&
michael@0 910 aEvent->eventStructType != NS_DRAG_EVENT &&
michael@0 911 aEvent->eventStructType != NS_POINTER_EVENT &&
michael@0 912 aEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT) ||
michael@0 913 !aPresContext ||
michael@0 914 !aEvent->AsGUIEvent()->widget) {
michael@0 915 return aDefaultPoint;
michael@0 916 }
michael@0 917
michael@0 918 nsIPresShell* shell = aPresContext->GetPresShell();
michael@0 919 if (!shell) {
michael@0 920 return CSSIntPoint(0, 0);
michael@0 921 }
michael@0 922
michael@0 923 nsIFrame* rootFrame = shell->GetRootFrame();
michael@0 924 if (!rootFrame) {
michael@0 925 return CSSIntPoint(0, 0);
michael@0 926 }
michael@0 927 nsPoint pt =
michael@0 928 nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent,
michael@0 929 LayoutDeviceIntPoint::ToUntyped(aPoint), rootFrame);
michael@0 930
michael@0 931 return CSSIntPoint::FromAppUnitsRounded(pt);
michael@0 932 }
michael@0 933
michael@0 934 // To be called ONLY by Event::GetType (which has the additional
michael@0 935 // logic for handling user-defined events).
michael@0 936 // static
michael@0 937 const char*
michael@0 938 Event::GetEventName(uint32_t aEventType)
michael@0 939 {
michael@0 940 switch(aEventType) {
michael@0 941 #define ID_TO_EVENT(name_, _id, _type, _struct) \
michael@0 942 case _id: return #name_;
michael@0 943 #include "mozilla/EventNameList.h"
michael@0 944 #undef ID_TO_EVENT
michael@0 945 default:
michael@0 946 break;
michael@0 947 }
michael@0 948 // XXXldb We can hit this case for WidgetEvent objects that we didn't
michael@0 949 // create and that are not user defined events since this function and
michael@0 950 // SetEventType are incomplete. (But fixing that requires fixing the
michael@0 951 // arrays in nsEventListenerManager too, since the events for which
michael@0 952 // this is a problem generally *are* created by Event.)
michael@0 953 return nullptr;
michael@0 954 }
michael@0 955
michael@0 956 bool
michael@0 957 Event::DefaultPrevented(JSContext* aCx) const
michael@0 958 {
michael@0 959 MOZ_ASSERT(aCx, "JS context must be specified");
michael@0 960
michael@0 961 NS_ENSURE_TRUE(mEvent, false);
michael@0 962
michael@0 963 // If preventDefault() has never been called, just return false.
michael@0 964 if (!mEvent->mFlags.mDefaultPrevented) {
michael@0 965 return false;
michael@0 966 }
michael@0 967
michael@0 968 // If preventDefault() has been called by content, return true. Otherwise,
michael@0 969 // i.e., preventDefault() has been called by chrome, return true only when
michael@0 970 // this is called by chrome.
michael@0 971 return mEvent->mFlags.mDefaultPreventedByContent || IsChrome(aCx);
michael@0 972 }
michael@0 973
michael@0 974 bool
michael@0 975 Event::GetPreventDefault() const
michael@0 976 {
michael@0 977 if (mOwner) {
michael@0 978 if (nsIDocument* doc = mOwner->GetExtantDoc()) {
michael@0 979 doc->WarnOnceAbout(nsIDocument::eGetPreventDefault);
michael@0 980 }
michael@0 981 }
michael@0 982 // GetPreventDefault() is legacy and Gecko specific method. Although,
michael@0 983 // the result should be same as defaultPrevented, we don't need to break
michael@0 984 // backward compatibility of legacy method. Let's behave traditionally.
michael@0 985 return DefaultPrevented();
michael@0 986 }
michael@0 987
michael@0 988 NS_IMETHODIMP
michael@0 989 Event::GetPreventDefault(bool* aReturn)
michael@0 990 {
michael@0 991 NS_ENSURE_ARG_POINTER(aReturn);
michael@0 992 *aReturn = GetPreventDefault();
michael@0 993 return NS_OK;
michael@0 994 }
michael@0 995
michael@0 996 NS_IMETHODIMP
michael@0 997 Event::GetDefaultPrevented(bool* aReturn)
michael@0 998 {
michael@0 999 NS_ENSURE_ARG_POINTER(aReturn);
michael@0 1000 // This method must be called by only event handlers implemented by C++.
michael@0 1001 // Then, the handlers must handle default action. So, this method don't need
michael@0 1002 // to check if preventDefault() has been called by content or chrome.
michael@0 1003 *aReturn = DefaultPrevented();
michael@0 1004 return NS_OK;
michael@0 1005 }
michael@0 1006
michael@0 1007 NS_IMETHODIMP_(void)
michael@0 1008 Event::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType)
michael@0 1009 {
michael@0 1010 if (aSerializeInterfaceType) {
michael@0 1011 IPC::WriteParam(aMsg, NS_LITERAL_STRING("event"));
michael@0 1012 }
michael@0 1013
michael@0 1014 nsString type;
michael@0 1015 GetType(type);
michael@0 1016 IPC::WriteParam(aMsg, type);
michael@0 1017
michael@0 1018 IPC::WriteParam(aMsg, Bubbles());
michael@0 1019 IPC::WriteParam(aMsg, Cancelable());
michael@0 1020 IPC::WriteParam(aMsg, IsTrusted());
michael@0 1021
michael@0 1022 // No timestamp serialization for now!
michael@0 1023 }
michael@0 1024
michael@0 1025 NS_IMETHODIMP_(bool)
michael@0 1026 Event::Deserialize(const IPC::Message* aMsg, void** aIter)
michael@0 1027 {
michael@0 1028 nsString type;
michael@0 1029 NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &type), false);
michael@0 1030
michael@0 1031 bool bubbles = false;
michael@0 1032 NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &bubbles), false);
michael@0 1033
michael@0 1034 bool cancelable = false;
michael@0 1035 NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &cancelable), false);
michael@0 1036
michael@0 1037 bool trusted = false;
michael@0 1038 NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &trusted), false);
michael@0 1039
michael@0 1040 nsresult rv = InitEvent(type, bubbles, cancelable);
michael@0 1041 NS_ENSURE_SUCCESS(rv, false);
michael@0 1042 SetTrusted(trusted);
michael@0 1043
michael@0 1044 return true;
michael@0 1045 }
michael@0 1046
michael@0 1047 NS_IMETHODIMP_(void)
michael@0 1048 Event::SetOwner(mozilla::dom::EventTarget* aOwner)
michael@0 1049 {
michael@0 1050 mOwner = nullptr;
michael@0 1051
michael@0 1052 if (!aOwner) {
michael@0 1053 return;
michael@0 1054 }
michael@0 1055
michael@0 1056 nsCOMPtr<nsINode> n = do_QueryInterface(aOwner);
michael@0 1057 if (n) {
michael@0 1058 mOwner = do_QueryInterface(n->OwnerDoc()->GetScopeObject());
michael@0 1059 return;
michael@0 1060 }
michael@0 1061
michael@0 1062 nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aOwner);
michael@0 1063 if (w) {
michael@0 1064 if (w->IsOuterWindow()) {
michael@0 1065 mOwner = w->GetCurrentInnerWindow();
michael@0 1066 } else {
michael@0 1067 mOwner.swap(w);
michael@0 1068 }
michael@0 1069 return;
michael@0 1070 }
michael@0 1071
michael@0 1072 nsCOMPtr<DOMEventTargetHelper> eth = do_QueryInterface(aOwner);
michael@0 1073 if (eth) {
michael@0 1074 mOwner = eth->GetOwner();
michael@0 1075 return;
michael@0 1076 }
michael@0 1077
michael@0 1078 #ifdef DEBUG
michael@0 1079 nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(aOwner);
michael@0 1080 MOZ_ASSERT(root, "Unexpected EventTarget!");
michael@0 1081 #endif
michael@0 1082 }
michael@0 1083
michael@0 1084 } // namespace dom
michael@0 1085 } // namespace mozilla
michael@0 1086
michael@0 1087 using namespace mozilla;
michael@0 1088 using namespace mozilla::dom;
michael@0 1089
michael@0 1090 nsresult
michael@0 1091 NS_NewDOMEvent(nsIDOMEvent** aInstancePtrResult,
michael@0 1092 EventTarget* aOwner,
michael@0 1093 nsPresContext* aPresContext,
michael@0 1094 WidgetEvent* aEvent)
michael@0 1095 {
michael@0 1096 Event* it = new Event(aOwner, aPresContext, aEvent);
michael@0 1097 NS_ADDREF(it);
michael@0 1098 *aInstancePtrResult = static_cast<Event*>(it);
michael@0 1099 return NS_OK;
michael@0 1100 }

mercurial