1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "components/nacl/renderer/file_downloader.h" 6 7 #include "base/callback.h" 8 #include "components/nacl/renderer/nexe_load_manager.h" 9 #include "net/base/net_errors.h" 10 #include "third_party/WebKit/public/platform/WebURLError.h" 11 #include "third_party/WebKit/public/platform/WebURLLoader.h" 12 #include "third_party/WebKit/public/platform/WebURLResponse.h" 13 14 namespace nacl { 15 16 FileDownloader::FileDownloader(scoped_ptr<blink::WebURLLoader> url_loader, 17 base::File file, 18 StatusCallback status_cb, 19 ProgressCallback progress_cb) 20 : url_loader_(url_loader.Pass()), 21 file_(file.Pass()), 22 status_cb_(status_cb), 23 progress_cb_(progress_cb), 24 http_status_code_(-1), 25 total_bytes_received_(0), 26 total_bytes_to_be_received_(-1), 27 status_(SUCCESS) { 28 CHECK(!status_cb.is_null()); 29 } 30 31 FileDownloader::~FileDownloader() { 32 } 33 34 void FileDownloader::Load(const blink::WebURLRequest& request) { 35 url_loader_->loadAsynchronously(request, this); 36 } 37 38 void FileDownloader::didReceiveResponse( 39 blink::WebURLLoader* loader, 40 const blink::WebURLResponse& response) { 41 http_status_code_ = response.httpStatusCode(); 42 if (http_status_code_ != 200) 43 status_ = FAILED; 44 45 // Set -1 if the content length is unknown. Set before issuing callback. 46 total_bytes_to_be_received_ = response.expectedContentLength(); 47 if (!progress_cb_.is_null()) 48 progress_cb_.Run(total_bytes_received_, total_bytes_to_be_received_); 49 } 50 51 void FileDownloader::didReceiveData( 52 blink::WebURLLoader* loader, 53 const char* data, 54 int data_length, 55 int encoded_data_length) { 56 if (status_ == SUCCESS) { 57 if (file_.Write(total_bytes_received_, data, data_length) == -1) { 58 status_ = FAILED; 59 return; 60 } 61 total_bytes_received_ += data_length; 62 if (!progress_cb_.is_null()) 63 progress_cb_.Run(total_bytes_received_, total_bytes_to_be_received_); 64 } 65 } 66 67 void FileDownloader::didFinishLoading( 68 blink::WebURLLoader* loader, 69 double finish_time, 70 int64_t total_encoded_data_length) { 71 if (status_ == SUCCESS) { 72 // Seek back to the beginning of the file that was just written so it's 73 // easy for consumers to use. 74 if (file_.Seek(base::File::FROM_BEGIN, 0) != 0) 75 status_ = FAILED; 76 } 77 status_cb_.Run(status_, file_.Pass(), http_status_code_); 78 delete this; 79 } 80 81 void FileDownloader::didFail( 82 blink::WebURLLoader* loader, 83 const blink::WebURLError& error) { 84 status_ = FAILED; 85 if (error.domain.equals(blink::WebString::fromUTF8(net::kErrorDomain))) { 86 switch (error.reason) { 87 case net::ERR_ACCESS_DENIED: 88 case net::ERR_NETWORK_ACCESS_DENIED: 89 status_ = ACCESS_DENIED; 90 break; 91 } 92 } else { 93 // It's a WebKit error. 94 status_ = ACCESS_DENIED; 95 } 96 } 97 98 } // namespace nacl 99