Diff
Modified: trunk/LayoutTests/ChangeLog (239511 => 239512)
--- trunk/LayoutTests/ChangeLog 2018-12-21 19:40:41 UTC (rev 239511)
+++ trunk/LayoutTests/ChangeLog 2018-12-21 19:57:14 UTC (rev 239512)
@@ -1,3 +1,14 @@
+2018-12-21 Zalan Bujtas <za...@apple.com>
+
+ Synchronous media query evaluation could destroy current Frame/FrameView.
+ https://bugs.webkit.org/show_bug.cgi?id=192781
+ <rdar://problem/34416793>
+
+ Reviewed by Chris Dumez.
+
+ * printing/print-with-media-query-destory-expected.txt: Added.
+ * printing/print-with-media-query-destory.html: Added.
+
2018-12-21 Alex Christensen <achristen...@webkit.org>
Revert r239503.
Added: trunk/LayoutTests/printing/print-with-media-query-destory-expected.txt (0 => 239512)
--- trunk/LayoutTests/printing/print-with-media-query-destory-expected.txt (rev 0)
+++ trunk/LayoutTests/printing/print-with-media-query-destory-expected.txt 2018-12-21 19:57:14 UTC (rev 239512)
@@ -0,0 +1,2 @@
+Pass if no crash or assert
+
Added: trunk/LayoutTests/printing/print-with-media-query-destory.html (0 => 239512)
--- trunk/LayoutTests/printing/print-with-media-query-destory.html (rev 0)
+++ trunk/LayoutTests/printing/print-with-media-query-destory.html 2018-12-21 19:57:14 UTC (rev 239512)
@@ -0,0 +1,28 @@
+<div>Pass if no crash or assert</div>
+<script>
+if (window.testRunner)
+ testRunner.dumpAsText();
+
+function wait() {
+if (window.testRunner)
+ testRunner.waitUntilDone();
+}
+
+function done() {
+if (window.testRunner)
+ testRunner.notifyDone();
+}
+</script>
+<iframe srcdoc="<script>
+window.matchMedia('print').addListener(function(mql) {
+ let parentWindow = window.parent;
+ window.frameElement.remove();
+ parentWindow.done();
+});
+
+if (window.internals) {
+ internals.setPrinting(800, 600);
+ window.parent.wait();
+} else
+ print();
+</script>">
Modified: trunk/Source/WebCore/ChangeLog (239511 => 239512)
--- trunk/Source/WebCore/ChangeLog 2018-12-21 19:40:41 UTC (rev 239511)
+++ trunk/Source/WebCore/ChangeLog 2018-12-21 19:57:14 UTC (rev 239512)
@@ -1,3 +1,33 @@
+2018-12-21 Zalan Bujtas <za...@apple.com>
+
+ Synchronous media query evaluation could destroy current Frame/FrameView.
+ https://bugs.webkit.org/show_bug.cgi?id=192781
+ <rdar://problem/34416793>
+
+ Reviewed by Chris Dumez.
+
+ Protect Frame and FrameView when coming back from printing and check if the current Frame/FrameView/FrameLoader objects are still valid.
+
+ Test: printing/print-with-media-query-destory.html
+
+ * loader/DocumentLoader.cpp:
+ (WebCore::DocumentLoader::finishedLoading):
+ * page/Frame.cpp:
+ (WebCore::Frame::setPrinting):
+ * page/FrameView.cpp:
+ (WebCore::FrameView::forceLayoutForPagination):
+ * page/PrintContext.cpp:
+ (WebCore::PrintContext::PrintContext):
+ (WebCore::PrintContext::computePageRects):
+ (WebCore::PrintContext::computePageRectsWithPageSizeInternal):
+ (WebCore::PrintContext::begin):
+ (WebCore::PrintContext::computeAutomaticScaleFactor):
+ (WebCore::PrintContext::spoolPage):
+ (WebCore::PrintContext::spoolRect):
+ (WebCore::PrintContext::end):
+ * page/PrintContext.h:
+ (WebCore::PrintContext::frame const): Deleted.
+
2018-12-21 Wenson Hsieh <wenson_hs...@apple.com>
Setting the file wrapper and content type of an attachment to a PDF should update its image
Modified: trunk/Source/WebCore/loader/DocumentLoader.cpp (239511 => 239512)
--- trunk/Source/WebCore/loader/DocumentLoader.cpp 2018-12-21 19:40:41 UTC (rev 239511)
+++ trunk/Source/WebCore/loader/DocumentLoader.cpp 2018-12-21 19:57:14 UTC (rev 239512)
@@ -445,6 +445,8 @@
if (!m_mainDocumentError.isNull())
return;
clearMainResourceLoader();
+ if (!frameLoader())
+ return;
if (!frameLoader()->stateMachine().creatingInitialEmptyDocument())
frameLoader()->checkLoadComplete();
Modified: trunk/Source/WebCore/page/Frame.cpp (239511 => 239512)
--- trunk/Source/WebCore/page/Frame.cpp 2018-12-21 19:40:41 UTC (rev 239511)
+++ trunk/Source/WebCore/page/Frame.cpp 2018-12-21 19:57:14 UTC (rev 239512)
@@ -661,22 +661,23 @@
void Frame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio, AdjustViewSizeOrNot shouldAdjustViewSize)
{
+ if (!view())
+ return;
// In setting printing, we should not validate resources already cached for the document.
// See https://bugs.webkit.org/show_bug.cgi?id=43704
ResourceCacheValidationSuppressor validationSuppressor(m_doc->cachedResourceLoader());
m_doc->setPrinting(printing);
- if (auto* frameView = view()) {
- frameView->adjustMediaTypeForPrinting(printing);
+ auto& frameView = *view();
+ frameView.adjustMediaTypeForPrinting(printing);
- m_doc->styleScope().didChangeStyleSheetEnvironment();
- if (shouldUsePrintingLayout())
- frameView->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio, shouldAdjustViewSize);
- else {
- frameView->forceLayout();
- if (shouldAdjustViewSize == AdjustViewSize)
- frameView->adjustViewSize();
- }
+ m_doc->styleScope().didChangeStyleSheetEnvironment();
+ if (shouldUsePrintingLayout())
+ frameView.forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio, shouldAdjustViewSize);
+ else {
+ frameView.forceLayout();
+ if (shouldAdjustViewSize == AdjustViewSize)
+ frameView.adjustViewSize();
}
// Subframes of the one we're printing don't lay out to the page size.
Modified: trunk/Source/WebCore/page/FrameView.cpp (239511 => 239512)
--- trunk/Source/WebCore/page/FrameView.cpp 2018-12-21 19:40:41 UTC (rev 239511)
+++ trunk/Source/WebCore/page/FrameView.cpp 2018-12-21 19:57:14 UTC (rev 239512)
@@ -4586,48 +4586,56 @@
void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor, AdjustViewSizeOrNot shouldAdjustViewSize)
{
+ if (!renderView())
+ return;
+
+ Ref<FrameView> protectedThis(*this);
+ auto& renderView = *this->renderView();
+
// Dumping externalRepresentation(frame().renderer()).ascii() is a good trick to see
// the state of things before and after the layout
- if (RenderView* renderView = this->renderView()) {
- float pageLogicalWidth = renderView->style().isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
- float pageLogicalHeight = renderView->style().isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
+ float pageLogicalWidth = renderView.style().isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
+ float pageLogicalHeight = renderView.style().isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
- renderView->setPageLogicalSize({ floor(pageLogicalWidth), floor(pageLogicalHeight) });
- renderView->setNeedsLayoutAndPrefWidthsRecalc();
- forceLayout();
+ renderView.setPageLogicalSize({ floor(pageLogicalWidth), floor(pageLogicalHeight) });
+ renderView.setNeedsLayoutAndPrefWidthsRecalc();
+ forceLayout();
+ if (hasOneRef())
+ return;
- // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
- // page width when shrunk, we will lay out at maximum shrink and clip extra content.
- // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
- // implementation should not do this!
- bool horizontalWritingMode = renderView->style().isHorizontalWritingMode();
- const LayoutRect& documentRect = renderView->documentRect();
- LayoutUnit docLogicalWidth = horizontalWritingMode ? documentRect.width() : documentRect.height();
- if (docLogicalWidth > pageLogicalWidth) {
- int expectedPageWidth = std::min<float>(documentRect.width(), pageSize.width() * maximumShrinkFactor);
- int expectedPageHeight = std::min<float>(documentRect.height(), pageSize.height() * maximumShrinkFactor);
- FloatSize maxPageSize = frame().resizePageRectsKeepingRatio(FloatSize(originalPageSize.width(), originalPageSize.height()), FloatSize(expectedPageWidth, expectedPageHeight));
- pageLogicalWidth = horizontalWritingMode ? maxPageSize.width() : maxPageSize.height();
- pageLogicalHeight = horizontalWritingMode ? maxPageSize.height() : maxPageSize.width();
+ // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
+ // page width when shrunk, we will lay out at maximum shrink and clip extra content.
+ // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
+ // implementation should not do this!
+ bool horizontalWritingMode = renderView.style().isHorizontalWritingMode();
+ const LayoutRect& documentRect = renderView.documentRect();
+ LayoutUnit docLogicalWidth = horizontalWritingMode ? documentRect.width() : documentRect.height();
+ if (docLogicalWidth > pageLogicalWidth) {
+ int expectedPageWidth = std::min<float>(documentRect.width(), pageSize.width() * maximumShrinkFactor);
+ int expectedPageHeight = std::min<float>(documentRect.height(), pageSize.height() * maximumShrinkFactor);
+ FloatSize maxPageSize = frame().resizePageRectsKeepingRatio(FloatSize(originalPageSize.width(), originalPageSize.height()), FloatSize(expectedPageWidth, expectedPageHeight));
+ pageLogicalWidth = horizontalWritingMode ? maxPageSize.width() : maxPageSize.height();
+ pageLogicalHeight = horizontalWritingMode ? maxPageSize.height() : maxPageSize.width();
- renderView->setPageLogicalSize({ floor(pageLogicalWidth), floor(pageLogicalHeight) });
- renderView->setNeedsLayoutAndPrefWidthsRecalc();
- forceLayout();
+ renderView.setPageLogicalSize({ floor(pageLogicalWidth), floor(pageLogicalHeight) });
+ renderView.setNeedsLayoutAndPrefWidthsRecalc();
+ forceLayout();
+ if (hasOneRef())
+ return;
- const LayoutRect& updatedDocumentRect = renderView->documentRect();
- LayoutUnit docLogicalHeight = horizontalWritingMode ? updatedDocumentRect.height() : updatedDocumentRect.width();
- LayoutUnit docLogicalTop = horizontalWritingMode ? updatedDocumentRect.y() : updatedDocumentRect.x();
- LayoutUnit docLogicalRight = horizontalWritingMode ? updatedDocumentRect.maxX() : updatedDocumentRect.maxY();
- LayoutUnit clippedLogicalLeft;
- if (!renderView->style().isLeftToRightDirection())
- clippedLogicalLeft = docLogicalRight - pageLogicalWidth;
- LayoutRect overflow(clippedLogicalLeft, docLogicalTop, pageLogicalWidth, docLogicalHeight);
+ const LayoutRect& updatedDocumentRect = renderView.documentRect();
+ LayoutUnit docLogicalHeight = horizontalWritingMode ? updatedDocumentRect.height() : updatedDocumentRect.width();
+ LayoutUnit docLogicalTop = horizontalWritingMode ? updatedDocumentRect.y() : updatedDocumentRect.x();
+ LayoutUnit docLogicalRight = horizontalWritingMode ? updatedDocumentRect.maxX() : updatedDocumentRect.maxY();
+ LayoutUnit clippedLogicalLeft;
+ if (!renderView.style().isLeftToRightDirection())
+ clippedLogicalLeft = docLogicalRight - pageLogicalWidth;
+ LayoutRect overflow(clippedLogicalLeft, docLogicalTop, pageLogicalWidth, docLogicalHeight);
- if (!horizontalWritingMode)
- overflow = overflow.transposedRect();
- renderView->clearLayoutOverflow();
- renderView->addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
- }
+ if (!horizontalWritingMode)
+ overflow = overflow.transposedRect();
+ renderView.clearLayoutOverflow();
+ renderView.addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
}
if (shouldAdjustViewSize)
Modified: trunk/Source/WebCore/page/PrintContext.cpp (239511 => 239512)
--- trunk/Source/WebCore/page/PrintContext.cpp 2018-12-21 19:40:41 UTC (rev 239511)
+++ trunk/Source/WebCore/page/PrintContext.cpp 2018-12-21 19:57:14 UTC (rev 239512)
@@ -34,7 +34,7 @@
namespace WebCore {
PrintContext::PrintContext(Frame* frame)
- : m_frame(frame)
+ : FrameDestructionObserver(frame)
{
}
@@ -46,10 +46,14 @@
void PrintContext::computePageRects(const FloatRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, float& outPageHeight, bool allowHorizontalTiling)
{
+ if (!frame())
+ return;
+
+ auto& frame = *this->frame();
m_pageRects.clear();
outPageHeight = 0;
- if (!m_frame->document() || !m_frame->view() || !m_frame->document()->renderView())
+ if (!frame.document() || !frame.view() || !frame.document()->renderView())
return;
if (userScaleFactor <= 0) {
@@ -57,9 +61,9 @@
return;
}
- RenderView* view = m_frame->document()->renderView();
+ RenderView* view = frame.document()->renderView();
const IntRect& documentRect = view->documentRect();
- FloatSize pageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(printRect.width(), printRect.height()), FloatSize(documentRect.width(), documentRect.height()));
+ FloatSize pageSize = frame.resizePageRectsKeepingRatio(FloatSize(printRect.width(), printRect.height()), FloatSize(documentRect.width(), documentRect.height()));
float pageWidth = pageSize.width();
float pageHeight = pageSize.height();
@@ -82,11 +86,15 @@
void PrintContext::computePageRectsWithPageSizeInternal(const FloatSize& pageSizeInPixels, bool allowInlineDirectionTiling)
{
- if (!m_frame->document() || !m_frame->view() || !m_frame->document()->renderView())
+ if (!frame())
return;
- RenderView* view = m_frame->document()->renderView();
+ auto& frame = *this->frame();
+ if (!frame.document() || !frame.view() || !frame.document()->renderView())
+ return;
+ RenderView* view = frame.document()->renderView();
+
IntRect docRect = view->documentRect();
int pageWidth = pageSizeInPixels.width();
@@ -151,26 +159,34 @@
void PrintContext::begin(float width, float height)
{
+ if (!frame())
+ return;
+
+ auto& frame = *this->frame();
// This function can be called multiple times to adjust printing parameters without going back to screen mode.
m_isPrinting = true;
FloatSize originalPageSize = FloatSize(width, height);
- FloatSize minLayoutSize = m_frame->resizePageRectsKeepingRatio(originalPageSize, FloatSize(width * minimumShrinkFactor(), height * minimumShrinkFactor()));
+ FloatSize minLayoutSize = frame.resizePageRectsKeepingRatio(originalPageSize, FloatSize(width * minimumShrinkFactor(), height * minimumShrinkFactor()));
// This changes layout, so callers need to make sure that they don't paint to screen while in printing mode.
- m_frame->setPrinting(true, minLayoutSize, originalPageSize, maximumShrinkFactor() / minimumShrinkFactor(), AdjustViewSize);
+ frame.setPrinting(true, minLayoutSize, originalPageSize, maximumShrinkFactor() / minimumShrinkFactor(), AdjustViewSize);
}
float PrintContext::computeAutomaticScaleFactor(const FloatSize& availablePaperSize)
{
- if (!m_frame->view())
+ if (!frame())
return 1;
+ auto& frame = *this->frame();
+ if (!frame.view())
+ return 1;
+
bool useViewWidth = true;
- if (m_frame->document() && m_frame->document()->renderView())
- useViewWidth = m_frame->document()->renderView()->style().isHorizontalWritingMode();
+ if (frame.document() && frame.document()->renderView())
+ useViewWidth = frame.document()->renderView()->style().isHorizontalWritingMode();
- float viewLogicalWidth = useViewWidth ? m_frame->view()->contentsWidth() : m_frame->view()->contentsHeight();
+ float viewLogicalWidth = useViewWidth ? frame.view()->contentsWidth() : frame.view()->contentsHeight();
if (viewLogicalWidth < 1)
return 1;
@@ -181,6 +197,10 @@
void PrintContext::spoolPage(GraphicsContext& ctx, int pageNumber, float width)
{
+ if (!frame())
+ return;
+
+ auto& frame = *this->frame();
// FIXME: Not correct for vertical text.
IntRect pageRect = m_pageRects[pageNumber];
float scale = width / pageRect.width();
@@ -189,27 +209,35 @@
ctx.scale(scale);
ctx.translate(-pageRect.x(), -pageRect.y());
ctx.clip(pageRect);
- m_frame->view()->paintContents(ctx, pageRect);
- outputLinkedDestinations(ctx, *m_frame->document(), pageRect);
+ frame.view()->paintContents(ctx, pageRect);
+ outputLinkedDestinations(ctx, *frame.document(), pageRect);
ctx.restore();
}
void PrintContext::spoolRect(GraphicsContext& ctx, const IntRect& rect)
{
+ if (!frame())
+ return;
+
+ auto& frame = *this->frame();
// FIXME: Not correct for vertical text.
ctx.save();
ctx.translate(-rect.x(), -rect.y());
ctx.clip(rect);
- m_frame->view()->paintContents(ctx, rect);
- outputLinkedDestinations(ctx, *m_frame->document(), rect);
+ frame.view()->paintContents(ctx, rect);
+ outputLinkedDestinations(ctx, *frame.document(), rect);
ctx.restore();
}
void PrintContext::end()
{
+ if (!frame())
+ return;
+
+ auto& frame = *this->frame();
ASSERT(m_isPrinting);
m_isPrinting = false;
- m_frame->setPrinting(false, FloatSize(), FloatSize(), 0, AdjustViewSize);
+ frame.setPrinting(false, FloatSize(), FloatSize(), 0, AdjustViewSize);
m_linkedDestinations = nullptr;
}
Modified: trunk/Source/WebCore/page/PrintContext.h (239511 => 239512)
--- trunk/Source/WebCore/page/PrintContext.h 2018-12-21 19:40:41 UTC (rev 239511)
+++ trunk/Source/WebCore/page/PrintContext.h 2018-12-21 19:57:14 UTC (rev 239512)
@@ -20,6 +20,7 @@
#pragma once
+#include "FrameDestructionObserver.h"
#include <wtf/Forward.h>
#include <wtf/HashMap.h>
#include <wtf/Vector.h>
@@ -36,13 +37,11 @@
class IntRect;
class Node;
-class PrintContext {
+class PrintContext : public FrameDestructionObserver {
public:
WEBCORE_EXPORT explicit PrintContext(Frame*);
WEBCORE_EXPORT ~PrintContext();
- Frame* frame() const { return m_frame; }
-
// Break up a page into rects without relayout.
// FIXME: This means that CSS page breaks won't be on page boundary if the size is different than what was passed to begin(). That's probably not always desirable.
// FIXME: Header and footer height should be applied before layout, not after.
@@ -96,7 +95,6 @@
static constexpr float maximumShrinkFactor() { return 2; }
protected:
- Frame* m_frame;
Vector<IntRect> m_pageRects;
private: