Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(886)

Side by Side Diff: chrome/browser/renderer_host/download_resource_handler.cc

Issue 7664005: Move DownloadResourceHandler to content. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "chrome/browser/renderer_host/download_resource_handler.h"
6
7 #include <string>
8
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/metrics/stats_counters.h"
12 #include "base/stringprintf.h"
13 #include "chrome/browser/download/download_util.h"
14 #include "content/browser/browser_thread.h"
15 #include "content/browser/download/download_create_info.h"
16 #include "content/browser/download/download_file_manager.h"
17 #include "content/browser/download/download_item.h"
18 #include "content/browser/download/download_request_handle.h"
19 #include "content/browser/renderer_host/global_request_id.h"
20 #include "content/browser/renderer_host/resource_dispatcher_host.h"
21 #include "content/browser/renderer_host/resource_dispatcher_host_request_info.h"
22 #include "content/common/resource_response.h"
23 #include "net/base/io_buffer.h"
24 #include "net/http/http_response_headers.h"
25 #include "net/url_request/url_request_context.h"
26
27 DownloadResourceHandler::DownloadResourceHandler(
28 ResourceDispatcherHost* rdh,
29 int render_process_host_id,
30 int render_view_id,
31 int request_id,
32 const GURL& url,
33 DownloadFileManager* download_file_manager,
34 net::URLRequest* request,
35 bool save_as,
36 const DownloadSaveInfo& save_info)
37 : download_id_(-1),
38 global_id_(render_process_host_id, request_id),
39 render_view_id_(render_view_id),
40 content_length_(0),
41 download_file_manager_(download_file_manager),
42 request_(request),
43 save_as_(save_as),
44 save_info_(save_info),
45 buffer_(new DownloadBuffer),
46 rdh_(rdh),
47 is_paused_(false) {
48 download_util::RecordDownloadCount(download_util::UNTHROTTLED_COUNT);
49 }
50
51 bool DownloadResourceHandler::OnUploadProgress(int request_id,
52 uint64 position,
53 uint64 size) {
54 return true;
55 }
56
57 // Not needed, as this event handler ought to be the final resource.
58 bool DownloadResourceHandler::OnRequestRedirected(int request_id,
59 const GURL& url,
60 ResourceResponse* response,
61 bool* defer) {
62 return true;
63 }
64
65 // Send the download creation information to the download thread.
66 bool DownloadResourceHandler::OnResponseStarted(int request_id,
67 ResourceResponse* response) {
68 VLOG(20) << __FUNCTION__ << "()" << DebugString()
69 << " request_id = " << request_id;
70 download_start_time_ = base::TimeTicks::Now();
71 std::string content_disposition;
72 request_->GetResponseHeaderByName("content-disposition",
73 &content_disposition);
74 set_content_disposition(content_disposition);
75 set_content_length(response->response_head.content_length);
76
77 const ResourceDispatcherHostRequestInfo* request_info =
78 ResourceDispatcherHost::InfoForRequest(request_);
79
80 download_id_ = download_file_manager_->GetNextId();
81
82 // Deleted in DownloadManager.
83 DownloadCreateInfo* info = new DownloadCreateInfo;
84 info->url_chain = request_->url_chain();
85 info->referrer_url = GURL(request_->referrer());
86 info->start_time = base::Time::Now();
87 info->received_bytes = 0;
88 info->total_bytes = content_length_;
89 info->state = DownloadItem::IN_PROGRESS;
90 info->download_id = download_id_;
91 info->has_user_gesture = request_info->has_user_gesture();
92 info->request_handle = DownloadRequestHandle(rdh_,
93 global_id_.child_id,
94 render_view_id_,
95 global_id_.request_id);
96 info->content_disposition = content_disposition_;
97 info->mime_type = response->response_head.mime_type;
98 download_util::RecordDownloadMimeType(info->mime_type);
99 // TODO(ahendrickson) -- Get the last modified time and etag, so we can
100 // resume downloading.
101
102 std::string content_type_header;
103 if (!response->response_head.headers ||
104 !response->response_head.headers->GetMimeType(&content_type_header))
105 content_type_header = "";
106 info->original_mime_type = content_type_header;
107
108 info->prompt_user_for_save_location =
109 save_as_ && save_info_.file_path.empty();
110 info->referrer_charset = request_->context()->referrer_charset();
111 info->save_info = save_info_;
112 BrowserThread::PostTask(
113 BrowserThread::UI, FROM_HERE,
114 NewRunnableMethod(
115 download_file_manager_, &DownloadFileManager::StartDownload, info));
116
117 // We can't start saving the data before we create the file on disk.
118 // The request will be un-paused in DownloadFileManager::CreateDownloadFile.
119 rdh_->PauseRequest(global_id_.child_id, global_id_.request_id, true);
120
121 return true;
122 }
123
124 bool DownloadResourceHandler::OnWillStart(int request_id,
125 const GURL& url,
126 bool* defer) {
127 return true;
128 }
129
130 // Create a new buffer, which will be handed to the download thread for file
131 // writing and deletion.
132 bool DownloadResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
133 int* buf_size, int min_size) {
134 DCHECK(buf && buf_size);
135 if (!read_buffer_) {
136 *buf_size = min_size < 0 ? kReadBufSize : min_size;
137 read_buffer_ = new net::IOBuffer(*buf_size);
138 }
139 *buf = read_buffer_.get();
140 return true;
141 }
142
143 // Pass the buffer to the download file writer.
144 bool DownloadResourceHandler::OnReadCompleted(int request_id, int* bytes_read) {
145 if (!*bytes_read)
146 return true;
147 DCHECK(read_buffer_);
148 base::AutoLock auto_lock(buffer_->lock);
149 bool need_update = buffer_->contents.empty();
150
151 // We are passing ownership of this buffer to the download file manager.
152 net::IOBuffer* buffer = NULL;
153 read_buffer_.swap(&buffer);
154 buffer_->contents.push_back(std::make_pair(buffer, *bytes_read));
155 if (need_update) {
156 BrowserThread::PostTask(
157 BrowserThread::FILE, FROM_HERE,
158 NewRunnableMethod(download_file_manager_,
159 &DownloadFileManager::UpdateDownload,
160 download_id_,
161 buffer_.get()));
162 }
163
164 // We schedule a pause outside of the read loop if there is too much file
165 // writing work to do.
166 if (buffer_->contents.size() > kLoadsToWrite)
167 StartPauseTimer();
168
169 return true;
170 }
171
172 bool DownloadResourceHandler::OnResponseCompleted(
173 int request_id,
174 const net::URLRequestStatus& status,
175 const std::string& security_info) {
176 VLOG(20) << __FUNCTION__ << "()" << DebugString()
177 << " request_id = " << request_id
178 << " status.status() = " << status.status()
179 << " status.os_error() = " << status.os_error();
180 int error_code = (status.status() == net::URLRequestStatus::FAILED) ?
181 status.os_error() : 0;
182 // We transfer ownership to |DownloadFileManager| to delete |buffer_|,
183 // so that any functions queued up on the FILE thread are executed
184 // before deletion.
185 BrowserThread::PostTask(
186 BrowserThread::FILE, FROM_HERE,
187 NewRunnableMethod(download_file_manager_,
188 &DownloadFileManager::OnResponseCompleted,
189 download_id_,
190 buffer_.release(),
191 error_code,
192 security_info));
193 read_buffer_ = NULL;
194 return true;
195 }
196
197 void DownloadResourceHandler::OnRequestClosed() {
198 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration",
199 base::TimeTicks::Now() - download_start_time_);
200 }
201
202 // If the content-length header is not present (or contains something other
203 // than numbers), the incoming content_length is -1 (unknown size).
204 // Set the content length to 0 to indicate unknown size to DownloadManager.
205 void DownloadResourceHandler::set_content_length(const int64& content_length) {
206 content_length_ = 0;
207 if (content_length > 0)
208 content_length_ = content_length;
209 }
210
211 void DownloadResourceHandler::set_content_disposition(
212 const std::string& content_disposition) {
213 content_disposition_ = content_disposition;
214 }
215
216 void DownloadResourceHandler::CheckWriteProgress() {
217 if (!buffer_.get())
218 return; // The download completed while we were waiting to run.
219
220 size_t contents_size;
221 {
222 base::AutoLock lock(buffer_->lock);
223 contents_size = buffer_->contents.size();
224 }
225
226 bool should_pause = contents_size > kLoadsToWrite;
227
228 // We'll come back later and see if it's okay to unpause the request.
229 if (should_pause)
230 StartPauseTimer();
231
232 if (is_paused_ != should_pause) {
233 rdh_->PauseRequest(global_id_.child_id, global_id_.request_id,
234 should_pause);
235 is_paused_ = should_pause;
236 }
237 }
238
239 DownloadResourceHandler::~DownloadResourceHandler() {
240 }
241
242 void DownloadResourceHandler::StartPauseTimer() {
243 if (!pause_timer_.IsRunning())
244 pause_timer_.Start(base::TimeDelta::FromMilliseconds(kThrottleTimeMs), this,
245 &DownloadResourceHandler::CheckWriteProgress);
246 }
247
248 std::string DownloadResourceHandler::DebugString() const {
249 return base::StringPrintf("{"
250 " url_ = " "\"%s\""
251 " download_id_ = " "%d"
252 " global_id_ = {"
253 " child_id = " "%d"
254 " request_id = " "%d"
255 " }"
256 " render_view_id_ = " "%d"
257 " save_info_.file_path = \"%" PRFilePath "\""
258 " }",
259 request_->url().spec().c_str(),
260 download_id_,
261 global_id_.child_id,
262 global_id_.request_id,
263 render_view_id_,
264 save_info_.file_path.value().c_str());
265 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698