New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 619197 link

Starred by 1 user

Issue metadata

Status: Fixed
Owner:
Closed: Jul 2016
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux , Windows
Pri: 2
Type: Bug



Sign in to add a comment

Incorrect background when increasing an OOPIF's width/height.

Project Member Reported by alex...@chromium.org, Jun 10 2016

Issue description

With --site-per-process:
(1) Go to http://csreis.github.io/cross-site-iframe.html
(2) Click "Go cross-site (simple page)"
(3) In devtools, enter:
document.querySelector("iframe").style="background-color: green; position: fixed; left: 0; top: 0;  width: 100%; height: 100%; "

What is the expected output?
The iframe is stretched to page bounds and filled with green color.

What do you see instead?
The iframe is stretched to a smaller area in upper left, with strange artifacts around it.

I discovered this while debugging fullscreening an <iframe> element for an OOPIF, and it turned out that the problem is more generic (for fullscreen, it was triggered by applying UA styles in fullscreen.css).  

Note that this only happens on Linux and Windows (I've tried Linux dev 53.0.2763.0 and Windows canary 53.0.2764.0).  Mac canary 53.0.2764.0 works fine.

See screenshots of correct behavior (Mac) and incorrect behavior (Windows).

Ken or Lucas - any ideas on what could be happening?

 
expected.png
224 KB View Download
actual.png
267 KB View Download
Summary: Incorrect background when increasing an OOPIF's width/height. (was: Incorrect size/background when applying fixed position and 100% width/height to an OOPIF)
I've poked around at this a bit.  Note that there's a typo in the URL in step (1): it should be http://csreis.github.io/tests/cross-site-iframe.html.

This actually doesn't seem dependent on percentage widths or fixed position.  Also, the size of the child frame is actually correct - verified this by putting more text in the frame and observing where it clips.  

What does seem to trigger it is resizing an OOPIF to a size greater than its original size.  So, a simpler repro is to use this in step (3):
document.querySelector("iframe").style="background-color: green; width: 600;".  This produces the attached screenshot.  (The iframe's original width is 500.)  It's also not a race: you can do the width change and the background change in two separate steps, and it will still fail.  Also, it doesn't matter whether (2) or (3) comes first.

The painting code on the parent frame side seems fine (BoxPainter::paintBoxDecorationBackgroundWithRect seems to be the place where this background is picked up).  It appears that something about the child frame surface setup in the parent renderer is screwing this up - if I comment out the SetChildFrameSurface call in RenderWidgetHostViewChildFrame::OnSwapCompositorFrame, the background becomes correct (but of course the child frame stops painting).  IIUC, the child frame is supposed to be transparent (i.e. it should paint the text "csreis.github.io" over the green background produced by the parent renderer), and I do see the is_transparent set to true in the |frame| that arrives to OnSwapCompositorFrame.  But interestingly, keeping the SetChildFrameSurface but commenting out the SubmitCompositorFrame call doesn't fix the background (so it's not like the child renderer paints something incorrect, I guess?).  I'll keep poking at this; I don't really know this code at all, so if someone that does has any ideas, that's be great.

wrong_background.png
28.7 KB View Download
I've been playing around with a test page for this, so the simplest repro is: run chrome with --site-per-process, go to http://alexmos17.github.io/tests/bg-frame.html, click "change width", click "change background".  (The order of the two clicks doesn't matter, both lead to the bug).

I still don't have a good lead on this, but I've traced each renderer's output using Frame Viewer in chrome://tracing, and outputs from both renderers appear correct (i.e., the snapshots that I see for cc::LayerTreeHostImpl): the main frame renderer has the green background for the iframe (with correct new width) as well as the two buttons, and the subframe renderer has the transparent text.  So I'd guess that the bug here has something to do with how the two surfaces are composited following the resize and background change.
Cc: jbau...@chromium.org
The area outside the green is essentially garbage because no compositor is drawing to it. It's the parent compositor that's supposed to be drawing the green? Either it things the surface contents are actually opaque in that region, or it's clipping the surface contents but not realizing it.
If I do  
"layer->setOpaque(false);
  layer->SetContentsOpaqueIsFixed(true);"
(after making layer a cc_blink::WebLayerImpl) in ChildFrameCompositingHelper::OnSetSurface then the page seems to work.

So for some reason the parent compositor thinks the child is opaque, even though it shouldn't be. Must the parent compositor always assume that the contents of the iframe could be transparent, or should there be some way to hint either way?

Comment 5 by lfg@chromium.org, Jul 13 2016

Yes, it's the parent's compositor that's supposed to be drawing the green, since the background color is set on the iframe element.

There must be something that changes in the parent compositor to make it think the layer becomes opaque on resize. I think jbauman@'s suggested fix in #4 is correct, but I'll try to poke at this today to figure out why it only happens on resize.

Comment 6 by lfg@chromium.org, Jul 13 2016

Here's an overview of the problem:

For rendering OOPIFs, we use a WebLayer created in content, which gets set here: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp?rcl=1468423091&l=547.

When setting the background color on the <iframe> element, the CSS style in the LayoutIFrame changes, and it eventually triggers  https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp?rcl=1468408847&l=328. Since we now have a background in the CSS style for the LayoutObject (the LayoutIFrame in this case) LayoutBox::backgroundIsKnownToBeOpaqueInRect, starts returning true (before it got short-circuited since hasAlpha was false -- the background was transparent). This will then change the opacity of the content layer: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp?rcl=1468423091&l=1049.


Comment 7 by lfg@chromium.org, Jul 13 2016

It's not obvious to me why blink tries to change the opacity on the platform layer, and going through the history doesn't help much. This code has been there for a very long time.

Overall, I think jbauman@'s suggestion in #4 should work correctly, and I'll put up a patch with it tomorrow, unless anyone else has a better idea.

Comment 8 by lfg@chromium.org, Jul 13 2016

Also to add: There's no resize needed to trigger this. Just a background-color on the iframe, and make it big enough, since it needs to be bigger than the layer borders.
Cc: -lfg@chromium.org
Owner: lfg@chromium.org
Thanks John and Lucas for diagnosing this, this makes much more sense.  Lucas - I'll assign to you for now if you don't mind.  The suggestion in #4 makes sense, I think.  It doesn't seem like that layer should ever be opaque, is there?

I also noticed that this problem doesn't seem to occur with <webview>.  Is that doing something different with surface setup?  Just mentioning this as another thing that might be worth checking.

Comment 10 by lfg@chromium.org, Jul 14 2016

Status: Started (was: Available)
Re#9: It does affect <webview> if you apply the background-color to the object inside the shadow dom. If you apply the background-color to the custom element, then it ends up working (I haven't debugged, but my guess is that we have 2 different LayoutObjects, and in this case the parent always draws, since the object tag is always transparent).

Project Member

Comment 11 by bugdroid1@chromium.org, Jul 20 2016

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/04c6bd6016500a2396142e07d09c582745350827

commit 04c6bd6016500a2396142e07d09c582745350827
Author: lfg <lfg@chromium.org>
Date: Wed Jul 20 17:02:52 2016

Fix incorrect rendering of background color in out-of-process iframes.

BUG= 619197 

Review-Url: https://codereview.chromium.org/2144353002
Cr-Commit-Position: refs/heads/master@{#406591}

[modify] https://crrev.com/04c6bd6016500a2396142e07d09c582745350827/content/renderer/child_frame_compositing_helper.cc

Comment 12 by lfg@chromium.org, Jul 20 2016

Status: Fixed (was: Started)

Sign in to add a comment