Closed Bug 918863 Opened 11 years ago Closed 11 years ago

[B2G][Browser][Youtube]Search does not execute after pressing enter

Categories

(Firefox OS Graveyard :: Gaia::Keyboard, defect)

ARM
Gonk (Firefox OS)
defect
Not set
normal

Tracking

(blocking-b2g:koi+, firefox26 wontfix, firefox27 wontfix, firefox28 verified, b2g-v1.2 verified)

VERIFIED FIXED
1.3 Sprint 6 - 12/6
blocking-b2g koi+
Tracking Status
firefox26 --- wontfix
firefox27 --- wontfix
firefox28 --- verified
b2g-v1.2 --- verified

People

(Reporter: gbennett, Assigned: janjongboom)

References

Details

(Keywords: regression, Whiteboard: burirun1)

Attachments

(3 files, 5 obsolete files)

Attached file YoutubeSearchLOG.txt (deleted) —
Description:
The youtube search bar doesn't run after entering text and pressing enter.

Repro Steps:
1) Updated Buri 1.2 mozRIL to Build ID: 20130920004004
2) Launch browser
3) Go to youtube.com
4) Type in the youtube search bar and press enter

Actual:
Text dissapears and search does not occur.

Expected:
Search occurs.

Environmental Variables
Devices: Buri 1.2 mozRIL
Build ID: 20130920004004
Gecko: http://hg.mozilla.org/releases/mozilla-aurora/rev/46b216260c1d
Gaia: 88e73da95f1c550f2fb0572480a40c989d37c997
Platform Version: 26.0a2

Note: Possibly related to https://bugzilla.mozilla.org/show_bug.cgi?id=890953 and this issue does not occur when using the search on google.com
Repro frequency: 100%, 3/3
See attached: YoutubeSearchLOG.txt
blocking-b2g: --- → koi?
Component: Gaia::Browser → General
QA Contact: sparsons
This issue started to occur on the 9/01 Buri 1.2 build: Build ID: 20130901040215

Environmental Variables
Build ID: 20130901040215
Gecko: http://hg.mozilla.org/mozilla-central/rev/b6c29e434519
Gaia: 9fb5802df60a9081846d704def01df814ed8fbd4
Platform Version: 26.0a1
RIL Version: 01.01.00.019.197 

Previously, the issue from bug 908061 (The keyboard doesn't disappear when performing a search) occurred. To be fair, the issue still occurs but beforehand the user was able to perform a search whereas now, the Enter button doesn't work so a search cannot be performed. 

Last working build for this issue was 8/31 Buri 1.2 Build ID: 20130831040212

Environmental Variables
Build ID: 20130831040212
Gecko: http://hg.mozilla.org/mozilla-central/rev/4ba8dda1ee31
Gaia: 8b6a2452cbf0c3458581d929d4ebf77a53ea0b07
Platform Version: 26.0a1
RIL Version: 01.01.00.019.197
Whiteboard: burirun1
blocking-b2g: koi? → koi+
blocking-b2g: koi+ → koi?
Whiteboard: burirun1 → burirun1, [systemsfe]
Just spoke offline to :gwagner, and he is going to help find an assignee here..
blocking-b2g: koi? → koi+
Whiteboard: burirun1, [systemsfe] → burirun1
Whiteboard: burirun1 → burirun1 [systemsfe]
Candice Serran changed story state to started in Pivotal Tracker
Assignee: nobody → aus
Status: NEW → ASSIGNED
Target Milestone: --- → 1.3 Sprint 3 - 10/25
NI on Ghislian here on next steps and eta of fixing this as the targeted milestone for this has already past.
Flags: needinfo?(aus)
This is still under investigation with no hard ETA.
Flags: needinfo?(aus)
Target Milestone: 1.3 Sprint 3 - 10/25 → 1.3 Sprint 4 - 11/8
(In reply to Ghislain 'Aus' Lacroix from comment #5)
> This is still under investigation with no hard ETA.

We are close to shipping 1.2 and less that 3-4 weeks away, is there anything else that QA or other folks can help with to aid with your investigation here ?
Flags: needinfo?(aus)
Target Milestone: 1.3 Sprint 4 - 11/8 → 1.3 Sprint 5 - 11/22
(In reply to Jason Smith [:jsmith] from comment #8)
> Push log btw for reference:
> 
> http://hg.mozilla.org/mozilla-central/
> pushloghtml?fromchange=4ba8dda1ee31&tochange=b6c29e434519

Hmm...there's nothing that stands out at all on what caused this in the gecko changesets. Let me check the gaia push log.
The gaia push log shows evidence that this is a fallout from the third party keyboard work:

https://github.com/mozilla-b2g/gaia/commit/e3c6257c515ab9a7a5a1eda711f9b7e81538030d

https://github.com/mozilla-b2g/gaia/commit/dcd1deda300bfaf6fcd1df990eb97ec20f843c6b

Rudy - Any ideas why?
Component: General → Gaia::Keyboard
Flags: needinfo?(rlu)
Seems like a bug of inputContext::sendKey().
If I changed it back to using the deprecated mozKeyboard.sendKey.

See the change for how I reverted the code,
https://github.com/RudyLu/gaia/commit/f4daebc18c5ba1701562fefd1f3cc1b454e4b5ae

Jan, Xulei,

Would you be interested to take a look if you have free cycles?
Flags: needinfo?(xyuan)
Flags: needinfo?(rlu)
Flags: needinfo?(janjongboom)
I found that we will specify charCode=0 for [Enter] key, and if we specify charCode=keyCode=13 here, it will trigger page reload.
https://mxr.mozilla.org/mozilla-central/source/dom/inputmethod/forms.js#514
Blocks: 858383
(In reply to Rudy Lu [:rudyl] from comment #12)
> I found that we will specify charCode=0 for [Enter] key, and if we specify
> charCode=keyCode=13 here, it will trigger page reload.
> https://mxr.mozilla.org/mozilla-central/source/dom/inputmethod/forms.js#514

It is strange. From MDN, only one of charCode and keyCode could be set, not both (https://developer.mozilla.org/en-US/docs/Web/API/event.charCode). The hardware
keyboard doesn't set charCode for [Enter] key either.

Anyway, I'll take a look at this bug around next monday.
Flags: needinfo?(xyuan)
koi+ is for 1.2. We should use 1.2 target milestone rather than 1.3 target milestone.
Target Milestone: 1.3 Sprint 5 - 11/22 → 1.2 C5(Nov22)
I had made some investigation in bug 908061 but nothing stand out. I don't think the key events themselves had any difference that results YouTube behaves incorrectly (except bug 908061 comment 32, but applying the patch to fix that does not solve the problem).
(In reply to Rudy Lu [:rudyl] from comment #11)
> Seems like a bug of inputContext::sendKey().
> If I changed it back to using the deprecated mozKeyboard.sendKey.
> 
> See the change for how I reverted the code,
> https://github.com/RudyLu/gaia/commit/
> f4daebc18c5ba1701562fefd1f3cc1b454e4b5ae
> 
> Jan, Xulei,
> 
> Would you be interested to take a look if you have free cycles?

That shouldn't make any difference because calling on the two different sendKey() functions result the same ipc message (thus, the same key and key events) in the content process if I read the code correctly -- Xulei and Jan could verify.
Attached patch youtube v1 patch (obsolete) (deleted) — Splinter Review
It seems Youtube search input needs to do some special work between key down, key press and key up events, but soft keyboard API will send these three events at once and doesn't give any time for the Youtube search input to do its work between events and it makes Youtuebe search input fail to handle the enter key events.

To work around this issue, the patch will send the three key events by three times instead of once.
Attachment #8333725 - Flags: review?(janjongboom)
Flags: needinfo?(janjongboom)
@Rudy, Can you help verify the above patch works on device? I cannot access Youtube on device, because I need a network proxy to access Youtube, but failed to set that proxy on real device.
Flags: needinfo?(rlu)
I built and re-flashed Gecko on my Keon but it doesn't make any difference... On which device did you test this?
If I change line 524 in dom/inputmethod/forms.js to this it fixes the issue:

["keydown", "keypress", "keyup"].forEach(function(type) {
  domWindowUtils.sendKeyEvent(type, 
                              json.keyCode, json.keyCode == 13 ? json.keyCode : json.charCode,
                              json.modifiers);
});

Either, we used to send charCode and keyCode when sending VK_RETURN and/or VK_ENTER before or we would set charCode and not keyCode. I hope this info is helpful for you guys as it's been requested that I let you guys take care of this one. :)
Assignee: aus → nobody
Flags: needinfo?(aus)
Assignee: nobody → xyuan
Whiteboard: burirun1 [systemsfe] → burirun1
(In reply to Jan Jongboom [:janjongboom] from comment #19)
> I built and re-flashed Gecko on my Keon but it doesn't make any
> difference... On which device did you test this?
On no device. I tested 1.2 branch on b2g-desktop. I have problem to access youtube on device. 
Do you have resource to take this?
Flags: needinfo?(janjongboom)
Comment on attachment 8333725 [details] [diff] [review]
youtube v1 patch

Tried this patch on buri but found that it did not resolve this issue.
Attachment #8333725 - Flags: feedback-
Flags: needinfo?(rlu)
Taking it.
Assignee: xyuan → janjongboom
Flags: needinfo?(janjongboom)
Alright, some problems that I have found.

1. The use of MutationObserver is not correct. If we watch the parentNode of the element, but the parentNode also gets deleted we don't get a notification. This is what happens in YouTube (whole content div gets replaced, and we never get a notification). Therefore we never |blur()|. We should listen to document.body instead and then use |contains|.
2. YT uses a pattern that goes like, listen to |keydown|, then attach |keyup| I presume. Because these two are events they should happen on a tick later. I think this is what :yxl also did, but perhaps the Thread Manager actually emits them on the same tick on device. If I put each event in a setTimeout all is well. Please review carefully. I have 15 ms. here because that worked on my Keon. 0 ms. didn't...
Attached patch Patch v2 (obsolete) (deleted) — Splinter Review
Two issues found when using YT patched: doesn't search when pressing ENTER and keyboard doesn't hide when it does.
Attachment #8334469 - Flags: review?(xyuan)
Attachment #8334469 - Flags: feedback?(rlu)
Attachment #8333725 - Attachment is obsolete: true
Attachment #8333725 - Flags: review?(janjongboom)
Comment on attachment 8334469 [details] [diff] [review]
Patch v2

Review of attachment 8334469 [details] [diff] [review]:
-----------------------------------------------------------------

Jan, really thanks for the help. The patch looks good, though still needs a polish.
It's much clear that we need a short time interval among the key events.
I'm concerning that these interval may compromise performance of the keyboard.
But it seems we have no other choice before Youtube fixing its website. So
I expect to shorten the time interval among key events as soon as possible.

::: dom/inputmethod/forms.js
@@ +289,3 @@
>            });
>          });
> +        if (del) {

Check if the removed element contains self.focusedElement. There is a case that we need this check: https://bugzilla.mozilla.org/show_bug.cgi?id=914100#c31

@@ -341,5 @@
>          }
>  
> -        if (!target) {
> -          break;
> -        }

Why do you remove this check?

@@ +512,5 @@
>  
> +        // We'll need to send these events to the client, but we can't
> +        // send them all at once. Some sites bind up in ev handler of keydown
> +        function sendNextEvent(eventNames) {
> +          let eventName = eventNames.splice(0, 1)[0];

Use |eventNames.shift()| instead of |eventNames.splice(0, 1)[0]|.

@@ +524,5 @@
> +            return;
> +          }
> +          // Make sure every event is called on separate tick
> +          content.setTimeout(function() {
> +            domWindowUtils.sendKeyEvent(eventName, json.keyCode,

set FormAssistant._editing to true before generating the key event. Otherwise the FormAssistant will treat this key event as an event faked by the page content and calls |sendKeyboardState| in function EditAction to ask keyboard to reset.

@@ +532,2 @@
>          }
> +        sendNextEvent(['keydown', 'keypress', 'keyup']);

The first event(keydown) doesn't need a timeout delay. We can make an improvement here.
Attachment #8334469 - Flags: review?(xyuan) → feedback+
Comment on attachment 8334469 [details] [diff] [review]
Patch v2

I have tested this patch and it works to resolve this issue about youtube.
However, I am a little concerned about the delay between sending each of the keydown, keypress, and keyup events.

Not sure if this is the best practice to do this.

Fabrice, do you happen to know if this approach is ok?
Thanks.
Attachment #8334469 - Flags: feedback?(rlu) → feedback+
Hi Fabrice, 
Please refer to my question in Comment 27.
Thanks.
Flags: needinfo?(fabrice)
(In reply to Yuan Xulei [:yxl] from comment #26)
> > -        if (!target) {
> > -          break;
> > -        }
> 
> Why do you remove this check?
The check is there twice (also at start of function)

I'll change the others. I think this is not a YT only problem by the way. I guess there are more sites that write code in a similar fashion. If fabrice has a better idea than using a setTimeout that would be very welcome.
Attached patch Patch v3 (obsolete) (deleted) — Splinter Review
Updated patch. The thing is that we can't execute keypress immediately with keydown either, if I do that then YT breaks again. So I guess they're doing something fancy there...
Attachment #8334469 - Attachment is obsolete: true
Attachment #8335210 - Flags: review?(xyuan)
setTimeout() is a bad idea indeed. Just posting events to the main thread as in https://mxr.mozilla.org/mozilla-central/source/dom/inputmethod/MozKeyboard.js#82 should work.
Flags: needinfo?(fabrice)
Comment on attachment 8335210 [details] [diff] [review]
Patch v3

Review of attachment 8335210 [details] [diff] [review]:
-----------------------------------------------------------------

r=me, but please address the comment before check in.

::: dom/inputmethod/forms.js
@@ +3,5 @@
>  /* This Source Code Form is subject to the terms of the Mozilla Public
>   * License, v. 2.0. If a copy of the MPL was not distributed with this file,
>   * You can obtain one at http://mozilla.org/MPL/2.0/. */
>  
> +// "use strict";

Comment out by mistake?

@@ +337,5 @@
>          } else if (target instanceof HTMLDocument) {
>            target = target.body;
>          } else if (target instanceof HTMLIFrameElement) {
>            target = target.contentDocument ? target.contentDocument.body
>                                            : null;

The target may be set to null here.

@@ -341,5 @@
>          }
>  
> -        if (!target) {
> -          break;
> -        }

So we need to check the target twice.

@@ +504,5 @@
>          break;
>        }
>  
>        case "Forms:Input:SendKey":
> +        let self = this;

It is recommended to use bind.
Attachment #8335210 - Flags: review?(xyuan) → review+
(In reply to Fabrice Desré [:fabrice] from comment #31)
> setTimeout() is a bad idea indeed. Just posting events to the main thread as
> in
> https://mxr.mozilla.org/mozilla-central/source/dom/inputmethod/MozKeyboard.
> js#82 should work.

Jan had tested the thread events way (see comment 24), but it is not well enough to solve this issue. So we have to fall back to the setTimeout way :(
(In reply to Yuan Xulei [:yxl] from comment #33)
> (In reply to Fabrice Desré [:fabrice] from comment #31)
> > setTimeout() is a bad idea indeed. Just posting events to the main thread as
> > in
> > https://mxr.mozilla.org/mozilla-central/source/dom/inputmethod/MozKeyboard.
> > js#82 should work.
> 
> Jan had tested the thread events way (see comment 24), but it is not well
> enough to solve this issue. So we have to fall back to the setTimeout way :(

We must understand why this doesn't work. I disagree with landing a 15ms (!!) timeout in keyboard event dispatching.
Please note that also on 1.1 the YT page does not behave as expected (keyboard never pops down f.e.).
I have been digging deep today in the source of the YT mobile website. In the searchbox mode when you deminify it there is the following line:

d && ((b = Va.Mj()) && wa(b) ? Va.Lm(a.shiftKey) : ca.defer(function() { Va.Lm(a.shiftKey) })

ca.defer is like setImmediate, and Va.Lm executes the search query. The first part of the expression always executes to NULL on FF desktop, Chrome desktop and FxOS. The reason why the search query is not executed is that between this execution moment and the moment the defer'ed code runs that the search box is emptied. This happens in some code that is called |g.zu| (which is shorthand for |Vm.prototype.zu|). I don't know why this function is being called on FxOS, but it seems there is an explicit |click| action because if you attach a click handler like:

document.querySelector('._mgv').addEventListener('click', function() { console.log('click') })

And type a query and press enter, the event handler kicks in. Unfortunately Firefox cannot deminify inline scripts so I can't trace back to where this might be called... The click handler is different from a normal click in that:

* mozInputSource is 1 (MOZ_SOURCE_MOUSE) and not 5 (MOZ_SOURCE_TOUCH)
* all positions (clientX, clientY etc) are 0
* e.detail is 0 instead of 1
* The explicitOriginalTarget is the input box rather than the button.

So this is a generated event I guess, but I can't figure out where it came from... Nor why upping the timeouts on keypress/keyup would help, as they occur after this has happened.
Attached patch Patch v4 (obsolete) (deleted) — Splinter Review
Here is the updated patch by the way. If anyone knows a way to debug inline JS in Firefox or has another great idea please add it :p
Attachment #8335210 - Attachment is obsolete: true
Flags: needinfo?(fabrice)
Jan, great work in youtube-land! can you try to write a sample self contained page that showcases the issue? That would help understand why dispatching events to the main thread doesn't work.
Flags: needinfo?(fabrice)
No, I have no f*ing clue what the root cause of this is because I can't trace the call to the clear button back due to the minified source. Maybe I can set up a small proxy this weekend.
I am working on a test case page now so people can have place to test this on.
http://jsfiddle.net/timdream/jPWE9/

This test will attach keypress/keyup listener when

-- keydown took place
-- keydown took place and AFTER setImmediate
-- keydown took place and AFTER setTimeout(0)

(the test script will clean up all event listener after 500ms and draw a line in the log)

On a Mac the test result for a key press is:

1385354627201: keyup setImmediate
1385354627200: keyup setTimeout
1385354627200: keyup keydownListener
1385354627200: keyup
1385354627121: keypress keydownListener
1385354627119: keypress
1385354627116: keydown

On FxOS with Browser we currently got something like:

1385354627200: keyup keydownListener
1385354627200: keyup
1385354627121: keypress keydownListener
1385354627119: keypress
1385354627116: keydown

So no setImmediate/setTimeout event listeners is fired.
(In reply to Jan Jongboom [:janjongboom] from comment #37)
> Created attachment 8336056 [details] [diff] [review]
> Patch v4
> 
> Here is the updated patch by the way. If anyone knows a way to debug inline
> JS in Firefox or has another great idea please add it :p

This patch do:

1385354627201: keyup setImmediate
1385354627200: keyup setTimeout
1385354627200: keyup keydownListener
1385354627200: keyup
0000000000000: keypress setTimeout
1385354627121: keypress keydownListener
1385354627119: keypress
1385354627116: keydown

Which triggers one more event listener.
Comment on attachment 8336056 [details] [diff] [review]
Patch v4

>User Jan Jongboom <janjongboom@gmail.com>
>Bug 918863 - MutationObserver doesnt recognize all deleted elements, keyup event fires too quickly after keydown. r=yxl
>
>diff --git a/dom/inputmethod/forms.js b/dom/inputmethod/forms.js
>--- a/dom/inputmethod/forms.js
>+++ b/dom/inputmethod/forms.js
>+          }, 8);

Strangely, change this from 8 to 0 will not fix YouTube.

>+        }.bind(this);
Attached patch Tentative patch (obsolete) (deleted) — Splinter Review
Here is my patch based on Jan's work, I've ensure the events are fired in a way like everyone else (see comment 41) but this patch does not work with YouTube.
Yeah, so there is a timing issue in YouTube code and I can't find out what it is :P
Attachment #8338341 - Attachment is patch: true
Hallvord, can you help isolate the cause of this issue with YouTube?
Pressing enter with the form focused will send a click event on the button that looks most likely to be the form's default button. (HTML sucks at this point because there's no way to say "the default submit button of this form is the foo element"). Now, YouTube has re-organised their UI a little bit - when you type into the input, two grey elements appear overlaying it: one "clear" button (x in a ball) and one "search" button (magnifier). The "clear" button happens to be the first <BUTTON> element in source code order, so voila - each time the user presses enter, we fire a fake "click" event on the "clear the input" button.

The race condition possibly occurs because this click event is fired and the input is cleared before the onchange and/or key events are done processing the input? I don't quite understand yet what we're doing different from other browsers here.
This issue also occurs in Chrome on Android for me:
1) Type a search, press enter
2) Go back
3) Try to search again, press enter
 -> input is cleared, no search happens
fwiw, this issue (entering search terms disappearing after enter) occurs in any Firefox browsers with ghostery too when the search is tied to Google on a third part Web site, such as MDN in the past or The Guardian now. Not sure if it helps, but Ghostery may block "AJAX Google search API".

I can contact Google so we can help them to surface the issue on their side for the Firefox OS and Chrome on Android case.
There is one piece missing to understand this totally: figure out why the same thing doesn't happen in other browsers (or not until one navigates back in Chrome). In other browsers, under a normal search, enter does *not* fire a click event on the button (but it does do so in all browser in a simplified page with only input+button). Something the JS does prevents that event from firing - if I take a snapshot of the generated HTML in the search state and strip out the JS, a click event *will* fire on the "clear" button. I've been playing around with trying to stop propagation of some of the events or messing with keyCode/charCode properties of the enter keypress' events - I know cancelling the keypress will prevent the click event, and this is probably the reason click doesn't fire - but I haven't really found the code that does this cancelling.
(And aside for Karl: several of the event listeners (presumably one of those stop enter from firing click) are registered from scripts delivered from s.ytimg.com - if Ghostery blocks those, it will cause this issue.)
Hallvord, I will contact next week Google, after Thanks Giving hangover in USA. In the meantime if you find something new, do not hesitate to put it here. The more background the better.
Making sure we set event.charCode to 13 rather than 0 in the enter keypress event makes the page work -

var ccGetter = Event.prototype.__lookupGetter__('charCode');
Event.prototype.__defineGetter__('charCode', function(){
	if(this.type === 'keypress' && this.keyCode === 13) return 13;
	return ccGetter.call(this);
});

Now - Chrome's getter/setter support is weird or lacking here, neither this code nor an attempt with KeyboardEvent.prototype seems to do anything, so I can't verify that reversing this will make the problem happen there. Also, on FirefoxOS neither alert() nor console.log() seems to do anything inside this getter (huh??), so I can't even figure out where the property is used by logging stacks..
The bug basically is: even if keydown was cancelled, Gecko fires a normal keypress event here. This keypress doesn't get cancelled (partly because the code expects keypress to have a significant charCode property - but charCode for enter keypress is 0 for some reason) - and causes a click event to get fired on the "clear" button.

Several possible fixes:
* make sure charCode is 13 for enter keypress (should be done anyway)

and either
* make sure we don't fire keypress if keydown was cancelled (best, standards-compatible)
or 
* fire a "pre-cancelled" keypress if keydown was cancelled (Gecko used to do this - but it was a hack, perceived as necessary for legacy compat. If we can get away with not doing so we should avoid it IMO).
Yeah, we shouldn't fire keypress if keydown was cancelled.
Here's a patch that doesn't send the keypress if keydown is canceled and that fixes the problem on YT!
Attachment #8336056 - Attachment is obsolete: true
Attachment #8338341 - Attachment is obsolete: true
Attachment #8341017 - Flags: review?(xyuan)
Attachment #8341017 - Flags: review?(xyuan) → review?(kchen)
Attachment #8341017 - Flags: review?(kchen) → review+
https://hg.mozilla.org/mozilla-central/rev/0e1a6c3f5769
Status: ASSIGNED → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: 1.2 C5(Nov22) → 1.3 Sprint 6 - 12/6
Pressing the return key now activates the YouTube search correctly.

1.2 Environmental Variables:
Device: Buri v1.2 COM RIL
BuildID: 20131205004003
Gaia: 0659f16b9790b1cf9eba4d80743fcc774d2ffe3a
Gecko: af2c7ebb5967
Version: 26.0
Firmware Version: V1.2_20131115

1.3 Environmental Variables:
Device: Buri v1.3 MOZ RIL
BuildID: 20131205040201
Gaia: 1dd0e5c644b4c677a4e8fa02e50d52136db489d9
Gecko: 725c36b5de1a
Version: 28.0a1
Firmware Version: V1.2_20131115
Status: RESOLVED → VERIFIED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: