Bug 976673 part.2 Allow to steal focus by JS at handling mouseup event r=enndeakin

This commit is contained in:
Masayuki Nakano 2014-06-18 15:13:00 +09:00
parent 37b7f48906
commit cff50b8c01
4 changed files with 37 additions and 35 deletions

View File

@ -233,7 +233,7 @@ nsFocusManager::Observe(nsISupports *aSubject,
mFirstFocusEvent = nullptr;
mWindowBeingLowered = nullptr;
mDelayedBlurFocusEvents.Clear();
mMouseDownEventHandlingDocument = nullptr;
mMouseButtonEventHandlingDocument = nullptr;
}
return NS_OK;
@ -1198,10 +1198,10 @@ nsFocusManager::SetFocusInner(nsIContent* aNewContent, int32_t aFlags,
// is in chrome, any web contents should not be able to steal the focus.
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mFocusedContent));
sendFocusEvent = nsContentUtils::CanCallerAccess(domNode);
if (!sendFocusEvent && mMouseDownEventHandlingDocument) {
// However, while mouse down event is handling, the handling document's
if (!sendFocusEvent && mMouseButtonEventHandlingDocument) {
// However, while mouse button event is handling, the handling document's
// script should be able to steal focus.
domNode = do_QueryInterface(mMouseDownEventHandlingDocument);
domNode = do_QueryInterface(mMouseButtonEventHandlingDocument);
sendFocusEvent = nsContentUtils::CanCallerAccess(domNode);
}
}
@ -3468,8 +3468,8 @@ nsFocusManager::MarkUncollectableForCCGeneration(uint32_t aGeneration)
sInstance->mFirstFocusEvent->OwnerDoc()->
MarkUncollectableForCCGeneration(aGeneration);
}
if (sInstance->mMouseDownEventHandlingDocument) {
sInstance->mMouseDownEventHandlingDocument->
if (sInstance->mMouseButtonEventHandlingDocument) {
sInstance->mMouseButtonEventHandlingDocument->
MarkUncollectableForCCGeneration(aGeneration);
}
}

View File

@ -75,13 +75,13 @@ public:
nsresult ContentRemoved(nsIDocument* aDocument, nsIContent* aContent);
/**
* Called when mouse button down event handling is started and finished.
* Called when mouse button event handling is started and finished.
*/
void SetMouseButtonDownHandlingDocument(nsIDocument* aDocument)
void SetMouseButtonHandlingDocument(nsIDocument* aDocument)
{
NS_ASSERTION(!aDocument || !mMouseDownEventHandlingDocument,
NS_ASSERTION(!aDocument || !mMouseButtonEventHandlingDocument,
"Some mouse button down events are nested?");
mMouseDownEventHandlingDocument = aDocument;
mMouseButtonEventHandlingDocument = aDocument;
}
/**
@ -515,13 +515,15 @@ private:
// and fire them later.
nsTArray<nsDelayedBlurOrFocusEvent> mDelayedBlurFocusEvents;
// A document which is handling a mouse button down event.
// A document which is handling a mouse button event.
// When a mouse down event process is finished, ESM sets focus to the target
// content. Therefore, while DOM event handlers are handling mouse down
// events, the handlers should be able to steal focus from any elements even
// if focus is in chrome content. So, if this isn't nullptr and the caller
// can access the document node, the caller should succeed in moving focus.
nsCOMPtr<nsIDocument> mMouseDownEventHandlingDocument;
// content if it's not consumed. Therefore, while DOM event handlers are
// handling mouse down events or preceding mosue down event is consumed but
// handling mouse up events, they should be able to steal focus from any
// elements even if focus is in chrome content. So, if this isn't nullptr
// and the caller can access the document node, the caller should succeed in
// moving focus.
nsCOMPtr<nsIDocument> mMouseButtonEventHandlingDocument;
static bool sTestMode;

View File

@ -5545,24 +5545,26 @@ AutoHandlingUserInputStatePusher::AutoHandlingUserInputStatePusher(
nsIDocument* aDocument) :
mIsHandlingUserInput(aIsHandlingUserInput),
mIsMouseDown(aEvent && aEvent->message == NS_MOUSE_BUTTON_DOWN),
mResetFMMouseDownState(false)
mResetFMMouseButtonHandlingState(false)
{
if (!aIsHandlingUserInput) {
return;
}
EventStateManager::StartHandlingUserInput();
if (!mIsMouseDown) {
if (mIsMouseDown) {
nsIPresShell::SetCapturingContent(nullptr, 0);
nsIPresShell::AllowMouseCapture(true);
}
if (!aDocument || !aEvent || !aEvent->mFlags.mIsTrusted) {
return;
}
nsIPresShell::SetCapturingContent(nullptr, 0);
nsIPresShell::AllowMouseCapture(true);
if (!aDocument || !aEvent->mFlags.mIsTrusted) {
return;
mResetFMMouseButtonHandlingState = (aEvent->message == NS_MOUSE_BUTTON_DOWN ||
aEvent->message == NS_MOUSE_BUTTON_UP);
if (mResetFMMouseButtonHandlingState) {
nsFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE_VOID(fm);
fm->SetMouseButtonHandlingDocument(aDocument);
}
nsFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE_VOID(fm);
fm->SetMouseButtonDownHandlingDocument(aDocument);
mResetFMMouseDownState = true;
}
AutoHandlingUserInputStatePusher::~AutoHandlingUserInputStatePusher()
@ -5571,16 +5573,14 @@ AutoHandlingUserInputStatePusher::~AutoHandlingUserInputStatePusher()
return;
}
EventStateManager::StopHandlingUserInput();
if (!mIsMouseDown) {
return;
if (mIsMouseDown) {
nsIPresShell::AllowMouseCapture(false);
}
nsIPresShell::AllowMouseCapture(false);
if (!mResetFMMouseDownState) {
return;
if (mResetFMMouseButtonHandlingState) {
nsFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE_VOID(fm);
fm->SetMouseButtonHandlingDocument(nullptr);
}
nsFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE_VOID(fm);
fm->SetMouseButtonDownHandlingDocument(nullptr);
}
} // namespace mozilla

View File

@ -912,7 +912,7 @@ public:
protected:
bool mIsHandlingUserInput;
bool mIsMouseDown;
bool mResetFMMouseDownState;
bool mResetFMMouseButtonHandlingState;
private:
// Hide so that this class can only be stack-allocated