OLD | NEW |
1 // Copyright 2015 PDFium Authors. All rights reserved. | 1 // Copyright 2015 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <algorithm> | 5 #include <algorithm> |
6 #include <memory> | 6 #include <memory> |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "public/fpdfview.h" | 10 #include "public/fpdfview.h" |
(...skipping 27 matching lines...) Expand all Loading... |
38 bool IsOpened() const { return !!file_contents_; } | 38 bool IsOpened() const { return !!file_contents_; } |
39 | 39 |
40 FPDF_FILEACCESS* file_access() { return &file_access_; } | 40 FPDF_FILEACCESS* file_access() { return &file_access_; } |
41 FX_DOWNLOADHINTS* hints() { return this; } | 41 FX_DOWNLOADHINTS* hints() { return this; } |
42 FX_FILEAVAIL* file_avail() { return this; } | 42 FX_FILEAVAIL* file_avail() { return this; } |
43 | 43 |
44 const std::vector<std::pair<size_t, size_t>>& requested_segments() const { | 44 const std::vector<std::pair<size_t, size_t>>& requested_segments() const { |
45 return requested_segments_; | 45 return requested_segments_; |
46 } | 46 } |
47 | 47 |
48 void ClearRequestedSegments() { requested_segments_.clear(); } | 48 size_t max_requested_bound() const { return max_requested_bound_; } |
| 49 |
| 50 void ClearRequestedSegments() { |
| 51 requested_segments_.clear(); |
| 52 max_requested_bound_ = 0; |
| 53 } |
49 | 54 |
50 bool is_new_data_available() const { return is_new_data_available_; } | 55 bool is_new_data_available() const { return is_new_data_available_; } |
51 void set_is_new_data_available(bool is_new_data_available) { | 56 void set_is_new_data_available(bool is_new_data_available) { |
52 is_new_data_available_ = is_new_data_available; | 57 is_new_data_available_ = is_new_data_available; |
53 } | 58 } |
54 | 59 |
| 60 size_t max_already_available_bound() const { |
| 61 return available_ranges_.empty() ? 0 : available_ranges_.rbegin()->second; |
| 62 } |
| 63 |
55 private: | 64 private: |
56 void SetDataAvailable(size_t start, size_t size) { | 65 void SetDataAvailable(size_t start, size_t size) { |
57 if (size == 0) | 66 if (size == 0) |
58 return; | 67 return; |
59 const auto range = std::make_pair(start, start + size); | 68 const auto range = std::make_pair(start, start + size); |
60 if (available_ranges_.empty()) { | 69 if (available_ranges_.empty()) { |
61 available_ranges_.insert(range); | 70 available_ranges_.insert(range); |
62 return; | 71 return; |
63 } | 72 } |
64 auto start_it = available_ranges_.upper_bound(range); | 73 auto start_it = available_ranges_.upper_bound(range); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 std::min(static_cast<unsigned long>(file_length_), pos + size); | 111 std::min(static_cast<unsigned long>(file_length_), pos + size); |
103 if (end <= pos) | 112 if (end <= pos) |
104 return 0; | 113 return 0; |
105 memcpy(pBuf, file_contents_.get() + pos, end - pos); | 114 memcpy(pBuf, file_contents_.get() + pos, end - pos); |
106 SetDataAvailable(pos, end - pos); | 115 SetDataAvailable(pos, end - pos); |
107 return static_cast<int>(end - pos); | 116 return static_cast<int>(end - pos); |
108 } | 117 } |
109 | 118 |
110 void AddSegmentImpl(size_t offset, size_t size) { | 119 void AddSegmentImpl(size_t offset, size_t size) { |
111 requested_segments_.push_back(std::make_pair(offset, size)); | 120 requested_segments_.push_back(std::make_pair(offset, size)); |
| 121 max_requested_bound_ = std::max(max_requested_bound_, offset + size); |
112 } | 122 } |
113 | 123 |
114 bool IsDataAvailImpl(size_t offset, size_t size) { | 124 bool IsDataAvailImpl(size_t offset, size_t size) { |
115 if (offset + size > file_length_) | 125 if (offset + size > file_length_) |
116 return false; | 126 return false; |
117 if (is_new_data_available_) { | 127 if (is_new_data_available_) { |
118 SetDataAvailable(offset, size); | 128 SetDataAvailable(offset, size); |
119 return true; | 129 return true; |
120 } | 130 } |
121 return CheckDataAlreadyAvailable(offset, size); | 131 return CheckDataAlreadyAvailable(offset, size); |
(...skipping 14 matching lines...) Expand all Loading... |
136 size_t offset, | 146 size_t offset, |
137 size_t size) { | 147 size_t size) { |
138 return static_cast<TestAsyncLoader*>(pThis)->IsDataAvailImpl(offset, size); | 148 return static_cast<TestAsyncLoader*>(pThis)->IsDataAvailImpl(offset, size); |
139 } | 149 } |
140 | 150 |
141 FPDF_FILEACCESS file_access_; | 151 FPDF_FILEACCESS file_access_; |
142 | 152 |
143 std::unique_ptr<char, pdfium::FreeDeleter> file_contents_; | 153 std::unique_ptr<char, pdfium::FreeDeleter> file_contents_; |
144 size_t file_length_; | 154 size_t file_length_; |
145 std::vector<std::pair<size_t, size_t>> requested_segments_; | 155 std::vector<std::pair<size_t, size_t>> requested_segments_; |
| 156 size_t max_requested_bound_ = 0; |
146 bool is_new_data_available_ = true; | 157 bool is_new_data_available_ = true; |
147 | 158 |
148 using Range = std::pair<size_t, size_t>; | 159 using Range = std::pair<size_t, size_t>; |
149 struct range_compare { | 160 struct range_compare { |
150 bool operator()(const Range& lval, const Range& rval) const { | 161 bool operator()(const Range& lval, const Range& rval) const { |
151 return lval.first < rval.first; | 162 return lval.first < rval.first; |
152 } | 163 } |
153 }; | 164 }; |
154 using RangesContainer = std::set<Range, range_compare>; | 165 using RangesContainer = std::set<Range, range_compare>; |
155 RangesContainer available_ranges_; | 166 RangesContainer available_ranges_; |
(...skipping 22 matching lines...) Expand all Loading... |
178 document_ = FPDFAvail_GetDocument(avail_, nullptr); | 189 document_ = FPDFAvail_GetDocument(avail_, nullptr); |
179 ASSERT_TRUE(document_); | 190 ASSERT_TRUE(document_); |
180 ASSERT_EQ(PDF_DATA_AVAIL, FPDFAvail_IsPageAvail(avail_, 1, loader.hints())); | 191 ASSERT_EQ(PDF_DATA_AVAIL, FPDFAvail_IsPageAvail(avail_, 1, loader.hints())); |
181 | 192 |
182 // No new data available, to prevent load "Pages" node. | 193 // No new data available, to prevent load "Pages" node. |
183 loader.set_is_new_data_available(false); | 194 loader.set_is_new_data_available(false); |
184 FPDF_PAGE page = LoadPage(1); | 195 FPDF_PAGE page = LoadPage(1); |
185 EXPECT_TRUE(page); | 196 EXPECT_TRUE(page); |
186 UnloadPage(page); | 197 UnloadPage(page); |
187 } | 198 } |
| 199 |
| 200 TEST_F(FPDFDataAvailEmbeddertest, |
| 201 DoNotLoadMainCrossRefForFirstPageIfLinearized) { |
| 202 TestAsyncLoader loader("feature_linearized_loading.pdf"); |
| 203 avail_ = FPDFAvail_Create(loader.file_avail(), loader.file_access()); |
| 204 ASSERT_EQ(PDF_DATA_AVAIL, FPDFAvail_IsDocAvail(avail_, loader.hints())); |
| 205 document_ = FPDFAvail_GetDocument(avail_, nullptr); |
| 206 ASSERT_TRUE(document_); |
| 207 const int first_page_num = FPDFAvail_GetFirstPageNum(document_); |
| 208 |
| 209 // The main cross ref table should not be processed. |
| 210 // (It is always at file end) |
| 211 EXPECT_GT(loader.file_access()->m_FileLen, |
| 212 loader.max_already_available_bound()); |
| 213 |
| 214 // Prevent access to non requested data to coerce the parser to send new |
| 215 // request for non available (non requested before) data. |
| 216 loader.set_is_new_data_available(false); |
| 217 FPDFAvail_IsPageAvail(avail_, first_page_num, loader.hints()); |
| 218 |
| 219 // The main cross ref table should not be requested. |
| 220 // (It is always at file end) |
| 221 EXPECT_GT(loader.file_access()->m_FileLen, loader.max_requested_bound()); |
| 222 |
| 223 // Allow parse page. |
| 224 loader.set_is_new_data_available(true); |
| 225 ASSERT_EQ(PDF_DATA_AVAIL, |
| 226 FPDFAvail_IsPageAvail(avail_, first_page_num, loader.hints())); |
| 227 |
| 228 // The main cross ref table should not be processed. |
| 229 // (It is always at file end) |
| 230 EXPECT_GT(loader.file_access()->m_FileLen, |
| 231 loader.max_already_available_bound()); |
| 232 |
| 233 // Prevent loading data, while page loading. |
| 234 loader.set_is_new_data_available(false); |
| 235 FPDF_PAGE page = LoadPage(first_page_num); |
| 236 EXPECT_TRUE(page); |
| 237 UnloadPage(page); |
| 238 } |
OLD | NEW |