Home | History | Annotate | Download | only in fileapi
      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