| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "storage/browser/fileapi/file_system_url_request_job.h" | 5 #include "storage/browser/fileapi/file_system_url_request_job.h" | 
| 6 | 6 | 
| 7 #include <vector> | 7 #include <vector> | 
| 8 | 8 | 
| 9 #include "base/bind.h" | 9 #include "base/bind.h" | 
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 55 FileSystemURLRequestJob::FileSystemURLRequestJob( | 55 FileSystemURLRequestJob::FileSystemURLRequestJob( | 
| 56     URLRequest* request, | 56     URLRequest* request, | 
| 57     NetworkDelegate* network_delegate, | 57     NetworkDelegate* network_delegate, | 
| 58     const std::string& storage_domain, | 58     const std::string& storage_domain, | 
| 59     FileSystemContext* file_system_context) | 59     FileSystemContext* file_system_context) | 
| 60     : URLRequestJob(request, network_delegate), | 60     : URLRequestJob(request, network_delegate), | 
| 61       storage_domain_(storage_domain), | 61       storage_domain_(storage_domain), | 
| 62       file_system_context_(file_system_context), | 62       file_system_context_(file_system_context), | 
| 63       is_directory_(false), | 63       is_directory_(false), | 
| 64       remaining_bytes_(0), | 64       remaining_bytes_(0), | 
| 65       weak_factory_(this) { | 65       range_parse_result_(net::OK), | 
| 66 } | 66       weak_factory_(this) {} | 
| 67 | 67 | 
| 68 FileSystemURLRequestJob::~FileSystemURLRequestJob() {} | 68 FileSystemURLRequestJob::~FileSystemURLRequestJob() {} | 
| 69 | 69 | 
| 70 void FileSystemURLRequestJob::Start() { | 70 void FileSystemURLRequestJob::Start() { | 
| 71   base::MessageLoop::current()->PostTask( | 71   base::MessageLoop::current()->PostTask( | 
| 72       FROM_HERE, | 72       FROM_HERE, | 
| 73       base::Bind(&FileSystemURLRequestJob::StartAsync, | 73       base::Bind(&FileSystemURLRequestJob::StartAsync, | 
| 74                  weak_factory_.GetWeakPtr())); | 74                  weak_factory_.GetWeakPtr())); | 
| 75 } | 75 } | 
| 76 | 76 | 
| 77 void FileSystemURLRequestJob::Kill() { | 77 void FileSystemURLRequestJob::Kill() { | 
| 78   reader_.reset(); | 78   reader_.reset(); | 
| 79   URLRequestJob::Kill(); | 79   URLRequestJob::Kill(); | 
| 80   weak_factory_.InvalidateWeakPtrs(); | 80   weak_factory_.InvalidateWeakPtrs(); | 
| 81 } | 81 } | 
| 82 | 82 | 
| 83 bool FileSystemURLRequestJob::ReadRawData(net::IOBuffer* dest, | 83 int FileSystemURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size) { | 
| 84                                           int dest_size, |  | 
| 85                                           int* bytes_read) { |  | 
| 86   DCHECK_NE(dest_size, 0); | 84   DCHECK_NE(dest_size, 0); | 
| 87   DCHECK(bytes_read); |  | 
| 88   DCHECK_GE(remaining_bytes_, 0); | 85   DCHECK_GE(remaining_bytes_, 0); | 
| 89 | 86 | 
| 90   if (reader_.get() == NULL) | 87   if (reader_.get() == NULL) | 
| 91     return false; | 88     return net::ERR_FAILED; | 
| 92 | 89 | 
| 93   if (remaining_bytes_ < dest_size) | 90   if (remaining_bytes_ < dest_size) | 
| 94     dest_size = static_cast<int>(remaining_bytes_); | 91     dest_size = remaining_bytes_; | 
| 95 | 92 | 
| 96   if (!dest_size) { | 93   if (!dest_size) | 
| 97     *bytes_read = 0; | 94     return 0; | 
| 98     return true; |  | 
| 99   } |  | 
| 100 | 95 | 
| 101   const int rv = reader_->Read(dest, dest_size, | 96   const int rv = reader_->Read(dest, dest_size, | 
| 102                                base::Bind(&FileSystemURLRequestJob::DidRead, | 97                                base::Bind(&FileSystemURLRequestJob::DidRead, | 
| 103                                           weak_factory_.GetWeakPtr())); | 98                                           weak_factory_.GetWeakPtr())); | 
| 104   if (rv >= 0) { | 99   if (rv >= 0) { | 
| 105     // Data is immediately available. |  | 
| 106     *bytes_read = rv; |  | 
| 107     remaining_bytes_ -= rv; | 100     remaining_bytes_ -= rv; | 
| 108     DCHECK_GE(remaining_bytes_, 0); | 101     DCHECK_GE(remaining_bytes_, 0); | 
| 109     return true; |  | 
| 110   } | 102   } | 
| 111   if (rv == net::ERR_IO_PENDING) | 103 | 
| 112     SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); | 104   return rv; | 
| 113   else |  | 
| 114     NotifyFailed(rv); |  | 
| 115   return false; |  | 
| 116 } | 105 } | 
| 117 | 106 | 
| 118 bool FileSystemURLRequestJob::GetMimeType(std::string* mime_type) const { | 107 bool FileSystemURLRequestJob::GetMimeType(std::string* mime_type) const { | 
| 119   DCHECK(request_); | 108   DCHECK(request_); | 
| 120   DCHECK(url_.is_valid()); | 109   DCHECK(url_.is_valid()); | 
| 121   base::FilePath::StringType extension = url_.path().Extension(); | 110   base::FilePath::StringType extension = url_.path().Extension(); | 
| 122   if (!extension.empty()) | 111   if (!extension.empty()) | 
| 123     extension = extension.substr(1); | 112     extension = extension.substr(1); | 
| 124   return net::GetWellKnownMimeTypeFromExtension(extension, mime_type); | 113   return net::GetWellKnownMimeTypeFromExtension(extension, mime_type); | 
| 125 } | 114 } | 
| 126 | 115 | 
|  | 116 // Extracts headers that this job cares about from the supplied request headers. | 
|  | 117 // Currently this job only cares about the Range header. Note that validation is | 
|  | 118 // deferred to DidGetMetaData(), because this method may be called with a | 
|  | 119 // net::URLRequest::Delegate call still on the stack, which means | 
|  | 120 // NotifyStartError is not safe to call (it may reenter the delegate). | 
| 127 void FileSystemURLRequestJob::SetExtraRequestHeaders( | 121 void FileSystemURLRequestJob::SetExtraRequestHeaders( | 
| 128     const net::HttpRequestHeaders& headers) { | 122     const net::HttpRequestHeaders& headers) { | 
| 129   std::string range_header; | 123   std::string range_header; | 
| 130   if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { | 124   if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { | 
| 131     std::vector<net::HttpByteRange> ranges; | 125     std::vector<net::HttpByteRange> ranges; | 
|  | 126 | 
| 132     if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { | 127     if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { | 
| 133       if (ranges.size() == 1) { | 128       if (ranges.size() == 1) { | 
| 134         byte_range_ = ranges[0]; | 129         byte_range_ = ranges[0]; | 
| 135       } else { | 130       } else { | 
| 136         // We don't support multiple range requests in one single URL request. | 131         // We don't support multiple range requests in one single URL request. | 
|  | 132         // Saves the failure which will be reported in DidGetMetaData. | 
| 137         // TODO(adamk): decide whether we want to support multiple range | 133         // TODO(adamk): decide whether we want to support multiple range | 
| 138         // requests. | 134         // requests. | 
| 139         NotifyFailed(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); | 135         range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; | 
| 140       } | 136       } | 
| 141     } | 137     } | 
| 142   } | 138   } | 
| 143 } | 139 } | 
| 144 | 140 | 
| 145 void FileSystemURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) { | 141 void FileSystemURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) { | 
| 146   if (response_info_) | 142   if (response_info_) | 
| 147     *info = *response_info_; | 143     *info = *response_info_; | 
| 148 } | 144 } | 
| 149 | 145 | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 161   if (!url_.is_valid()) { | 157   if (!url_.is_valid()) { | 
| 162     file_system_context_->AttemptAutoMountForURLRequest( | 158     file_system_context_->AttemptAutoMountForURLRequest( | 
| 163         request_, | 159         request_, | 
| 164         storage_domain_, | 160         storage_domain_, | 
| 165         base::Bind(&FileSystemURLRequestJob::DidAttemptAutoMount, | 161         base::Bind(&FileSystemURLRequestJob::DidAttemptAutoMount, | 
| 166                    weak_factory_.GetWeakPtr())); | 162                    weak_factory_.GetWeakPtr())); | 
| 167     return; | 163     return; | 
| 168   } | 164   } | 
| 169   if (!file_system_context_->CanServeURLRequest(url_)) { | 165   if (!file_system_context_->CanServeURLRequest(url_)) { | 
| 170     // In incognito mode the API is not usable and there should be no data. | 166     // In incognito mode the API is not usable and there should be no data. | 
| 171     NotifyFailed(net::ERR_FILE_NOT_FOUND); | 167     NotifyStartError(URLRequestStatus::FromError(net::ERR_FILE_NOT_FOUND)); | 
| 172     return; | 168     return; | 
| 173   } | 169   } | 
| 174   file_system_context_->operation_runner()->GetMetadata( | 170   file_system_context_->operation_runner()->GetMetadata( | 
| 175       url_, | 171       url_, | 
| 176       base::Bind(&FileSystemURLRequestJob::DidGetMetadata, | 172       base::Bind(&FileSystemURLRequestJob::DidGetMetadata, | 
| 177                  weak_factory_.GetWeakPtr())); | 173                  weak_factory_.GetWeakPtr())); | 
| 178 } | 174 } | 
| 179 | 175 | 
| 180 void FileSystemURLRequestJob::DidAttemptAutoMount(base::File::Error result) { | 176 void FileSystemURLRequestJob::DidAttemptAutoMount(base::File::Error result) { | 
| 181   if (result >= 0 && | 177   if (result >= 0 && | 
| 182       file_system_context_->CrackURL(request_->url()).is_valid()) { | 178       file_system_context_->CrackURL(request_->url()).is_valid()) { | 
| 183     StartAsync(); | 179     StartAsync(); | 
| 184   } else { | 180   } else { | 
| 185     NotifyFailed(net::ERR_FILE_NOT_FOUND); | 181     NotifyStartError(URLRequestStatus::FromError(net::ERR_FILE_NOT_FOUND)); | 
| 186   } | 182   } | 
| 187 } | 183 } | 
| 188 | 184 | 
| 189 void FileSystemURLRequestJob::DidGetMetadata( | 185 void FileSystemURLRequestJob::DidGetMetadata( | 
| 190     base::File::Error error_code, | 186     base::File::Error error_code, | 
| 191     const base::File::Info& file_info) { | 187     const base::File::Info& file_info) { | 
| 192   if (error_code != base::File::FILE_OK) { | 188   if (error_code != base::File::FILE_OK) { | 
| 193     NotifyFailed(error_code == base::File::FILE_ERROR_INVALID_URL ? | 189     NotifyStartError(URLRequestStatus::FromError( | 
| 194                  net::ERR_INVALID_URL : net::ERR_FILE_NOT_FOUND); | 190         error_code == base::File::FILE_ERROR_INVALID_URL | 
|  | 191             ? net::ERR_INVALID_URL | 
|  | 192             : net::ERR_FILE_NOT_FOUND)); | 
| 195     return; | 193     return; | 
| 196   } | 194   } | 
| 197 | 195 | 
| 198   // We may have been orphaned... | 196   // We may have been orphaned... | 
| 199   if (!request_) | 197   if (!request_) | 
| 200     return; | 198     return; | 
| 201 | 199 | 
| 202   is_directory_ = file_info.is_directory; | 200   is_directory_ = file_info.is_directory; | 
| 203 | 201 | 
| 204   if (!byte_range_.ComputeBounds(file_info.size)) { | 202   if (range_parse_result_ != net::OK) { | 
| 205     NotifyFailed(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); | 203     NotifyStartError(URLRequestStatus::FromError(range_parse_result_)); | 
| 206     return; | 204     return; | 
| 207   } | 205   } | 
| 208 | 206 | 
|  | 207   if (!byte_range_.ComputeBounds(file_info.size)) { | 
|  | 208     NotifyStartError( | 
|  | 209         URLRequestStatus::FromError(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); | 
|  | 210     return; | 
|  | 211   } | 
|  | 212 | 
| 209   if (is_directory_) { | 213   if (is_directory_) { | 
| 210     NotifyHeadersComplete(); | 214     NotifyHeadersComplete(); | 
| 211     return; | 215     return; | 
| 212   } | 216   } | 
| 213 | 217 | 
| 214   remaining_bytes_ = byte_range_.last_byte_position() - | 218   remaining_bytes_ = byte_range_.last_byte_position() - | 
| 215                      byte_range_.first_byte_position() + 1; | 219                      byte_range_.first_byte_position() + 1; | 
| 216   DCHECK_GE(remaining_bytes_, 0); | 220   DCHECK_GE(remaining_bytes_, 0); | 
| 217 | 221 | 
| 218   DCHECK(!reader_.get()); | 222   DCHECK(!reader_.get()); | 
| 219   reader_ = file_system_context_->CreateFileStreamReader( | 223   reader_ = file_system_context_->CreateFileStreamReader( | 
| 220       url_, byte_range_.first_byte_position(), remaining_bytes_, base::Time()); | 224       url_, byte_range_.first_byte_position(), remaining_bytes_, base::Time()); | 
| 221 | 225 | 
| 222   set_expected_content_size(remaining_bytes_); | 226   set_expected_content_size(remaining_bytes_); | 
| 223   response_info_.reset(new net::HttpResponseInfo()); | 227   response_info_.reset(new net::HttpResponseInfo()); | 
| 224   response_info_->headers = CreateHttpResponseHeaders(); | 228   response_info_->headers = CreateHttpResponseHeaders(); | 
| 225   NotifyHeadersComplete(); | 229   NotifyHeadersComplete(); | 
| 226 } | 230 } | 
| 227 | 231 | 
| 228 void FileSystemURLRequestJob::DidRead(int result) { | 232 void FileSystemURLRequestJob::DidRead(int result) { | 
| 229   if (result > 0) | 233   if (result >= 0) { | 
| 230     SetStatus(URLRequestStatus());  // Clear the IO_PENDING status | 234     remaining_bytes_ -= result; | 
| 231   else if (result == 0) | 235     DCHECK_GE(remaining_bytes_, 0); | 
| 232     NotifyDone(URLRequestStatus()); | 236   } | 
| 233   else |  | 
| 234     NotifyFailed(result); |  | 
| 235 | 237 | 
| 236   remaining_bytes_ -= result; | 238   ReadRawDataComplete(result); | 
| 237   DCHECK_GE(remaining_bytes_, 0); |  | 
| 238 |  | 
| 239   NotifyReadComplete(result); |  | 
| 240 } | 239 } | 
| 241 | 240 | 
| 242 bool FileSystemURLRequestJob::IsRedirectResponse(GURL* location, | 241 bool FileSystemURLRequestJob::IsRedirectResponse(GURL* location, | 
| 243                                                  int* http_status_code) { | 242                                                  int* http_status_code) { | 
| 244   if (is_directory_) { | 243   if (is_directory_) { | 
| 245     // This happens when we discovered the file is a directory, so needs a | 244     // This happens when we discovered the file is a directory, so needs a | 
| 246     // slash at the end of the path. | 245     // slash at the end of the path. | 
| 247     std::string new_path = request_->url().path(); | 246     std::string new_path = request_->url().path(); | 
| 248     new_path.push_back('/'); | 247     new_path.push_back('/'); | 
| 249     GURL::Replacements replacements; | 248     GURL::Replacements replacements; | 
| 250     replacements.SetPathStr(new_path); | 249     replacements.SetPathStr(new_path); | 
| 251     *location = request_->url().ReplaceComponents(replacements); | 250     *location = request_->url().ReplaceComponents(replacements); | 
| 252     *http_status_code = 301;  // simulate a permanent redirect | 251     *http_status_code = 301;  // simulate a permanent redirect | 
| 253     return true; | 252     return true; | 
| 254   } | 253   } | 
| 255 | 254 | 
| 256   return false; | 255   return false; | 
| 257 } | 256 } | 
| 258 | 257 | 
| 259 void FileSystemURLRequestJob::NotifyFailed(int rv) { |  | 
| 260   NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); |  | 
| 261 } |  | 
| 262 |  | 
| 263 }  // namespace storage | 258 }  // namespace storage | 
| OLD | NEW | 
|---|