Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / net / url_request / url_fetcher_response_writer.cc
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