Commit d5e7514d authored by Morten Stenshorne's avatar Morten Stenshorne Committed by Commit Bot

Let OBJECT frames persist through reattachment when possible.

If we need to reattach any OBJECT when entering printing, we cannot wait
for the resource to load again. This was especially bad for LayoutNG,
which switches the document back to legacy layout for printing, so that
everything gets reattached, so that no OBJECT would print.

To fix this, allow ContentFrame() to be re-used when re-attaching.

Bug: 913929
Change-Id: I3b11b0550a775c8df1c0449c2438569aa8219091
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1459542Reviewed-by: default avatarRune Lillesveen <futhark@chromium.org>
Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Commit-Queue: Morten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#654821}
parent bef3962e
......@@ -262,7 +262,8 @@ void HTMLPlugInElement::DidMoveToNewDocument(Document& old_document) {
void HTMLPlugInElement::AttachLayoutTree(AttachContext& context) {
HTMLFrameOwnerElement::AttachLayoutTree(context);
if (!GetLayoutObject() || UseFallbackContent()) {
LayoutObject* layout_object = GetLayoutObject();
if (!layout_object || UseFallbackContent()) {
// If we don't have a layoutObject we have to dispose of any plugins
// which we persisted over a reattach.
if (persisted_plugin_) {
......@@ -272,23 +273,31 @@ void HTMLPlugInElement::AttachLayoutTree(AttachContext& context) {
return;
}
if (!IsImageType() && NeedsPluginUpdate() && GetLayoutEmbeddedObject() &&
!GetLayoutEmbeddedObject()->ShowsUnavailablePluginIndicator() &&
GetObjectContentType() != ObjectContentType::kPlugin &&
!is_delaying_load_event_) {
// This element may have been attached previously, and if we created a frame
// back then, re-use it now. We do not want to reload the frame if we don't
// have to, as that would cause us to lose any state changed after loading.
// Re-using the frame also matters if we have to re-attach for printing; we
// don't support reloading anything during printing (the frame would just show
// up blank then).
const Frame* content_frame = ContentFrame();
if (content_frame && !dispose_view_) {
SetEmbeddedContentView(content_frame->View());
} else if (!IsImageType() && NeedsPluginUpdate() &&
GetLayoutEmbeddedObject() &&
!GetLayoutEmbeddedObject()->ShowsUnavailablePluginIndicator() &&
GetObjectContentType() != ObjectContentType::kPlugin &&
!is_delaying_load_event_) {
is_delaying_load_event_ = true;
GetDocument().IncrementLoadEventDelayCount();
GetDocument().LoadPluginsSoon();
}
if (LayoutObject* layout_object = GetLayoutObject()) {
if (image_loader_ && layout_object->IsLayoutImage()) {
LayoutImageResource* image_resource =
ToLayoutImage(layout_object)->ImageResource();
image_resource->SetImageResource(image_loader_->GetContent());
}
if (!layout_object->IsFloatingOrOutOfFlowPositioned())
context.previous_in_flow = layout_object;
if (image_loader_ && layout_object->IsLayoutImage()) {
LayoutImageResource* image_resource =
ToLayoutImage(layout_object)->ImageResource();
image_resource->SetImageResource(image_loader_->GetContent());
}
if (!layout_object->IsFloatingOrOutOfFlowPositioned())
context.previous_in_flow = layout_object;
dispose_view_ = false;
}
......@@ -356,6 +365,13 @@ void HTMLPlugInElement::DetachLayoutTree(const AttachContext& context) {
SetEmbeddedContentView(nullptr);
}
// We should attempt to use the same view afterwards, so that we don't lose
// state. But only if we're reattaching. Otherwise we need to throw it away,
// since there's no telling what's going to happen next, and it wouldn't be
// safe to keep it.
if (!context.performing_reattach)
dispose_view_ = true;
ResetInstance();
HTMLFrameOwnerElement::DetachLayoutTree(context);
......
......@@ -329,7 +329,6 @@ crbug.com/591099 paint/invalidation/overflow/opacity-change-on-overflow-float.ht
crbug.com/591099 paint/invalidation/scroll/fixed-under-composited-fixed-scrolled.html [ Failure ]
crbug.com/591099 paint/invalidation/svg/svg-background-partial-redraw.html [ Failure ]
crbug.com/591099 paint/invalidation/svg/transform-focus-ring-repaint.html [ Failure ]
crbug.com/591099 printing/iframe-svg-in-object-print.html [ Failure ]
crbug.com/591099 storage/indexeddb/objectstore-cursor.html [ Pass ]
crbug.com/591099 svg/zoom/page/zoom-svg-float-border-padding.xml [ Pass ]
crbug.com/591099 tables/mozilla/bugs/bug14159-1.html [ Pass ]
......
<!DOCTYPE html>
<html class="reftest-wait">
<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
<link rel="help" href="https://www.w3.org/TR/css-display-3/">
<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#replaced-elements">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<iframe id="victim" src="support/red-square.html" style="width:100px; height:100px; border:none;"></iframe>
<script>
var loaded_once = false;
victim.onload = function() {
// The child document should only load once. It should not be reloaded
// by changing the display type of the IFRAME.
if (loaded_once)
return;
loaded_once = true;
var childDoc = victim.contentWindow.document;
// Change the red background to green. This will revert back to red if
// the document gets reloaded (which shouldn't happen) when re-attaching
// #victim.
childDoc.getElementById("square").style.background = "green";
document.offsetTop;
victim.style.display = "block";
document.documentElement.className = "";
}
</script>
</html>
<!DOCTYPE html>
<html class="reftest-wait">
<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
<link rel="help" href="https://www.w3.org/TR/css-display-3/">
<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#replaced-elements">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<object id="victim" data="support/red-square.html" style="width:100px; height:100px;"></object>
<script>
var loaded_once = false;
victim.onload = function() {
// The child document should only load once. It should not be reloaded
// by changing the display type of the OBJECT.
if (loaded_once)
return;
loaded_once = true;
var childDoc = victim.contentWindow.document;
// Change the red background to green. This will revert back to red if
// the document gets reloaded (which shouldn't happen) when re-attaching
// #victim.
childDoc.getElementById("square").style.background = "green";
document.offsetTop;
victim.style.display = "block";
document.documentElement.className = "";
}
</script>
</html>
<!DOCTYPE html>
<style>
body { margin:0; }
</style>
<div id="square" style="width:100px; height:100px; background:red;"></div>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment