Commit e98901a4 authored by Lei Zhang's avatar Lei Zhang Committed by Commit Bot

PDF: Make DocumentLoader an interface.

To make it easier to write fake DocumentLoaders for testing. Split the
implementation off into DocumentLoaderImpl.

Change-Id: I44f16c757b8a9be133936c41c231a552a7e05f0a
Reviewed-on: https://chromium-review.googlesource.com/1013998
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: default avatardsinclair <dsinclair@chromium.org>
Cr-Commit-Position: refs/heads/master@{#553816}
parent b0478d0c
...@@ -36,8 +36,9 @@ if (enable_pdf) { ...@@ -36,8 +36,9 @@ if (enable_pdf) {
sources = [ sources = [
"chunk_stream.h", "chunk_stream.h",
"document_loader.cc",
"document_loader.h", "document_loader.h",
"document_loader_impl.cc",
"document_loader_impl.h",
"draw_utils.cc", "draw_utils.cc",
"draw_utils.h", "draw_utils.h",
"out_of_process_instance.cc", "out_of_process_instance.cc",
...@@ -103,7 +104,7 @@ if (enable_pdf) { ...@@ -103,7 +104,7 @@ if (enable_pdf) {
test("pdf_unittests") { test("pdf_unittests") {
sources = [ sources = [
"chunk_stream_unittest.cc", "chunk_stream_unittest.cc",
"document_loader_unittest.cc", "document_loader_impl_unittest.cc",
"pdf_transform_unittest.cc", "pdf_transform_unittest.cc",
"range_set_unittest.cc", "range_set_unittest.cc",
"run_all_unittests.cc", "run_all_unittests.cc",
......
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "base/macros.h"
#include "pdf/chunk_stream.h"
#include "ppapi/utility/completion_callback_factory.h"
namespace pp { namespace pp {
class Instance; class Instance;
} }
...@@ -25,9 +21,6 @@ class URLLoaderWrapper; ...@@ -25,9 +21,6 @@ class URLLoaderWrapper;
class DocumentLoader { class DocumentLoader {
public: public:
// Number was chosen in crbug.com/78264#c8
static constexpr uint32_t kDefaultRequestSize = 65536;
class Client { class Client {
public: public:
virtual ~Client() = default; virtual ~Client() = default;
...@@ -48,84 +41,27 @@ class DocumentLoader { ...@@ -48,84 +41,27 @@ class DocumentLoader {
virtual void CancelBrowserDownload() = 0; virtual void CancelBrowserDownload() = 0;
}; };
explicit DocumentLoader(Client* client); virtual ~DocumentLoader() = default;
~DocumentLoader();
bool Init(std::unique_ptr<URLLoaderWrapper> loader, const std::string& url); virtual bool Init(std::unique_ptr<URLLoaderWrapper> loader,
const std::string& url) = 0;
// Data access interface. Return true if successful. // Data access interface. Return true if successful.
bool GetBlock(uint32_t position, uint32_t size, void* buf) const; virtual bool GetBlock(uint32_t position, uint32_t size, void* buf) const = 0;
// Data availability interface. Return true if data is available. // Data availability interface. Return true if data is available.
bool IsDataAvailable(uint32_t position, uint32_t size) const; virtual bool IsDataAvailable(uint32_t position, uint32_t size) const = 0;
// Data request interface. // Data request interface.
void RequestData(uint32_t position, uint32_t size); virtual void RequestData(uint32_t position, uint32_t size) {}
bool IsDocumentComplete() const; virtual bool IsDocumentComplete() const = 0;
void SetDocumentSize(uint32_t size); virtual void SetDocumentSize(uint32_t size) {}
uint32_t GetDocumentSize() const; virtual uint32_t GetDocumentSize() const = 0;
uint32_t bytes_received() const { return bytes_received_; } virtual uint32_t BytesReceived() const = 0;
// Clear pending requests from the queue. // Clear pending requests from the queue.
void ClearPendingRequests(); virtual void ClearPendingRequests() {}
// Exposed for unit tests.
void SetPartialLoadingEnabled(bool enabled);
bool is_partial_loader_active() const { return is_partial_loader_active_; }
private:
using DataStream = ChunkStream<kDefaultRequestSize>;
struct Chunk {
Chunk();
~Chunk();
void Clear();
uint32_t chunk_index = 0;
uint32_t data_size = 0;
std::unique_ptr<DataStream::ChunkData> chunk_data;
};
// Called by the completion callback of the document's URLLoader.
void DidOpenPartial(int32_t result);
// Call to read data from the document's URLLoader.
void ReadMore();
// Called by the completion callback of the document's URLLoader.
void DidRead(int32_t result);
bool ShouldCancelLoading() const;
void ContinueDownload();
// Called when we complete server request.
void ReadComplete();
bool SaveBuffer(char* input, uint32_t input_size);
void SaveChunkData();
uint32_t EndOfCurrentChunk() const;
Client* const client_;
std::string url_;
std::unique_ptr<URLLoaderWrapper> loader_;
pp::CompletionCallbackFactory<DocumentLoader> loader_factory_;
DataStream chunk_stream_;
bool partial_loading_enabled_ = true;
bool is_partial_loader_active_ = false;
static constexpr uint32_t kReadBufferSize = 256 * 1024;
char buffer_[kReadBufferSize];
// The current chunk DocumentLoader is working with.
Chunk chunk_;
// In units of Chunks.
RangeSet pending_requests_;
uint32_t bytes_received_ = 0;
DISALLOW_COPY_AND_ASSIGN(DocumentLoader);
}; };
} // namespace chrome_pdf } // namespace chrome_pdf
......
...@@ -2,13 +2,12 @@ ...@@ -2,13 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "pdf/document_loader.h" #include "pdf/document_loader_impl.h"
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <algorithm> #include <algorithm>
#include <memory>
#include <utility> #include <utility>
#include "base/logging.h" #include "base/logging.h"
...@@ -53,23 +52,23 @@ bool IsValidContentType(const std::string& type) { ...@@ -53,23 +52,23 @@ bool IsValidContentType(const std::string& type) {
} // namespace } // namespace
DocumentLoader::Chunk::Chunk() = default; DocumentLoaderImpl::Chunk::Chunk() = default;
DocumentLoader::Chunk::~Chunk() = default; DocumentLoaderImpl::Chunk::~Chunk() = default;
void DocumentLoader::Chunk::Clear() { void DocumentLoaderImpl::Chunk::Clear() {
chunk_index = 0; chunk_index = 0;
data_size = 0; data_size = 0;
chunk_data.reset(); chunk_data.reset();
} }
DocumentLoader::DocumentLoader(Client* client) DocumentLoaderImpl::DocumentLoaderImpl(Client* client)
: client_(client), loader_factory_(this) {} : client_(client), loader_factory_(this) {}
DocumentLoader::~DocumentLoader() = default; DocumentLoaderImpl::~DocumentLoaderImpl() = default;
bool DocumentLoader::Init(std::unique_ptr<URLLoaderWrapper> loader, bool DocumentLoaderImpl::Init(std::unique_ptr<URLLoaderWrapper> loader,
const std::string& url) { const std::string& url) {
DCHECK(url_.empty()); DCHECK(url_.empty());
DCHECK(!loader_); DCHECK(!loader_);
...@@ -119,25 +118,29 @@ bool DocumentLoader::Init(std::unique_ptr<URLLoaderWrapper> loader, ...@@ -119,25 +118,29 @@ bool DocumentLoader::Init(std::unique_ptr<URLLoaderWrapper> loader,
return true; return true;
} }
bool DocumentLoader::IsDocumentComplete() const { bool DocumentLoaderImpl::IsDocumentComplete() const {
return chunk_stream_.IsComplete(); return chunk_stream_.IsComplete();
} }
void DocumentLoader::SetDocumentSize(uint32_t size) { void DocumentLoaderImpl::SetDocumentSize(uint32_t size) {
chunk_stream_.set_eof_pos(size); chunk_stream_.set_eof_pos(size);
} }
uint32_t DocumentLoader::GetDocumentSize() const { uint32_t DocumentLoaderImpl::GetDocumentSize() const {
return chunk_stream_.eof_pos(); return chunk_stream_.eof_pos();
} }
void DocumentLoader::ClearPendingRequests() { uint32_t DocumentLoaderImpl::BytesReceived() const {
return bytes_received_;
}
void DocumentLoaderImpl::ClearPendingRequests() {
pending_requests_.Clear(); pending_requests_.Clear();
} }
bool DocumentLoader::GetBlock(uint32_t position, bool DocumentLoaderImpl::GetBlock(uint32_t position,
uint32_t size, uint32_t size,
void* buf) const { void* buf) const {
base::CheckedNumeric<uint32_t> addition_result = position; base::CheckedNumeric<uint32_t> addition_result = position;
addition_result += size; addition_result += size;
if (!addition_result.IsValid()) if (!addition_result.IsValid())
...@@ -146,7 +149,8 @@ bool DocumentLoader::GetBlock(uint32_t position, ...@@ -146,7 +149,8 @@ bool DocumentLoader::GetBlock(uint32_t position,
gfx::Range(position, addition_result.ValueOrDie()), buf); gfx::Range(position, addition_result.ValueOrDie()), buf);
} }
bool DocumentLoader::IsDataAvailable(uint32_t position, uint32_t size) const { bool DocumentLoaderImpl::IsDataAvailable(uint32_t position,
uint32_t size) const {
base::CheckedNumeric<uint32_t> addition_result = position; base::CheckedNumeric<uint32_t> addition_result = position;
addition_result += size; addition_result += size;
if (!addition_result.IsValid()) if (!addition_result.IsValid())
...@@ -155,7 +159,7 @@ bool DocumentLoader::IsDataAvailable(uint32_t position, uint32_t size) const { ...@@ -155,7 +159,7 @@ bool DocumentLoader::IsDataAvailable(uint32_t position, uint32_t size) const {
gfx::Range(position, addition_result.ValueOrDie())); gfx::Range(position, addition_result.ValueOrDie()));
} }
void DocumentLoader::RequestData(uint32_t position, uint32_t size) { void DocumentLoaderImpl::RequestData(uint32_t position, uint32_t size) {
if (size == 0 || IsDataAvailable(position, size)) if (size == 0 || IsDataAvailable(position, size))
return; return;
...@@ -190,14 +194,14 @@ void DocumentLoader::RequestData(uint32_t position, uint32_t size) { ...@@ -190,14 +194,14 @@ void DocumentLoader::RequestData(uint32_t position, uint32_t size) {
pending_requests_.Union(requested_chunks); pending_requests_.Union(requested_chunks);
} }
void DocumentLoader::SetPartialLoadingEnabled(bool enabled) { void DocumentLoaderImpl::SetPartialLoadingEnabled(bool enabled) {
partial_loading_enabled_ = enabled; partial_loading_enabled_ = enabled;
if (!enabled) { if (!enabled) {
is_partial_loader_active_ = false; is_partial_loader_active_ = false;
} }
} }
bool DocumentLoader::ShouldCancelLoading() const { bool DocumentLoaderImpl::ShouldCancelLoading() const {
if (!loader_) if (!loader_)
return true; return true;
if (!partial_loading_enabled_ || pending_requests_.IsEmpty()) if (!partial_loading_enabled_ || pending_requests_.IsEmpty())
...@@ -207,7 +211,7 @@ bool DocumentLoader::ShouldCancelLoading() const { ...@@ -207,7 +211,7 @@ bool DocumentLoader::ShouldCancelLoading() const {
return !pending_requests_.Intersects(current_range); return !pending_requests_.Intersects(current_range);
} }
void DocumentLoader::ContinueDownload() { void DocumentLoaderImpl::ContinueDownload() {
if (!ShouldCancelLoading()) if (!ShouldCancelLoading())
return ReadMore(); return ReadMore();
...@@ -252,10 +256,10 @@ void DocumentLoader::ContinueDownload() { ...@@ -252,10 +256,10 @@ void DocumentLoader::ContinueDownload() {
loader_->OpenRange( loader_->OpenRange(
url_, url_, start, length, url_, url_, start, length,
loader_factory_.NewCallback(&DocumentLoader::DidOpenPartial)); loader_factory_.NewCallback(&DocumentLoaderImpl::DidOpenPartial));
} }
void DocumentLoader::DidOpenPartial(int32_t result) { void DocumentLoaderImpl::DidOpenPartial(int32_t result) {
if (result != PP_OK) { if (result != PP_OK) {
return ReadComplete(); return ReadComplete();
} }
...@@ -288,13 +292,13 @@ void DocumentLoader::DidOpenPartial(int32_t result) { ...@@ -288,13 +292,13 @@ void DocumentLoader::DidOpenPartial(int32_t result) {
return ContinueDownload(); return ContinueDownload();
} }
void DocumentLoader::ReadMore() { void DocumentLoaderImpl::ReadMore() {
loader_->ReadResponseBody( loader_->ReadResponseBody(
buffer_, sizeof(buffer_), buffer_, sizeof(buffer_),
loader_factory_.NewCallback(&DocumentLoader::DidRead)); loader_factory_.NewCallback(&DocumentLoaderImpl::DidRead));
} }
void DocumentLoader::DidRead(int32_t result) { void DocumentLoaderImpl::DidRead(int32_t result) {
if (result < 0) { if (result < 0) {
// An error occurred. // An error occurred.
// The renderer will detect that we're missing data and will display a // The renderer will detect that we're missing data and will display a
...@@ -322,7 +326,7 @@ void DocumentLoader::DidRead(int32_t result) { ...@@ -322,7 +326,7 @@ void DocumentLoader::DidRead(int32_t result) {
return ContinueDownload(); return ContinueDownload();
} }
bool DocumentLoader::SaveBuffer(char* input, uint32_t input_size) { bool DocumentLoaderImpl::SaveBuffer(char* input, uint32_t input_size) {
const uint32_t document_size = GetDocumentSize(); const uint32_t document_size = GetDocumentSize();
if (document_size != 0) { if (document_size != 0) {
// If the HTTP server sends more data than expected, then truncate // If the HTTP server sends more data than expected, then truncate
...@@ -368,17 +372,17 @@ bool DocumentLoader::SaveBuffer(char* input, uint32_t input_size) { ...@@ -368,17 +372,17 @@ bool DocumentLoader::SaveBuffer(char* input, uint32_t input_size) {
return true; return true;
} }
void DocumentLoader::SaveChunkData() { void DocumentLoaderImpl::SaveChunkData() {
chunk_stream_.SetChunkData(chunk_.chunk_index, std::move(chunk_.chunk_data)); chunk_stream_.SetChunkData(chunk_.chunk_index, std::move(chunk_.chunk_data));
chunk_.data_size = 0; chunk_.data_size = 0;
++chunk_.chunk_index; ++chunk_.chunk_index;
} }
uint32_t DocumentLoader::EndOfCurrentChunk() const { uint32_t DocumentLoaderImpl::EndOfCurrentChunk() const {
return chunk_.chunk_index * DataStream::kChunkSize + chunk_.data_size; return chunk_.chunk_index * DataStream::kChunkSize + chunk_.data_size;
} }
void DocumentLoader::ReadComplete() { void DocumentLoaderImpl::ReadComplete() {
if (GetDocumentSize() != 0) { if (GetDocumentSize() != 0) {
// If there is remaining data in |chunk_|, then save whatever can be saved. // If there is remaining data in |chunk_|, then save whatever can be saved.
// e.g. In the underrun case. // e.g. In the underrun case.
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PDF_DOCUMENT_LOADER_IMPL_H_
#define PDF_DOCUMENT_LOADER_IMPL_H_
#include <memory>
#include <string>
#include "base/macros.h"
#include "pdf/chunk_stream.h"
#include "pdf/document_loader.h"
#include "ppapi/utility/completion_callback_factory.h"
namespace chrome_pdf {
class DocumentLoaderImpl : public DocumentLoader {
public:
// Number was chosen in https://crbug.com/78264#c8
static constexpr uint32_t kDefaultRequestSize = 65536;
explicit DocumentLoaderImpl(Client* client);
~DocumentLoaderImpl() override;
// DocumentLoader:
bool Init(std::unique_ptr<URLLoaderWrapper> loader,
const std::string& url) override;
bool GetBlock(uint32_t position, uint32_t size, void* buf) const override;
bool IsDataAvailable(uint32_t position, uint32_t size) const override;
void RequestData(uint32_t position, uint32_t size) override;
bool IsDocumentComplete() const override;
void SetDocumentSize(uint32_t size) override;
uint32_t GetDocumentSize() const override;
uint32_t BytesReceived() const override;
void ClearPendingRequests() override;
// Exposed for unit tests.
void SetPartialLoadingEnabled(bool enabled);
bool is_partial_loader_active() const { return is_partial_loader_active_; }
private:
using DataStream = ChunkStream<kDefaultRequestSize>;
struct Chunk {
Chunk();
~Chunk();
void Clear();
uint32_t chunk_index = 0;
uint32_t data_size = 0;
std::unique_ptr<DataStream::ChunkData> chunk_data;
};
// Called by the completion callback of the document's URLLoader.
void DidOpenPartial(int32_t result);
// Call to read data from the document's URLLoader.
void ReadMore();
// Called by the completion callback of the document's URLLoader.
void DidRead(int32_t result);
bool ShouldCancelLoading() const;
void ContinueDownload();
// Called when we complete server request.
void ReadComplete();
bool SaveBuffer(char* input, uint32_t input_size);
void SaveChunkData();
uint32_t EndOfCurrentChunk() const;
Client* const client_;
std::string url_;
std::unique_ptr<URLLoaderWrapper> loader_;
pp::CompletionCallbackFactory<DocumentLoaderImpl> loader_factory_;
DataStream chunk_stream_;
bool partial_loading_enabled_ = true;
bool is_partial_loader_active_ = false;
static constexpr uint32_t kReadBufferSize = 256 * 1024;
char buffer_[kReadBufferSize];
// The current chunk DocumentLoader is working with.
Chunk chunk_;
// In units of Chunks.
RangeSet pending_requests_;
uint32_t bytes_received_ = 0;
DISALLOW_COPY_AND_ASSIGN(DocumentLoaderImpl);
};
} // namespace chrome_pdf
#endif // PDF_DOCUMENT_LOADER_IMPL_H_
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "gin/array_buffer.h" #include "gin/array_buffer.h"
#include "gin/public/gin_embedders.h" #include "gin/public/gin_embedders.h"
#include "gin/public/isolate_holder.h" #include "gin/public/isolate_holder.h"
#include "pdf/document_loader_impl.h"
#include "pdf/draw_utils.h" #include "pdf/draw_utils.h"
#include "pdf/pdf_transform.h" #include "pdf/pdf_transform.h"
#include "pdf/pdfium/pdfium_api_string_buffer_adapter.h" #include "pdf/pdfium/pdfium_api_string_buffer_adapter.h"
...@@ -1226,7 +1227,7 @@ bool PDFiumEngine::HandleDocumentLoad(const pp::URLLoader& loader) { ...@@ -1226,7 +1227,7 @@ bool PDFiumEngine::HandleDocumentLoad(const pp::URLLoader& loader) {
std::make_unique<URLLoaderWrapperImpl>(GetPluginInstance(), loader); std::make_unique<URLLoaderWrapperImpl>(GetPluginInstance(), loader);
loader_wrapper->SetResponseHeaders(headers_); loader_wrapper->SetResponseHeaders(headers_);
doc_loader_ = std::make_unique<DocumentLoader>(this); doc_loader_ = std::make_unique<DocumentLoaderImpl>(this);
if (doc_loader_->Init(std::move(loader_wrapper), url_)) { if (doc_loader_->Init(std::move(loader_wrapper), url_)) {
// request initial data. // request initial data.
doc_loader_->RequestData(0, 1); doc_loader_->RequestData(0, 1);
...@@ -1318,7 +1319,7 @@ void PDFiumEngine::OnPendingRequestComplete() { ...@@ -1318,7 +1319,7 @@ void PDFiumEngine::OnPendingRequestComplete() {
} }
void PDFiumEngine::OnNewDataReceived() { void PDFiumEngine::OnNewDataReceived() {
client_->DocumentLoadProgress(doc_loader_->bytes_received(), client_->DocumentLoadProgress(doc_loader_->BytesReceived(),
doc_loader_->GetDocumentSize()); doc_loader_->GetDocumentSize());
} }
...@@ -1388,7 +1389,7 @@ void PDFiumEngine::FinishLoadingDocument() { ...@@ -1388,7 +1389,7 @@ void PDFiumEngine::FinishLoadingDocument() {
document_features.is_tagged = FPDFCatalog_IsTagged(doc_); document_features.is_tagged = FPDFCatalog_IsTagged(doc_);
document_features.form_type = static_cast<FormType>(FPDF_GetFormType(doc_)); document_features.form_type = static_cast<FormType>(FPDF_GetFormType(doc_));
client_->DocumentLoadComplete(document_features, client_->DocumentLoadComplete(document_features,
doc_loader_->bytes_received()); doc_loader_->BytesReceived());
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment