#include "components/printing/renderer/print_render_frame_helper.h"
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
#include "base/auto_reset.h"
#include "base/check_is_test.h"
#include "base/debug/alias.h"
#include "base/functional/bind.h"
#include "base/i18n/rtl.h"
#include "base/json/json_writer.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/shared_memory_mapping.h"
#include "base/metrics/histogram_functions.h"
#include "base/no_destructor.h"
#include "base/numerics/safe_conversions.h"
#include "base/process/process_handle.h"
#include "base/run_loop.h"
#include "base/strings/escape.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/task/single_thread_task_runner.h"
#include "base/trace_event/trace_event.h"
#include "base/types/fixed_array.h"
#include "build/build_config.h"
#include "components/grit/components_resources.h"
#include "components/printing/common/print_params.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_thread.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "printing/buildflags/buildflags.h"
#include "printing/metafile_skia.h"
#include "printing/mojom/print.mojom.h"
#include "printing/page_number.h"
#include "printing/print_job_constants.h"
#include "printing/units.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/common/css/page_orientation.h"
#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
#include "third_party/blink/public/common/page/browsing_context_group_info.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/common/web_preferences/web_preferences.h"
#include "third_party/blink/public/mojom/fenced_frame/fenced_frame.mojom.h"
#include "third_party/blink/public/mojom/page/prerender_page_param.mojom.h"
#include "third_party/blink/public/mojom/page/widget.mojom.h"
#include "third_party/blink/public/mojom/partitioned_popins/partitioned_popin_params.mojom.h"
#include "third_party/blink/public/mojom/widget/platform_widget.mojom.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/web/web_console_message.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/web/web_frame_owner_properties.h"
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_navigation_control.h"
#include "third_party/blink/public/web/web_non_composited_widget_client.h"
#include "third_party/blink/public/web/web_plugin.h"
#include "third_party/blink/public/web/web_print_page_description.h"
#include "third_party/blink/public/web/web_print_params.h"
#include "third_party/blink/public/web/web_print_preset_options.h"
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/public/web/web_view.h"
#include "third_party/blink/public/web/web_view_client.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/accessibility/ax_tree_update.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/size_f.h"
WebPreferences;
namespace printing {
namespace {
#ifndef STATIC_ASSERT_ENUM
#define STATIC_ASSERT_ENUM(a, b) …
#endif
enum PrintPreviewHelperEvents { … };
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
bool g_is_preview_enabled = …;
#else
bool g_is_preview_enabled = false;
#endif
const char kPageLoadScriptFormat[] = …;
const char kPageSetupScriptFormat[] = …;
constexpr int kAllowedIpcDepthForPrint = …;
struct PageSizeMarginsWithOrientation { … };
enum class DebugEvent { … };
constexpr size_t kDebugEventMaxCount = …;
size_t g_debug_events_index = …;
base::FixedArray<DebugEvent>& GetDebugEvents() { … }
void RecordDebugEvent(DebugEvent event) { … }
void ExecuteScript(blink::WebLocalFrame* frame,
const char* script_format,
const base::Value& parameters) { … }
int GetDPI(const mojom::PrintParams& print_params) { … }
bool IsPrintScalingOptionCenterOnPaper(const mojom::PrintParams& params) { … }
bool ShouldIgnoreCssPageSize(bool ignore_css_margins,
const mojom::PrintParams& params) { … }
mojom::PageOrientation FromBlinkPageOrientation(
blink::PageOrientation orientation) { … }
blink::WebPrintPageDescription GetDefaultPageDescription(
const mojom::PrintParams& page_params) { … }
mojom::PrintParamsPtr GetCssPrintParams(blink::WebLocalFrame* frame,
uint32_t page_index,
const mojom::PrintParams& page_params) { … }
mojom::PageSizeMarginsPtr CalculatePageLayoutFromPrintParams(
const mojom::PrintParams& params) { … }
mojom::PageSizeMarginsPtr ConvertedPageSizeMargins(
const mojom::PageSizeMarginsPtr& orig_page_layout,
float old_unit,
float new_unit) { … }
blink::WebPrintParams ComputeWebKitPrintParamsInDesiredDpi(
const mojom::PrintParams& print_params,
bool source_is_pdf,
bool ignore_css_margins) { … }
bool IsPrintingPdfFrame(blink::WebLocalFrame* frame,
const blink::WebNode& node) { … }
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
bool IsPrintToPdfRequested(const base::Value::Dict& job_settings) { … }
void GetPageSizeAndOrientationInfo(blink::WebLocalFrame* frame,
uint32_t total_page_count,
bool* all_pages_have_custom_size,
bool* all_pages_have_custom_orientation) { … }
#endif
#if BUILDFLAG(ENABLE_PRINTING)
bool PDFShouldDisableScalingBasedOnPreset(
const blink::WebPrintPresetOptions& options,
const mojom::PrintParams& params,
bool ignore_page_size) { … }
bool PDFShouldDisableScaling(blink::WebLocalFrame* frame,
const blink::WebNode& node,
const mojom::PrintParams& params,
bool ignore_page_size) { … }
#endif
mojom::MarginType GetMarginsForPdf(blink::WebLocalFrame* frame,
const blink::WebNode& node,
const mojom::PrintParams& params) { … }
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
gfx::SizeF GetPdfPageSize(const gfx::SizeF& page_size, int dpi) { … }
ScalingType ScalingTypeFromJobSettings(const base::Value::Dict& job_settings) { … }
mojom::PrintScalingOption GetPrintScalingOption(
blink::WebLocalFrame* frame,
const blink::WebNode& node,
bool source_is_html,
const base::Value::Dict& job_settings,
const mojom::PrintParams& params) { … }
#endif
PageSizeMarginsWithOrientation ComputePageLayoutForCss(
blink::WebLocalFrame* frame,
uint32_t page_index,
const mojom::PrintParams& page_params,
bool ignore_css_margins) { … }
bool CopyMetafileDataToReadOnlySharedMem(
const MetafileSkia& metafile,
base::ReadOnlySharedMemoryRegion* region) { … }
bool CopyMetafileDataToDidPrintContentParams(
const MetafileSkia& metafile,
mojom::DidPrintContentParams* params) { … }
void PrintHeaderAndFooter(cc::PaintCanvas* canvas,
blink::WebLocalFrame& frame,
uint32_t page_index,
uint32_t total_pages,
const blink::WebLocalFrame& source_frame,
const mojom::PageSizeMargins& page_layout,
const mojom::PrintParams& params) { … }
void RenderPageContent(blink::WebLocalFrame* frame,
uint32_t page_index,
cc::PaintCanvas* canvas) { … }
class HeaderAndFooterContext { … };
}
FrameReference::FrameReference(blink::WebLocalFrame* frame) { … }
FrameReference::FrameReference() { … }
FrameReference::~FrameReference() = default;
void FrameReference::Reset(blink::WebLocalFrame* frame) { … }
blink::WebLocalFrame* FrameReference::GetFrame() { … }
blink::WebView* FrameReference::view() { … }
ClosuresForMojoResponse::ClosuresForMojoResponse() = default;
ClosuresForMojoResponse::~ClosuresForMojoResponse() { … }
void ClosuresForMojoResponse::SetScriptedPrintPreviewQuitClosure(
base::OnceClosure quit_print_preview) { … }
bool ClosuresForMojoResponse::HasScriptedPrintPreviewQuitClosure() const { … }
void ClosuresForMojoResponse::RunScriptedPrintPreviewQuitClosure() { … }
class PrepareFrameAndViewForPrint : public blink::WebViewClient,
public blink::WebNonCompositedWidgetClient,
public blink::WebLocalFrameClient { … };
PrepareFrameAndViewForPrint::PrepareFrameAndViewForPrint(
blink::WebLocalFrame* frame,
const blink::WebNode& node)
: … { … }
PrepareFrameAndViewForPrint::~PrepareFrameAndViewForPrint() { … }
void PrepareFrameAndViewForPrint::EnterPrintModeInternal(
const mojom::PrintParams& params,
bool ignore_css_margins) { … }
void PrepareFrameAndViewForPrint::BeginPrinting(
const WebPreferences& preferences,
const mojom::PrintParams& params,
bool ignore_css_margins,
base::OnceClosure on_ready) { … }
void PrepareFrameAndViewForPrint::EnterPrintMode(
const mojom::PrintParams& params,
bool ignore_css_margins) { … }
void PrepareFrameAndViewForPrint::CopySelection(
const mojom::PrintParams& params,
const WebPreferences& preferences) { … }
void PrepareFrameAndViewForPrint::DidStopLoading() { … }
void PrepareFrameAndViewForPrint::BindToFrame(
blink::WebNavigationControl* navigation_control) { … }
blink::WebLocalFrame* PrepareFrameAndViewForPrint::CreateChildFrame(
blink::mojom::TreeScopeType scope,
const blink::WebString& name,
const blink::WebString& fallback_name,
const blink::FramePolicy& frame_policy,
const blink::WebFrameOwnerProperties& frame_owner_properties,
blink::FrameOwnerElementType frame_owner_type,
blink::WebPolicyContainerBindParams policy_container_bind_params,
ukm::SourceId document_ukm_source_id,
FinishChildFrameCreationFn finish_creation) { … }
void PrepareFrameAndViewForPrint::FrameDetached() { … }
scoped_refptr<network::SharedURLLoaderFactory>
PrepareFrameAndViewForPrint::GetURLLoaderFactory() { … }
void PrepareFrameAndViewForPrint::CallOnReady() { … }
void PrepareFrameAndViewForPrint::FinishPrinting() { … }
bool PrintRenderFrameHelper::Delegate::IsScriptedPrintEnabled() { … }
bool PrintRenderFrameHelper::Delegate::ShouldGenerateTaggedPDF() { … }
PrintRenderFrameHelper::PrintRenderFrameHelper(
content::RenderFrame* render_frame,
std::unique_ptr<Delegate> delegate)
: … { … }
PrintRenderFrameHelper::~PrintRenderFrameHelper() { … }
const mojo::AssociatedRemote<mojom::PrintManagerHost>&
PrintRenderFrameHelper::GetPrintManagerHost() { … }
void PrintRenderFrameHelper::SetWebDocumentCollectionCallbackForTest(
PreviewDocumentTestCallback callback) { … }
bool PrintRenderFrameHelper::IsScriptInitiatedPrintAllowed(
blink::WebLocalFrame* frame,
bool user_initiated) { … }
void PrintRenderFrameHelper::DidStartNavigation(
const GURL& url,
std::optional<blink::WebNavigationType> navigation_type) { … }
void PrintRenderFrameHelper::DidFailProvisionalLoad() { … }
void PrintRenderFrameHelper::DidFinishLoad() { … }
void PrintRenderFrameHelper::DidFinishLoadForPrinting() { … }
void PrintRenderFrameHelper::ScriptedPrint(bool user_initiated) { … }
void PrintRenderFrameHelper::WillBeDestroyed() { … }
void PrintRenderFrameHelper::OnDestruct() { … }
void PrintRenderFrameHelper::BindPrintRenderFrameReceiver(
mojo::PendingAssociatedReceiver<mojom::PrintRenderFrame> receiver) { … }
void PrintRenderFrameHelper::PrintRequestedPages() { … }
void PrintRenderFrameHelper::PrintRequestedPagesInternal(
bool already_notified_frame) { … }
void PrintRenderFrameHelper::PrintWithParams(
mojom::PrintPagesParamsPtr settings,
PrintWithParamsCallback callback) { … }
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
void PrintRenderFrameHelper::PrintForSystemDialog() { … }
void PrintRenderFrameHelper::SetPrintPreviewUI(
mojo::PendingAssociatedRemote<mojom::PrintPreviewUI> preview) { … }
void PrintRenderFrameHelper::InitiatePrintPreview(
#if BUILDFLAG(IS_CHROMEOS_ASH)
mojo::PendingAssociatedRemote<mojom::PrintRenderer> print_renderer,
#endif
bool has_selection) { … }
void PrintRenderFrameHelper::PrintPreview(base::Value::Dict settings) { … }
void PrintRenderFrameHelper::OnPrintPreviewDialogClosed() { … }
#endif
void PrintRenderFrameHelper::PrintFrameContent(
mojom::PrintFrameContentParamsPtr params,
PrintFrameContentCallback callback) { … }
void PrintRenderFrameHelper::PrintingDone(bool success) { … }
void PrintRenderFrameHelper::ConnectToPdfRenderer() { … }
void PrintRenderFrameHelper::PrintNodeUnderContextMenu() { … }
void PrintRenderFrameHelper::UpdateFrameMarginsCssInfo(
const base::Value::Dict& settings) { … }
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
void PrintRenderFrameHelper::PrepareFrameForPreviewDocument() { … }
void PrintRenderFrameHelper::OnFramePreparedForPreviewDocument() { … }
PrintRenderFrameHelper::CreatePreviewDocumentResult
PrintRenderFrameHelper::CreatePreviewDocument() { … }
bool PrintRenderFrameHelper::RenderPreviewPage(
uint32_t page_index,
blink::WebLocalFrame* header_footer_frame) { … }
bool PrintRenderFrameHelper::FinalizePrintReadyDocument() { … }
#if BUILDFLAG(IS_CHROMEOS_ASH)
void PrintRenderFrameHelper::OnPreviewDocumentCreated(
int document_cookie,
base::TimeTicks begin_time,
base::ReadOnlySharedMemoryRegion preview_document_region) {
if (document_cookie != print_pages_params_->params->document_cookie) {
return;
}
bool success =
ProcessPreviewDocument(begin_time, std::move(preview_document_region));
DidFinishPrinting(success ? PrintingResult::kOk
: PrintingResult::kFailPreview);
}
#endif
bool PrintRenderFrameHelper::ProcessPreviewDocument(
base::TimeTicks begin_time,
base::ReadOnlySharedMemoryRegion preview_document_region) { … }
int PrintRenderFrameHelper::GetFitToPageScaleFactor(
const gfx::RectF& printable_area_in_points) { … }
#endif
void PrintRenderFrameHelper::PrintNode(const blink::WebNode& node) { … }
void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
const blink::WebNode& node,
PrintRequestType print_request_type) { … }
void PrintRenderFrameHelper::DidFinishPrinting(PrintingResult result) { … }
void PrintRenderFrameHelper::Reset() { … }
void PrintRenderFrameHelper::OnFramePreparedForPrintPages() { … }
void PrintRenderFrameHelper::PrintPages() { … }
bool PrintRenderFrameHelper::PrintPagesNative(
blink::WebLocalFrame* frame,
uint32_t page_count,
const std::vector<uint32_t>& printed_pages) { … }
void PrintRenderFrameHelper::FinishFramePrinting() { … }
void PrintRenderFrameHelper::IPCReceived() { … }
void PrintRenderFrameHelper::IPCProcessed() { … }
bool PrintRenderFrameHelper::InitPrintSettings(blink::WebLocalFrame* frame,
const blink::WebNode& node) { … }
uint32_t PrintRenderFrameHelper::CalculateNumberOfPages(
blink::WebLocalFrame* frame,
const blink::WebNode& node) { … }
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
mojom::OptionsFromDocumentParamsPtr
PrintRenderFrameHelper::SetOptionsFromPdfDocument() { … }
bool PrintRenderFrameHelper::UpdatePrintSettings(
blink::WebLocalFrame* frame,
const blink::WebNode& node,
base::Value::Dict passed_job_settings) { … }
#endif
mojom::PrintPagesParamsPtr PrintRenderFrameHelper::GetPrintSettingsFromUser(
blink::WebLocalFrame* frame,
const blink::WebNode& node,
uint32_t expected_pages_count,
PrintRequestType print_request_type) { … }
bool PrintRenderFrameHelper::RenderPagesForPrint(blink::WebLocalFrame* frame,
const blink::WebNode& node) { … }
void PrintRenderFrameHelper::PrintPageInternal(
const mojom::PrintParams& params,
uint32_t page_index,
uint32_t page_count,
blink::WebLocalFrame* frame,
blink::WebLocalFrame* header_footer_frame,
MetafileSkia* metafile) { … }
void PrintRenderFrameHelper::SetupOnStopLoadingTimeout() { … }
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
void PrintRenderFrameHelper::ShowScriptedPrintPreview() { … }
void PrintRenderFrameHelper::RequestPrintPreview(PrintPreviewRequestType type,
bool already_notified_frame) { … }
bool PrintRenderFrameHelper::CheckForCancel() { … }
bool PrintRenderFrameHelper::PreviewPageRendered(
uint32_t page_index,
std::unique_ptr<MetafileSkia> metafile) { … }
void PrintRenderFrameHelper::OnPreviewDisconnect() { … }
#endif
PrintRenderFrameHelper::PrintPreviewContext::PrintPreviewContext() = default;
PrintRenderFrameHelper::PrintPreviewContext::~PrintPreviewContext() = default;
void PrintRenderFrameHelper::PrintPreviewContext::InitWithFrame(
blink::WebLocalFrame* web_frame) { … }
void PrintRenderFrameHelper::PrintPreviewContext::InitWithNode(
const blink::WebNode& web_node) { … }
void PrintRenderFrameHelper::PrintPreviewContext::DispatchBeforePrintEvent(
base::WeakPtr<PrintRenderFrameHelper> weak_this) { … }
void PrintRenderFrameHelper::PrintPreviewContext::DispatchAfterPrintEvent() { … }
void PrintRenderFrameHelper::PrintPreviewContext::OnPrintPreview() { … }
bool PrintRenderFrameHelper::PrintPreviewContext::CreatePreviewDocument(
std::unique_ptr<PrepareFrameAndViewForPrint> prepared_frame,
const PageRanges& pages,
mojom::SkiaDocumentType doc_type,
int document_cookie,
bool require_document_metafile) { … }
void PrintRenderFrameHelper::PrintPreviewContext::RenderedPreviewPage(
const base::TimeDelta& page_time) { … }
void PrintRenderFrameHelper::PrintPreviewContext::RenderedPreviewDocument(
const base::TimeDelta document_time) { … }
void PrintRenderFrameHelper::PrintPreviewContext::AllPagesRendered() { … }
void PrintRenderFrameHelper::PrintPreviewContext::FinalizePrintReadyDocument() { … }
void PrintRenderFrameHelper::PrintPreviewContext::Finished() { … }
void PrintRenderFrameHelper::PrintPreviewContext::Failed(bool report_error) { … }
uint32_t PrintRenderFrameHelper::PrintPreviewContext::GetNextPageIndex() { … }
bool PrintRenderFrameHelper::PrintPreviewContext::IsRendering() const { … }
#if BUILDFLAG(IS_CHROMEOS_ASH)
bool PrintRenderFrameHelper::PrintPreviewContext::IsForArc() const {
DCHECK_NE(state_, State::kUninitialized);
return is_for_arc_;
}
#endif
bool PrintRenderFrameHelper::PrintPreviewContext::IsPlugin() const { … }
bool PrintRenderFrameHelper::PrintPreviewContext::IsModifiable() const { … }
bool PrintRenderFrameHelper::PrintPreviewContext::HasSelection() { … }
bool PrintRenderFrameHelper::PrintPreviewContext::
IsLastPageOfPrintReadyMetafile() const { … }
bool PrintRenderFrameHelper::PrintPreviewContext::IsFinalPageRendered() const { … }
#if BUILDFLAG(IS_CHROMEOS_ASH)
void PrintRenderFrameHelper::PrintPreviewContext::SetIsForArc(bool is_for_arc) {
is_for_arc_ = is_for_arc;
}
#endif
void PrintRenderFrameHelper::PrintPreviewContext::set_error(
enum PrintPreviewErrorBuckets error) { … }
blink::WebLocalFrame*
PrintRenderFrameHelper::PrintPreviewContext::source_frame() { … }
const blink::WebNode& PrintRenderFrameHelper::PrintPreviewContext::source_node()
const { … }
blink::WebLocalFrame*
PrintRenderFrameHelper::PrintPreviewContext::prepared_frame() { … }
const blink::WebNode&
PrintRenderFrameHelper::PrintPreviewContext::prepared_node() const { … }
uint32_t PrintRenderFrameHelper::PrintPreviewContext::total_page_count() const { … }
const std::vector<uint32_t>&
PrintRenderFrameHelper::PrintPreviewContext::pages_to_render() const { … }
size_t PrintRenderFrameHelper::PrintPreviewContext::pages_rendered_count()
const { … }
MetafileSkia* PrintRenderFrameHelper::PrintPreviewContext::metafile() { … }
ContentProxySet*
PrintRenderFrameHelper::PrintPreviewContext::typeface_content_info() { … }
void PrintRenderFrameHelper::PrintPreviewContext::ClearContext() { … }
void PrintRenderFrameHelper::PrintPreviewContext::CalculatePluginAttributes() { … }
void PrintRenderFrameHelper::SetPrintPagesParams(
const mojom::PrintPagesParams& settings) { … }
void PrintRenderFrameHelper::QuitScriptedPrintPreviewRunLoop() { … }
PrintRenderFrameHelper::ScopedIPC::ScopedIPC(
base::WeakPtr<PrintRenderFrameHelper> weak_this)
: … { … }
PrintRenderFrameHelper::ScopedIPC::~ScopedIPC() { … }
PrintRenderFrameHelper::ScriptingThrottler::ScriptingThrottler() = default;
bool PrintRenderFrameHelper::ScriptingThrottler::IsAllowed(
blink::WebLocalFrame* frame) { … }
void PrintRenderFrameHelper::ScriptingThrottler::Reset() { … }
}