Update PDF plugin to provide save data in blocks.
To avoid running out of memory, get data from the plugin and save it in maximum 16MB blocks. The process is done as follows. 1. Viewer asks for the suggested file name from Plugin. 2. Viewer shows the file picker user interface to the user and opens the selected file. 3. Viewer asks Plugin for file content. 4. Plugin returns the file content, capped at 16MB limit. It also sends the total file size. 5. Viewer writes the data to the file. 6. If the returned data is not all of the file, Viewer asks for the next block of data from Plugin, passing the offset to the beginning of the next block, and repeats until all of data is received and saved. The new approach uses already downloaded PDF data to save original PDFs and in contrast to the existing approach, does not redownload the PDF. Also by removing the memory limitation, the limit on the maximum size is increased from 10MB to 2GB. This CL only updates the plugin side, and the UI update is done in http://crrev.com/c/6362354 Bug: 394111292 Change-Id: I82f16c524a3bdac037f8157242a8e65fa9ccfb83 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6252966 Commit-Queue: Ramin Halavati <rhalavati@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org> Cr-Commit-Position: refs/heads/main@{#1437328}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
8edff7fcad
commit
b3bff9f439
@ -165,6 +165,9 @@ constexpr int kCompletePDFIndex = -1;
|
||||
// A different negative value to differentiate itself from `kCompletePDFIndex`.
|
||||
constexpr int kInvalidPDFIndex = -2;
|
||||
|
||||
// Get save data from plugin in maximum 16 MB blocks.
|
||||
constexpr uint32_t kMaxSaveBufferSize = 16 * 1000 * 1000;
|
||||
|
||||
// Enumeration of pinch states.
|
||||
// This should match PinchPhase enum in
|
||||
// chrome/browser/resources/pdf/viewport.ts.
|
||||
@ -267,6 +270,17 @@ bool IsSaveDataSizeValid(size_t size) {
|
||||
return size > 0 && size <= PdfViewWebPlugin::kMaximumSavedFileSize;
|
||||
}
|
||||
|
||||
base::Value::Dict CreateSaveDataBlockMessage(
|
||||
const std::string& token,
|
||||
PdfViewWebPlugin::SaveDataBlock data) {
|
||||
base::Value::Dict message;
|
||||
message.Set("type", "saveDataBlock");
|
||||
message.Set("token", token);
|
||||
message.Set("dataToSave", std::move(data.block));
|
||||
message.Set("totalFileSize", base::checked_cast<int>(data.total_file_size));
|
||||
return message;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#if BUILDFLAG(ENABLE_PDF_INK2)
|
||||
@ -407,6 +421,13 @@ class PdfViewWebPlugin::PdfInkModuleClientImpl : public PdfInkModuleClient {
|
||||
};
|
||||
#endif // BUILDFLAG(ENABLE_PDF_INK2)
|
||||
|
||||
PdfViewWebPlugin::SaveDataBlock::SaveDataBlock() = default;
|
||||
PdfViewWebPlugin::SaveDataBlock::SaveDataBlock(
|
||||
PdfViewWebPlugin::SaveDataBlock&& other) noexcept = default;
|
||||
PdfViewWebPlugin::SaveDataBlock& PdfViewWebPlugin::SaveDataBlock::operator=(
|
||||
PdfViewWebPlugin::SaveDataBlock&&) noexcept = default;
|
||||
PdfViewWebPlugin::SaveDataBlock::~SaveDataBlock() = default;
|
||||
|
||||
std::unique_ptr<PDFiumEngine> PdfViewWebPlugin::Client::CreateEngine(
|
||||
PDFiumEngineClient* client,
|
||||
PDFiumFormFiller::ScriptOption script_option) {
|
||||
@ -423,7 +444,8 @@ PdfViewWebPlugin::PdfViewWebPlugin(
|
||||
ink_module_client_(MaybeCreatePdfInkModuleClient(*this)),
|
||||
ink_module_(MaybeCreatePdfInkModule(ink_module_client_.get())),
|
||||
#endif
|
||||
initial_params_(std::move(params)) {
|
||||
initial_params_(std::move(params)),
|
||||
max_save_buffer_size_(kMaxSaveBufferSize) {
|
||||
DCHECK(pdf_host_);
|
||||
pdf_host_->SetListener(listener_receiver_.BindNewPipeAndPassRemote());
|
||||
}
|
||||
@ -1625,12 +1647,18 @@ void PdfViewWebPlugin::OnMessage(const base::Value::Dict& message) {
|
||||
&PdfViewWebPlugin::HandleGetPageBoundingBoxMessage},
|
||||
{"getPasswordComplete",
|
||||
&PdfViewWebPlugin::HandleGetPasswordCompleteMessage},
|
||||
{"getSaveDataBlock",
|
||||
&PdfViewWebPlugin::HandleGetSaveDataBlockMessage},
|
||||
{"getSelectedText", &PdfViewWebPlugin::HandleGetSelectedTextMessage},
|
||||
{"getSuggestedFileName",
|
||||
&PdfViewWebPlugin::HandleGetSuggestedFileName},
|
||||
{"getThumbnail", &PdfViewWebPlugin::HandleGetThumbnailMessage},
|
||||
{"highlightTextFragments",
|
||||
&PdfViewWebPlugin::HandleHighlightTextFragmentsMessage},
|
||||
{"print", &PdfViewWebPlugin::HandlePrintMessage},
|
||||
{"loadPreviewPage", &PdfViewWebPlugin::HandleLoadPreviewPageMessage},
|
||||
{"releaseSaveInBlockBuffers",
|
||||
&PdfViewWebPlugin::HandleReleaseSaveInBlockBuffers},
|
||||
{"resetPrintPreviewMode",
|
||||
&PdfViewWebPlugin::HandleResetPrintPreviewModeMessage},
|
||||
{"rotateClockwise", &PdfViewWebPlugin::HandleRotateClockwiseMessage},
|
||||
@ -1726,6 +1754,26 @@ void PdfViewWebPlugin::HandleGetSelectedTextMessage(
|
||||
client_->PostMessage(std::move(reply));
|
||||
}
|
||||
|
||||
void PdfViewWebPlugin::HandleGetSaveDataBlockMessage(
|
||||
const base::Value::Dict& message) {
|
||||
const std::string& token = *message.FindString("token");
|
||||
SaveRequestType request_type =
|
||||
static_cast<SaveRequestType>(message.FindInt("saveRequestType").value());
|
||||
uint32_t offset = static_cast<uint32_t>(message.FindInt("offset").value());
|
||||
uint32_t block_size =
|
||||
static_cast<uint32_t>(message.FindInt("blockSize").value());
|
||||
|
||||
client_->PostMessage(CreateSaveDataBlockMessage(
|
||||
token, SaveBlockToBuffer(request_type, offset, block_size)));
|
||||
}
|
||||
|
||||
void PdfViewWebPlugin::HandleGetSuggestedFileName(
|
||||
const base::Value::Dict& message) {
|
||||
base::Value::Dict reply = PrepareReplyMessage(message);
|
||||
reply.Set("fileName", GetFileNameForSaveFromUrl(url_));
|
||||
client_->PostMessage(std::move(reply));
|
||||
}
|
||||
|
||||
void PdfViewWebPlugin::HandleGetThumbnailMessage(
|
||||
const base::Value::Dict& message) {
|
||||
const int page_index = message.FindInt("pageIndex").value();
|
||||
@ -2024,7 +2072,7 @@ void PdfViewWebPlugin::SaveToBuffer(SaveRequestType request_type,
|
||||
uint32_t length = engine_->GetLoadedByteSize();
|
||||
if (IsSaveDataSizeValid(length)) {
|
||||
base::Value::BlobStorage data(length);
|
||||
if (engine_->ReadLoadedBytes(data)) {
|
||||
if (engine_->ReadLoadedBytes(0, data)) {
|
||||
data_to_save = base::Value(std::move(data));
|
||||
}
|
||||
}
|
||||
@ -2037,6 +2085,73 @@ void PdfViewWebPlugin::SaveToBuffer(SaveRequestType request_type,
|
||||
client_->PostMessage(std::move(message));
|
||||
}
|
||||
|
||||
uint32_t PdfViewWebPlugin::VerifyParamsAndGetSaveBlockSize(
|
||||
uint32_t total_file_size,
|
||||
uint32_t offset,
|
||||
uint32_t block_size) {
|
||||
if (block_size) {
|
||||
// Block size should be less than max threshold.
|
||||
CHECK_LE(block_size, max_save_buffer_size_);
|
||||
} else {
|
||||
// `block_size` is allowed to be 0 only when offset is 0 since the caller
|
||||
// may not know the total file size at that point.
|
||||
CHECK(!offset);
|
||||
}
|
||||
CHECK_LT(offset, total_file_size);
|
||||
if (block_size) {
|
||||
CHECK_LE(block_size, total_file_size - offset);
|
||||
} else {
|
||||
block_size = std::min(max_save_buffer_size_, total_file_size);
|
||||
}
|
||||
return block_size;
|
||||
}
|
||||
|
||||
PdfViewWebPlugin::SaveDataBlock PdfViewWebPlugin::SaveBlockToBuffer(
|
||||
SaveRequestType request_type,
|
||||
uint32_t offset,
|
||||
uint32_t block_size) {
|
||||
engine_->KillFormFocus();
|
||||
|
||||
SaveDataBlock result;
|
||||
if (request_type == SaveRequestType::kOriginal) {
|
||||
// This function does not handle files larger than INT_MAX.
|
||||
if (engine_->GetLoadedByteSize() <= static_cast<uint32_t>(INT_MAX)) {
|
||||
result.total_file_size = engine_->GetLoadedByteSize();
|
||||
block_size = VerifyParamsAndGetSaveBlockSize(result.total_file_size,
|
||||
offset, block_size);
|
||||
result.block.resize(block_size);
|
||||
if (!engine_->ReadLoadedBytes(offset, result.block)) {
|
||||
result.block.resize(0);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (offset == 0) {
|
||||
save_data_buffer_ = engine_->GetSaveData();
|
||||
// This function does not handle files larger than INT_MAX.
|
||||
if (save_data_buffer_.size() > static_cast<uint32_t>(INT_MAX)) {
|
||||
ReleaseSaveBuffer();
|
||||
}
|
||||
} else {
|
||||
CHECK(save_data_buffer_.size());
|
||||
}
|
||||
if (save_data_buffer_.size()) {
|
||||
result.total_file_size = static_cast<uint32_t>(save_data_buffer_.size());
|
||||
block_size = VerifyParamsAndGetSaveBlockSize(result.total_file_size, offset,
|
||||
block_size);
|
||||
result.block.resize(block_size);
|
||||
base::span(result.block)
|
||||
.copy_from(base::span(save_data_buffer_).subspan(offset, block_size));
|
||||
// Drop the buffer if everything is returned.
|
||||
if (offset + block_size == result.total_file_size) {
|
||||
ReleaseSaveBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PdfViewWebPlugin::SaveToFile(const std::string& token) {
|
||||
engine_->KillFormFocus();
|
||||
|
||||
@ -2048,6 +2163,11 @@ void PdfViewWebPlugin::SaveToFile(const std::string& token) {
|
||||
pdf_host_->SaveUrlAs(GURL(url_), network::mojom::ReferrerPolicy::kDefault);
|
||||
}
|
||||
|
||||
void PdfViewWebPlugin::ReleaseSaveBuffer() {
|
||||
std::vector<uint8_t> empty;
|
||||
save_data_buffer_.swap(empty);
|
||||
}
|
||||
|
||||
void PdfViewWebPlugin::SetPluginCanSave(bool can_save) {
|
||||
if (plugin_can_save_ == can_save) {
|
||||
return;
|
||||
@ -2626,6 +2746,11 @@ void PdfViewWebPlugin::SendLoadingProgress(double percentage) {
|
||||
client_->PostMessage(std::move(message));
|
||||
}
|
||||
|
||||
void PdfViewWebPlugin::HandleReleaseSaveInBlockBuffers(
|
||||
const base::Value::Dict& /*message*/) {
|
||||
ReleaseSaveBuffer();
|
||||
}
|
||||
|
||||
void PdfViewWebPlugin::HandleResetPrintPreviewModeMessage(
|
||||
const base::Value::Dict& message) {
|
||||
const std::string& url = *message.FindString("url");
|
||||
|
@ -258,6 +258,16 @@ class PdfViewWebPlugin final : public PDFiumEngineClient,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct SaveDataBlock {
|
||||
SaveDataBlock();
|
||||
SaveDataBlock(SaveDataBlock&& other) noexcept;
|
||||
SaveDataBlock& operator=(SaveDataBlock&&) noexcept;
|
||||
~SaveDataBlock();
|
||||
|
||||
std::vector<uint8_t> block;
|
||||
uint32_t total_file_size = 0;
|
||||
};
|
||||
|
||||
PdfViewWebPlugin(std::unique_ptr<Client> client,
|
||||
mojo::AssociatedRemote<pdf::mojom::PdfHost> pdf_host,
|
||||
blink::WebPluginParams params);
|
||||
@ -488,6 +498,14 @@ class PdfViewWebPlugin final : public PDFiumEngineClient,
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_PDF_INK2)
|
||||
|
||||
void SetMaxSaveBufferSizeForTesting(uint32_t max_save_buffer_size) {
|
||||
max_save_buffer_size_ = max_save_buffer_size;
|
||||
}
|
||||
|
||||
bool IsSaveDataBufferEmptyForTesting() const {
|
||||
return save_data_buffer_.empty();
|
||||
}
|
||||
|
||||
private:
|
||||
// Callback that runs after `LoadUrl()`. The `loader` is the loader used to
|
||||
// load the URL, and `result` is the result code for the load.
|
||||
@ -552,10 +570,13 @@ class PdfViewWebPlugin final : public PDFiumEngineClient,
|
||||
void HandleGetNamedDestinationMessage(const base::Value::Dict& message);
|
||||
void HandleGetPageBoundingBoxMessage(const base::Value::Dict& message);
|
||||
void HandleGetPasswordCompleteMessage(const base::Value::Dict& message);
|
||||
void HandleGetSaveDataBlockMessage(const base::Value::Dict& message);
|
||||
void HandleGetSelectedTextMessage(const base::Value::Dict& message);
|
||||
void HandleGetSuggestedFileName(const base::Value::Dict& message);
|
||||
void HandleGetThumbnailMessage(const base::Value::Dict& message);
|
||||
void HandleHighlightTextFragmentsMessage(const base::Value::Dict& message);
|
||||
void HandlePrintMessage(const base::Value::Dict& /*message*/);
|
||||
void HandleReleaseSaveInBlockBuffers(const base::Value::Dict& /*message*/);
|
||||
void HandleRotateClockwiseMessage(const base::Value::Dict& /*message*/);
|
||||
void HandleRotateCounterclockwiseMessage(
|
||||
const base::Value::Dict& /*message*/);
|
||||
@ -571,6 +592,26 @@ class PdfViewWebPlugin final : public PDFiumEngineClient,
|
||||
void SaveToBuffer(SaveRequestType request_type, const std::string& token);
|
||||
void SaveToFile(const std::string& token);
|
||||
|
||||
// Returns `block_size` bytes to save the PDF with `request_type`, starting
|
||||
// from location `offset`. Since the caller may not know the exact file size,
|
||||
// the first request (when `offset` is 0) can be called with `block_size` 0
|
||||
// and in that case, the entire file data, capped at 16MB limit is returned.
|
||||
// The function also returns the total file size.
|
||||
// Note that it only handles files less than INT_MAX size, and if the file is
|
||||
// larger than that, it returns 0 as file size and no data.
|
||||
SaveDataBlock SaveBlockToBuffer(SaveRequestType request_type,
|
||||
uint32_t offset,
|
||||
uint32_t block_size);
|
||||
|
||||
// For a call to `SaveBlockToBuffer`, ensures `offset` and `block_size` have
|
||||
// expected values and returns the effective `block_size`.
|
||||
uint32_t VerifyParamsAndGetSaveBlockSize(uint32_t total_file_size,
|
||||
uint32_t offset,
|
||||
uint32_t block_size);
|
||||
|
||||
// Release buffered data for saving.
|
||||
void ReleaseSaveBuffer();
|
||||
|
||||
// Sets whether the plugin can and should handle the save by using `pdf_host_`
|
||||
// to notify the browser. Prevents duplicate notifications to the browser if
|
||||
// the state has not changed.
|
||||
@ -946,6 +987,16 @@ class PdfViewWebPlugin final : public PDFiumEngineClient,
|
||||
// Queue of available preview pages to load next.
|
||||
base::queue<PreviewPageInfo> preview_pages_info_;
|
||||
|
||||
// Buffer for saving data by Web UI.
|
||||
// `SaveBlockToBuffer` allocates this variable when WebUI requests saving the
|
||||
// PDF by getting the content in blocks, and the content needs to be buffered
|
||||
// during the save process. It is released when saving is finished or
|
||||
// canceled.
|
||||
std::vector<uint8_t> save_data_buffer_;
|
||||
|
||||
// Maximum size of save data in each block.
|
||||
uint32_t max_save_buffer_size_;
|
||||
|
||||
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
bool show_searchify_in_progress_ = false;
|
||||
|
||||
|
@ -2293,6 +2293,135 @@ TEST_F(PdfViewWebPluginSaveTest, EditedInEditMode) {
|
||||
})"));
|
||||
}
|
||||
|
||||
class PdfViewWebPluginSaveInBlocksTest : public PdfViewWebPluginTest {
|
||||
protected:
|
||||
base::Value::Dict CreateRequest(
|
||||
PdfViewWebPlugin::SaveRequestType request_type,
|
||||
uint32_t offset,
|
||||
uint32_t block_size,
|
||||
std::string token) {
|
||||
base::Value::Dict dict;
|
||||
dict.Set("type", "getSaveDataBlock");
|
||||
dict.Set("saveRequestType", static_cast<int>(request_type));
|
||||
dict.Set("offset", static_cast<int>(offset));
|
||||
dict.Set("blockSize", static_cast<int>(block_size));
|
||||
dict.Set("token", token);
|
||||
return dict;
|
||||
}
|
||||
|
||||
void ExpectResponse(base::span<const uint8_t> data,
|
||||
uint32_t offset,
|
||||
uint32_t block_size,
|
||||
std::string token) {
|
||||
base::Value value(base::Value::Type::DICT);
|
||||
value.GetDict().Set("type", "saveDataBlock");
|
||||
value.GetDict().Set("token", token);
|
||||
value.GetDict().Set("dataToSave",
|
||||
base::Value(data.subspan(offset, block_size)));
|
||||
value.GetDict().Set("totalFileSize",
|
||||
base::Value(static_cast<int>(data.size())));
|
||||
EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(value)));
|
||||
}
|
||||
|
||||
void SetUpClient() override {
|
||||
// Ignore non - "saveDataBlock" `PdfViewWebPlugin::Client::PostMessage()`
|
||||
// calls.
|
||||
EXPECT_CALL(*client_ptr_, PostMessage)
|
||||
.WillRepeatedly([](const base::Value::Dict& message) {
|
||||
EXPECT_NE("saveDataBlock", *message.FindString("type"));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(PdfViewWebPluginSaveInBlocksTest, GetSuggestedFileName) {
|
||||
EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
|
||||
"type": "getSuggestedFileNameReply",
|
||||
"messageId": "foo",
|
||||
"fileName": "example.pdf",
|
||||
})")));
|
||||
|
||||
plugin_->OnMessage(ParseMessage(R"({
|
||||
"type": "getSuggestedFileName",
|
||||
"messageId": "foo",
|
||||
})"));
|
||||
|
||||
pdf_receiver_.FlushForTesting();
|
||||
}
|
||||
|
||||
TEST_F(PdfViewWebPluginSaveInBlocksTest, OriginalInOneBlock) {
|
||||
base::span data(TestPDFiumEngine::kLoadedData);
|
||||
ExpectResponse(data, 0, data.size(), "token-1");
|
||||
plugin_->OnMessage(CreateRequest(PdfViewWebPlugin::SaveRequestType::kOriginal,
|
||||
0, 0, "token-1"));
|
||||
EXPECT_TRUE(plugin_->IsSaveDataBufferEmptyForTesting());
|
||||
pdf_receiver_.FlushForTesting();
|
||||
}
|
||||
|
||||
TEST_F(PdfViewWebPluginSaveInBlocksTest, OriginalInMulipleBlocks) {
|
||||
plugin_->SetMaxSaveBufferSizeForTesting(3);
|
||||
|
||||
base::span data(TestPDFiumEngine::kLoadedData);
|
||||
ASSERT_GT(data.size(), 3u);
|
||||
ExpectResponse(data, 0, 3, "token-1");
|
||||
ExpectResponse(data, 3, data.size() - 3, "token-2");
|
||||
plugin_->OnMessage(CreateRequest(PdfViewWebPlugin::SaveRequestType::kOriginal,
|
||||
0, 0, "token-1"));
|
||||
EXPECT_TRUE(plugin_->IsSaveDataBufferEmptyForTesting());
|
||||
plugin_->OnMessage(CreateRequest(PdfViewWebPlugin::SaveRequestType::kOriginal,
|
||||
3, data.size() - 3, "token-2"));
|
||||
EXPECT_TRUE(plugin_->IsSaveDataBufferEmptyForTesting());
|
||||
pdf_receiver_.FlushForTesting();
|
||||
}
|
||||
|
||||
TEST_F(PdfViewWebPluginSaveInBlocksTest, EditedInOneBlock) {
|
||||
plugin_->EnteredEditMode();
|
||||
|
||||
base::span data(TestPDFiumEngine::kSaveData);
|
||||
ExpectResponse(data, 0, data.size(), "token-1");
|
||||
plugin_->OnMessage(CreateRequest(PdfViewWebPlugin::SaveRequestType::kEdited,
|
||||
0, 0, "token-1"));
|
||||
EXPECT_TRUE(plugin_->IsSaveDataBufferEmptyForTesting());
|
||||
pdf_receiver_.FlushForTesting();
|
||||
}
|
||||
|
||||
TEST_F(PdfViewWebPluginSaveInBlocksTest, EditedInMultipleBlock) {
|
||||
plugin_->EnteredEditMode();
|
||||
plugin_->SetMaxSaveBufferSizeForTesting(2);
|
||||
|
||||
base::span data(TestPDFiumEngine::kSaveData);
|
||||
ASSERT_GT(data.size(), 2u);
|
||||
ExpectResponse(data, 0, 2, "token-1");
|
||||
ExpectResponse(data, 2, data.size() - 2, "token-2");
|
||||
|
||||
plugin_->OnMessage(CreateRequest(PdfViewWebPlugin::SaveRequestType::kEdited,
|
||||
0, 0, "token-1"));
|
||||
EXPECT_FALSE(plugin_->IsSaveDataBufferEmptyForTesting());
|
||||
plugin_->OnMessage(CreateRequest(PdfViewWebPlugin::SaveRequestType::kEdited,
|
||||
2, data.size() - 2, "token-2"));
|
||||
EXPECT_TRUE(plugin_->IsSaveDataBufferEmptyForTesting());
|
||||
pdf_receiver_.FlushForTesting();
|
||||
}
|
||||
|
||||
TEST_F(PdfViewWebPluginSaveInBlocksTest, ReleaseSaveBuffer) {
|
||||
plugin_->EnteredEditMode();
|
||||
plugin_->SetMaxSaveBufferSizeForTesting(2);
|
||||
|
||||
base::span data(TestPDFiumEngine::kSaveData);
|
||||
ASSERT_GT(data.size(), 2u);
|
||||
ExpectResponse(data, 0, 2, "token-1");
|
||||
|
||||
plugin_->OnMessage(CreateRequest(PdfViewWebPlugin::SaveRequestType::kEdited,
|
||||
0, 0, "token-1"));
|
||||
EXPECT_FALSE(plugin_->IsSaveDataBufferEmptyForTesting());
|
||||
|
||||
base::Value::Dict message;
|
||||
message.Set("type", "releaseSaveInBlockBuffers");
|
||||
plugin_->OnMessage(message);
|
||||
EXPECT_TRUE(plugin_->IsSaveDataBufferEmptyForTesting());
|
||||
|
||||
pdf_receiver_.FlushForTesting();
|
||||
}
|
||||
|
||||
class PdfViewWebPluginSubmitFormTest
|
||||
: public PdfViewWebPluginWithoutInitializeTest {
|
||||
protected:
|
||||
|
@ -1258,8 +1258,9 @@ uint32_t PDFiumEngine::GetLoadedByteSize() {
|
||||
return doc_loader_->GetDocumentSize();
|
||||
}
|
||||
|
||||
bool PDFiumEngine::ReadLoadedBytes(base::span<uint8_t> buffer) {
|
||||
return doc_loader_->GetBlock(0, buffer.size(), buffer.data());
|
||||
bool PDFiumEngine::ReadLoadedBytes(uint32_t offset,
|
||||
base::span<uint8_t> buffer) {
|
||||
return doc_loader_->GetBlock(offset, buffer.size(), buffer.data());
|
||||
}
|
||||
|
||||
void PDFiumEngine::SetFormSelectedText(FPDF_FORMHANDLE form_handle,
|
||||
|
@ -377,12 +377,12 @@ class PDFiumEngine : public DocumentLoader::Client, public IFSDK_PAUSE {
|
||||
|
||||
virtual uint32_t GetLoadedByteSize();
|
||||
|
||||
// Copies data from `doc_loader_` into `buffer`.
|
||||
// Copies data from `doc_loader_` into `buffer` starting from `offset`.
|
||||
// - `buffer` is completely filled, so its size should be less than or equal
|
||||
// to GetLoadedByteSize().
|
||||
// to GetLoadedByteSize() - `offset`.
|
||||
//
|
||||
// Returns true on success and writes into `buffer. Returns false on failure.
|
||||
virtual bool ReadLoadedBytes(base::span<uint8_t> buffer);
|
||||
virtual bool ReadLoadedBytes(uint32_t offset, base::span<uint8_t> buffer);
|
||||
|
||||
// Requests rendering the page at `page_index` as a thumbnail at a given
|
||||
// `device_pixel_ratio`. Runs `send_callback` with the rendered thumbnail.
|
||||
|
@ -53,8 +53,9 @@ uint32_t TestPDFiumEngine::GetLoadedByteSize() {
|
||||
return sizeof(kLoadedData);
|
||||
}
|
||||
|
||||
bool TestPDFiumEngine::ReadLoadedBytes(base::span<uint8_t> buffer) {
|
||||
buffer.copy_from(base::span(kLoadedData).first(buffer.size()));
|
||||
bool TestPDFiumEngine::ReadLoadedBytes(uint32_t offset,
|
||||
base::span<uint8_t> buffer) {
|
||||
buffer.copy_from(base::span(kLoadedData).subspan(offset, buffer.size()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ class TestPDFiumEngine : public PDFiumEngine {
|
||||
|
||||
uint32_t GetLoadedByteSize() override;
|
||||
|
||||
bool ReadLoadedBytes(base::span<uint8_t> buffer) override;
|
||||
bool ReadLoadedBytes(uint32_t offset, base::span<uint8_t> buffer) override;
|
||||
|
||||
MOCK_METHOD(void,
|
||||
RequestThumbnail,
|
||||
|
Reference in New Issue
Block a user