url_request_file_dir_job.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_file_dir_job.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/sys_string_conversions.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h" 177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h> 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestFileDirJob::URLRequestFileDirJob(URLRequest* request, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetworkDelegate* network_delegate, 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& dir_path) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : URLRequestJob(request, network_delegate), 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) lister_(dir_path, this), 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dir_path_(dir_path), 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canceled_(false), 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list_complete_(false), 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wrote_header_(false), 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_pending_(false), 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_length_(0), 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_(this) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFileDirJob::StartAsync() { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lister_.Start(); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyHeadersComplete(); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFileDirJob::Start() { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start reading asynchronously so that all error reporting and data 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // callbacks happen as they would for network requests. 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&URLRequestFileDirJob::StartAsync, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_.GetWeakPtr())); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFileDirJob::Kill() { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (canceled_) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canceled_ = true; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!list_complete_) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lister_.Cancel(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequestJob::Kill(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_.InvalidateWeakPtrs(); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLRequestFileDirJob::ReadRawData(IOBuffer* buf, int buf_size, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* bytes_read) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(bytes_read); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bytes_read = 0; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_done()) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FillReadBuffer(buf->data(), buf_size, bytes_read)) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We are waiting for more data 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_pending_ = true; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_ = buf; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_length_ = buf_size; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLRequestFileDirJob::GetMimeType(std::string* mime_type) const { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *mime_type = "text/html"; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLRequestFileDirJob::GetCharset(std::string* charset) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All the filenames are converted to UTF-8 before being added. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *charset = "utf-8"; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFileDirJob::OnListFile( 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DirectoryLister::DirectoryListerData& data) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We wait to write out the header until we get the first file, so that we 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can catch errors from DirectoryLister and show an error page. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!wrote_header_) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::string16& title = dir_path_.value(); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jungshik): Add SysNativeMBToUTF16 to sys_string_conversions. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On Mac, need to add NFKC->NFC conversion either here or in file_path. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On Linux, the file system encoding is not defined, but we assume that 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SysNativeMBToWide takes care of it at least for now. We can try something 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // more sophisticated if necessary later. 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::string16& title = WideToUTF16( 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SysNativeMBToWide(dir_path_.value())); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_.append(GetDirectoryListingHeader(title)); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wrote_header_ = true; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string raw_bytes; // Empty on Windows means UTF-8 encoded name. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TOOD(jungshik): The same issue as for the directory name. 1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::FilePath filename = data.info.GetName(); 1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::string& raw_bytes = filename.value(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data_.append(GetDirectoryListingEntry( 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data.info.GetName().LossyDisplayName(), 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) raw_bytes, 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data.info.IsDirectory(), 129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data.info.GetSize(), 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data.info.GetLastModifiedTime())); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(darin): coalesce more? 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompleteRead(); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFileDirJob::OnListDone(int error) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!canceled_); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error != OK) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_pending_ = false; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, error)); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list_complete_ = true; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompleteRead(); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestFileDirJob::~URLRequestFileDirJob() {} 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFileDirJob::CompleteRead() { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read_pending_) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_read; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FillReadBuffer(read_buffer_->data(), read_buffer_length_, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bytes_read)) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We completed the read, so reset the read buffer. 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_pending_ = false; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_ = NULL; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_length_ = 0; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetStatus(URLRequestStatus()); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyReadComplete(bytes_read); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO: Better error code. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, 0)); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLRequestFileDirJob::FillReadBuffer(char* buf, int buf_size, 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* bytes_read) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(bytes_read); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bytes_read = 0; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = std::min(buf_size, static_cast<int>(data_.size())); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (count) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(buf, &data_[0], count); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_.erase(0, count); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bytes_read = count; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (list_complete_) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // EOF 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 189