Fixing bug 252326. Fixing some popup blocker problems. Making sure only trusted events get mark trusted, and only allow popups while processing trusted (initiated by the user) events. Patch by trev@gtchat.de and jst@mozilla.org, r=bzbarsky@mit.edu, rs=brendan@mozilla.org, bryner@biranryner.com

This commit is contained in:
jst%mozilla.jstenback.com 2004-09-04 19:28:46 +00:00
Родитель 2eeff3edb0
Коммит 63c881aeb2
27 изменённых файлов: 589 добавлений и 252 удалений

Просмотреть файл

@ -39,7 +39,7 @@
#include "nsCOMPtr.h"
#include "nsDOMEvent.h"
#include "nsIEventStateManager.h"
#include "nsEventStateManager.h"
#include "nsIFrame.h"
#include "nsIContent.h"
#include "nsIPresShell.h"
@ -68,19 +68,19 @@ static const char* const sEventNames[] = {
"popupBlocked", "DOMActivate", "DOMFocusIn", "DOMFocusOut"
};
static char *sPopupAllowedEvents;
nsDOMEvent::nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent)
{
mPresContext = aPresContext;
mEventIsTrusted = PR_FALSE;
if (aEvent) {
mEvent = aEvent;
mEventIsInternal = PR_FALSE;
mEventIsTrusted = PR_TRUE;
}
else {
mEventIsInternal = PR_TRUE;
mEventIsTrusted = PR_FALSE;
/*
A derived class might want to allocate its own type of aEvent
(derived from nsEvent). To do this, it should take care to pass
@ -89,8 +89,8 @@ nsDOMEvent::nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent)
nsDOMFooEvent::nsDOMFooEvent(..., nsEvent* aEvent)
: nsDOMEvent(..., aEvent ? aEvent : new nsFooEvent())
Then, to override the mEventIsInternal and mEventIsTrusted
assignments done by the base ctor, it should do this in its own ctor:
Then, to override the mEventIsInternal assignments done by the
base ctor, it should do this in its own ctor:
nsDOMFooEvent::nsDOMFooEvent(..., nsEvent* aEvent)
...
@ -98,11 +98,9 @@ nsDOMEvent::nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent)
...
if (aEvent) {
mEventIsInternal = PR_FALSE;
mEventIsTrusted = PR_TRUE;
}
else {
mEventIsInternal = PR_TRUE;
mEventIsTrusted = PR_FALSE;
}
...
}
@ -286,7 +284,12 @@ nsDOMEvent::HasOriginalTarget(PRBool* aResult)
NS_IMETHODIMP
nsDOMEvent::SetTrusted(PRBool aTrusted)
{
mEventIsTrusted = aTrusted;
if (aTrusted) {
mEvent->internalAppFlags |= NS_APP_EVENT_FLAG_TRUSTED;
} else {
mEvent->internalAppFlags &= ~NS_APP_EVENT_FLAG_TRUSTED;
}
return NS_OK;
}
@ -360,7 +363,7 @@ nsDOMEvent::PreventCapture()
NS_IMETHODIMP
nsDOMEvent::GetIsTrusted(PRBool *aIsTrusted)
{
*aIsTrusted = mEventIsTrusted;
*aIsTrusted = mEvent->internalAppFlags & NS_APP_EVENT_FLAG_TRUSTED;
return NS_OK;
}
@ -461,7 +464,6 @@ nsDOMEvent::InitEvent(const nsAString& aEventTypeArg, PRBool aCanBubbleArg, PRBo
NS_ENSURE_SUCCESS(SetEventType(aEventTypeArg), NS_ERROR_FAILURE);
mEvent->flags |= aCanBubbleArg ? NS_EVENT_FLAG_NONE : NS_EVENT_FLAG_CANT_BUBBLE;
mEvent->flags |= aCancelableArg ? NS_EVENT_FLAG_NONE : NS_EVENT_FLAG_CANT_CANCEL;
mEvent->internalAppFlags |= NS_APP_EVENT_FLAG_NONE;
return NS_OK;
}
@ -516,10 +518,10 @@ nsDOMEvent::IsHandled(PRBool* aIsHandled)
NS_IMETHODIMP
nsDOMEvent::SetHandled(PRBool aHandled)
{
if(aHandled)
if(aHandled)
mEvent->internalAppFlags |= NS_APP_EVENT_FLAG_HANDLED;
else
mEvent->internalAppFlags &= ~NS_APP_EVENT_FLAG_HANDLED;
mEvent->internalAppFlags &= ~NS_APP_EVENT_FLAG_HANDLED;
return NS_OK;
}
@ -532,6 +534,204 @@ nsDOMEvent::GetInternalNSEvent(nsEvent** aNSEvent)
return NS_OK;
}
// return true if eventName is contained within events, delimited by
// spaces
static PRBool
PopupAllowedForEvent(const char *eventName)
{
if (!sPopupAllowedEvents) {
nsDOMEvent::PopupAllowedEventsChanged();
if (!sPopupAllowedEvents) {
return PR_FALSE;
}
}
nsDependentCString events(sPopupAllowedEvents);
nsAFlatCString::const_iterator start, end;
nsAFlatCString::const_iterator startiter(events.BeginReading(start));
events.EndReading(end);
while (startiter != end) {
nsAFlatCString::const_iterator enditer(end);
if (!FindInReadable(nsDependentCString(eventName), startiter, enditer))
return PR_FALSE;
// the match is surrounded by spaces, or at a string boundary
if ((startiter == start || *--startiter == ' ') &&
(enditer == end || *enditer == ' ')) {
return PR_TRUE;
}
// Move on and see if there are other matches. (The delimitation
// requirement makes it pointless to begin the next search before
// the end of the invalid match just found.)
startiter = enditer;
}
return PR_FALSE;
}
// static
PopupControlState
nsDOMEvent::GetEventPopupControlState(nsEvent *aEvent)
{
// generally if an event handler is running, new windows are disallowed.
// check for exceptions:
PopupControlState abuse = openAbused;
switch(aEvent->eventStructType) {
case NS_EVENT :
// For these following events only allow popups if they're
// triggered while handling user input. See
// nsPresShell::HandleEventInternal() for details.
if (nsEventStateManager::IsHandlingUserInput()) {
switch(aEvent->message) {
case NS_FORM_SELECTED :
if (::PopupAllowedForEvent("select"))
abuse = openControlled;
case NS_FORM_CHANGE :
if (::PopupAllowedForEvent("change"))
abuse = openControlled;
}
}
break;
case NS_GUI_EVENT :
// For this following event only allow popups if it's triggered
// while handling user input. See
// nsPresShell::HandleEventInternal() for details.
if (nsEventStateManager::IsHandlingUserInput()) {
switch(aEvent->message) {
case NS_FORM_INPUT :
if (::PopupAllowedForEvent("input"))
abuse = openControlled;
break;
}
}
break;
case NS_INPUT_EVENT :
// For this following event only allow popups if it's triggered
// while handling user input. See
// nsPresShell::HandleEventInternal() for details.
if (nsEventStateManager::IsHandlingUserInput()) {
switch(aEvent->message) {
case NS_FORM_CHANGE :
if (::PopupAllowedForEvent("change"))
abuse = openControlled;
break;
}
}
break;
case NS_KEY_EVENT :
if (aEvent->internalAppFlags & NS_APP_EVENT_FLAG_TRUSTED) {
PRUint32 key = NS_STATIC_CAST(nsKeyEvent *, aEvent)->keyCode;
switch(aEvent->message) {
case NS_KEY_PRESS :
// return key on focused button. see note at NS_MOUSE_LEFT_CLICK.
if (key == nsIDOMKeyEvent::DOM_VK_RETURN)
abuse = openAllowed;
else if (::PopupAllowedForEvent("keypress"))
abuse = openControlled;
break;
case NS_KEY_UP :
// space key on focused button. see note at NS_MOUSE_LEFT_CLICK.
if (key == nsIDOMKeyEvent::DOM_VK_SPACE)
abuse = openAllowed;
else if (::PopupAllowedForEvent("keyup"))
abuse = openControlled;
break;
case NS_KEY_DOWN :
if (::PopupAllowedForEvent("keydown"))
abuse = openControlled;
break;
}
}
break;
case NS_MOUSE_EVENT :
if (aEvent->internalAppFlags & NS_APP_EVENT_FLAG_TRUSTED) {
switch(aEvent->message) {
case NS_MOUSE_LEFT_BUTTON_UP :
if (::PopupAllowedForEvent("mouseup"))
abuse = openControlled;
break;
case NS_MOUSE_LEFT_BUTTON_DOWN :
if (::PopupAllowedForEvent("mousedown"))
abuse = openControlled;
break;
case NS_MOUSE_LEFT_CLICK :
/* Click events get special treatment because of their
historical status as a more legitimate event handler. If
click popups are enabled in the prefs, clear the popup
status completely. */
if (::PopupAllowedForEvent("click"))
abuse = openAllowed;
break;
case NS_MOUSE_LEFT_DOUBLECLICK :
if (::PopupAllowedForEvent("dblclick"))
abuse = openControlled;
break;
}
}
break;
case NS_SCRIPT_ERROR_EVENT :
switch(aEvent->message) {
case NS_SCRIPT_ERROR :
// Any error event will allow popups, if enabled in the pref.
if (::PopupAllowedForEvent("error"))
abuse = openControlled;
break;
}
break;
case NS_FORM_EVENT :
// For these following events only allow popups if they're
// triggered while handling user input. See
// nsPresShell::HandleEventInternal() for details.
if (nsEventStateManager::IsHandlingUserInput()) {
switch(aEvent->message) {
case NS_FORM_SUBMIT :
if (::PopupAllowedForEvent("submit"))
abuse = openControlled;
break;
case NS_FORM_RESET :
if (::PopupAllowedForEvent("reset"))
abuse = openControlled;
break;
}
}
break;
}
return abuse;
}
// static
void
nsDOMEvent::PopupAllowedEventsChanged()
{
if (sPopupAllowedEvents) {
nsMemory::Free(sPopupAllowedEvents);
}
nsAdoptingCString str =
nsContentUtils::GetCharPref("dom.popup_allowed_events");
// We'll want to do this even if str is empty to avoid looking up
// this pref all the time if it's not set.
sPopupAllowedEvents = ToNewCString(str);
}
// static
void
nsDOMEvent::Shutdown()
{
if (sPopupAllowedEvents) {
nsMemory::Free(sPopupAllowedEvents);
}
}
// static
const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
{
switch(aEventType) {
@ -599,7 +799,7 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
case NS_SCROLL_EVENT:
return sEventNames[eDOMEvents_scroll];
case NS_TEXT_TEXT:
return sEventNames[eDOMEvents_text];
return sEventNames[eDOMEvents_text];
case NS_XUL_POPUP_SHOWING:
return sEventNames[eDOMEvents_popupShowing];
case NS_XUL_POPUP_SHOWN:

Просмотреть файл

@ -44,6 +44,7 @@
#include "nsIPrivateDOMEvent.h"
#include "nsCOMPtr.h"
#include "nsIDOMEventTarget.h"
#include "nsPIDOMWindow.h"
#include "nsPresContext.h"
#include "nsPoint.h"
#include "nsGUIEvent.h"
@ -146,6 +147,12 @@ public:
NS_IMETHOD IsHandled(PRBool* aHandled);
NS_IMETHOD SetHandled(PRBool aHandled);
static PopupControlState GetEventPopupControlState(nsEvent *aEvent);
static void PopupAllowedEventsChanged();
static void Shutdown();
protected:
// Internal helper functions
@ -161,7 +168,6 @@ protected:
nsCOMPtr<nsIDOMEventTarget> mExplicitOriginalTarget;
nsCOMPtr<nsIDOMEventTarget> mTmpRealOriginalTarget;
PRPackedBool mEventIsInternal;
PRPackedBool mEventIsTrusted;
void* mScriptObject;
};

Просмотреть файл

@ -49,11 +49,9 @@ nsDOMKeyboardEvent::nsDOMKeyboardEvent(nsPresContext* aPresContext, nsKeyEvent*
if (aEvent) {
mEventIsInternal = PR_FALSE;
mEventIsTrusted = PR_TRUE;
}
else {
mEventIsInternal = PR_TRUE;
mEventIsTrusted = PR_FALSE;
mEvent->time = PR_Now();
}
}

Просмотреть файл

@ -53,11 +53,9 @@ nsDOMMouseEvent::nsDOMMouseEvent(nsPresContext* aPresContext, nsInputEvent* aEve
if (aEvent) {
mEventIsInternal = PR_FALSE;
mEventIsTrusted = PR_TRUE;
}
else {
mEventIsInternal = PR_TRUE;
mEventIsTrusted = PR_FALSE;
mEvent->time = PR_Now();
mEvent->refPoint.x = mEvent->refPoint.y = mEvent->point.x = mEvent->point.y = 0;
}

Просмотреть файл

@ -47,14 +47,12 @@ nsDOMMutationEvent::nsDOMMutationEvent(nsPresContext* aPresContext, nsMutationEv
{
if ( aEvent ) {
mEventIsInternal = PR_FALSE;
mEventIsTrusted = PR_TRUE;
nsMutationEvent* mutation = (nsMutationEvent*)aEvent;
SetTarget(mutation->mTarget);
}
else
{
mEventIsInternal = PR_TRUE;
mEventIsTrusted = PR_FALSE;
}
}

Просмотреть файл

@ -49,11 +49,9 @@ nsDOMPopupBlockedEvent::nsDOMPopupBlockedEvent(nsPresContext* aPresContext, nsPo
if (aEvent) {
mEventIsInternal = PR_FALSE;
mEventIsTrusted = PR_TRUE;
}
else {
mEventIsInternal = PR_TRUE;
mEventIsTrusted = PR_FALSE;
mEvent->time = PR_Now();
}
}

Просмотреть файл

@ -48,11 +48,9 @@ nsDOMTextEvent::nsDOMTextEvent(nsPresContext* aPresContext, nsTextEvent* aEvent)
if (aEvent) {
mEventIsInternal = PR_FALSE;
mEventIsTrusted = PR_TRUE;
}
else {
mEventIsInternal = PR_TRUE;
mEventIsTrusted = PR_FALSE;
mEvent->time = PR_Now();
}

Просмотреть файл

@ -54,15 +54,13 @@
#include "nsIFrame.h"
nsDOMUIEvent::nsDOMUIEvent(nsPresContext* aPresContext, nsGUIEvent* aEvent)
: nsDOMEvent(aPresContext, aEvent)
: nsDOMEvent(aPresContext, aEvent)
{
if (aEvent) {
mEventIsInternal = PR_FALSE;
mEventIsTrusted = PR_TRUE;
}
else {
mEventIsInternal = PR_TRUE;
mEventIsTrusted = PR_FALSE;
mEvent->time = PR_Now();
}

Просмотреть файл

@ -440,6 +440,8 @@ nsresult nsEventListenerManager::RemoveAllListeners(PRBool aScriptOnly)
void nsEventListenerManager::Shutdown()
{
sAddListenerID = JSVAL_VOID;
nsDOMEvent::Shutdown();
}
NS_IMPL_ADDREF(nsEventListenerManager)
@ -1582,6 +1584,8 @@ nsresult nsEventListenerManager::HandleEvent(nsPresContext* aPresContext,
}
if (NS_SUCCEEDED(ret)) {
nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
for (int k = 0; !mListenersRemoved && listeners && k < listeners->Count(); ++k) {
nsListenerStruct* ls = NS_STATIC_CAST(nsListenerStruct*, listeners->ElementAt(k));
if (ls->mFlags & aFlags && ls->mGroupFlags == currentGroup) {

Просмотреть файл

@ -156,6 +156,7 @@ static PRBool sLeftClickOnly = PR_TRUE;
static PRBool sKeyCausesActivation = PR_TRUE;
static PRUint32 sESMInstanceCount = 0;
static PRInt32 sGeneralAccesskeyModifier = -1; // magic value of -1 means uninitialized
PRInt32 nsEventStateManager::sUserInputEventDepth = 0;
enum {
MOUSE_SCROLL_N_LINES,
@ -283,6 +284,8 @@ nsEventStateManager::Init()
prefBranch->AddObserver("mousewheel.withshiftkey.numlines", this, PR_TRUE);
prefBranch->AddObserver("mousewheel.withshiftkey.sysnumlines", this, PR_TRUE);
#endif
prefBranch->AddObserver("dom.popup_allowed_events", this, PR_TRUE);
}
if (sTextfieldSelectModel == eTextfieldSelect_unset) {
@ -358,6 +361,8 @@ nsEventStateManager::Shutdown()
prefBranch->RemoveObserver("mousewheel.withnokey.numlines", this);
prefBranch->RemoveObserver("mousewheel.withnokey.sysnumlines", this);
#endif
prefBranch->RemoveObserver("dom.popup_allowed_events", this);
}
m_haveShutdown = PR_TRUE;
@ -408,6 +413,8 @@ nsEventStateManager::Observe(nsISupports *aSubject,
} else if (data.EqualsLiteral("mousewheel.withnokey.numlines")) {
} else if (data.EqualsLiteral("mousewheel.withnokey.sysnumlines")) {
#endif
} else if (data.EqualsLiteral("dom.popup_allowed_events")) {
nsDOMEvent::PopupAllowedEventsChanged();
}
}
@ -1042,6 +1049,11 @@ nsEventStateManager::HandleAccessKey(nsPresContext* aPresContext,
// B) Click on it if the users prefs indicate to do so.
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(NS_MOUSE_LEFT_CLICK);
// Propagate trusted state to the new event.
event.internalAppFlags |=
aEvent->internalAppFlags & NS_APP_EVENT_FLAG_TRUSTED;
nsCOMPtr<nsIContent> oldTargetContent = mCurrentTargetContent;
mCurrentTargetContent = content;
content->HandleDOMEvent(mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);

Просмотреть файл

@ -146,6 +146,21 @@ public:
NS_IMETHOD MoveFocusToCaret(PRBool aCanFocusDoc, PRBool *aIsSelectionWithFocus);
NS_IMETHOD MoveCaretToFocus();
static void StartHandlingUserInput()
{
++sUserInputEventDepth;
}
static void StopHandlingUserInput()
{
--sUserInputEventDepth;
}
static PRBool IsHandlingUserInput()
{
return sUserInputEventDepth > 0;
}
protected:
friend class CurrentEventShepherd;
@ -334,6 +349,35 @@ protected:
nsCOMPtr<nsITimer> mClickHoldTimer;
#endif
static PRInt32 sUserInputEventDepth;
};
class nsAutoHandlingUserInputStatePusher
{
public:
nsAutoHandlingUserInputStatePusher(PRBool aIsHandlingUserInput)
: mIsHandlingUserInput(aIsHandlingUserInput)
{
if (aIsHandlingUserInput) {
nsEventStateManager::StartHandlingUserInput();
}
}
~nsAutoHandlingUserInputStatePusher()
{
if (mIsHandlingUserInput) {
nsEventStateManager::StopHandlingUserInput();
}
}
protected:
PRBool mIsHandlingUserInput;
private:
// Not meant to be implemented.
static void* operator new(size_t /*size*/) CPP_THROW_NEW;
static void operator delete(void* /*memory*/);
};
#endif // nsEventStateManager_h__

Просмотреть файл

@ -130,7 +130,7 @@ include $(topsrcdir)/config/rules.mk
INCLUDES += \
-I$(srcdir)/../../style/src \
-I$(srcdir)/../../../base/src \
-I$(srcdir)/../../base/src \
-I$(srcdir)/../../../events/src \
$(NULL)
DEFINES += -D_IMPL_NS_LAYOUT

Просмотреть файл

@ -45,6 +45,7 @@
#include "nsIDOMEventReceiver.h"
#include "nsIHTMLContent.h"
#include "nsGenericHTMLElement.h"
#include "nsEventStateManager.h"
#include "nsHTMLAtoms.h"
#include "nsStyleConsts.h"
#include "nsPresContext.h"
@ -68,6 +69,7 @@
#include "nsCategoryManagerUtils.h"
#include "nsISimpleEnumerator.h"
#include "nsIDOMWindowInternal.h"
#include "nsPIDOMWindow.h"
#include "nsRange.h"
#include "nsIScriptSecurityManager.h"
#include "nsNetUtil.h"
@ -269,6 +271,10 @@ protected:
PRPackedBool mIsSubmitting;
/** Whether the submission is to be deferred in case a script triggers it */
PRPackedBool mDeferSubmission;
/** Keep track of what the popup state was when the submit was initiated */
PopupControlState mSubmitPopupState;
/** Keep track of whether a submission was user-initiated or not */
PRBool mSubmitInitiatedFromUserInput;
/** The pending submission object */
nsCOMPtr<nsIFormSubmission> mPendingSubmission;
@ -425,6 +431,8 @@ nsHTMLFormElement::nsHTMLFormElement(nsINodeInfo *aNodeInfo)
mGeneratingReset(PR_FALSE),
mIsSubmitting(PR_FALSE),
mDeferSubmission(PR_FALSE),
mSubmitPopupState(openAbused),
mSubmitInitiatedFromUserInput(PR_FALSE),
mPendingSubmission(nsnull),
mSubmittingRequest(nsnull)
{
@ -821,7 +829,18 @@ nsHTMLFormElement::DoSubmit(nsPresContext* aPresContext, nsEvent* aEvent)
// prepare the submission object
//
BuildSubmission(aPresContext, submission, aEvent);
nsCOMPtr<nsPIDOMWindow> window =
do_QueryInterface(GetOwnerDoc()->GetScriptGlobalObject());
if (window) {
mSubmitPopupState = window->GetPopupControlState();
} else {
mSubmitPopupState = openAbused;
}
mSubmitInitiatedFromUserInput = nsEventStateManager::IsHandlingUserInput();
if(mDeferSubmission) {
// we are in an event handler, JS submitted so we have to
// defer this submission. let's remember it and return
@ -918,9 +937,17 @@ nsHTMLFormElement::SubmitSubmission(nsPresContext* aPresContext,
// Submit
//
nsCOMPtr<nsIDocShell> docShell;
rv = aFormSubmission->SubmitTo(actionURI, target, this, aPresContext,
getter_AddRefs(docShell),
getter_AddRefs(mSubmittingRequest));
{
nsAutoPopupStatePusher popupStatePusher(mSubmitPopupState);
nsAutoHandlingUserInputStatePusher userInpStatePusher(mSubmitInitiatedFromUserInput);
rv = aFormSubmission->SubmitTo(actionURI, target, this, aPresContext,
getter_AddRefs(docShell),
getter_AddRefs(mSubmittingRequest));
}
NS_ENSURE_SUBMIT_SUCCESS(rv);
// Even if the submit succeeds, it's possible for there to be no docshell

Просмотреть файл

@ -428,6 +428,9 @@ struct OnLinkClickEvent : public PLEvent {
~OnLinkClickEvent();
void HandleEvent() {
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mHandler->mScriptGlobal));
nsAutoPopupStatePusher popupStatePusher(window, mPopupState);
mHandler->OnLinkClickSync(mContent, mVerb, mURI,
mTargetSpec.get(), mPostDataStream,
mHeadersDataStream,
@ -441,6 +444,7 @@ struct OnLinkClickEvent : public PLEvent {
nsCOMPtr<nsIInputStream> mHeadersDataStream;
nsCOMPtr<nsIContent> mContent;
nsLinkVerb mVerb;
PopupControlState mPopupState;
};
static void PR_CALLBACK HandlePLEvent(OnLinkClickEvent* aEvent)
@ -470,6 +474,10 @@ OnLinkClickEvent::OnLinkClickEvent(nsWebShell* aHandler,
mContent = aContent;
mVerb = aVerb;
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mHandler->mScriptGlobal));
mPopupState = window->GetPopupControlState();
PL_InitEvent(this, nsnull,
(PLHandleEventProc) ::HandlePLEvent,
(PLDestroyEventProc) ::DestroyPLEvent);

Просмотреть файл

@ -52,6 +52,7 @@
class nsIEventQueue;
class nsIController;
struct PRThread;
struct OnLinkClickEvent;
typedef enum {
eCharsetReloadInit,
@ -115,6 +116,8 @@ public:
// NS_IMETHOD SetURL(const PRUnichar* aURL);
friend struct OnLinkClickEvent;
protected:
// void GetRootWebShellEvenIfChrome(nsIWebShell** aResult);
void InitFrameData();

Просмотреть файл

@ -48,3 +48,4 @@ EXPORTS=nsPIDOMWindow.h nsPIWindowRoot.h nsIFocusController.h
include $(topsrcdir)/config/rules.mk
DEFINES += -D_IMPL_NS_LAYOUT

Просмотреть файл

@ -49,6 +49,18 @@
#include "nsIURI.h"
#include "nsCOMPtr.h"
// Popup control state enum. The values in this enum must go from most
// permissive to least permissive so that its safe to push state in
// all situations. Pushing popup state onto the stack never makes the
// current popup state less permissive (see
// GlobalWindowImpl::PushPopupControlState()).
enum PopupControlState {
openAllowed = 0, // open that window without worries
openControlled, // it's a popup, but allow it
openAbused, // it's a popup. disallow it, but allow domain override.
openOverridden // disallow window open
};
class nsIDocShell;
class nsIFocusController;
struct nsTimeoutImpl;
@ -105,6 +117,10 @@ public:
virtual void SetOpenerScriptURL(nsIURI* aURI) = 0;
virtual PopupControlState PushPopupControlState(PopupControlState aState) const = 0;
virtual void PopPopupControlState(PopupControlState state) const = 0;
virtual PopupControlState GetPopupControlState() const = 0;
protected:
nsCOMPtr<nsIChromeEventHandler> mChromeEventHandler; // strong
nsCOMPtr<nsIDOMDocument> mDocument; // strong
@ -117,4 +133,57 @@ protected:
PRBool mIsDocumentLoaded;
};
#ifdef _IMPL_NS_LAYOUT
PopupControlState
PushPopupControlState(PopupControlState aState);
void
PopPopupControlState(PopupControlState aState);
#endif
// Helper chass that helps with pushing and poping popup control
// state. Note that this class looks different from within code that's
// part of the layout library than it does in code outside the layout
// library.
class nsAutoPopupStatePusher
{
public:
#ifdef _IMPL_NS_LAYOUT
nsAutoPopupStatePusher(PopupControlState aState)
: mOldState(::PushPopupControlState(aState))
{
}
~nsAutoPopupStatePusher()
{
PopPopupControlState(mOldState);
}
#else
nsAutoPopupStatePusher(nsPIDOMWindow *aWindow, PopupControlState aState)
: mWindow(aWindow), mOldState(openAbused)
{
if (aWindow) {
mOldState = aWindow->PushPopupControlState(aState);
}
}
~nsAutoPopupStatePusher()
{
if (mWindow) {
mWindow->PopPopupControlState(mOldState);
}
}
#endif
protected:
nsPIDOMWindow *mWindow; // WEAK
PopupControlState mOldState;
private:
// Not meant to be implemented.
static void* operator new(size_t /*size*/) CPP_THROW_NEW;
static void operator delete(void* /*memory*/);
};
#endif // nsPIDOMWindow_h__

Просмотреть файл

@ -156,11 +156,15 @@
// belonging to the back-end like nsIContentPolicy
#include "nsIPopupWindowManager.h"
nsIScriptSecurityManager *GlobalWindowImpl::sSecMan = nsnull;
nsIFactory *GlobalWindowImpl::sComputedDOMStyleFactory = nsnull;
static nsIEntropyCollector *gEntropyCollector = nsnull;
static PRInt32 gRefCnt = 0;
static PRInt32 gOpenPopupSpamCount = 0;
nsIScriptSecurityManager *GlobalWindowImpl::sSecMan = nsnull;
nsIFactory *GlobalWindowImpl::sComputedDOMStyleFactory = nsnull;
static PopupControlState gPopupControlState = openAbused;
static PRInt32 gRunningTimeoutDepth = 0;
#ifdef DEBUG_jst
PRInt32 gTimeoutCnt = 0;
#endif
@ -187,13 +191,6 @@ static const char kDOMSecurityWarningsBundleURL[] = "chrome://communicator/local
static const char kCryptoContractID[] = NS_CRYPTO_CONTRACTID;
static const char kPkcs11ContractID[] = NS_PKCS11_CONTRACTID;
// CheckForAbusePoint return values:
enum {
openAllowed = 0, // open that window without worries
openControlled, // it's a popup, but allow it
openAbused, // it's a popup. disallow it, but allow domain override.
openOverridden // disallow window open
};
// CheckOpenAllow return values:
enum {
allowNot = 0, // the window opening was denied
@ -204,36 +201,6 @@ enum {
};
// return true if eventName is contained within events, delimited by spaces
static PRBool
ContainsEventName(const char *eventName, const nsAFlatCString& events)
{
nsAFlatCString::const_iterator start, end;
events.BeginReading(start);
events.EndReading(end);
nsAFlatCString::const_iterator startiter(start);
while (startiter != end) {
nsAFlatCString::const_iterator enditer(end);
if (!FindInReadable(nsDependentCString(eventName), startiter, enditer))
return PR_FALSE;
// the match is surrounded by spaces, or at a string boundary
if ((startiter == start || *--startiter == ' ') &&
(enditer == end || *enditer == ' '))
return PR_TRUE;
/* Move on and see if there are other matches. (The delimitation
requirement makes it pointless to begin the next search before
the end of the invalid match just found.) */
startiter = enditer;
}
return PR_FALSE;
}
//*****************************************************************************
//*** GlobalWindowImpl: Object Management
//*****************************************************************************
@ -250,7 +217,6 @@ GlobalWindowImpl::GlobalWindowImpl()
mTimeoutInsertionPoint(&mTimeouts),
mTimeoutPublicIdCounter(1),
mTimeoutFiringDepth(0),
mLastMouseButtonAction(LL_ZERO),
mGlobalObjectOwner(nsnull),
mDocShell(nsnull),
mCurrentEvent(0)
@ -422,6 +388,42 @@ GlobalWindowImpl::SetOpenerScriptURL(nsIURI* aURI)
mOpenerScriptURL = aURI;
}
PopupControlState
PushPopupControlState(PopupControlState aState)
{
PopupControlState oldState = gPopupControlState;
if (aState < gPopupControlState) {
gPopupControlState = aState;
}
return oldState;
}
void
PopPopupControlState(PopupControlState aState)
{
gPopupControlState = aState;
}
PopupControlState
GlobalWindowImpl::PushPopupControlState(PopupControlState aState) const
{
return ::PushPopupControlState(aState);
}
void
GlobalWindowImpl::PopPopupControlState(PopupControlState aState) const
{
::PopPopupControlState(aState);
}
PopupControlState
GlobalWindowImpl::GetPopupControlState() const
{
return gPopupControlState;
}
nsresult
GlobalWindowImpl::SetNewDocument(nsIDOMDocument* aDocument,
PRBool aRemoveEventListeners,
@ -869,11 +871,6 @@ GlobalWindowImpl::HandleDOMEvent(nsPresContext* aPresContext,
if (aEvent->message == NS_PAGE_UNLOAD) {
mIsDocumentLoaded = PR_FALSE;
} else if ((aEvent->message >= NS_MOUSE_LEFT_BUTTON_UP &&
aEvent->message <= NS_MOUSE_RIGHT_BUTTON_DOWN) ||
(aEvent->message >= NS_MOUSE_LEFT_DOUBLECLICK &&
aEvent->message <= NS_MOUSE_RIGHT_CLICK)) {
mLastMouseButtonAction = PR_Now();
}
// Capturing stage
@ -2881,10 +2878,17 @@ GlobalWindowImpl::DisableExternalCapture()
static
PRBool IsPopupBlocked(nsIDOMDocument* aDoc)
{
PRBool blocked = PR_FALSE;
nsCOMPtr<nsIPopupWindowManager> pm =
do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID);
if (!pm) {
return PR_FALSE;
}
PRBool blocked = PR_TRUE;
nsCOMPtr<nsIDocument> doc(do_QueryInterface(aDoc));
nsCOMPtr<nsIPopupWindowManager> pm(do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID));
if (pm && doc) {
if (doc) {
PRUint32 permission = nsIPopupWindowManager::ALLOW_POPUP;
pm->TestPermission(doc->GetDocumentURI(), &permission);
blocked = (permission == nsIPopupWindowManager::DENY_POPUP);
@ -2950,7 +2954,7 @@ GlobalWindowImpl::CanSetProperty(const char *aPrefName)
* routine to determine whether to allow the new window.
* Returns a value from the CheckForAbusePoint enum.
*/
PRUint32
PopupControlState
GlobalWindowImpl::CheckForAbusePoint()
{
nsCOMPtr<nsIDocShellTreeItem> item(do_QueryInterface(mDocShell));
@ -2963,162 +2967,9 @@ GlobalWindowImpl::CheckForAbusePoint()
return openAllowed;
}
PRUint32 abuse = openAllowed; // level of abuse we've detected
// is the document being loaded or unloaded?
if (!mIsDocumentLoaded)
abuse = openAbused;
/* Disallow windows after a user-defined click delay.
This is a consideration secondary to document load because
of its stronger response (openOverridden). See bug 247017. */
if (abuse == openAllowed) {
PRInt32 delay = nsContentUtils::GetIntPref("dom.disable_open_click_delay");
if (delay != 0) {
PRTime now = PR_Now();
PRTime ll_delta;
PRUint32 delta;
LL_SUB(ll_delta, now, mLastMouseButtonAction);
LL_L2UI(delta, ll_delta);
if (delta/1000 > (PRUint32) delay)
abuse = openOverridden;
}
}
/* Is a timer running?
This is a consideration secondary to the user-defined click delay
because that seemed the Right Thing. See bug 197919 comment 45. */
if (abuse == openAllowed && mRunningTimeout)
abuse = openAbused;
if (abuse == openAllowed) {
// we'll need to know what DOM event is being processed now, if any
nsEvent *currentEvent = mCurrentEvent;
if (!currentEvent && mDocShell) {
/* The DOM window's current event is accurate for events that make it
all the way to the window. But it doesn't see events handled directly
by a target element. For those, check the EventStateManager. */
nsCOMPtr<nsIPresShell> presShell;
mDocShell->GetPresShell(getter_AddRefs(presShell));
if (presShell) {
nsPresContext *presContext = presShell->GetPresContext();
if (presContext)
presContext->EventStateManager()->GetCurrentEvent(&currentEvent);
}
}
// fetch pref string detailing which events are allowed
const nsAdoptingCString& eventPref =
nsContentUtils::GetCharPref("dom.popup_allowed_events");
// generally if an event handler is running, new windows are disallowed.
// check for exceptions:
if (currentEvent) {
abuse = openAbused;
switch(currentEvent->eventStructType) {
case NS_EVENT :
switch(currentEvent->message) {
case NS_FORM_SELECTED :
if (::ContainsEventName("select", eventPref))
abuse = openControlled;
break;
case NS_FORM_CHANGE :
if (::ContainsEventName("change", eventPref))
abuse = openControlled;
break;
case NS_RESIZE_EVENT :
if (::ContainsEventName("resize", eventPref))
abuse = openControlled;
break;
}
break;
case NS_GUI_EVENT :
switch(currentEvent->message) {
case NS_FORM_INPUT :
if (::ContainsEventName("input", eventPref))
abuse = openControlled;
break;
}
break;
case NS_INPUT_EVENT :
switch(currentEvent->message) {
case NS_FORM_CHANGE :
if (::ContainsEventName("change", eventPref))
abuse = openControlled;
break;
}
break;
case NS_KEY_EVENT : {
PRUint32 key = NS_STATIC_CAST(nsKeyEvent *, currentEvent)->keyCode;
switch(currentEvent->message) {
case NS_KEY_PRESS :
// return key on focused button. see note at NS_MOUSE_LEFT_CLICK.
if (key == nsIDOMKeyEvent::DOM_VK_RETURN)
abuse = openAllowed;
else if (::ContainsEventName("keypress", eventPref))
abuse = openControlled;
break;
case NS_KEY_UP :
// space key on focused button. see note at NS_MOUSE_LEFT_CLICK.
if (key == nsIDOMKeyEvent::DOM_VK_SPACE)
abuse = openAllowed;
else if (::ContainsEventName("keyup", eventPref))
abuse = openControlled;
break;
case NS_KEY_DOWN :
if (::ContainsEventName("keydown", eventPref))
abuse = openControlled;
break;
}
break;
}
case NS_MOUSE_EVENT :
switch(currentEvent->message) {
case NS_MOUSE_LEFT_BUTTON_UP :
if (::ContainsEventName("mouseup", eventPref))
abuse = openControlled;
break;
case NS_MOUSE_LEFT_BUTTON_DOWN :
if (::ContainsEventName("mousedown", eventPref))
abuse = openControlled;
break;
case NS_MOUSE_LEFT_CLICK :
/* Click events get special treatment because of their
historical status as a more legitimate event handler.
If click popups are enabled in the prefs, clear the
popup status completely. */
if (::ContainsEventName("click", eventPref))
abuse = openAllowed;
break;
case NS_MOUSE_LEFT_DOUBLECLICK :
if (::ContainsEventName("dblclick", eventPref))
abuse = openControlled;
break;
}
break;
case NS_SCRIPT_ERROR_EVENT :
switch(currentEvent->message) {
case NS_SCRIPT_ERROR :
if (::ContainsEventName("error", eventPref))
abuse = openControlled;
break;
}
break;
case NS_FORM_EVENT :
switch(currentEvent->message) {
case NS_FORM_SUBMIT :
if (::ContainsEventName("submit", eventPref))
abuse = openControlled;
break;
case NS_FORM_RESET :
if (::ContainsEventName("reset", eventPref))
abuse = openControlled;
break;
}
break;
} // switch
} // currentEvent
} // abuse == openAllowed
// level of abuse we've detected, initialized to the current popup
// state
PopupControlState abuse = gPopupControlState;
// limit the number of simultaneously open popups
if (abuse == openAbused || abuse == openControlled) {
@ -3135,7 +2986,7 @@ GlobalWindowImpl::CheckForAbusePoint()
or if its target is an extant window.
Returns a value from the CheckOpenAllow enum. */
PRUint32
GlobalWindowImpl::CheckOpenAllow(PRUint32 aAbuseLevel,
GlobalWindowImpl::CheckOpenAllow(PopupControlState aAbuseLevel,
const nsAString &aName)
{
PRUint32 allowWindow = allowNoAbuse; // (also used for openControlled)
@ -3249,7 +3100,7 @@ GlobalWindowImpl::Open(const nsAString& aUrl,
{
nsresult rv;
PRUint32 abuseLevel = CheckForAbusePoint();
PopupControlState abuseLevel = CheckForAbusePoint();
PRUint32 allowReason = CheckOpenAllow(abuseLevel, aName);
if (allowReason == allowNot) {
FireAbuseEvents(PR_TRUE, PR_FALSE, aUrl, aOptions);
@ -3311,7 +3162,7 @@ GlobalWindowImpl::Open(nsIDOMWindow **_retval)
}
}
PRUint32 abuseLevel = CheckForAbusePoint();
PopupControlState abuseLevel = CheckForAbusePoint();
PRUint32 allowReason = CheckOpenAllow(abuseLevel, name);
if (allowReason == allowNot) {
FireAbuseEvents(PR_TRUE, PR_FALSE, url, options);
@ -4894,6 +4745,23 @@ GlobalWindowImpl::SetTimeoutOrInterval(PRBool aIsInterval, PRInt32 *aReturn)
timeout->mWindow = this;
NS_ADDREF(timeout->mWindow);
// No popups from timeouts by default
timeout->mPopupState = openAbused;
if (gRunningTimeoutDepth == 0 && gPopupControlState < openAbused) {
// This timeout is *not* set from another timeout and it's set
// while popups are enabled. Propagate the state to the timeout if
// its delay (interval) is equal to or less than what
// "dom.disable_open_click_delay" is set to.
PRInt32 delay =
nsContentUtils::GetIntPref("dom.disable_open_click_delay");
if (interval <= (delay * PR_MSEC_PER_SEC)) {
timeout->mPopupState = gPopupControlState;
}
}
InsertTimeoutIntoList(mTimeoutInsertionPoint, timeout);
timeout->mPublicId = ++mTimeoutPublicIdCounter;
*aReturn = timeout->mPublicId;
@ -5013,10 +4881,21 @@ GlobalWindowImpl::RunTimeout(nsTimeoutImpl *aTimeout)
mRunningTimeout = timeout;
timeout->mRunning = PR_TRUE;
// Push this timeouts popup control state, which should only be
// eabled the first time a timeout fires that was created while
// popups were enabled and with a delay less than
// "dom.disable_open_click_delay".
nsAutoPopupStatePusher popupStatePusher(timeout->mPopupState);
// Clear the timeout's popup state, if any, to prevent interval
// timeouts from repeatedly opening poups.
timeout->mPopupState = openAbused;
// Hold on to the timeout in case mExpr or mFunObj releases its
// doc.
timeout->AddRef();
++gRunningTimeoutDepth;
++mTimeoutFiringDepth;
if (timeout->mExpr) {
@ -5047,6 +4926,8 @@ GlobalWindowImpl::RunTimeout(nsTimeoutImpl *aTimeout)
}
--mTimeoutFiringDepth;
--gRunningTimeoutDepth;
mRunningTimeout = last_running_timeout;
timeout->mRunning = PR_FALSE;

Просмотреть файл

@ -192,6 +192,10 @@ public:
virtual NS_HIDDEN_(void) SetOpenerScriptURL(nsIURI* aURI);
virtual NS_HIDDEN_(PopupControlState) PushPopupControlState(PopupControlState state) const;
virtual NS_HIDDEN_(void) PopPopupControlState(PopupControlState state) const;
virtual NS_HIDDEN_(PopupControlState) GetPopupControlState() const;
// nsIDOMViewCSS
NS_DECL_NSIDOMVIEWCSS
@ -246,8 +250,9 @@ protected:
nsresult GetScrollInfo(nsIScrollableView** aScrollableView, float* aP2T,
float* aT2P);
nsresult SecurityCheckURL(const char *aURL);
PRUint32 CheckForAbusePoint();
PRUint32 CheckOpenAllow(PRUint32 aAbuseLevel, const nsAString &aName);
PopupControlState CheckForAbusePoint();
PRUint32 CheckOpenAllow(PopupControlState aAbuseLevel,
const nsAString &aName);
void FireAbuseEvents(PRBool aBlocked, PRBool aWindow,
const nsAString &aPopupURL,
const nsAString &aPopupWindowFeatures);
@ -317,7 +322,6 @@ protected:
nsTimeoutImpl** mTimeoutInsertionPoint;
PRUint32 mTimeoutPublicIdCounter;
PRUint32 mTimeoutFiringDepth;
PRTime mLastMouseButtonAction;
nsString mStatus;
nsString mDefaultStatus;
@ -445,6 +449,10 @@ struct nsTimeoutImpl
// timeouts
nsTimeoutImpl *mNext;
// The popup state at timeout creation time if not created from
// another timeout
PopupControlState mPopupState;
private:
// reference count for shared usage
PRInt32 mRefCnt;

Просмотреть файл

@ -40,6 +40,7 @@
#include <mshtml.h>
#include <hlink.h>
#include "nsPIDOMWindow.h"
// A barely documented interface called ITargetFrame from IE
// This is needed for targeted Hlink* calls (e.g. HlinkNavigateString) to
@ -1831,6 +1832,12 @@ END_COM_MAP()
nsCOMPtr<nsILinkHandler> lh = do_QueryInterface(webNav);
if (lh)
{
nsCOMPtr<nsPIDOMWindow> window =
do_GetInterface(mDOMWindow);
nsAutoPopupStatePusher popupStatePusher(window,
openAllowed);
lh->OnLinkClick(nsnull, eLinkVerb_Replace,
uri, szTargetFrame ? szTargetFrame : mUseTarget);
}

Просмотреть файл

@ -76,8 +76,8 @@
#include "nsIViewObserver.h"
#include "nsContainerFrame.h"
#include "nsIDeviceContext.h"
#include "nsIEventStateManager.h"
#include "nsIDOMEvent.h"
#include "nsEventStateManager.h"
#include "nsDOMEvent.h"
#include "nsGUIEvent.h"
#include "nsHTMLParts.h"
#include "nsContentUtils.h"
@ -5899,6 +5899,37 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView,
nsresult rv = NS_OK;
if (!NS_EVENT_NEEDS_FRAME(aEvent) || GetCurrentEventFrame()) {
PRBool isHandlingUserInput = PR_FALSE;
if (aEvent->internalAppFlags & NS_APP_EVENT_FLAG_TRUSTED) {
switch (aEvent->message) {
case NS_GOTFOCUS:
case NS_LOSTFOCUS:
case NS_ACTIVATE:
case NS_DEACTIVATE:
// Treat focus/blur events as user input if they happen while
// executing trusted script, or no script at all. If they
// happen during execution of non-trusted script, then they
// should not be considerd user input.
if (!nsContentUtils::IsCallerChrome()) {
break;
}
case NS_MOUSE_LEFT_BUTTON_DOWN:
case NS_MOUSE_MIDDLE_BUTTON_DOWN:
case NS_MOUSE_RIGHT_BUTTON_DOWN:
case NS_MOUSE_LEFT_BUTTON_UP:
case NS_MOUSE_RIGHT_BUTTON_UP:
case NS_MOUSE_MIDDLE_BUTTON_UP:
case NS_KEY_PRESS:
case NS_KEY_DOWN:
case NS_KEY_UP:
isHandlingUserInput = PR_TRUE;
}
}
nsAutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput);
nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
// 1. Give event to event manager for pre event state changes and
// generation of synthetic events.

Просмотреть файл

@ -2286,6 +2286,8 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, const char *aTarge
}
}
nsAutoPopupStatePusher popupStatePusher(openAllowed);
rv = lh->OnLinkClick(content, eLinkVerb_Replace,
uri, unitarget.get(),
postDataStream, headersDataStream);

Просмотреть файл

@ -168,6 +168,7 @@ LOCAL_INCLUDES = \
-I$(srcdir)/../../style/src \
-I$(srcdir)/../../forms/src \
-I$(srcdir)/../../../base/src \
-I$(srcdir)/../../../../content/events/src \
-I$(srcdir) \
$(NULL)

Просмотреть файл

@ -2286,6 +2286,8 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, const char *aTarge
}
}
nsAutoPopupStatePusher popupStatePusher(openAllowed);
rv = lh->OnLinkClick(content, eLinkVerb_Replace,
uri, unitarget.get(),
postDataStream, headersDataStream);

Просмотреть файл

@ -76,8 +76,8 @@
#include "nsIViewObserver.h"
#include "nsContainerFrame.h"
#include "nsIDeviceContext.h"
#include "nsIEventStateManager.h"
#include "nsIDOMEvent.h"
#include "nsEventStateManager.h"
#include "nsDOMEvent.h"
#include "nsGUIEvent.h"
#include "nsHTMLParts.h"
#include "nsContentUtils.h"
@ -5899,6 +5899,37 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView,
nsresult rv = NS_OK;
if (!NS_EVENT_NEEDS_FRAME(aEvent) || GetCurrentEventFrame()) {
PRBool isHandlingUserInput = PR_FALSE;
if (aEvent->internalAppFlags & NS_APP_EVENT_FLAG_TRUSTED) {
switch (aEvent->message) {
case NS_GOTFOCUS:
case NS_LOSTFOCUS:
case NS_ACTIVATE:
case NS_DEACTIVATE:
// Treat focus/blur events as user input if they happen while
// executing trusted script, or no script at all. If they
// happen during execution of non-trusted script, then they
// should not be considerd user input.
if (!nsContentUtils::IsCallerChrome()) {
break;
}
case NS_MOUSE_LEFT_BUTTON_DOWN:
case NS_MOUSE_MIDDLE_BUTTON_DOWN:
case NS_MOUSE_RIGHT_BUTTON_DOWN:
case NS_MOUSE_LEFT_BUTTON_UP:
case NS_MOUSE_RIGHT_BUTTON_UP:
case NS_MOUSE_MIDDLE_BUTTON_UP:
case NS_KEY_PRESS:
case NS_KEY_DOWN:
case NS_KEY_UP:
isHandlingUserInput = PR_TRUE;
}
}
nsAutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput);
nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
// 1. Give event to event manager for pre event state changes and
// generation of synthetic events.

Просмотреть файл

@ -1772,6 +1772,11 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS
{
*aStatus = nsEventStatus_eIgnore;
// Mark all events coming through here as trusted events, as the
// only code that calls this is the widget code that translates OS
// events into mozilla events.
aEvent->internalAppFlags |= NS_APP_EVENT_FLAG_TRUSTED;
switch(aEvent->message)
{
case NS_SIZE:

Просмотреть файл

@ -108,8 +108,15 @@ class nsIURI;
#define NS_EVENT_CAPTURE_MASK (~(NS_EVENT_FLAG_INIT | NS_EVENT_FLAG_BUBBLE | NS_EVENT_FLAG_NO_CONTENT_DISPATCH))
#define NS_EVENT_BUBBLE_MASK (~(NS_EVENT_FLAG_INIT | NS_EVENT_FLAG_CAPTURE | NS_EVENT_FLAG_NO_CONTENT_DISPATCH))
#define NS_APP_EVENT_FLAG_NONE 0x0000
#define NS_APP_EVENT_FLAG_HANDLED 0x0001 // Similar to NS_EVENT_FLAG_NO_DEFAULT, but it allows focus
// Flags for internalAppFlags
#define NS_APP_EVENT_FLAG_NONE 0x00000000
// Similar to NS_EVENT_FLAG_NO_DEFAULT, but it allows focus
#define NS_APP_EVENT_FLAG_HANDLED 0x00000001
// True if the event came from a trusted source
#define NS_APP_EVENT_FLAG_TRUSTED 0x00000002
#define NS_EVENT_TYPE_NULL 0
@ -344,8 +351,8 @@ struct nsEvent {
point(0, 0),
refPoint(0, 0),
time(0),
flags(0),
internalAppFlags(0),
flags(0),
internalAppFlags(NS_APP_EVENT_FLAG_NONE),
userType(0)
{
}