0

Test that titles are embedded in generated PDFs

Bug: b/40864319
Change-Id: I40f1b52c3f3711871f01a3399e70cf1b47a28395
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5245754
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Ben Wagner <bungeman@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1265438}
This commit is contained in:
Ben Wagner
2024-02-26 21:15:47 +00:00
committed by Chromium LUCI CQ
parent 7c11ddf426
commit e22189bd85
7 changed files with 112 additions and 0 deletions

@ -432,6 +432,29 @@ IN_PROC_BROWSER_TEST_P(PrintToPdfProtocolTest, PrintToPdfAsStream) {
EXPECT_EQ(GetPixelRGB(bitmap_width() / 2, bitmap_height() / 2), 0xff0000u);
}
IN_PROC_BROWSER_TEST_P(PrintToPdfProtocolTest, Title) {
NavigateToURLBlockUntilNavigationsComplete("/print_to_pdf/basic.html");
Attach();
base::Value::Dict params;
params.Set("printBackground", true);
params.Set("paperWidth", kPaperWidth);
params.Set("paperHeight", kPaperHeight);
params.Set("marginTop", 0);
params.Set("marginLeft", 0);
params.Set("marginBottom", 0);
params.Set("marginRight", 0);
params.Set("transferMode", "ReturnAsStream");
PrintToPdfAsStream(std::move(params));
std::optional<chrome_pdf::DocumentMetadata> metadata =
chrome_pdf::GetPDFDocMetadata(pdf_span_);
ASSERT_TRUE(metadata);
EXPECT_EQ(metadata->title, "PrintToPdf Basic Test");
}
IN_PROC_BROWSER_TEST_P(PrintToPdfProtocolTest, PrintToPdfOOPIF) {
NavigateToURLBlockUntilNavigationsComplete("/print_to_pdf/oopif.html");

@ -38,6 +38,7 @@ source_set("loader") {
"document_loader_impl.h",
"result_codes.h",
"url_loader.h",
"url_loader_wrapper.h",
"url_loader_wrapper_impl.h",
]

@ -98,6 +98,13 @@ bool GetPDFDocInfo(base::span<const uint8_t> pdf_buffer,
return engine_exports->GetPDFDocInfo(pdf_buffer, page_count, max_page_width);
}
std::optional<DocumentMetadata> GetPDFDocMetadata(
base::span<const uint8_t> pdf_buffer) {
ScopedSdkInitializer scoped_sdk_initializer(/*enable_v8=*/false);
PDFEngineExports* engine_exports = PDFEngineExports::Get();
return engine_exports->GetPDFDocMetadata(pdf_buffer);
}
std::optional<bool> IsPDFDocTagged(base::span<const uint8_t> pdf_buffer) {
ScopedSdkInitializer scoped_sdk_initializer(/*enable_v8=*/true);
PDFEngineExports* engine_exports = PDFEngineExports::Get();

@ -11,6 +11,7 @@
#include "base/containers/span.h"
#include "base/values.h"
#include "build/build_config.h"
#include "pdf/document_metadata.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "pdf/flatten_pdf_result.h"
@ -105,6 +106,11 @@ bool GetPDFDocInfo(base::span<const uint8_t> pdf_buffer,
int* page_count,
float* max_page_width);
// Gets the PDF document metadata (see section 14.3.3 "Document Information
// Dictionary" of the ISO 32000-1:2008 spec).
std::optional<DocumentMetadata> GetPDFDocMetadata(
base::span<const uint8_t> pdf_buffer);
// Whether the PDF is Tagged (see ISO 32000-1:2008 14.8 "Tagged PDF").
// Returns true if it's a tagged (accessible) PDF, false if it's a valid
// PDF but untagged, and nullopt if the PDF can't be parsed.

@ -556,6 +556,11 @@ class PDFEngineExports {
int* page_count,
float* max_page_width) = 0;
// Gets the PDF document metadata (see section 14.3.3 "Document Information
// Dictionary" of the ISO 32000-1:2008 spec).
virtual std::optional<DocumentMetadata> GetPDFDocMetadata(
base::span<const uint8_t> pdf_buffer) = 0;
// Whether the PDF is Tagged (see ISO 32000-1:2008 14.8 "Tagged PDF").
// Returns true if it's a tagged (accessible) PDF, false if it's a valid
// PDF but untagged, and nullopt if the PDF can't be parsed.

@ -12,13 +12,19 @@
#include "base/no_destructor.h"
#include "base/numerics/checked_math.h"
#include "build/build_config.h"
#include "pdf/document_metadata.h"
#include "pdf/loader/document_loader.h"
#include "pdf/loader/url_loader_wrapper.h"
#include "pdf/pdfium/pdfium_api_string_buffer_adapter.h"
#include "pdf/pdfium/pdfium_document.h"
#include "pdf/pdfium/pdfium_document_metadata.h"
#include "pdf/pdfium/pdfium_mem_buffer_file_write.h"
#include "pdf/pdfium/pdfium_print.h"
#include "pdf/pdfium/pdfium_unsupported_features.h"
#include "printing/nup_parameters.h"
#include "printing/units.h"
#include "third_party/pdfium/public/cpp/fpdf_scopers.h"
#include "third_party/pdfium/public/fpdf_attachment.h"
#include "third_party/pdfium/public/fpdf_catalog.h"
#include "third_party/pdfium/public/fpdf_doc.h"
#include "third_party/pdfium/public/fpdf_ppo.h"
@ -36,6 +42,41 @@ namespace chrome_pdf {
namespace {
class DataDocumentLoader : public DocumentLoader {
public:
explicit DataDocumentLoader(base::span<const uint8_t> pdf_data)
: pdf_data_(pdf_data) {}
~DataDocumentLoader() override = default;
// DocumentLoader:
bool Init(std::unique_ptr<URLLoaderWrapper> loader,
const std::string& url) override {
NOTREACHED() << "PDFiumDocument doesn't call this";
return false;
}
bool GetBlock(uint32_t position, uint32_t size, void* buf) const override {
if (!IsDataAvailable(position, size)) {
return false;
}
memcpy(buf, pdf_data_.data() + position, size);
return true;
}
bool IsDataAvailable(uint32_t position, uint32_t size) const override {
CHECK_LE(position, GetDocumentSize());
CHECK_LE(size, GetDocumentSize() - position);
return true;
}
void RequestData(uint32_t position, uint32_t size) override {}
bool IsDocumentComplete() const override { return true; }
uint32_t GetDocumentSize() const override { return pdf_data_.size(); }
uint32_t BytesReceived() const override { return pdf_data_.size(); }
void ClearPendingRequests() override {}
private:
const base::span<const uint8_t> pdf_data_;
};
int CalculatePosition(FPDF_PAGE page,
const PDFiumEngineExports::RenderingSettings& settings,
gfx::Rect* dest) {
@ -418,6 +459,32 @@ bool PDFiumEngineExports::GetPDFDocInfo(base::span<const uint8_t> pdf_buffer,
return true;
}
std::optional<DocumentMetadata> PDFiumEngineExports::GetPDFDocMetadata(
base::span<const uint8_t> pdf_buffer) {
ScopedUnsupportedFeature scoped_unsupported_feature(
ScopedUnsupportedFeature::kNoEngine);
DataDocumentLoader loader(pdf_buffer);
PDFiumDocument pdfium_doc(&loader);
pdfium_doc.file_access().m_FileLen = pdf_buffer.size();
pdfium_doc.CreateFPDFAvailability();
FPDF_AVAIL pdf_avail = pdfium_doc.fpdf_availability();
if (!pdf_avail) {
return std::nullopt;
}
pdfium_doc.LoadDocument("");
if (!pdfium_doc.doc()) {
return std::nullopt;
}
return GetPDFiumDocumentMetadata(
pdfium_doc.doc(), pdf_buffer.size(), FPDF_GetPageCount(pdfium_doc.doc()),
FPDFAvail_IsLinearized(pdf_avail) == PDF_LINEARIZED,
FPDFDoc_GetAttachmentCount(pdfium_doc.doc()) > 0);
}
std::optional<bool> PDFiumEngineExports::IsPDFDocTagged(
base::span<const uint8_t> pdf_buffer) {
ScopedUnsupportedFeature scoped_unsupported_feature(

@ -9,6 +9,7 @@
#include <stdint.h>
#include "build/build_config.h"
#include "pdf/document_metadata.h"
#include "pdf/pdf_engine.h"
namespace chrome_pdf {
@ -49,6 +50,8 @@ class PDFiumEngineExports : public PDFEngineExports {
bool GetPDFDocInfo(base::span<const uint8_t> pdf_buffer,
int* page_count,
float* max_page_width) override;
std::optional<DocumentMetadata> GetPDFDocMetadata(
base::span<const uint8_t> pdf_buffer) override;
std::optional<bool> IsPDFDocTagged(
base::span<const uint8_t> pdf_buffer) override;
base::Value GetPDFStructTreeForPage(base::span<const uint8_t> pdf_buffer,