12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_fetcher_response_writer.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/location.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/sequenced_task_runner.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/task_runner_util.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/base/file_stream.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/io_buffer.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net {
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)URLFetcherStringWriter* URLFetcherResponseWriter::AsStringWriter() {
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return NULL;
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)URLFetcherFileWriter* URLFetcherResponseWriter::AsFileWriter() {
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return NULL;
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)URLFetcherStringWriter::URLFetcherStringWriter() {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)URLFetcherStringWriter::~URLFetcherStringWriter() {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int URLFetcherStringWriter::Initialize(const CompletionCallback& callback) {
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  data_.clear();
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return OK;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int URLFetcherStringWriter::Write(IOBuffer* buffer,
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  int num_bytes,
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const CompletionCallback& callback) {
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  data_.append(buffer->data(), num_bytes);
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return num_bytes;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int URLFetcherStringWriter::Finish(const CompletionCallback& callback) {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Do nothing.
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return OK;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)URLFetcherStringWriter* URLFetcherStringWriter::AsStringWriter() {
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return this;
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)URLFetcherFileWriter::URLFetcherFileWriter(
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> file_task_runner,
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const base::FilePath& file_path)
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : file_task_runner_(file_task_runner),
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      file_path_(file_path),
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      owns_file_(false),
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      weak_factory_(this) {
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(file_task_runner_.get());
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)URLFetcherFileWriter::~URLFetcherFileWriter() {
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CloseAndDeleteFile();
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) {
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  file_stream_.reset(new FileStream(file_task_runner_));
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int result = ERR_IO_PENDING;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (file_path_.empty()) {
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::FilePath* temp_file_path = new base::FilePath;
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PostTaskAndReplyWithResult(
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        file_task_runner_.get(),
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        FROM_HERE,
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::Bind(&base::CreateTemporaryFile, temp_file_path),
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&URLFetcherFileWriter::DidCreateTempFile,
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_factory_.GetWeakPtr(),
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   callback,
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   base::Owned(temp_file_path)));
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    result = file_stream_->Open(
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        file_path_,
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        base::File::FLAG_WRITE | base::File::FLAG_ASYNC |
8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        base::File::FLAG_CREATE_ALWAYS,
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&URLFetcherFileWriter::DidOpenFile,
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_factory_.GetWeakPtr(),
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   callback));
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK_NE(OK, result);
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return result;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int URLFetcherFileWriter::Write(IOBuffer* buffer,
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                int num_bytes,
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                const CompletionCallback& callback) {
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(file_stream_);
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(owns_file_);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int result = file_stream_->Write(buffer, num_bytes,
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                   base::Bind(&URLFetcherFileWriter::DidWrite,
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                              weak_factory_.GetWeakPtr(),
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                              callback));
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (result < 0 && result != ERR_IO_PENDING)
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CloseAndDeleteFile();
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return result;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int URLFetcherFileWriter::Finish(const CompletionCallback& callback) {
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If the file_stream_ still exists at this point, close it.
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (file_stream_) {
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int result = file_stream_->Close(base::Bind(
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &URLFetcherFileWriter::CloseComplete,
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        weak_factory_.GetWeakPtr(), callback));
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (result != ERR_IO_PENDING)
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      file_stream_.reset();
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return result;
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return OK;
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)URLFetcherFileWriter* URLFetcherFileWriter::AsFileWriter() {
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return this;
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void URLFetcherFileWriter::DisownFile() {
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Disowning is done by the delegate's OnURLFetchComplete method.
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The file should be closed by the time that method is called.
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!file_stream_);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  owns_file_ = false;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void URLFetcherFileWriter::DidWrite(const CompletionCallback& callback,
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                    int result) {
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (result < 0)
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CloseAndDeleteFile();
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  callback.Run(result);
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void URLFetcherFileWriter::CloseAndDeleteFile() {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!owns_file_)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  file_stream_.reset();
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DisownFile();
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  file_task_runner_->PostTask(FROM_HERE,
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                              base::Bind(base::IgnoreResult(&base::DeleteFile),
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         file_path_,
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         false /* recursive */));
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void URLFetcherFileWriter::DidCreateTempFile(const CompletionCallback& callback,
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                             base::FilePath* temp_file_path,
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                             bool success) {
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!success) {
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    callback.Run(ERR_FILE_NOT_FOUND);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  file_path_ = *temp_file_path;
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  owns_file_ = true;
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int result = file_stream_->Open(
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      file_path_,
16523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      base::File::FLAG_WRITE | base::File::FLAG_ASYNC |
16623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      base::File::FLAG_OPEN,
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&URLFetcherFileWriter::DidOpenFile,
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 weak_factory_.GetWeakPtr(),
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 callback));
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (result != ERR_IO_PENDING)
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DidOpenFile(callback, result);
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void URLFetcherFileWriter::DidOpenFile(const CompletionCallback& callback,
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       int result) {
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (result == OK)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    owns_file_ = true;
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  else
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CloseAndDeleteFile();
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  callback.Run(result);
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void URLFetcherFileWriter::CloseComplete(const CompletionCallback& callback,
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                         int result) {
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Destroy |file_stream_| whether or not the close succeeded.
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  file_stream_.reset();
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(result);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace net
192