url_request_file_dir_job.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)// found in the LICENSE file. 493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "net/url_request/url_request_file_dir_job.h" 693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "base/bind.h" 893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "base/compiler_specific.h" 993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "base/message_loop/message_loop.h" 1093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "base/strings/sys_string_conversions.h" 1193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 1293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "base/time/time.h" 1393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "net/base/io_buffer.h" 1493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "net/base/net_errors.h" 1593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "net/base/net_util.h" 1693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "net/url_request/url_request_status.h" 1793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "url/gurl.h" 1893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 1993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#if defined(OS_POSIX) 2093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include <sys/stat.h> 2193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#endif 2293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 2393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)namespace net { 2493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 2593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)URLRequestFileDirJob::URLRequestFileDirJob(URLRequest* request, 2693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) NetworkDelegate* network_delegate, 2793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) const base::FilePath& dir_path) 2893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) : URLRequestJob(request, network_delegate), 2993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) lister_(dir_path, this), 3093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) dir_path_(dir_path), 3193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) canceled_(false), 3293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) list_complete_(false), 3393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) wrote_header_(false), 3493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) read_pending_(false), 3593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) read_buffer_length_(0), 3693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) weak_factory_(this) { 3793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)} 3893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 39c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void URLRequestFileDirJob::StartAsync() { 4093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) lister_.Start(); 41e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 4293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) NotifyHeadersComplete(); 4393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)} 4493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 4593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void URLRequestFileDirJob::Start() { 4693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // Start reading asynchronously so that all error reporting and data 4793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // callbacks happen as they would for network requests. 4893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) base::MessageLoop::current()->PostTask( 4993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) FROM_HERE, 5093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) base::Bind(&URLRequestFileDirJob::StartAsync, 5193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) weak_factory_.GetWeakPtr())); 5293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)} 5393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 5493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void URLRequestFileDirJob::Kill() { 5593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (canceled_) 5693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) return; 5793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 5893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) canceled_ = true; 5993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 6093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (!list_complete_) 6109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) lister_.Cancel(); 6293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 6309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) URLRequestJob::Kill(); 6493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 6593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) weak_factory_.InvalidateWeakPtrs(); 6609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 6709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 6893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)bool URLRequestFileDirJob::ReadRawData(IOBuffer* buf, int buf_size, 6993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) int* bytes_read) { 7093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) DCHECK(bytes_read); 7193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) *bytes_read = 0; 7293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (is_done()) 7409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return true; 7593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 7609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (FillReadBuffer(buf->data(), buf_size, bytes_read)) 777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return true; 7893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 7993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // We are waiting for more data 8093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) read_pending_ = true; 81e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) read_buffer_ = buf; 8293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) read_buffer_length_ = buf_size; 8393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); 8451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) return false; 8593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)} 8693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 87bool URLRequestFileDirJob::GetMimeType(std::string* mime_type) const { 88 *mime_type = "text/html"; 89 return true; 90} 91 92bool URLRequestFileDirJob::GetCharset(std::string* charset) { 93 // All the filenames are converted to UTF-8 before being added. 94 *charset = "utf-8"; 95 return true; 96} 97 98void URLRequestFileDirJob::OnListFile( 99 const DirectoryLister::DirectoryListerData& data) { 100 // We wait to write out the header until we get the first file, so that we 101 // can catch errors from DirectoryLister and show an error page. 102 if (!wrote_header_) { 103#if defined(OS_WIN) 104 const base::string16& title = dir_path_.value(); 105#elif defined(OS_POSIX) 106 // TODO(jungshik): Add SysNativeMBToUTF16 to sys_string_conversions. 107 // On Mac, need to add NFKC->NFC conversion either here or in file_path. 108 // On Linux, the file system encoding is not defined, but we assume that 109 // SysNativeMBToWide takes care of it at least for now. We can try something 110 // more sophisticated if necessary later. 111 const base::string16& title = WideToUTF16( 112 base::SysNativeMBToWide(dir_path_.value())); 113#endif 114 data_.append(GetDirectoryListingHeader(title)); 115 wrote_header_ = true; 116 } 117 118#if defined(OS_WIN) 119 std::string raw_bytes; // Empty on Windows means UTF-8 encoded name. 120#elif defined(OS_POSIX) 121 // TOOD(jungshik): The same issue as for the directory name. 122 base::FilePath filename = data.info.GetName(); 123 const std::string& raw_bytes = filename.value(); 124#endif 125 data_.append(GetDirectoryListingEntry( 126 data.info.GetName().LossyDisplayName(), 127 raw_bytes, 128 data.info.IsDirectory(), 129 data.info.GetSize(), 130 data.info.GetLastModifiedTime())); 131 132 // TODO(darin): coalesce more? 133 CompleteRead(); 134} 135 136void URLRequestFileDirJob::OnListDone(int error) { 137 DCHECK(!canceled_); 138 if (error != OK) { 139 read_pending_ = false; 140 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, error)); 141 } else { 142 list_complete_ = true; 143 CompleteRead(); 144 } 145} 146 147URLRequestFileDirJob::~URLRequestFileDirJob() {} 148 149void URLRequestFileDirJob::CompleteRead() { 150 if (read_pending_) { 151 int bytes_read; 152 if (FillReadBuffer(read_buffer_->data(), read_buffer_length_, 153 &bytes_read)) { 154 // We completed the read, so reset the read buffer. 155 read_pending_ = false; 156 read_buffer_ = NULL; 157 read_buffer_length_ = 0; 158 159 SetStatus(URLRequestStatus()); 160 NotifyReadComplete(bytes_read); 161 } else { 162 NOTREACHED(); 163 // TODO: Better error code. 164 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, 0)); 165 } 166 } 167} 168 169bool URLRequestFileDirJob::FillReadBuffer(char* buf, int buf_size, 170 int* bytes_read) { 171 DCHECK(bytes_read); 172 173 *bytes_read = 0; 174 175 int count = std::min(buf_size, static_cast<int>(data_.size())); 176 if (count) { 177 memcpy(buf, &data_[0], count); 178 data_.erase(0, count); 179 *bytes_read = count; 180 return true; 181 } else if (list_complete_) { 182 // EOF 183 return true; 184 } 185 return false; 186} 187 188} // namespace net 189