Bug 930843 part.2 NS_UI_ACTIVATE event should be trusted event even if it's caused by an untrusted event r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Sat, 22 Aug 2015 13:02:39 +0900
changeset 291521 6eaeb32125f4ce179182e8742e0cb43c6251ebc8
parent 291520 2518b11aca2618c587702399b5fc9749f27e02ea
child 291522 a7b04b9e4f17de3f5010b6cc53032517efbfa570
push idunknown
push userunknown
push dateunknown
reviewerssmaug
bugs930843
milestone43.0a1
Bug 930843 part.2 NS_UI_ACTIVATE event should be trusted event even if it's caused by an untrusted event r=smaug
dom/base/Element.cpp
dom/events/UIEvent.cpp
dom/html/HTMLButtonElement.cpp
dom/html/HTMLInputElement.cpp
widget/BasicEvents.h
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -2978,35 +2978,38 @@ Element::PostHandleEventForLinks(EventCh
         break;
       }
 
       // The default action is simply to dispatch DOMActivate
       nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
       if (shell) {
         // single-click
         nsEventStatus status = nsEventStatus_eIgnore;
-        InternalUIEvent actEvent(mouseEvent->mFlags.mIsTrusted, NS_UI_ACTIVATE);
+        // DOMActive event should be trusted since the activation is actually
+        // occurred even if the cause is an untrusted click event.
+        InternalUIEvent actEvent(true, NS_UI_ACTIVATE, mouseEvent);
         actEvent.detail = 1;
 
         rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
         if (NS_SUCCEEDED(rv)) {
           aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
         }
       }
     }
     break;
   }
   case NS_UI_ACTIVATE:
     {
       if (aVisitor.mEvent->originalTarget == this) {
         nsAutoString target;
         GetLinkTarget(target);
+        const InternalUIEvent* activeEvent = aVisitor.mEvent->AsUIEvent();
+        MOZ_ASSERT(activeEvent);
         nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
-                                    true, true,
-                                    aVisitor.mEvent->mFlags.mIsTrusted);
+                                    true, true, activeEvent->IsTrustable());
         aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
       }
     }
     break;
 
   case NS_KEY_PRESS:
     {
       WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent();
--- a/dom/events/UIEvent.cpp
+++ b/dom/events/UIEvent.cpp
@@ -24,17 +24,17 @@
 
 namespace mozilla {
 namespace dom {
 
 UIEvent::UIEvent(EventTarget* aOwner,
                  nsPresContext* aPresContext,
                  WidgetGUIEvent* aEvent)
   : Event(aOwner, aPresContext,
-          aEvent ? aEvent : new InternalUIEvent(false, 0))
+          aEvent ? aEvent : new InternalUIEvent(false, 0, nullptr))
   , mClientPoint(0, 0)
   , mLayerPoint(0, 0)
   , mPagePoint(0, 0)
   , mMovementPoint(0, 0)
   , mIsPointerLocked(EventStateManager::sIsPointerLocked)
   , mLastClientPoint(EventStateManager::sLastClientPoint)
 {
   if (aEvent) {
--- a/dom/html/HTMLButtonElement.cpp
+++ b/dom/html/HTMLButtonElement.cpp
@@ -245,20 +245,19 @@ HTMLButtonElement::PostHandleEvent(Event
   nsresult rv = NS_OK;
   if (!aVisitor.mPresContext) {
     return rv;
   }
 
   if (aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault) {
     WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
     if (mouseEvent && mouseEvent->IsLeftClickEvent()) {
-      // XXX Activating actually occurs even if it's caused by untrusted event.
-      //     Therefore, shouldn't this be always trusted event?
-      InternalUIEvent actEvent(aVisitor.mEvent->mFlags.mIsTrusted,
-                               NS_UI_ACTIVATE);
+      // DOMActive event should be trusted since the activation is actually
+      // occurred even if the cause is an untrusted click event.
+      InternalUIEvent actEvent(true, NS_UI_ACTIVATE, mouseEvent);
       actEvent.detail = 1;
 
       nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
       if (shell) {
         nsEventStatus status = nsEventStatus_eIgnore;
         mInInternalActivate = true;
         shell->HandleDOMEventWithTarget(this, &actEvent, &status);
         mInInternalActivate = false;
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -3624,20 +3624,19 @@ HTMLInputElement::PostHandleEvent(EventC
   // the click event handling, and allow cancellation of DOMActivate to cancel
   // the click.
   if (aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault &&
       !IsSingleLineTextControl(true) &&
       mType != NS_FORM_INPUT_NUMBER) {
     WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
     if (mouseEvent && mouseEvent->IsLeftClickEvent() &&
         !ShouldPreventDOMActivateDispatch(aVisitor.mEvent->originalTarget)) {
-      // XXX Activating actually occurs even if it's caused by untrusted event.
-      //     Therefore, shouldn't this be always trusted event?
-      InternalUIEvent actEvent(aVisitor.mEvent->mFlags.mIsTrusted,
-                               NS_UI_ACTIVATE);
+      // DOMActive event should be trusted since the activation is actually
+      // occurred even if the cause is an untrusted click event.
+      InternalUIEvent actEvent(true, NS_UI_ACTIVATE, mouseEvent);
       actEvent.detail = 1;
 
       nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
       if (shell) {
         nsEventStatus status = nsEventStatus_eIgnore;
         mInInternalActivate = true;
         rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
         mInInternalActivate = false;
--- a/widget/BasicEvents.h
+++ b/widget/BasicEvents.h
@@ -714,57 +714,78 @@ public:
  * XXX Why this inherits WidgetGUIEvent rather than WidgetEvent?
  ******************************************************************************/
 
 class InternalUIEvent : public WidgetGUIEvent
 {
 protected:
   InternalUIEvent()
     : detail(0)
+    , mCausedByUntrustedEvent(false)
   {
   }
 
   InternalUIEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
                   EventClassID aEventClassID)
     : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID)
     , detail(0)
+    , mCausedByUntrustedEvent(false)
   {
   }
 
   InternalUIEvent(bool aIsTrusted, uint32_t aMessage,
                   EventClassID aEventClassID)
     : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, aEventClassID)
     , detail(0)
+    , mCausedByUntrustedEvent(false)
   {
   }
 
 public:
   virtual InternalUIEvent* AsUIEvent() override { return this; }
 
-  InternalUIEvent(bool aIsTrusted, uint32_t aMessage)
+  /**
+   * If the UIEvent is caused by another event (e.g., click event),
+   * aEventCausesThisEvent should be the event.  If there is no such event,
+   * this should be nullptr.
+   */
+  InternalUIEvent(bool aIsTrusted, uint32_t aMessage,
+                  const WidgetEvent* aEventCausesThisEvent)
     : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, eUIEventClass)
     , detail(0)
+    , mCausedByUntrustedEvent(
+        aEventCausesThisEvent && !aEventCausesThisEvent->mFlags.mIsTrusted)
   {
   }
 
   virtual WidgetEvent* Duplicate() const override
   {
     MOZ_ASSERT(mClass == eUIEventClass,
                "Duplicate() must be overridden by sub class");
-    InternalUIEvent* result = new InternalUIEvent(false, mMessage);
+    InternalUIEvent* result = new InternalUIEvent(false, mMessage, nullptr);
     result->AssignUIEventData(*this, true);
     result->mFlags = mFlags;
     return result;
   }
 
   int32_t detail;
+  // mCausedByUntrustedEvent is true if the event is caused by untrusted event.
+  bool mCausedByUntrustedEvent;
+
+  // If you check the event is a trusted event and NOT caused by an untrusted
+  // event, IsTrustable() returns what you expected.
+  bool IsTrustable() const
+  {
+    return mFlags.mIsTrusted && !mCausedByUntrustedEvent;
+  }
 
   void AssignUIEventData(const InternalUIEvent& aEvent, bool aCopyTargets)
   {
     AssignGUIEventData(aEvent, aCopyTargets);
 
     detail = aEvent.detail;
+    mCausedByUntrustedEvent = aEvent.mCausedByUntrustedEvent;
   }
 };
 
 } // namespace mozilla
 
 #endif // mozilla_BasicEvents_h__