Closed Bug 1245068 Opened 9 years ago Closed 9 years ago

[e10s] Ctrl+mouse wheel to change zoom level doesn't work if web page is not focused

Categories

(Core :: DOM: Content Processes, defect, P1)

defect

Tracking

()

VERIFIED FIXED
mozilla49
Tracking Status
e10s + ---
firefox46 --- affected
firefox47 --- affected
firefox48 --- wontfix
firefox49 --- verified

People

(Reporter: arni2033, Assigned: ting)

References

(Depends on 1 open bug)

Details

(Whiteboard: dom-triaged)

Crash Data

Attachments

(1 file, 3 obsolete files)

>>>   My Info:   Win7_64, Nightly 46, 32bit, ID 20160201030241
STR:
1. Open http://example.org/
2. Press Ctrl+F to open and focus Findbar
3. Place mouse pointer over the page content, hold Ctrl and rotate mouse wheel up and down

AR:  Tab crashes
ER:  Tab should change zoom level
Sorry, the actual result is "No visible action"

AR:  No visible action
ER:  Tab should change zoom level
This is quite easily reproducible using steps from comment 0, in e10s. I get this content crash https://crash-stats.mozilla.com/report/index/6ccc4d4c-0936-4d9d-859d-4c8d32160202

Works as expected in a new non-e10s window.

Win 7, Nightly 47.0a1, 20160201030241 - FAIL (content crash)
Mac 10.9.5, Nightly 47.0a1, 20160202030232 - FAIL (content crash)
Ubuntu 14.04.2, Nightly	47.0a1, 20160202030232 - n/a (ctrl + mouse wheel doesn't do anything, in this scenario, in e10s nor non-e10s)

This only happens with mouse wheel control of zoom size. using keyboard (ctrl/cmd + +/-) shorts cuts produces expected results.
Crash Signature: [@ mozilla::EventStateManager::GetContentViewer ]
The crash was fixed in bug 1244582, I believe. The ctrl+mousewheel code is not handled in APZ, so I'm not sure where this bug belongs. It is e10s-specific though, and I can repro even on DevEdition.
tracking-e10s: --- → ?
Component: Panning and Zooming → DOM: Content Processes
Whiteboard: dom-noted
Priority: -- → P1
Whiteboard: dom-noted → dom-triaged
Summary: [e10s] Ctrl+mouse wheel to change zoom level doesn't work if chrome input fields are focused → [e10s] Ctrl+mouse wheel to change zoom level doesn't work if web page is not focused
Do you know why are Activate/Deactivate (WindowRaised/WindowLowered) required for a remote browser when nsFocusManager::Focus() and nsFocusManager::Blur()? Thanks.
Flags: needinfo?(enndeakin)
To indicate to the child process when it is focused or blurred. That isn't the problem here.

Likely, some code somewhere is checking if the window is active so that the zoom action doesn't apply when the window is in the background. This is correct, but should be checking this state in the parent process, or this state could be exposed in the focus manager.
Flags: needinfo?(enndeakin)
(In reply to Neil Deakin from comment #6)
> Likely, some code somewhere is checking if the window is active so that the
> zoom action doesn't apply when the window is in the background. This is

The checking is in EventStateManager::ChangeFullZoom():

https://dxr.mozilla.org/mozilla-central/rev/6adc822f5e27a55551faeb6c47a9bd8b0859a23b/dom/events/EventStateManager.cpp#2049

In this case, EventStateManager::GetContentViewer() returns error because nsFocusManager::GetFocusedWindow() returns null. mFocusedWindow is cleared by RecvDeactivate() (WindowLowered()) when Blur() gets called:

https://dxr.mozilla.org/mozilla-central/rev/6adc822f5e27a55551faeb6c47a9bd8b0859a23b/dom/base/nsFocusManager.cpp#780
https://dxr.mozilla.org/mozilla-central/rev/6adc822f5e27a55551faeb6c47a9bd8b0859a23b/dom/base/nsFocusManager.cpp#1717

Child process gets RecvDeactivate() called when parent calls Blur(), but later when parent calls Focus() on the input field, child does not RecvActivate() because it can't QI to nsIFrameLoaderOwner:

https://dxr.mozilla.org/mozilla-central/rev/6adc822f5e27a55551faeb6c47a9bd8b0859a23b/dom/base/nsFocusManager.cpp#1892-1893
Both isElementinFocusedWindow and isElementInActiveWindow are true when the input field gets focused:

https://dxr.mozilla.org/mozilla-central/rev/6adc822f5e27a55551faeb6c47a9bd8b0859a23b/dom/base/nsFocusManager.cpp#1200
https://dxr.mozilla.org/mozilla-central/rev/6adc822f5e27a55551faeb6c47a9bd8b0859a23b/dom/base/nsFocusManager.cpp#1232

The problem seems to be:

a. How we check whether the new focused content belong to a remote browser, or
b. Should we SendDectivate() when Blur() in parent has aIsLeavingDocument false? Because RecvDeactivate() goes to WindowLowered() which calls Blur() with aIsLeavingDocument true.
> https://dxr.mozilla.org/mozilla-central/rev/
> 6adc822f5e27a55551faeb6c47a9bd8b0859a23b/dom/events/EventStateManager.
> cpp#2049

OK so that code is a little unusual. It tries to get the focused window but then effectively ignores it and just gets the root window a few lines down. It does however have the effect of breaking out when the window isn't active, except that it dumps warnings on the console (even in non-e10s!)

For non-e10s, it should just have just used something like mDocument->GetWindow()->GetPrivateRoot()

then compared it to nsIFocusManager::GetActiveWindow.

For e10s however, you would need to take that root window and, if it is a TabChild, check if TabChild::ParentIsActive returns true to see if the window is active.
(In reply to Neil Deakin from comment #9)
> For non-e10s, it should just have just used something like
> mDocument->GetWindow()->GetPrivateRoot()
> 
> then compared it to nsIFocusManager::GetActiveWindow.
> 
> For e10s however, you would need to take that root window and, if it is a
> TabChild, check if TabChild::ParentIsActive returns true to see if the
> window is active.

I am not sure I understand this. Does that mean EventStateManager::GetContentViewer() should return error if the root window is a TabChild and TabChild::ParentIsActive() returns false?

The problem from what I understand now is when ctrl+f, nsFocusManager::SetFocus() triggers Blur() for the browser element and Focus() for the input element. Blur() will SendDeactivate() to the child process and clear the mFocusedWindow, but Focus() will not SendActivate(). That's why EventStateManager::GetContentViewer() returns error and EventStateManager::ChangeFullZoom() does nothing.
Attached file wip (obsolete) —
Tried to fix it as comment 9, I am not sure I am doing it correctly though it fixes the issue.

I guess you meant to skip GetFocusedWindow() for both e10s and non-e10s cases and just get root window by mDocument->GetWindow()->GetPrivateRoot()?
Attachment #8748069 - Flags: feedback?(enndeakin)
> I am not sure I understand this. Does that mean
> EventStateManager::GetContentViewer() should return error if the root window
> is a TabChild and TabChild::ParentIsActive() returns false?

It shouldn't return an error at all in those cases. Not having a focused window is a normal state, not an error state.


> The problem from what I understand now is when ctrl+f,
> nsFocusManager::SetFocus() triggers Blur() for the browser element and
> Focus() for the input element. Blur() will SendDeactivate() to the child
> process and clear the mFocusedWindow, but Focus() will not SendActivate().

Are you sure? Do you have some steps I could use here to look?
Comment on attachment 8748069 [details]
wip

># HG changeset patch
># User Ting-Yu Chou <janus926@gmail.com>
># Date 1462258332 -28800
>#      Tue May 03 14:52:12 2016 +0800
># Node ID 237a0a675532a08edc014cb585e12f9e891ea2a4
># Parent  77cead2cd20300623eea2416bc9bce4d5021df09
>[mq]: bug-1245068
>
>diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp
>--- a/dom/events/EventStateManager.cpp
>+++ b/dom/events/EventStateManager.cpp
>@@ -13,16 +13,17 @@
> #include "mozilla/MathAlgorithms.h"
> #include "mozilla/MouseEvents.h"
> #include "mozilla/TextComposition.h"
> #include "mozilla/TextEvents.h"
> #include "mozilla/TouchEvents.h"
> #include "mozilla/dom/ContentChild.h"
> #include "mozilla/dom/DragEvent.h"
> #include "mozilla/dom/Event.h"
>+#include "mozilla/dom/TabChild.h"
> #include "mozilla/dom/TabParent.h"
> #include "mozilla/dom/UIEvent.h"
> 
> #include "ContentEventHandler.h"
> #include "IMEContentObserver.h"
> #include "WheelHandlingHelper.h"
> 
> #include "nsCOMPtr.h"
>@@ -2010,21 +2011,27 @@ EventStateManager::GetContentViewer(nsIC
> {
>   *aCv = nullptr;
> 
>   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
>   if(!fm) return NS_ERROR_FAILURE;
> 
>   nsCOMPtr<mozIDOMWindowProxy> focusedWindow;
>   fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
>-  if (!focusedWindow) return NS_ERROR_FAILURE;
>-
>-  auto* ourWindow = nsPIDOMWindowOuter::From(focusedWindow);
>-
>-  nsCOMPtr<nsPIDOMWindowOuter> rootWindow = ourWindow->GetPrivateRoot();
>+
>+  nsCOMPtr<nsPIDOMWindowOuter> rootWindow
>+  if (focusedWindow) {
>+    rootWindow = nsPIDOMWindowOuter::From(focusedWindow)->GetPrivateRoot()

Does GetContentViewer get called from the EventStateManager associated with the window where the wheel event occurred? I would expect that to be the case. If so, then you don't need the focused window at all (which, for example, could be in a window on another screen) mDocument->GetWindow()->GetPrivateRoot() will return the toplevel window for that window.


>+  } else if (XRE_IsContentProcess()) {
>+    rootWindow = mDocument->GetWindow()->GetPrivateRoot();
>+    TabChild* tabChild = TabChild::GetFrom(rootWindow);
>+    if (tabChild && !tabChild->ParentIsActive()) {
>+      return NS_ERROR_FAILURE;

You don't need to check for XRE_IsContentProcess(), and instead assume that if a TabChild is null that it isn't a child process.
Attachment #8748069 - Flags: feedback?(enndeakin) → feedback-
(In reply to Neil Deakin from comment #13)
> > The problem from what I understand now is when ctrl+f,
> > nsFocusManager::SetFocus() triggers Blur() for the browser element and
> > Focus() for the input element. Blur() will SendDeactivate() to the child
> > process and clear the mFocusedWindow, but Focus() will not SendActivate().
> 
> Are you sure? Do you have some steps I could use here to look?

Quite sure, just follow the STR of the bug description.
Well that's correct then. The findbar should be focused after step 3 and not the content.
Assignee: nobody → janus926
Attached patch patch v1 (obsolete) — Splinter Review
Attachment #8749518 - Flags: review?(enndeakin)
Attachment #8748069 - Attachment is obsolete: true
Comment on attachment 8749518 [details] [diff] [review]
patch v1

>+    nsCOMPtr<mozIDOMWindowProxy> activeWindow;
>+    fm->GetActiveWindow(getter_AddRefs(activeWindow));
>+    if (rootWindow != activeWindow) return NS_ERROR_FAILURE;
>+  } else {
>+    if (!tabChild->ParentIsActive()) return NS_ERROR_FAILURE;
>+  }
> 
Both of these should return NS_OK as not having a focused window isn't an error. Otherwise, this will dump errors on the console when NS_ENSURE_SUCCESS is then invoked by the caller.
Attachment #8749518 - Flags: review?(enndeakin) → review+
(In reply to Neil Deakin from comment #18)
> Both of these should return NS_OK as not having a focused window isn't an
> error. Otherwise, this will dump errors on the console when
> NS_ENSURE_SUCCESS is then invoked by the caller.

Then a null checking in the caller is going to be needed, both ChangeTextSize() and ChangeFullZoom() expect |cv| a valid pointer after NS_ENSURE_SUCCESS.

Also does that mean when GetContentViewer() returns OK and a null pointer, ChangeTextSize() and ChangeFullZoom() will return OK?

Thank you for your help and reviewing. :)
Flags: needinfo?(enndeakin)
> Then a null checking in the caller is going to be needed, both
> ChangeTextSize() and ChangeFullZoom() expect |cv| a valid pointer after
> NS_ENSURE_SUCCESS.

Yes, just add a null-check.
 
> Also does that mean when GetContentViewer() returns OK and a null pointer,
> ChangeTextSize() and ChangeFullZoom() will return OK?

Yes.
Flags: needinfo?(enndeakin)
Attached patch patch v2 (obsolete) — Splinter Review
Addressed review comments. Try: https://treeherder.mozilla.org/#/jobs?repo=try&revision=5ebe7b8635c0
Attachment #8749518 - Attachment is obsolete: true
Attached patch patch v3Splinter Review
Fixed failed try cases.
Attachment #8750579 - Attachment is obsolete: true
(In reply to Ting-Yu Chou [:ting] from comment #22)
> https://treeherder.mozilla.org/#/jobs?repo=try&revision=717fb8de99e4

Try looks good.
Keywords: checkin-needed
https://hg.mozilla.org/mozilla-central/rev/a95651b07928
Status: NEW → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla49
ting, is this fix worth uplifting to 48?
Flags: needinfo?(janus926)
I think no, because I expect there won't be a big portion of users that run into this bug. But if you want, we need to take bug 1274888 as well, because my patch here lacks a null checker.
Flags: needinfo?(janus926)
wontfix for 49 based on Ting's comment 28.
Flags: qe-verify+
I've reproduced the initial issue on Nightly 47.0a1 (02-02-2016). 

Verified fixed on Windows 7 x64 and Mac OSX 10.9.5 using Firefox 49 Beta 5 (buildID: 20160818050015) with/without e10s.
Status: RESOLVED → VERIFIED
Depends on: 1328070
Depends on: 1363285
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: