Skip to content

Commit

Permalink
Reland of Improve linearized pdf load/show time."
Browse files Browse the repository at this point in the history
Use received bytes count as the value for progress, not chunks count.

Reason for reland: 
The fix of revert reason has been added.

Bug: 755061

Original change's description:
> Revert "Reland of Improve linearized pdf load/show time."
>
> This reverts commit 9a6d148.
>
> Reason for revert: https://crbug.com/755061. This appears to be
> causing a serious regression in loading. The loading bar does not
> appear as expected and appears all at once at the end as the screen
> displays. There is 5-6seconds of nothing happening which makes it look
> like the browser has stopped working.
>
>
> Original change's description:
> > Reland of Improve linearized pdf load/show time.
> >
> > XFA forms loading has been fixed.
> > Now for document with single non XFA page, the form load first.
> > This is necessary for correct loading pages, because in XFA document
> > the page count and them contents may be changed after loading form.
> >
> > See
> > https://codereview.chromium.org/2558573002/
> >
> > For test this:
> >  build chromium pdf with XFA support
> >  and open any document from
> >  https://www.idrsolutions.com/jpdfforms/xfa-html5-example-conversions/
> >
> > Original CL:
> >  https://codereview.chromium.org/2455403002/
> >
> > Original description:
> >  Improve linearized pdf load/show time.
> >  Reduce Pdf Plugin's count of reconnects.
> >  Add tests for PDFPlugin DocumentLoader.
> >
> >  DocumentLoader was splitted into separate components, and missing tests was added for them.
> >
> >  The main ideas in this CL are:
> >
> >  1) Do not reset browser initiated connection at start (includes case when we can use range requests), if we request data near current downloading position.
> >  2) Request as much data as we can on each request, and continue loading data using current range request. (like tape rewind)
> >  3) Isolate RangeRequest logic into DocumentLoader. Method OnPendingRequestComplete is called, when we receive requested data (main connection, or Range connection). (like tape playing without rewing).
> >  4) Fill this logic by tests.
> >
> >  Example URL:
> >  http://www.major-landrover.ru/upload/attachments/f/9/f96aab07dab04ae89c8a509ec1ef2b31.pdf
> >  Comparison of changes:
> >  https://drive.google.com/file/d/0BzWfMBOuik2QNGg0SG93Y3lpUlE/view?usp=sharing
> >
> > Change-Id: I97bb25d2e82bcb4ba2e060af8128f49b9c0680d9
> > Reviewed-on: https://chromium-review.googlesource.com/581292
> > Reviewed-by: Robert Sesek <rsesek@chromium.org>
> > Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
> > Commit-Queue: Art Snake <art-snake@yandex-team.ru>
> > Cr-Commit-Position: refs/heads/master@{#489755}
>
>

TBR=rsesek@chromium.org

Change-Id: I78e10565f639c26faae29b3cf854419208af8665
Reviewed-on: https://chromium-review.googlesource.com/615302
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: (000 09-08 - 09-18) dsinclair <dsinclair@chromium.org>
Cr-Commit-Position: refs/heads/master@{#501344}
  • Loading branch information
art-snake authored and Commit Bot committed Sep 12, 2017
1 parent fdaaebe commit af1b434
Show file tree
Hide file tree
Showing 23 changed files with 2,961 additions and 792 deletions.
12 changes: 11 additions & 1 deletion pdf/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ if (enable_pdf) {
"//ppapi/cpp:objects",
"//ppapi/cpp/private:internal_module",
"//ui/base",
"//ui/gfx/range",
]

sources = [
"chunk_stream.cc",
"chunk_stream.h",
"document_loader.cc",
"document_loader.h",
Expand All @@ -45,6 +45,13 @@ if (enable_pdf) {
"pdf_engine.h",
"preview_mode_client.cc",
"preview_mode_client.h",
"range_set.cc",
"range_set.h",
"timer.cc",
"timer.h",
"url_loader_wrapper.h",
"url_loader_wrapper_impl.cc",
"url_loader_wrapper_impl.h",
]

if (pdf_engine == 0) {
Expand Down Expand Up @@ -80,6 +87,8 @@ if (enable_pdf) {
test("pdf_unittests") {
sources = [
"chunk_stream_unittest.cc",
"document_loader_unittest.cc",
"range_set_unittest.cc",
"run_all_unittests.cc",
]

Expand All @@ -91,6 +100,7 @@ if (enable_pdf) {
"//ppapi/cpp",
"//testing/gmock",
"//testing/gtest",
"//ui/gfx/range",
]
}
} else {
Expand Down
1 change: 1 addition & 0 deletions pdf/DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ include_rules = [
"+ppapi",
"+ui/base/window_open_disposition.h",
"+ui/events/keycodes/keyboard_codes.h",
"+ui/gfx/range/range.h",
"+v8/include/v8.h"
]
166 changes: 0 additions & 166 deletions pdf/chunk_stream.cc

This file was deleted.

119 changes: 86 additions & 33 deletions pdf/chunk_stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,103 @@
#define PDF_CHUNK_STREAM_H_

#include <stddef.h>
#include <string.h>

#include <map>
#include <utility>
#include <algorithm>
#include <array>
#include <memory>
#include <vector>

#include "pdf/range_set.h"

namespace chrome_pdf {

// This class collects a chunks of data into one data stream. Client can check
// if data in certain range is available, and get missing chunks of data.
template <uint32_t N>
class ChunkStream {
public:
ChunkStream();
~ChunkStream();

void Clear();

void Preallocate(size_t stream_size);
size_t GetSize() const;

bool WriteData(size_t offset, void* buffer, size_t size);
bool ReadData(size_t offset, size_t size, void* buffer) const;

// Returns vector of pairs where first is an offset, second is a size.
bool GetMissedRanges(size_t offset,
size_t size,
std::vector<std::pair<size_t, size_t>>* ranges) const;
bool IsRangeAvailable(size_t offset, size_t size) const;
size_t GetFirstMissingByte() const;

// Finds the first byte of the missing byte interval that offset belongs to.
size_t GetFirstMissingByteInInterval(size_t offset) const;
// Returns the last byte of the missing byte interval that offset belongs to.
size_t GetLastMissingByteInInterval(size_t offset) const;
static constexpr uint32_t kChunkSize = N;
using ChunkData = typename std::array<unsigned char, N>;

ChunkStream() {}
~ChunkStream() {}

void SetChunkData(uint32_t chunk_index, std::unique_ptr<ChunkData> data) {
if (!data)
return;
if (chunk_index >= data_.size()) {
data_.resize(chunk_index + 1);
}
if (!data_[chunk_index]) {
++filled_chunks_count_;
}
data_[chunk_index] = std::move(data);
filled_chunks_.Union(gfx::Range(chunk_index, chunk_index + 1));
}

bool ReadData(const gfx::Range& range, void* buffer) const {
if (!IsRangeAvailable(range)) {
return false;
}
unsigned char* data_buffer = static_cast<unsigned char*>(buffer);
uint32_t start = range.start();
while (start != range.end()) {
const uint32_t chunk_index = GetChunkIndex(start);
const uint32_t chunk_start = start % kChunkSize;
const uint32_t len =
std::min(kChunkSize - chunk_start, range.end() - start);
memcpy(data_buffer, data_[chunk_index]->data() + chunk_start, len);
data_buffer += len;
start += len;
}
return true;
}

uint32_t GetChunkIndex(uint32_t offset) const { return offset / kChunkSize; }

gfx::Range GetChunksRange(uint32_t offset, uint32_t size) const {
return gfx::Range(GetChunkIndex(offset),
GetChunkIndex(offset + size + kChunkSize - 1));
}

bool IsRangeAvailable(const gfx::Range& range) const {
if (!range.IsValid() || range.is_reversed() ||
(eof_pos_ > 0 && eof_pos_ < range.end()))
return false;
if (range.is_empty())
return true;
const gfx::Range chunks_range(GetChunkIndex(range.start()),
GetChunkIndex(range.end() + kChunkSize - 1));
return filled_chunks_.Contains(chunks_range);
}

void set_eof_pos(uint32_t eof_pos) { eof_pos_ = eof_pos; }
uint32_t eof_pos() const { return eof_pos_; }

const RangeSet& filled_chunks() const { return filled_chunks_; }

bool IsComplete() const {
return eof_pos_ > 0 && IsRangeAvailable(gfx::Range(0, eof_pos_));
}

void Clear() {
data_.clear();
eof_pos_ = 0;
filled_chunks_.Clear();
filled_chunks_count_ = 0;
}

uint32_t filled_chunks_count() const { return filled_chunks_count_; }
uint32_t total_chunks_count() const {
return GetChunkIndex(eof_pos_ + kChunkSize - 1);
}

private:
std::map<size_t, size_t>::const_iterator GetStartChunk(size_t offset) const;

std::vector<unsigned char> data_;

// Key: offset of the chunk.
// Value: size of the chunk.
std::map<size_t, size_t> chunks_;

size_t stream_size_;
std::vector<std::unique_ptr<ChunkData>> data_;
uint32_t eof_pos_ = 0;
RangeSet filled_chunks_;
uint32_t filled_chunks_count_ = 0;
};

}; // namespace chrome_pdf
Expand Down
Loading

0 comments on commit af1b434

Please sign in to comment.