root/net/url_request/url_fetcher_response_writer.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. AsStringWriter
  2. AsFileWriter
  3. Initialize
  4. Finish
  5. AsStringWriter
  6. owns_file_
  7. Initialize
  8. Finish
  9. AsFileWriter
  10. DisownFile
  11. DidWrite
  12. CloseAndDeleteFile
  13. DidCreateTempFile
  14. DidOpenFile
  15. CloseComplete

// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/url_request/url_fetcher_response_writer.h"

#include "base/file_util.h"
#include "base/location.h"
#include "base/sequenced_task_runner.h"
#include "base/task_runner_util.h"
#include "net/base/file_stream.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"

namespace net {

URLFetcherStringWriter* URLFetcherResponseWriter::AsStringWriter() {
  return NULL;
}

URLFetcherFileWriter* URLFetcherResponseWriter::AsFileWriter() {
  return NULL;
}

URLFetcherStringWriter::URLFetcherStringWriter() {
}

URLFetcherStringWriter::~URLFetcherStringWriter() {
}

int URLFetcherStringWriter::Initialize(const CompletionCallback& callback) {
  data_.clear();
  return OK;
}

int URLFetcherStringWriter::Write(IOBuffer* buffer,
                                  int num_bytes,
                                  const CompletionCallback& callback) {
  data_.append(buffer->data(), num_bytes);
  return num_bytes;
}

int URLFetcherStringWriter::Finish(const CompletionCallback& callback) {
  // Do nothing.
  return OK;
}

URLFetcherStringWriter* URLFetcherStringWriter::AsStringWriter() {
  return this;
}

URLFetcherFileWriter::URLFetcherFileWriter(
    scoped_refptr<base::SequencedTaskRunner> file_task_runner,
    const base::FilePath& file_path)
    : weak_factory_(this),
      file_task_runner_(file_task_runner),
      file_path_(file_path),
      owns_file_(false) {
  DCHECK(file_task_runner_.get());
}

URLFetcherFileWriter::~URLFetcherFileWriter() {
  CloseAndDeleteFile();
}

int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) {
  file_stream_.reset(new FileStream(NULL));

  int result = ERR_IO_PENDING;
  if (file_path_.empty()) {
    base::FilePath* temp_file_path = new base::FilePath;
    base::PostTaskAndReplyWithResult(
        file_task_runner_.get(),
        FROM_HERE,
        base::Bind(&base::CreateTemporaryFile, temp_file_path),
        base::Bind(&URLFetcherFileWriter::DidCreateTempFile,
                   weak_factory_.GetWeakPtr(),
                   callback,
                   base::Owned(temp_file_path)));
  } else {
    result = file_stream_->Open(
        file_path_,
        base::File::FLAG_WRITE | base::File::FLAG_ASYNC |
        base::File::FLAG_CREATE_ALWAYS,
        base::Bind(&URLFetcherFileWriter::DidOpenFile,
                   weak_factory_.GetWeakPtr(),
                   callback));
    DCHECK_NE(OK, result);
  }
  return result;
}

int URLFetcherFileWriter::Write(IOBuffer* buffer,
                                int num_bytes,
                                const CompletionCallback& callback) {
  DCHECK(file_stream_);
  DCHECK(owns_file_);

  int result = file_stream_->Write(buffer, num_bytes,
                                   base::Bind(&URLFetcherFileWriter::DidWrite,
                                              weak_factory_.GetWeakPtr(),
                                              callback));
  if (result < 0 && result != ERR_IO_PENDING)
    CloseAndDeleteFile();

  return result;
}

int URLFetcherFileWriter::Finish(const CompletionCallback& callback) {
  // If the file_stream_ still exists at this point, close it.
  if (file_stream_) {
    int result = file_stream_->Close(base::Bind(
        &URLFetcherFileWriter::CloseComplete,
        weak_factory_.GetWeakPtr(), callback));
    if (result != ERR_IO_PENDING)
      file_stream_.reset();
    return result;
  }
  return OK;
}

URLFetcherFileWriter* URLFetcherFileWriter::AsFileWriter() {
  return this;
}

void URLFetcherFileWriter::DisownFile() {
  // Disowning is done by the delegate's OnURLFetchComplete method.
  // The file should be closed by the time that method is called.
  DCHECK(!file_stream_);

  owns_file_ = false;
}

void URLFetcherFileWriter::DidWrite(const CompletionCallback& callback,
                                    int result) {
  if (result < 0)
    CloseAndDeleteFile();

  callback.Run(result);
}

void URLFetcherFileWriter::CloseAndDeleteFile() {
  if (!owns_file_)
    return;

  file_stream_.reset();
  DisownFile();
  file_task_runner_->PostTask(FROM_HERE,
                              base::Bind(base::IgnoreResult(&base::DeleteFile),
                                         file_path_,
                                         false /* recursive */));
}

void URLFetcherFileWriter::DidCreateTempFile(const CompletionCallback& callback,
                                             base::FilePath* temp_file_path,
                                             bool success) {
  if (!success) {
    callback.Run(ERR_FILE_NOT_FOUND);
    return;
  }
  file_path_ = *temp_file_path;
  owns_file_ = true;
  const int result = file_stream_->Open(
      file_path_,
      base::File::FLAG_WRITE | base::File::FLAG_ASYNC |
      base::File::FLAG_OPEN,
      base::Bind(&URLFetcherFileWriter::DidOpenFile,
                 weak_factory_.GetWeakPtr(),
                 callback));
  if (result != ERR_IO_PENDING)
    DidOpenFile(callback, result);
}

void URLFetcherFileWriter::DidOpenFile(const CompletionCallback& callback,
                                       int result) {
  if (result == OK)
    owns_file_ = true;
  else
    CloseAndDeleteFile();

  callback.Run(result);
}

void URLFetcherFileWriter::CloseComplete(const CompletionCallback& callback,
                                         int result) {
  // Destroy |file_stream_| whether or not the close succeeded.
  file_stream_.reset();
  callback.Run(result);
}

}  // namespace net

/* [<][>][^][v][top][bottom][index][help] */