Fix null-dereference in PrintRenderFrameHelper::PrintPageInternal()
Check if the RenderFrame still exists after rendering for printing, but before rendering the headers/footers. Bail out if it is not. To let PrintRenderFrameHelper know not to continue, change PrintPageInternal() to return a result and check that in the callers. Then add an appropriate PrintPreviewContext::set_error() calls and new error types to handle the error when print previewing. Bug: 371445200 Change-Id: I21f4273796d54db5f1602f42920b9d623ce77c41 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5955790 Reviewed-by: Alan Screen <awscreen@chromium.org> Commit-Queue: Lei Zhang <thestig@chromium.org> Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com> Cr-Commit-Position: refs/heads/main@{#1373571}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
65fdaf60ba
commit
5d6835b376
components/printing/renderer
tools/metrics/histograms
@ -29,6 +29,7 @@
|
||||
#include "base/memory/shared_memory_mapping.h"
|
||||
#include "base/metrics/histogram_functions.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
#include "base/process/process_handle.h"
|
||||
#include "base/run_loop.h"
|
||||
@ -1838,26 +1839,41 @@ bool PrintRenderFrameHelper::RenderPreviewPage(
|
||||
render_metafile->UtilizeTypefaceContext(
|
||||
print_preview_context_.typeface_content_info());
|
||||
base::TimeTicks begin_time = base::TimeTicks::Now();
|
||||
PrintPageInternal(print_params, page_index,
|
||||
print_preview_context_.total_page_count(),
|
||||
print_preview_context_.prepared_frame(),
|
||||
header_footer_frame, render_metafile);
|
||||
print_preview_context_.RenderedPreviewPage(base::TimeTicks::Now() -
|
||||
begin_time);
|
||||
PrintPageInternalResult result = PrintPageInternal(
|
||||
print_params, page_index, print_preview_context_.total_page_count(),
|
||||
print_preview_context_.prepared_frame(), header_footer_frame,
|
||||
render_metafile);
|
||||
switch (result) {
|
||||
case PrintPageInternalResult::kSuccess:
|
||||
print_preview_context_.RenderedPreviewPage(base::TimeTicks::Now() -
|
||||
begin_time);
|
||||
|
||||
// For non-modifiable content, there is no need to call PreviewPageRendered()
|
||||
// since it generally renders very fast. Just render and send the finished
|
||||
// document to the browser.
|
||||
if (!print_preview_context_.IsModifiable())
|
||||
return true;
|
||||
// For non-modifiable content, there is no need to call
|
||||
// PreviewPageRendered() since it generally renders very fast.
|
||||
// Just render and send the finished document to the browser.
|
||||
if (!print_preview_context_.IsModifiable()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Let the browser know this page has been rendered. Send
|
||||
// |page_render_metafile|, which contains the rendering for just this one
|
||||
// page. Then the browser can update the user visible print preview one page
|
||||
// at a time, instead of waiting for the entire document to be rendered.
|
||||
page_render_metafile =
|
||||
render_metafile->GetMetafileForCurrentPage(print_params.printed_doc_type);
|
||||
return PreviewPageRendered(page_index, std::move(page_render_metafile));
|
||||
// Let the browser know this page has been rendered. Send
|
||||
// `page_render_metafile`, which contains the rendering for just this one
|
||||
// page. Then the browser can update the user visible print preview one
|
||||
// page at a time, instead of waiting for the entire document to be
|
||||
// rendered.
|
||||
page_render_metafile = render_metafile->GetMetafileForCurrentPage(
|
||||
print_params.printed_doc_type);
|
||||
return PreviewPageRendered(page_index, std::move(page_render_metafile));
|
||||
|
||||
case PrintPageInternalResult::kNoCanvas:
|
||||
print_preview_context_.set_error(PrintPreviewErrorBuckets::kNoCanvas);
|
||||
return false;
|
||||
|
||||
case PrintPageInternalResult::kNoRenderFrame:
|
||||
print_preview_context_.set_error(
|
||||
PrintPreviewErrorBuckets::kNoRenderFrame);
|
||||
return false;
|
||||
}
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
bool PrintRenderFrameHelper::FinalizePrintReadyDocument() {
|
||||
@ -2278,8 +2294,12 @@ bool PrintRenderFrameHelper::PrintPagesNative(
|
||||
header_footer_frame = header_footer_context->frame();
|
||||
}
|
||||
for (uint32_t printed_page : printed_pages) {
|
||||
PrintPageInternal(print_params, printed_page, page_count, frame,
|
||||
header_footer_frame, &metafile);
|
||||
PrintPageInternalResult result =
|
||||
PrintPageInternal(print_params, printed_page, page_count, frame,
|
||||
header_footer_frame, &metafile);
|
||||
if (result != PrintPageInternalResult::kSuccess) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2488,7 +2508,8 @@ bool PrintRenderFrameHelper::RenderPagesForPrint(blink::WebLocalFrame* frame,
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrintRenderFrameHelper::PrintPageInternal(
|
||||
PrintRenderFrameHelper::PrintPageInternalResult
|
||||
PrintRenderFrameHelper::PrintPageInternal(
|
||||
const mojom::PrintParams& params,
|
||||
uint32_t page_index,
|
||||
uint32_t page_count,
|
||||
@ -2530,12 +2551,16 @@ void PrintRenderFrameHelper::PrintPageInternal(
|
||||
page_size_in_points, gfx::Rect(page_size_in_points),
|
||||
kScaleFactorInPoints, layout.page_orientation);
|
||||
}
|
||||
if (!canvas)
|
||||
return;
|
||||
if (!canvas) {
|
||||
return PrintPageInternalResult::kNoCanvas;
|
||||
}
|
||||
|
||||
canvas->SetPrintingMetafile(metafile);
|
||||
|
||||
RenderPageContent(frame, page_index, canvas);
|
||||
if (render_frame_gone_) {
|
||||
return PrintPageInternalResult::kNoRenderFrame;
|
||||
}
|
||||
|
||||
// Render headers and footers after the page content, as suggested in the spec
|
||||
// (the term "page margin boxes" is a generalization of headers and footers):
|
||||
@ -2552,6 +2577,8 @@ void PrintRenderFrameHelper::PrintPageInternal(
|
||||
// Since `metafile` is known to have a non-null `canvas` at this point,
|
||||
// FinishPage() cannot fail.
|
||||
CHECK(ret);
|
||||
|
||||
return PrintPageInternalResult::kSuccess;
|
||||
}
|
||||
|
||||
void PrintRenderFrameHelper::SetupOnStopLoadingTimeout() {
|
||||
|
@ -207,6 +207,8 @@ class PrintRenderFrameHelper
|
||||
// kInvalidPrinterSettingsDeprecated = 7,
|
||||
// kMetafileCaptureFailedDeprecated = 8,
|
||||
kEmptyPrinterSettings = 9,
|
||||
kNoCanvas = 10,
|
||||
kNoRenderFrame = 11,
|
||||
kLastEnum // Always last.
|
||||
};
|
||||
|
||||
@ -222,6 +224,12 @@ class PrintRenderFrameHelper
|
||||
kScripted,
|
||||
};
|
||||
|
||||
enum class PrintPageInternalResult {
|
||||
kSuccess,
|
||||
kNoCanvas,
|
||||
kNoRenderFrame,
|
||||
};
|
||||
|
||||
// Helper to make it easy to correctly call IPCReceived() and IPCProcessed().
|
||||
class ScopedIPC {
|
||||
public:
|
||||
@ -367,12 +375,13 @@ class PrintRenderFrameHelper
|
||||
const blink::WebNode& node);
|
||||
|
||||
// Helper function for rendering page at `page_index` to `metafile`.
|
||||
void PrintPageInternal(const mojom::PrintParams& params,
|
||||
uint32_t page_index,
|
||||
uint32_t page_count,
|
||||
blink::WebLocalFrame* frame,
|
||||
blink::WebLocalFrame* header_footer_frame,
|
||||
MetafileSkia* metafile);
|
||||
PrintPageInternalResult PrintPageInternal(
|
||||
const mojom::PrintParams& params,
|
||||
uint32_t page_index,
|
||||
uint32_t page_count,
|
||||
blink::WebLocalFrame* frame,
|
||||
blink::WebLocalFrame* header_footer_frame,
|
||||
MetafileSkia* metafile);
|
||||
|
||||
// Helper methods -----------------------------------------------------------
|
||||
|
||||
|
@ -29230,6 +29230,8 @@ Called by update_net_error_codes.py.-->
|
||||
<int value="7" label="Received bad printer settings (Deprecated)"/>
|
||||
<int value="8" label="Capture metadata failed (Deprecated)"/>
|
||||
<int value="9" label="Got empty printer settings"/>
|
||||
<int value="10" label="No Canvas"/>
|
||||
<int value="11" label="No RenderFrame"/>
|
||||
</enum>
|
||||
|
||||
<enum name="PrivacySandboxAggregationServiceKeyFetcherStatus">
|
||||
|
Reference in New Issue
Block a user