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

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

Issue 6713008: Don't destroy a request while it is being processed (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: . Created 9 years, 9 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
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/renderer_host/download_throttling_resource_handler.h" 5 #include "chrome/browser/renderer_host/download_throttling_resource_handler.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "chrome/browser/download/download_util.h" 8 #include "chrome/browser/download/download_util.h"
9 #include "chrome/browser/renderer_host/download_resource_handler.h" 9 #include "chrome/browser/renderer_host/download_resource_handler.h"
10 #include "content/browser/renderer_host/resource_dispatcher_host.h" 10 #include "content/browser/renderer_host/resource_dispatcher_host.h"
11 #include "content/common/resource_response.h" 11 #include "content/common/resource_response.h"
12 #include "net/base/io_buffer.h" 12 #include "net/base/io_buffer.h"
13 #include "net/base/mime_sniffer.h" 13 #include "net/base/mime_sniffer.h"
14 14
15 DownloadThrottlingResourceHandler::DownloadThrottlingResourceHandler( 15 DownloadThrottlingResourceHandler::DownloadThrottlingResourceHandler(
16 ResourceDispatcherHost* host, 16 ResourceDispatcherHost* host,
17 net::URLRequest* request, 17 net::URLRequest* request,
18 const GURL& url, 18 const GURL& url,
19 int render_process_host_id, 19 int render_process_host_id,
20 int render_view_id, 20 int render_view_id,
21 int request_id, 21 int request_id,
22 bool in_complete) 22 bool in_complete)
23 : host_(host), 23 : host_(host),
24 request_(request), 24 request_(request),
25 url_(url), 25 url_(url),
26 render_process_host_id_(render_process_host_id), 26 render_process_host_id_(render_process_host_id),
27 render_view_id_(render_view_id), 27 render_view_id_(render_view_id),
28 request_id_(request_id), 28 request_id_(request_id),
29 tmp_buffer_length_(0), 29 tmp_buffer_length_(0),
30 ignore_on_read_complete_(in_complete) { 30 ignore_on_read_complete_(in_complete),
31 request_closed_(false) {
31 // Pause the request. 32 // Pause the request.
32 host_->PauseRequest(render_process_host_id_, request_id_, true); 33 host_->PauseRequest(render_process_host_id_, request_id_, true);
34
35 // Add a reference to ourselves to keep this object alive until we
36 // receive a callback from DownloadRequestLimiter. The reference is
37 // released in ContinueDownload() and CancelDownload().
38 AddRef();
39
33 host_->download_request_limiter()->CanDownloadOnIOThread( 40 host_->download_request_limiter()->CanDownloadOnIOThread(
34 render_process_host_id_, render_view_id, this); 41 render_process_host_id_, render_view_id, request_id, this);
35
36 BrowserThread::PostTask( 42 BrowserThread::PostTask(
37 BrowserThread::UI, FROM_HERE, 43 BrowserThread::UI, FROM_HERE,
38 NewRunnableFunction(&download_util::NotifyDownloadInitiated, 44 NewRunnableFunction(&download_util::NotifyDownloadInitiated,
39 render_process_host_id_, render_view_id_)); 45 render_process_host_id_, render_view_id_));
40 } 46 }
41 47
42 DownloadThrottlingResourceHandler::~DownloadThrottlingResourceHandler() { 48 DownloadThrottlingResourceHandler::~DownloadThrottlingResourceHandler() {
43 } 49 }
44 50
45 bool DownloadThrottlingResourceHandler::OnUploadProgress(int request_id, 51 bool DownloadThrottlingResourceHandler::OnUploadProgress(int request_id,
46 uint64 position, 52 uint64 position,
47 uint64 size) { 53 uint64 size) {
54 DCHECK(!request_closed_);
48 if (download_handler_.get()) 55 if (download_handler_.get())
49 return download_handler_->OnUploadProgress(request_id, position, size); 56 return download_handler_->OnUploadProgress(request_id, position, size);
50 return true; 57 return true;
51 } 58 }
52 59
53 bool DownloadThrottlingResourceHandler::OnRequestRedirected( 60 bool DownloadThrottlingResourceHandler::OnRequestRedirected(
54 int request_id, 61 int request_id,
55 const GURL& url, 62 const GURL& url,
56 ResourceResponse* response, 63 ResourceResponse* response,
57 bool* defer) { 64 bool* defer) {
65 DCHECK(!request_closed_);
58 if (download_handler_.get()) { 66 if (download_handler_.get()) {
59 return download_handler_->OnRequestRedirected( 67 return download_handler_->OnRequestRedirected(
60 request_id, url, response, defer); 68 request_id, url, response, defer);
61 } 69 }
62 url_ = url; 70 url_ = url;
63 return true; 71 return true;
64 } 72 }
65 73
66 bool DownloadThrottlingResourceHandler::OnResponseStarted( 74 bool DownloadThrottlingResourceHandler::OnResponseStarted(
67 int request_id, 75 int request_id,
68 ResourceResponse* response) { 76 ResourceResponse* response) {
77 DCHECK(!request_closed_);
69 if (download_handler_.get()) 78 if (download_handler_.get())
70 return download_handler_->OnResponseStarted(request_id, response); 79 return download_handler_->OnResponseStarted(request_id, response);
71 response_ = response; 80 response_ = response;
72 return true; 81 return true;
73 } 82 }
74 83
75 bool DownloadThrottlingResourceHandler::OnWillStart(int request_id, 84 bool DownloadThrottlingResourceHandler::OnWillStart(int request_id,
76 const GURL& url, 85 const GURL& url,
77 bool* defer) { 86 bool* defer) {
87 DCHECK(!request_closed_);
78 if (download_handler_.get()) 88 if (download_handler_.get())
79 return download_handler_->OnWillStart(request_id, url, defer); 89 return download_handler_->OnWillStart(request_id, url, defer);
80 return true; 90 return true;
81 } 91 }
82 92
83 bool DownloadThrottlingResourceHandler::OnWillRead(int request_id, 93 bool DownloadThrottlingResourceHandler::OnWillRead(int request_id,
84 net::IOBuffer** buf, 94 net::IOBuffer** buf,
85 int* buf_size, 95 int* buf_size,
86 int min_size) { 96 int min_size) {
97 DCHECK(!request_closed_);
87 if (download_handler_.get()) 98 if (download_handler_.get())
88 return download_handler_->OnWillRead(request_id, buf, buf_size, min_size); 99 return download_handler_->OnWillRead(request_id, buf, buf_size, min_size);
89 100
90 // We should only have this invoked once, as such we only deal with one 101 // We should only have this invoked once, as such we only deal with one
91 // tmp buffer. 102 // tmp buffer.
92 DCHECK(!tmp_buffer_.get()); 103 DCHECK(!tmp_buffer_.get());
93 // If the caller passed a negative |min_size| then chose an appropriate 104 // If the caller passed a negative |min_size| then chose an appropriate
94 // default. The BufferedResourceHandler requires this to be at least 2 times 105 // default. The BufferedResourceHandler requires this to be at least 2 times
95 // the size required for mime detection. 106 // the size required for mime detection.
96 if (min_size < 0) 107 if (min_size < 0)
97 min_size = 2 * net::kMaxBytesToSniff; 108 min_size = 2 * net::kMaxBytesToSniff;
98 tmp_buffer_ = new net::IOBuffer(min_size); 109 tmp_buffer_ = new net::IOBuffer(min_size);
99 *buf = tmp_buffer_.get(); 110 *buf = tmp_buffer_.get();
100 *buf_size = min_size; 111 *buf_size = min_size;
101 return true; 112 return true;
102 } 113 }
103 114
104 bool DownloadThrottlingResourceHandler::OnReadCompleted(int request_id, 115 bool DownloadThrottlingResourceHandler::OnReadCompleted(int request_id,
105 int* bytes_read) { 116 int* bytes_read) {
117 DCHECK(!request_closed_);
106 if (ignore_on_read_complete_) { 118 if (ignore_on_read_complete_) {
107 // See comments above definition for details on this. 119 // See comments above definition for details on this.
108 ignore_on_read_complete_ = false; 120 ignore_on_read_complete_ = false;
109 return true; 121 return true;
110 } 122 }
111 if (!*bytes_read) 123 if (!*bytes_read)
112 return true; 124 return true;
113 125
114 if (tmp_buffer_.get()) { 126 if (tmp_buffer_.get()) {
115 DCHECK(!tmp_buffer_length_); 127 DCHECK(!tmp_buffer_length_);
116 tmp_buffer_length_ = *bytes_read; 128 tmp_buffer_length_ = *bytes_read;
117 if (download_handler_.get()) 129 if (download_handler_.get())
118 CopyTmpBufferToDownloadHandler(); 130 CopyTmpBufferToDownloadHandler();
119 return true; 131 return true;
120 } 132 }
121 if (download_handler_.get()) 133 if (download_handler_.get())
122 return download_handler_->OnReadCompleted(request_id, bytes_read); 134 return download_handler_->OnReadCompleted(request_id, bytes_read);
123 return true; 135 return true;
124 } 136 }
125 137
126 bool DownloadThrottlingResourceHandler::OnResponseCompleted( 138 bool DownloadThrottlingResourceHandler::OnResponseCompleted(
127 int request_id, 139 int request_id,
128 const net::URLRequestStatus& status, 140 const net::URLRequestStatus& status,
129 const std::string& security_info) { 141 const std::string& security_info) {
142 DCHECK(!request_closed_);
130 if (download_handler_.get()) 143 if (download_handler_.get())
131 return download_handler_->OnResponseCompleted(request_id, status, 144 return download_handler_->OnResponseCompleted(request_id, status,
132 security_info); 145 security_info);
133 146
134 // For a download, if ResourceDispatcher::Read() fails, 147 // For a download, if ResourceDispatcher::Read() fails,
135 // ResourceDispatcher::OnresponseStarted() will call 148 // ResourceDispatcher::OnresponseStarted() will call
136 // OnResponseCompleted(), and we will end up here with an error 149 // OnResponseCompleted(), and we will end up here with an error
137 // status. 150 // status.
138 if (!status.is_success()) 151 if (!status.is_success())
139 return false; 152 return false;
140 NOTREACHED(); 153 NOTREACHED();
141 return true; 154 return true;
142 } 155 }
143 156
144 void DownloadThrottlingResourceHandler::OnRequestClosed() { 157 void DownloadThrottlingResourceHandler::OnRequestClosed() {
158 DCHECK(!request_closed_);
145 if (download_handler_.get()) 159 if (download_handler_.get())
146 download_handler_->OnRequestClosed(); 160 download_handler_->OnRequestClosed();
161 request_closed_ = true;
147 } 162 }
148 163
149 void DownloadThrottlingResourceHandler::CancelDownload() { 164 void DownloadThrottlingResourceHandler::CancelDownload() {
150 host_->CancelRequest(render_process_host_id_, request_id_, false); 165 if (!request_closed_)
166 host_->CancelRequest(render_process_host_id_, request_id_, false);
167 Release(); // Release the additional reference from constructor.
151 } 168 }
152 169
153 void DownloadThrottlingResourceHandler::ContinueDownload() { 170 void DownloadThrottlingResourceHandler::ContinueDownload() {
154 DCHECK(!download_handler_.get()); 171 DCHECK(!download_handler_.get());
155 download_handler_ = 172 if (!request_closed_) {
Randy Smith (Not in Mondays) 2011/03/21 17:31:01 nit: I'd suggest restructuring this routing by put
rvargas (doing something else) 2011/03/21 22:38:10 The problem would be if we hold the last reference
asanka 2011/03/22 14:52:42 It's not very pretty, but as rvargas points out, o
Randy Smith (Not in Mondays) 2011/03/22 14:55:45 Fair enough; destruction could happen right then,
156 new DownloadResourceHandler(host_, 173 download_handler_ =
157 render_process_host_id_, 174 new DownloadResourceHandler(host_,
158 render_view_id_, 175 render_process_host_id_,
159 request_id_, 176 render_view_id_,
160 url_, 177 request_id_,
161 host_->download_file_manager(), 178 url_,
162 request_, 179 host_->download_file_manager(),
163 false, 180 request_,
164 DownloadSaveInfo()); 181 false,
165 if (response_.get()) 182 DownloadSaveInfo());
166 download_handler_->OnResponseStarted(request_id_, response_.get()); 183 if (response_.get())
184 download_handler_->OnResponseStarted(request_id_, response_.get());
167 185
168 if (tmp_buffer_length_) 186 if (tmp_buffer_length_)
169 CopyTmpBufferToDownloadHandler(); 187 CopyTmpBufferToDownloadHandler();
170 188
171 // And let the request continue. 189 // And let the request continue.
172 host_->PauseRequest(render_process_host_id_, request_id_, false); 190 host_->PauseRequest(render_process_host_id_, request_id_, false);
173 } 191 }
174 192 Release(); // Release the addtional reference from constructor.
175 int DownloadThrottlingResourceHandler::GetRequestId() {
176 return request_id_;
177 } 193 }
178 194
179 void DownloadThrottlingResourceHandler::CopyTmpBufferToDownloadHandler() { 195 void DownloadThrottlingResourceHandler::CopyTmpBufferToDownloadHandler() {
180 // Copy over the tmp buffer. 196 // Copy over the tmp buffer.
181 net::IOBuffer* buffer; 197 net::IOBuffer* buffer;
182 int buf_size; 198 int buf_size;
183 if (download_handler_->OnWillRead(request_id_, &buffer, &buf_size, 199 if (download_handler_->OnWillRead(request_id_, &buffer, &buf_size,
184 tmp_buffer_length_)) { 200 tmp_buffer_length_)) {
185 CHECK(buf_size >= tmp_buffer_length_); 201 CHECK(buf_size >= tmp_buffer_length_);
186 memcpy(buffer->data(), tmp_buffer_->data(), tmp_buffer_length_); 202 memcpy(buffer->data(), tmp_buffer_->data(), tmp_buffer_length_);
187 download_handler_->OnReadCompleted(request_id_, &tmp_buffer_length_); 203 download_handler_->OnReadCompleted(request_id_, &tmp_buffer_length_);
188 } 204 }
189 tmp_buffer_length_ = 0; 205 tmp_buffer_length_ = 0;
190 tmp_buffer_ = NULL; 206 tmp_buffer_ = NULL;
191 } 207 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698