Home | History | Annotate | Download | only in url_request
      1 // Copyright (c) 2013 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 "net/url_request/url_fetcher_response_writer.h"
      6 
      7 #include "base/file_util.h"
      8 #include "base/location.h"
      9 #include "base/task_runner.h"
     10 #include "base/task_runner_util.h"
     11 #include "net/base/file_stream.h"
     12 #include "net/base/io_buffer.h"
     13 #include "net/base/net_errors.h"
     14 
     15 namespace net {
     16 
     17 URLFetcherStringWriter::URLFetcherStringWriter(std::string* string)
     18     : string_(string) {
     19 }
     20 
     21 URLFetcherStringWriter::~URLFetcherStringWriter() {
     22 }
     23 
     24 int URLFetcherStringWriter::Initialize(const CompletionCallback& callback) {
     25   // Do nothing.
     26   return OK;
     27 }
     28 
     29 int URLFetcherStringWriter::Write(IOBuffer* buffer,
     30                                   int num_bytes,
     31                                   const CompletionCallback& callback) {
     32   string_->append(buffer->data(), num_bytes);
     33   return num_bytes;
     34 }
     35 
     36 int URLFetcherStringWriter::Finish(const CompletionCallback& callback) {
     37   // Do nothing.
     38   return OK;
     39 }
     40 
     41 URLFetcherFileWriter::URLFetcherFileWriter(
     42     scoped_refptr<base::TaskRunner> file_task_runner)
     43     : error_code_(OK),
     44       weak_factory_(this),
     45       file_task_runner_(file_task_runner),
     46       owns_file_(false),
     47       total_bytes_written_(0) {
     48   DCHECK(file_task_runner_.get());
     49 }
     50 
     51 URLFetcherFileWriter::~URLFetcherFileWriter() {
     52   CloseAndDeleteFile();
     53 }
     54 
     55 int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) {
     56   DCHECK(!file_stream_);
     57   DCHECK(!owns_file_);
     58 
     59   file_stream_.reset(new FileStream(NULL));
     60 
     61   int result = ERR_IO_PENDING;
     62   if (file_path_.empty()) {
     63     base::FilePath* temp_file_path = new base::FilePath;
     64     base::PostTaskAndReplyWithResult(
     65         file_task_runner_.get(),
     66         FROM_HERE,
     67         base::Bind(&file_util::CreateTemporaryFile, temp_file_path),
     68         base::Bind(&URLFetcherFileWriter::DidCreateTempFile,
     69                    weak_factory_.GetWeakPtr(),
     70                    callback,
     71                    base::Owned(temp_file_path)));
     72   } else {
     73     result = file_stream_->Open(
     74         file_path_,
     75         base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC |
     76         base::PLATFORM_FILE_CREATE_ALWAYS,
     77         base::Bind(&URLFetcherFileWriter::DidOpenFile,
     78                    weak_factory_.GetWeakPtr(),
     79                    callback));
     80     DCHECK_NE(OK, result);
     81     if (result != ERR_IO_PENDING)
     82       error_code_ = result;
     83   }
     84   return result;
     85 }
     86 
     87 int URLFetcherFileWriter::Write(IOBuffer* buffer,
     88                                 int num_bytes,
     89                                 const CompletionCallback& callback) {
     90   DCHECK(file_stream_);
     91   DCHECK(owns_file_);
     92 
     93   int result = file_stream_->Write(buffer, num_bytes,
     94                                    base::Bind(&URLFetcherFileWriter::DidWrite,
     95                                               weak_factory_.GetWeakPtr(),
     96                                               callback));
     97   if (result < 0 && result != ERR_IO_PENDING) {
     98     error_code_ = result;
     99     CloseAndDeleteFile();
    100   }
    101   return result;
    102 }
    103 
    104 int URLFetcherFileWriter::Finish(const CompletionCallback& callback) {
    105   file_stream_.reset();
    106   return OK;
    107 }
    108 
    109 void URLFetcherFileWriter::DidWrite(const CompletionCallback& callback,
    110                                     int result) {
    111   if (result < 0) {
    112     error_code_ = result;
    113     CloseAndDeleteFile();
    114   }
    115   callback.Run(result);
    116 }
    117 
    118 void URLFetcherFileWriter::DisownFile() {
    119   // Disowning is done by the delegate's OnURLFetchComplete method.
    120   // The file should be closed by the time that method is called.
    121   DCHECK(!file_stream_);
    122 
    123   owns_file_ = false;
    124 }
    125 
    126 void URLFetcherFileWriter::CloseAndDeleteFile() {
    127   if (!owns_file_)
    128     return;
    129 
    130   file_stream_.reset();
    131   DisownFile();
    132   file_task_runner_->PostTask(FROM_HERE,
    133                               base::Bind(base::IgnoreResult(&base::DeleteFile),
    134                                          file_path_,
    135                                          false /* recursive */));
    136 }
    137 
    138 void URLFetcherFileWriter::DidCreateTempFile(const CompletionCallback& callback,
    139                                              base::FilePath* temp_file_path,
    140                                              bool success) {
    141   if (!success) {
    142     error_code_ = ERR_FILE_NOT_FOUND;
    143     callback.Run(error_code_);
    144     return;
    145   }
    146   file_path_ = *temp_file_path;
    147   owns_file_ = true;
    148   const int result = file_stream_->Open(
    149       file_path_,
    150       base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC |
    151       base::PLATFORM_FILE_OPEN,
    152       base::Bind(&URLFetcherFileWriter::DidOpenFile,
    153                  weak_factory_.GetWeakPtr(),
    154                  callback));
    155   if (result != ERR_IO_PENDING)
    156     DidOpenFile(callback, result);
    157 }
    158 
    159 void URLFetcherFileWriter::DidOpenFile(const CompletionCallback& callback,
    160                                        int result) {
    161   if (result == OK) {
    162     total_bytes_written_ = 0;
    163     owns_file_ = true;
    164   } else {
    165     error_code_ = result;
    166     CloseAndDeleteFile();
    167   }
    168   callback.Run(result);
    169 }
    170 
    171 }  // namespace net
    172