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/sequenced_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* URLFetcherResponseWriter::AsStringWriter() {
     18   return NULL;
     19 }
     20 
     21 URLFetcherFileWriter* URLFetcherResponseWriter::AsFileWriter() {
     22   return NULL;
     23 }
     24 
     25 URLFetcherStringWriter::URLFetcherStringWriter() {
     26 }
     27 
     28 URLFetcherStringWriter::~URLFetcherStringWriter() {
     29 }
     30 
     31 int URLFetcherStringWriter::Initialize(const CompletionCallback& callback) {
     32   data_.clear();
     33   return OK;
     34 }
     35 
     36 int URLFetcherStringWriter::Write(IOBuffer* buffer,
     37                                   int num_bytes,
     38                                   const CompletionCallback& callback) {
     39   data_.append(buffer->data(), num_bytes);
     40   return num_bytes;
     41 }
     42 
     43 int URLFetcherStringWriter::Finish(const CompletionCallback& callback) {
     44   // Do nothing.
     45   return OK;
     46 }
     47 
     48 URLFetcherStringWriter* URLFetcherStringWriter::AsStringWriter() {
     49   return this;
     50 }
     51 
     52 URLFetcherFileWriter::URLFetcherFileWriter(
     53     scoped_refptr<base::SequencedTaskRunner> file_task_runner,
     54     const base::FilePath& file_path)
     55     : file_task_runner_(file_task_runner),
     56       file_path_(file_path),
     57       owns_file_(false),
     58       weak_factory_(this) {
     59   DCHECK(file_task_runner_.get());
     60 }
     61 
     62 URLFetcherFileWriter::~URLFetcherFileWriter() {
     63   CloseAndDeleteFile();
     64 }
     65 
     66 int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) {
     67   file_stream_.reset(new FileStream(file_task_runner_));
     68 
     69   int result = ERR_IO_PENDING;
     70   if (file_path_.empty()) {
     71     base::FilePath* temp_file_path = new base::FilePath;
     72     base::PostTaskAndReplyWithResult(
     73         file_task_runner_.get(),
     74         FROM_HERE,
     75         base::Bind(&base::CreateTemporaryFile, temp_file_path),
     76         base::Bind(&URLFetcherFileWriter::DidCreateTempFile,
     77                    weak_factory_.GetWeakPtr(),
     78                    callback,
     79                    base::Owned(temp_file_path)));
     80   } else {
     81     result = file_stream_->Open(
     82         file_path_,
     83         base::File::FLAG_WRITE | base::File::FLAG_ASYNC |
     84         base::File::FLAG_CREATE_ALWAYS,
     85         base::Bind(&URLFetcherFileWriter::DidOpenFile,
     86                    weak_factory_.GetWeakPtr(),
     87                    callback));
     88     DCHECK_NE(OK, result);
     89   }
     90   return result;
     91 }
     92 
     93 int URLFetcherFileWriter::Write(IOBuffer* buffer,
     94                                 int num_bytes,
     95                                 const CompletionCallback& callback) {
     96   DCHECK(file_stream_);
     97   DCHECK(owns_file_);
     98 
     99   int result = file_stream_->Write(buffer, num_bytes,
    100                                    base::Bind(&URLFetcherFileWriter::DidWrite,
    101                                               weak_factory_.GetWeakPtr(),
    102                                               callback));
    103   if (result < 0 && result != ERR_IO_PENDING)
    104     CloseAndDeleteFile();
    105 
    106   return result;
    107 }
    108 
    109 int URLFetcherFileWriter::Finish(const CompletionCallback& callback) {
    110   // If the file_stream_ still exists at this point, close it.
    111   if (file_stream_) {
    112     int result = file_stream_->Close(base::Bind(
    113         &URLFetcherFileWriter::CloseComplete,
    114         weak_factory_.GetWeakPtr(), callback));
    115     if (result != ERR_IO_PENDING)
    116       file_stream_.reset();
    117     return result;
    118   }
    119   return OK;
    120 }
    121 
    122 URLFetcherFileWriter* URLFetcherFileWriter::AsFileWriter() {
    123   return this;
    124 }
    125 
    126 void URLFetcherFileWriter::DisownFile() {
    127   // Disowning is done by the delegate's OnURLFetchComplete method.
    128   // The file should be closed by the time that method is called.
    129   DCHECK(!file_stream_);
    130 
    131   owns_file_ = false;
    132 }
    133 
    134 void URLFetcherFileWriter::DidWrite(const CompletionCallback& callback,
    135                                     int result) {
    136   if (result < 0)
    137     CloseAndDeleteFile();
    138 
    139   callback.Run(result);
    140 }
    141 
    142 void URLFetcherFileWriter::CloseAndDeleteFile() {
    143   if (!owns_file_)
    144     return;
    145 
    146   file_stream_.reset();
    147   DisownFile();
    148   file_task_runner_->PostTask(FROM_HERE,
    149                               base::Bind(base::IgnoreResult(&base::DeleteFile),
    150                                          file_path_,
    151                                          false /* recursive */));
    152 }
    153 
    154 void URLFetcherFileWriter::DidCreateTempFile(const CompletionCallback& callback,
    155                                              base::FilePath* temp_file_path,
    156                                              bool success) {
    157   if (!success) {
    158     callback.Run(ERR_FILE_NOT_FOUND);
    159     return;
    160   }
    161   file_path_ = *temp_file_path;
    162   owns_file_ = true;
    163   const int result = file_stream_->Open(
    164       file_path_,
    165       base::File::FLAG_WRITE | base::File::FLAG_ASYNC |
    166       base::File::FLAG_OPEN,
    167       base::Bind(&URLFetcherFileWriter::DidOpenFile,
    168                  weak_factory_.GetWeakPtr(),
    169                  callback));
    170   if (result != ERR_IO_PENDING)
    171     DidOpenFile(callback, result);
    172 }
    173 
    174 void URLFetcherFileWriter::DidOpenFile(const CompletionCallback& callback,
    175                                        int result) {
    176   if (result == OK)
    177     owns_file_ = true;
    178   else
    179     CloseAndDeleteFile();
    180 
    181   callback.Run(result);
    182 }
    183 
    184 void URLFetcherFileWriter::CloseComplete(const CompletionCallback& callback,
    185                                          int result) {
    186   // Destroy |file_stream_| whether or not the close succeeded.
    187   file_stream_.reset();
    188   callback.Run(result);
    189 }
    190 
    191 }  // namespace net
    192