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 3 // found in the LICENSE file. 4 5 #include "webkit/browser/fileapi/file_system_dir_url_request_job.h" 6 7 #include <algorithm> 8 9 #include "base/bind.h" 10 #include "base/compiler_specific.h" 11 #include "base/message_loop/message_loop.h" 12 #include "base/platform_file.h" 13 #include "base/strings/sys_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "base/time/time.h" 16 #include "build/build_config.h" 17 #include "net/base/io_buffer.h" 18 #include "net/base/net_errors.h" 19 #include "net/base/net_util.h" 20 #include "net/url_request/url_request.h" 21 #include "url/gurl.h" 22 #include "webkit/browser/fileapi/file_system_context.h" 23 #include "webkit/browser/fileapi/file_system_operation_runner.h" 24 #include "webkit/browser/fileapi/file_system_url.h" 25 #include "webkit/common/fileapi/directory_entry.h" 26 27 using net::NetworkDelegate; 28 using net::URLRequest; 29 using net::URLRequestJob; 30 using net::URLRequestStatus; 31 32 namespace fileapi { 33 34 FileSystemDirURLRequestJob::FileSystemDirURLRequestJob( 35 URLRequest* request, 36 NetworkDelegate* network_delegate, 37 FileSystemContext* file_system_context) 38 : URLRequestJob(request, network_delegate), 39 file_system_context_(file_system_context), 40 weak_factory_(this) { 41 } 42 43 FileSystemDirURLRequestJob::~FileSystemDirURLRequestJob() { 44 } 45 46 bool FileSystemDirURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size, 47 int *bytes_read) { 48 int count = std::min(dest_size, static_cast<int>(data_.size())); 49 if (count > 0) { 50 memcpy(dest->data(), data_.data(), count); 51 data_.erase(0, count); 52 } 53 *bytes_read = count; 54 return true; 55 } 56 57 void FileSystemDirURLRequestJob::Start() { 58 base::MessageLoop::current()->PostTask( 59 FROM_HERE, 60 base::Bind(&FileSystemDirURLRequestJob::StartAsync, 61 weak_factory_.GetWeakPtr())); 62 } 63 64 void FileSystemDirURLRequestJob::Kill() { 65 URLRequestJob::Kill(); 66 weak_factory_.InvalidateWeakPtrs(); 67 } 68 69 bool FileSystemDirURLRequestJob::GetMimeType(std::string* mime_type) const { 70 *mime_type = "text/html"; 71 return true; 72 } 73 74 bool FileSystemDirURLRequestJob::GetCharset(std::string* charset) { 75 *charset = "utf-8"; 76 return true; 77 } 78 79 void FileSystemDirURLRequestJob::StartAsync() { 80 if (!request_) 81 return; 82 url_ = file_system_context_->CrackURL(request_->url()); 83 file_system_context_->operation_runner()->ReadDirectory( 84 url_, 85 base::Bind(&FileSystemDirURLRequestJob::DidReadDirectory, this)); 86 } 87 88 void FileSystemDirURLRequestJob::DidReadDirectory( 89 base::PlatformFileError result, 90 const std::vector<DirectoryEntry>& entries, 91 bool has_more) { 92 if (result != base::PLATFORM_FILE_OK) { 93 int rv = net::ERR_FILE_NOT_FOUND; 94 if (result == base::PLATFORM_FILE_ERROR_INVALID_URL) 95 rv = net::ERR_INVALID_URL; 96 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); 97 return; 98 } 99 100 if (!request_) 101 return; 102 103 if (data_.empty()) { 104 base::FilePath relative_path = url_.path(); 105 #if defined(OS_POSIX) 106 relative_path = base::FilePath(FILE_PATH_LITERAL("/") + relative_path.value()); 107 #endif 108 const base::string16& title = relative_path.LossyDisplayName(); 109 data_.append(net::GetDirectoryListingHeader(title)); 110 } 111 112 typedef std::vector<DirectoryEntry>::const_iterator EntryIterator; 113 for (EntryIterator it = entries.begin(); it != entries.end(); ++it) { 114 const base::string16& name = base::FilePath(it->name).LossyDisplayName(); 115 data_.append(net::GetDirectoryListingEntry( 116 name, std::string(), it->is_directory, it->size, 117 it->last_modified_time)); 118 } 119 120 if (has_more) { 121 file_system_context_->operation_runner()->ReadDirectory( 122 url_, 123 base::Bind(&FileSystemDirURLRequestJob::DidReadDirectory, this)); 124 } else { 125 set_expected_content_size(data_.size()); 126 NotifyHeadersComplete(); 127 } 128 } 129 130 } // namespace fileapi 131