| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium 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 "pdf/document_loader.h" | 5 #include "pdf/document_loader.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 // e.g. resource has been removed from the server while loading it. 301 | 73 // e.g. resource has been removed from the server while loading it. 301 |
| 74 // indicates a redirect was returned which won't be successful because we | 74 // indicates a redirect was returned which won't be successful because we |
| 75 // disable following redirects for PDF loading (we assume they are already | 75 // disable following redirects for PDF loading (we assume they are already |
| 76 // resolved by the browser. | 76 // resolved by the browser. |
| 77 bool ResponseStatusSuccess(const pp::URLLoader& loader) { | 77 bool ResponseStatusSuccess(const pp::URLLoader& loader) { |
| 78 int32_t http_code = loader.GetResponseInfo().GetStatusCode(); | 78 int32_t http_code = loader.GetResponseInfo().GetStatusCode(); |
| 79 return (http_code < 400 && http_code != 301) || http_code >= 500; | 79 return (http_code < 400 && http_code != 301) || http_code >= 500; |
| 80 } | 80 } |
| 81 | 81 |
| 82 bool IsValidContentType(const std::string& type) { | 82 bool IsValidContentType(const std::string& type) { |
| 83 return (base::EndsWith(type, "/pdf", base::CompareCase::INSENSITIVE_ASCII) || | 83 return base::EndsWith(type, "/pdf", base::CompareCase::INSENSITIVE_ASCII) || |
| 84 base::EndsWith(type, ".pdf", base::CompareCase::INSENSITIVE_ASCII) || | 84 base::EndsWith(type, ".pdf", base::CompareCase::INSENSITIVE_ASCII) || |
| 85 base::EndsWith(type, "/x-pdf", | 85 base::EndsWith(type, "/x-pdf", base::CompareCase::INSENSITIVE_ASCII) || |
| 86 base::CompareCase::INSENSITIVE_ASCII) || | 86 base::EndsWith(type, "/*", base::CompareCase::INSENSITIVE_ASCII) || |
| 87 base::EndsWith(type, "/*", base::CompareCase::INSENSITIVE_ASCII) || | 87 base::EndsWith(type, "/acrobat", |
| 88 base::EndsWith(type, "/acrobat", | 88 base::CompareCase::INSENSITIVE_ASCII) || |
| 89 base::CompareCase::INSENSITIVE_ASCII) || | 89 base::EndsWith(type, "/unknown", base::CompareCase::INSENSITIVE_ASCII); |
| 90 base::EndsWith(type, "/unknown", | |
| 91 base::CompareCase::INSENSITIVE_ASCII)); | |
| 92 } | 90 } |
| 93 | 91 |
| 94 } // namespace | 92 } // namespace |
| 95 | 93 |
| 96 DocumentLoader::Client::~Client() { | 94 DocumentLoader::Client::~Client() {} |
| 97 } | |
| 98 | 95 |
| 99 DocumentLoader::DocumentLoader(Client* client) | 96 DocumentLoader::DocumentLoader(Client* client) |
| 100 : client_(client), partial_document_(false), request_pending_(false), | 97 : client_(client), |
| 101 current_pos_(0), current_chunk_size_(0), current_chunk_read_(0), | 98 partial_document_(false), |
| 102 document_size_(0), header_request_(true), is_multipart_(false) { | 99 request_pending_(false), |
| 100 current_pos_(0), |
| 101 current_chunk_size_(0), |
| 102 current_chunk_read_(0), |
| 103 document_size_(0), |
| 104 header_request_(true), |
| 105 is_multipart_(false) { |
| 103 loader_factory_.Initialize(this); | 106 loader_factory_.Initialize(this); |
| 104 } | 107 } |
| 105 | 108 |
| 106 DocumentLoader::~DocumentLoader() { | 109 DocumentLoader::~DocumentLoader() {} |
| 107 } | |
| 108 | 110 |
| 109 bool DocumentLoader::Init(const pp::URLLoader& loader, | 111 bool DocumentLoader::Init(const pp::URLLoader& loader, |
| 110 const std::string& url, | 112 const std::string& url, |
| 111 const std::string& headers) { | 113 const std::string& headers) { |
| 112 DCHECK(url_.empty()); | 114 DCHECK(url_.empty()); |
| 113 | 115 |
| 114 // Check that the initial response status is a valid one. | 116 // Check that the initial response status is a valid one. |
| 115 if (!ResponseStatusSuccess(loader)) | 117 if (!ResponseStatusSuccess(loader)) |
| 116 return false; | 118 return false; |
| 117 | 119 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 return false; | 176 return false; |
| 175 | 177 |
| 176 if (content_length > 0) | 178 if (content_length > 0) |
| 177 chunk_stream_.Preallocate(content_length); | 179 chunk_stream_.Preallocate(content_length); |
| 178 | 180 |
| 179 document_size_ = content_length; | 181 document_size_ = content_length; |
| 180 requests_count_ = 0; | 182 requests_count_ = 0; |
| 181 | 183 |
| 182 // Enable partial loading only if file size is above the threshold. | 184 // Enable partial loading only if file size is above the threshold. |
| 183 // It will allow avoiding latency for multiple requests. | 185 // It will allow avoiding latency for multiple requests. |
| 184 if (content_length > kMinFileSize && | 186 if (content_length > kMinFileSize && accept_ranges_bytes && |
| 185 accept_ranges_bytes && | |
| 186 !content_encoded) { | 187 !content_encoded) { |
| 187 LoadPartialDocument(); | 188 LoadPartialDocument(); |
| 188 } else { | 189 } else { |
| 189 LoadFullDocument(); | 190 LoadFullDocument(); |
| 190 } | 191 } |
| 191 return true; | 192 return true; |
| 192 } | 193 } |
| 193 | 194 |
| 194 void DocumentLoader::LoadPartialDocument() { | 195 void DocumentLoader::LoadPartialDocument() { |
| 195 // The current request is a full request (not a range request) so it starts at | 196 // The current request is a full request (not a range request) so it starts at |
| (...skipping 20 matching lines...) Expand all Loading... |
| 216 if (document_size_ == 0) // Document size unknown. | 217 if (document_size_ == 0) // Document size unknown. |
| 217 return false; | 218 return false; |
| 218 return IsDataAvailable(0, document_size_); | 219 return IsDataAvailable(0, document_size_); |
| 219 } | 220 } |
| 220 | 221 |
| 221 uint32_t DocumentLoader::GetAvailableData() const { | 222 uint32_t DocumentLoader::GetAvailableData() const { |
| 222 if (document_size_ == 0) { // If document size is unknown. | 223 if (document_size_ == 0) { // If document size is unknown. |
| 223 return current_pos_; | 224 return current_pos_; |
| 224 } | 225 } |
| 225 | 226 |
| 226 std::vector<std::pair<size_t, size_t> > ranges; | 227 std::vector<std::pair<size_t, size_t>> ranges; |
| 227 chunk_stream_.GetMissedRanges(0, document_size_, &ranges); | 228 chunk_stream_.GetMissedRanges(0, document_size_, &ranges); |
| 228 uint32_t available = document_size_; | 229 uint32_t available = document_size_; |
| 229 for (const auto& range : ranges) | 230 for (const auto& range : ranges) |
| 230 available -= range.second; | 231 available -= range.second; |
| 231 return available; | 232 return available; |
| 232 } | 233 } |
| 233 | 234 |
| 234 void DocumentLoader::ClearPendingRequests() { | 235 void DocumentLoader::ClearPendingRequests() { |
| 235 pending_requests_.erase(pending_requests_.begin(), | 236 pending_requests_.erase(pending_requests_.begin(), pending_requests_.end()); |
| 236 pending_requests_.end()); | |
| 237 } | 237 } |
| 238 | 238 |
| 239 bool DocumentLoader::GetBlock(uint32_t position, | 239 bool DocumentLoader::GetBlock(uint32_t position, |
| 240 uint32_t size, | 240 uint32_t size, |
| 241 void* buf) const { | 241 void* buf) const { |
| 242 return chunk_stream_.ReadData(position, size, buf); | 242 return chunk_stream_.ReadData(position, size, buf); |
| 243 } | 243 } |
| 244 | 244 |
| 245 bool DocumentLoader::IsDataAvailable(uint32_t position, uint32_t size) const { | 245 bool DocumentLoader::IsDataAvailable(uint32_t position, uint32_t size) const { |
| 246 return chunk_stream_.IsRangeAvailable(position, size); | 246 return chunk_stream_.IsRangeAvailable(position, size); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 259 if (IsDocumentComplete()) | 259 if (IsDocumentComplete()) |
| 260 return; | 260 return; |
| 261 | 261 |
| 262 pending_requests_.push_back(std::pair<size_t, size_t>(position, size)); | 262 pending_requests_.push_back(std::pair<size_t, size_t>(position, size)); |
| 263 DownloadPendingRequests(); | 263 DownloadPendingRequests(); |
| 264 } | 264 } |
| 265 | 265 |
| 266 void DocumentLoader::RemoveCompletedRanges() { | 266 void DocumentLoader::RemoveCompletedRanges() { |
| 267 // Split every request that has been partially downloaded already into smaller | 267 // Split every request that has been partially downloaded already into smaller |
| 268 // requests. | 268 // requests. |
| 269 std::vector<std::pair<size_t, size_t> > ranges; | 269 std::vector<std::pair<size_t, size_t>> ranges; |
| 270 auto it = pending_requests_.begin(); | 270 auto it = pending_requests_.begin(); |
| 271 while (it != pending_requests_.end()) { | 271 while (it != pending_requests_.end()) { |
| 272 chunk_stream_.GetMissedRanges(it->first, it->second, &ranges); | 272 chunk_stream_.GetMissedRanges(it->first, it->second, &ranges); |
| 273 pending_requests_.insert(it, ranges.begin(), ranges.end()); | 273 pending_requests_.insert(it, ranges.begin(), ranges.end()); |
| 274 ranges.clear(); | 274 ranges.clear(); |
| 275 pending_requests_.erase(it++); | 275 pending_requests_.erase(it++); |
| 276 } | 276 } |
| 277 } | 277 } |
| 278 | 278 |
| 279 void DocumentLoader::DownloadPendingRequests() { | 279 void DocumentLoader::DownloadPendingRequests() { |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 } else { | 409 } else { |
| 410 partial_document_ = false; | 410 partial_document_ = false; |
| 411 } | 411 } |
| 412 } | 412 } |
| 413 | 413 |
| 414 ReadMore(); | 414 ReadMore(); |
| 415 } | 415 } |
| 416 | 416 |
| 417 void DocumentLoader::ReadMore() { | 417 void DocumentLoader::ReadMore() { |
| 418 pp::CompletionCallback callback = | 418 pp::CompletionCallback callback = |
| 419 loader_factory_.NewCallback(&DocumentLoader::DidRead); | 419 loader_factory_.NewCallback(&DocumentLoader::DidRead); |
| 420 int rv = loader_.ReadResponseBody(buffer_, sizeof(buffer_), callback); | 420 int rv = loader_.ReadResponseBody(buffer_, sizeof(buffer_), callback); |
| 421 if (rv != PP_OK_COMPLETIONPENDING) | 421 if (rv != PP_OK_COMPLETIONPENDING) |
| 422 callback.Run(rv); | 422 callback.Run(rv); |
| 423 } | 423 } |
| 424 | 424 |
| 425 void DocumentLoader::DidRead(int32_t result) { | 425 void DocumentLoader::DidRead(int32_t result) { |
| 426 if (result <= 0) { | 426 if (result <= 0) { |
| 427 // If |result| == PP_OK, the document was loaded, otherwise an error was | 427 // If |result| == PP_OK, the document was loaded, otherwise an error was |
| 428 // encountered. Either way we want to stop processing the response. In the | 428 // encountered. Either way we want to stop processing the response. In the |
| 429 // case where an error occurred, the renderer will detect that we're missing | 429 // case where an error occurred, the renderer will detect that we're missing |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 current_request_offset_ + current_request_extended_size_) { | 508 current_request_offset_ + current_request_extended_size_) { |
| 509 loader_.Close(); | 509 loader_.Close(); |
| 510 } | 510 } |
| 511 } | 511 } |
| 512 | 512 |
| 513 ReadMore(); | 513 ReadMore(); |
| 514 } | 514 } |
| 515 | 515 |
| 516 bool DocumentLoader::SatisfyingRequest(size_t offset, size_t size) const { | 516 bool DocumentLoader::SatisfyingRequest(size_t offset, size_t size) const { |
| 517 return offset <= current_pos_ + kDefaultRequestSize && | 517 return offset <= current_pos_ + kDefaultRequestSize && |
| 518 current_pos_ < offset + size; | 518 current_pos_ < offset + size; |
| 519 } | 519 } |
| 520 | 520 |
| 521 void DocumentLoader::ReadComplete() { | 521 void DocumentLoader::ReadComplete() { |
| 522 if (!partial_document_) { | 522 if (!partial_document_) { |
| 523 if (document_size_ == 0) { | 523 if (document_size_ == 0) { |
| 524 // For the document with no 'content-length" specified we've collected all | 524 // For the document with no 'content-length" specified we've collected all |
| 525 // the chunks already. Let's allocate final document buffer and copy them | 525 // the chunks already. Let's allocate final document buffer and copy them |
| 526 // over. | 526 // over. |
| 527 chunk_stream_.Preallocate(current_pos_); | 527 chunk_stream_.Preallocate(current_pos_); |
| 528 uint32_t pos = 0; | 528 uint32_t pos = 0; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 550 | 550 |
| 551 void DocumentLoader::UpdateRendering() { | 551 void DocumentLoader::UpdateRendering() { |
| 552 if (header_request_) | 552 if (header_request_) |
| 553 client_->OnPartialDocumentLoaded(); | 553 client_->OnPartialDocumentLoaded(); |
| 554 else | 554 else |
| 555 client_->OnPendingRequestComplete(); | 555 client_->OnPendingRequestComplete(); |
| 556 header_request_ = false; | 556 header_request_ = false; |
| 557 } | 557 } |
| 558 | 558 |
| 559 } // namespace chrome_pdf | 559 } // namespace chrome_pdf |
| OLD | NEW |