Closed Bug 1604440 Opened 5 years ago Closed 2 years ago

onFirstContentfulPaint triggered on page complete

Categories

(GeckoView :: General, defect, P3)

72 Branch
Unspecified
All
defect

Tracking

(Not tracked)

RESOLVED INCOMPLETE

People

(Reporter: colormatch, Unassigned)

Details

User Agent: Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0

Steps to reproduce:

onFirstContentfulPaint seems to be triggered on page fully loaded, instead on first paint.

video of onFirstContentfulPaint vs onFirstComposite: https://v.redd.it/a5ngs7rc76541

Hi, Can you please let us know what behaviour you would like to see here? When is onFirstContentfulPaint being called in relation to onPageStop?

Flags: needinfo?(colormatch)

Hi Emily,
onFirstContentfulPaint should have been called as soon as something (anything) was rendered.

The behaviour is described in the documentation:

"Notification that the first content paint has occurred. This callback is invoked for the first content paint after a page has been loaded. The function onFirstComposite(GeckoSession) will be called once the compositor has started rendering. However, it is possible for the compositor to start rendering before there is any content to render. onFirstContentfulPaint() is called once some content has been rendered. It may be nothing more than the page background color. It is not an indication that the whole page has been rendered."

https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.ContentDelegate.html#onFirstContentfulPaint-org.mozilla.geckoview.GeckoSession-

Flags: needinfo?(colormatch)

Kris, we think this is a problem with graphics or layout. Could your team investigate please?

Flags: needinfo?(ktaeleman)

@colormatch: could you attach attach your about:support information? Thanks!

Flags: needinfo?(ktaeleman) → needinfo?(colormatch)
Priority: -- → P3

(In reply to Kris Taeleman (:ktaeleman) PTO until Jan 23. from comment #4)

@colormatch: could you attach attach your about:support information? Thanks!

That is an app running on built-in GeckoView beta, branch 72
I'm not sure how to get the "about:support" out of it. Any suggestions?

Flags: needinfo?(colormatch)

You should be able to type about:support into the URL bar of your app to retrieve the information.

Flags: needinfo?(etoop)

(In reply to colormatch from comment #5)

(In reply to Kris Taeleman (:ktaeleman) PTO until Jan 23. from comment #4)

@colormatch: could you attach attach your about:support information? Thanks!

That is an app running on built-in GeckoView beta, branch 72
I'm not sure how to get the "about:support" out of it. Any suggestions?

For the device-specific parts, you could attach the about:support results returned by some other GV-based app, ideally running the same GV version, like GV Example or Fenix Nightly.
This would, of course, not contain your app-specific config. For this, I can't think of anything better than temporarily modifying your app to render GeckoSession.loadUri("about:support") into a view.

Flags: needinfo?(etoop)

If you are able to get this in view, I would be interested in knowing which compositor is being used, Webrender or OpenGL. That should be somewhere mid page.

@Randall: After some code digging I noticed you have some experience with this, could you take a look?
It does not look webrender has anything to do with this (removing dependency).

No longer blocks: wr-74-android
Flags: needinfo?(rbarker)

(In reply to Kris Taeleman (:ktaeleman) from comment #10)

@Randall: After some code digging I noticed you have some experience with this, could you take a look?
It does not look webrender has anything to do with this (removing dependency).

I just teed off of the mFirstContentfulPaintTransactionId:

https://searchfox.org/mozilla-central/rev/623de665034eee43a54ff02939b61385ffd5990d/layout/base/nsPresContext.cpp#2388

If it is getting set too late, some one from graphics/layout would need to find a better place for it.

Flags: needinfo?(rbarker)

Hey Miko,
Could you take a look at this when you get some time?

Flags: needinfo?(mikokm)

It is hard to tell from the videos what the problem is. What is the expected behavior, and what is actually happening?
A reduced testcase would definitely be helpful.

I do not think it is an error for onFirstContentfulPaint to trigger when the page is fully loaded. The documentation is just saying that it is not guaranteed behavior.
Furthermore, showing or hiding content based on these events might influence the rendering even more: hiding a splash screen covering the whole screen is almost guaranteed to invalidate everything behind it, which in turn causes everything to be painted again, which might hide the "partial paint" events.

Flags: needinfo?(mikokm) → needinfo?(colormatch)

(In reply to Miko Mynttinen [:miko] from comment #13)

It is hard to tell from the videos what the problem is. What is the expected behavior, and what is actually happening?

Hi Miko,
I already described what exactly is happening in the video, and why it shows exactly and very clearly the problem with deviation from specification of the triggered event (which I quoted and linked for your convenience).

I do not think it is an error for onFirstContentfulPaint to trigger when the page is fully loaded. The documentation is just saying that it is not guaranteed behavior.

The specifications explicitly state :
" onFirstContentfulPaint() is called once some content has been rendered. It may be nothing more than the page background color. "
"It is not an indication that the whole page has been rendered." ,
and in no place in the documentation there's a warning that "it only works occasionally" .

Here is the documentation again: https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.ContentDelegate.html#onFirstContentfulPaint-org.mozilla.geckoview.GeckoSession-

Please let me know what document you are looking at, as it must be different from the current official documentation.

Furthermore, showing or hiding content based on these events might influence the rendering even more: hiding a splash screen covering the whole screen is almost guaranteed to invalidate everything behind it, which in turn causes everything to be painted again, which might hide the "partial paint" events.

It is quite clear on the video, that a lot has been rendered in those 2 seconds after onFirstContentfulPaint should have been triggered, and onFirstContentfulPaint only gets triggered after the the page is loaded (since GV does not cache js bytecode it takes a couple of seconds to recompile).

Can you please show me where (which line of code) you have onFirstContentfulPaint triggered, so I can assist you further.

Flags: needinfo?(colormatch)

Hey Miko, could you take a look at this, looks like this conversation has stalled and this is something that causes some ugly page load transitions.

Flags: needinfo?(mikokm)

(In reply to Kris Taeleman (:ktaeleman) from comment #15)

Hey Miko, could you take a look at this, looks like this conversation has stalled and this is something that causes some ugly page load transitions.

As per comment 14, this looks like a problem with GeckoView documentation/specification which needs to be addressed first.

Flags: needinfo?(mikokm)
Flags: needinfo?(rbarker)
Flags: needinfo?(rjesup)

I'm not sure what the documentation change is required. FxR has used this function since it was added with out issue.

Flags: needinfo?(rbarker)

I don't see how the documentation is wrong when onFirstContentfulPaint should be triggered on first paint, as described in the documentation.

After all this is the whole point for this event - to have a trigger when we have some visual ready, not after the whole page (backend code) is compiled/ready (which on some cases can cause unnecessary lag as shown here).

Flags: needinfo?(mikokm)
Flags: needinfo?(mikokm)

FirstContentfulPaint is supposed to fire when the first bit of content-based painting happens (some things like backgrounds aren't considered contentful, for that you want FirstPaint). We put markers in the profile for FirstContentfulPaint, showing when the page starts loading and when the event is triggered (note: the event may be trigger and be queued well before it runs - perhaps that's the issue here?)

Can someone get a profile showing the problem?

Flags: needinfo?(rjesup) → needinfo?(colormatch)

(In reply to Randell Jesup [:jesup] (needinfo me) from comment #19)

FirstContentfulPaint is supposed to fire when the first bit of content-based painting happens (some things like backgrounds aren't considered contentful, for that you want FirstPaint). We put markers in the profile for FirstContentfulPaint, showing when the page starts loading and when the event is triggered (note: the event may be trigger and be queued well before it runs - perhaps that's the issue here?)

Can someone get a profile showing the problem?

Jesup, that was exactly the problem. FirstContentfulPaint was triggered before even the background was drawn, which resulted in white "blink"/flash (which made things look bad, as the app I was building did not have white background, and the only way to integrate ended up having to wait for the page-complete event to show it for the user... which meant 2 more seconds waiting to load background JS after the UI was ready).
I hope you have fixed that issue. I gave up on waiting to be fixed and left the users waiting 2 more seconds instead of risking them getting seizure from the blink.

Flags: needinfo?(colormatch)

So comment 1 is incorrect then: "onFirstContentfulPaint seems to be triggered on page fully loaded, instead on first paint." vs " FirstContentfulPaint was triggered before even the background was drawn"

So it's not that it's fired late, it's that it fires earlier than you want.

I'll note that FCP wasn't really intended for this sort of use. It's mostly a performance metric; when we're ready to start rendering content and the user starts seeing something happen.

There's no guarantee in general that the background will be drawn before FCP, just that painting a background won't fire FCP on it's own. FCP can be anything other than a few things not considered content (like a background). If you need the background to be drawn before FCP, you may need to key further rendering off something else - load the background and nothing else, then add the other stuff on top of it once it renders. Hard to tell what's the right way without knowing a lot more about your application.

At this point, I don't see that there's a bug here, but if I'm wrong in the above analysis of your issue, please correct me.

Flags: needinfo?(colormatch)

A needinfo is requested from the reporter, however, the reporter is inactive on Bugzilla. Closing the bug as incomplete.

For more information, please visit auto_nag documentation.

Status: UNCONFIRMED → RESOLVED
Closed: 2 years ago
Flags: needinfo?(colormatch)
Resolution: --- → INCOMPLETE
You need to log in before you can comment on or make changes to this bug.