OLD | NEW |
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 "content/browser/download/download_file_manager.h" | 5 #include "content/browser/download/download_file_manager.h" |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "base/task.h" | 10 #include "base/task.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 // Life of |info| ends here. No more references to it after this method. | 58 // Life of |info| ends here. No more references to it after this method. |
59 scoped_ptr<DownloadCreateInfo> infop(info); | 59 scoped_ptr<DownloadCreateInfo> infop(info); |
60 | 60 |
61 scoped_ptr<DownloadFile> | 61 scoped_ptr<DownloadFile> |
62 download_file(new DownloadFile(info, download_manager)); | 62 download_file(new DownloadFile(info, download_manager)); |
63 if (net::OK != download_file->Initialize(get_hash)) { | 63 if (net::OK != download_file->Initialize(get_hash)) { |
64 info->request_handle.CancelRequest(); | 64 info->request_handle.CancelRequest(); |
65 return; | 65 return; |
66 } | 66 } |
67 | 67 |
68 int32 id = info->download_id; | 68 DownloadId global_id(download_manager, info->download_id); |
69 DCHECK(GetDownloadFile(id) == NULL); | 69 DCHECK(GetDownloadFile(global_id) == NULL); |
70 downloads_[id] = download_file.release(); | 70 downloads_[global_id] = download_file.release(); |
71 | 71 |
72 // The file is now ready, we can un-pause the request and start saving data. | 72 // The file is now ready, we can un-pause the request and start saving data. |
73 info->request_handle.ResumeRequest(); | 73 info->request_handle.ResumeRequest(); |
74 | 74 |
75 StartUpdateTimer(); | 75 StartUpdateTimer(); |
76 | 76 |
77 BrowserThread::PostTask( | 77 BrowserThread::PostTask( |
78 BrowserThread::UI, FROM_HERE, | 78 BrowserThread::UI, FROM_HERE, |
79 NewRunnableMethod(download_manager, | 79 NewRunnableMethod(download_manager, |
80 &DownloadManager::StartDownload, id)); | 80 &DownloadManager::StartDownload, info->download_id)); |
81 } | 81 } |
82 | 82 |
83 DownloadFile* DownloadFileManager::GetDownloadFile(int id) { | 83 DownloadFile* DownloadFileManager::GetDownloadFile(DownloadId global_id) { |
84 DownloadFileMap::iterator it = downloads_.find(id); | 84 DownloadFileMap::iterator it = downloads_.find(global_id); |
85 return it == downloads_.end() ? NULL : it->second; | 85 return it == downloads_.end() ? NULL : it->second; |
86 } | 86 } |
87 | 87 |
88 void DownloadFileManager::StartUpdateTimer() { | 88 void DownloadFileManager::StartUpdateTimer() { |
89 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 89 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
90 if (!update_timer_.IsRunning()) { | 90 if (!update_timer_.IsRunning()) { |
91 update_timer_.Start(FROM_HERE, | 91 update_timer_.Start(FROM_HERE, |
92 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), | 92 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), |
93 this, &DownloadFileManager::UpdateInProgressDownloads); | 93 this, &DownloadFileManager::UpdateInProgressDownloads); |
94 } | 94 } |
95 } | 95 } |
96 | 96 |
97 void DownloadFileManager::StopUpdateTimer() { | 97 void DownloadFileManager::StopUpdateTimer() { |
98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
99 update_timer_.Stop(); | 99 update_timer_.Stop(); |
100 } | 100 } |
101 | 101 |
102 void DownloadFileManager::UpdateInProgressDownloads() { | 102 void DownloadFileManager::UpdateInProgressDownloads() { |
103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
104 for (DownloadFileMap::iterator i = downloads_.begin(); | 104 for (DownloadFileMap::iterator i = downloads_.begin(); |
105 i != downloads_.end(); ++i) { | 105 i != downloads_.end(); ++i) { |
106 int id = i->first; | 106 DownloadId global_id = i->first; |
107 DownloadFile* download_file = i->second; | 107 DownloadFile* download_file = i->second; |
108 DownloadManager* manager = download_file->GetDownloadManager(); | 108 DownloadManager* manager = download_file->GetDownloadManager(); |
109 if (manager) { | 109 if (manager) { |
110 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 110 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
111 NewRunnableMethod(manager, &DownloadManager::UpdateDownload, | 111 NewRunnableMethod(manager, &DownloadManager::UpdateDownload, |
112 id, download_file->bytes_so_far())); | 112 global_id.local(), download_file->bytes_so_far())); |
113 } | 113 } |
114 } | 114 } |
115 } | 115 } |
116 | 116 |
117 int DownloadFileManager::GetNextId() { | |
118 return next_id_.GetNext(); | |
119 } | |
120 | |
121 void DownloadFileManager::StartDownload(DownloadCreateInfo* info) { | 117 void DownloadFileManager::StartDownload(DownloadCreateInfo* info) { |
122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
123 DCHECK(info); | 119 DCHECK(info); |
124 | 120 |
125 DownloadManager* manager = info->request_handle.GetDownloadManager(); | 121 DownloadManager* manager = info->request_handle.GetDownloadManager(); |
126 if (!manager) { | 122 if (!manager) { |
127 info->request_handle.CancelRequest(); | 123 info->request_handle.CancelRequest(); |
128 delete info; | 124 delete info; |
129 return; | 125 return; |
130 } | 126 } |
131 | 127 |
132 // TODO(phajdan.jr): fix the duplication of path info below. | 128 // TODO(phajdan.jr): fix the duplication of path info below. |
133 info->path = info->save_info.file_path; | 129 info->path = info->save_info.file_path; |
134 | 130 |
135 manager->CreateDownloadItem(info); | 131 manager->CreateDownloadItem(info); |
136 bool hash_needed = manager->delegate()->GenerateFileHash(); | 132 bool hash_needed = manager->delegate()->GenerateFileHash(); |
137 | 133 |
138 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 134 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
139 NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile, | 135 NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile, |
140 info, make_scoped_refptr(manager), hash_needed)); | 136 info, make_scoped_refptr(manager), hash_needed)); |
141 } | 137 } |
142 | 138 |
143 // We don't forward an update to the UI thread here, since we want to throttle | 139 // We don't forward an update to the UI thread here, since we want to throttle |
144 // the UI update rate via a periodic timer. If the user has cancelled the | 140 // the UI update rate via a periodic timer. If the user has cancelled the |
145 // download (in the UI thread), we may receive a few more updates before the IO | 141 // download (in the UI thread), we may receive a few more updates before the IO |
146 // thread gets the cancel message: we just delete the data since the | 142 // thread gets the cancel message: we just delete the data since the |
147 // DownloadFile has been deleted. | 143 // DownloadFile has been deleted. |
148 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) { | 144 void DownloadFileManager::UpdateDownload( |
| 145 DownloadId global_id, DownloadBuffer* buffer) { |
149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
150 std::vector<DownloadBuffer::Contents> contents; | 147 std::vector<DownloadBuffer::Contents> contents; |
151 { | 148 { |
152 base::AutoLock auto_lock(buffer->lock); | 149 base::AutoLock auto_lock(buffer->lock); |
153 contents.swap(buffer->contents); | 150 contents.swap(buffer->contents); |
154 } | 151 } |
155 | 152 |
156 DownloadFile* download_file = GetDownloadFile(id); | 153 DownloadFile* download_file = GetDownloadFile(global_id); |
157 bool had_error = false; | 154 bool had_error = false; |
158 for (size_t i = 0; i < contents.size(); ++i) { | 155 for (size_t i = 0; i < contents.size(); ++i) { |
159 net::IOBuffer* data = contents[i].first; | 156 net::IOBuffer* data = contents[i].first; |
160 const int data_len = contents[i].second; | 157 const int data_len = contents[i].second; |
161 if (!had_error && download_file) { | 158 if (!had_error && download_file) { |
162 net::Error write_result = | 159 net::Error write_result = |
163 download_file->AppendDataToFile(data->data(), data_len); | 160 download_file->AppendDataToFile(data->data(), data_len); |
164 if (write_result != net::OK) { | 161 if (write_result != net::OK) { |
165 // Write failed: interrupt the download. | 162 // Write failed: interrupt the download. |
166 DownloadManager* download_manager = download_file->GetDownloadManager(); | 163 DownloadManager* download_manager = download_file->GetDownloadManager(); |
167 had_error = true; | 164 had_error = true; |
168 | 165 |
169 int64 bytes_downloaded = download_file->bytes_so_far(); | 166 int64 bytes_downloaded = download_file->bytes_so_far(); |
170 // Calling this here in case we get more data, to avoid | 167 // Calling this here in case we get more data, to avoid |
171 // processing data after an error. That could lead to | 168 // processing data after an error. That could lead to |
172 // files that are corrupted if the later processing succeeded. | 169 // files that are corrupted if the later processing succeeded. |
173 CancelDownload(id); | 170 CancelDownload(global_id); |
174 download_file = NULL; // Was deleted in |CancelDownload|. | 171 download_file = NULL; // Was deleted in |CancelDownload|. |
175 | 172 |
176 if (download_manager) { | 173 if (download_manager) { |
177 BrowserThread::PostTask( | 174 BrowserThread::PostTask( |
178 BrowserThread::UI, | 175 BrowserThread::UI, |
179 FROM_HERE, | 176 FROM_HERE, |
180 NewRunnableMethod( | 177 NewRunnableMethod( |
181 download_manager, | 178 download_manager, |
182 &DownloadManager::OnDownloadError, | 179 &DownloadManager::OnDownloadError, |
183 id, | 180 global_id.local(), |
184 bytes_downloaded, | 181 bytes_downloaded, |
185 write_result)); | 182 write_result)); |
186 } | 183 } |
187 } | 184 } |
188 } | 185 } |
189 data->Release(); | 186 data->Release(); |
190 } | 187 } |
191 } | 188 } |
192 | 189 |
193 void DownloadFileManager::OnResponseCompleted( | 190 void DownloadFileManager::OnResponseCompleted( |
194 int id, | 191 DownloadId global_id, |
195 DownloadBuffer* buffer, | 192 DownloadBuffer* buffer, |
196 net::Error net_error, | 193 net::Error net_error, |
197 const std::string& security_info) { | 194 const std::string& security_info) { |
198 VLOG(20) << __FUNCTION__ << "()" << " id = " << id | 195 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id |
199 << " net_error = " << net_error | 196 << " net_error = " << net_error |
200 << " security_info = \"" << security_info << "\""; | 197 << " security_info = \"" << security_info << "\""; |
201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
202 delete buffer; | 199 delete buffer; |
203 DownloadFile* download_file = GetDownloadFile(id); | 200 DownloadFile* download_file = GetDownloadFile(global_id); |
204 if (!download_file) | 201 if (!download_file) |
205 return; | 202 return; |
206 | 203 |
207 download_file->Finish(); | 204 download_file->Finish(); |
208 | 205 |
209 DownloadManager* download_manager = download_file->GetDownloadManager(); | 206 DownloadManager* download_manager = download_file->GetDownloadManager(); |
210 if (!download_manager) { | 207 if (!download_manager) { |
211 CancelDownload(id); | 208 CancelDownload(global_id); |
212 return; | 209 return; |
213 } | 210 } |
214 | 211 |
215 std::string hash; | 212 std::string hash; |
216 if (!download_file->GetSha256Hash(&hash)) | 213 if (!download_file->GetSha256Hash(&hash)) |
217 hash.clear(); | 214 hash.clear(); |
218 | 215 |
219 // ERR_CONNECTION_CLOSED is allowed since a number of servers in the wild | 216 // ERR_CONNECTION_CLOSED is allowed since a number of servers in the wild |
220 // advertise a larger Content-Length than the amount of bytes in the message | 217 // advertise a larger Content-Length than the amount of bytes in the message |
221 // body, and then close the connection. Other browsers - IE8, Firefox 4.0.1, | 218 // body, and then close the connection. Other browsers - IE8, Firefox 4.0.1, |
222 // and Safari 5.0.4 - treat the download as complete in this case, so we | 219 // and Safari 5.0.4 - treat the download as complete in this case, so we |
223 // follow their lead. | 220 // follow their lead. |
224 if (net_error == net::OK || net_error == net::ERR_CONNECTION_CLOSED) { | 221 if (net_error == net::OK || net_error == net::ERR_CONNECTION_CLOSED) { |
225 BrowserThread::PostTask( | 222 BrowserThread::PostTask( |
226 BrowserThread::UI, | 223 BrowserThread::UI, |
227 FROM_HERE, | 224 FROM_HERE, |
228 NewRunnableMethod( | 225 NewRunnableMethod( |
229 download_manager, | 226 download_manager, |
230 &DownloadManager::OnResponseCompleted, | 227 &DownloadManager::OnResponseCompleted, |
231 id, | 228 global_id.local(), |
232 download_file->bytes_so_far(), | 229 download_file->bytes_so_far(), |
233 hash)); | 230 hash)); |
234 } else { | 231 } else { |
235 BrowserThread::PostTask( | 232 BrowserThread::PostTask( |
236 BrowserThread::UI, | 233 BrowserThread::UI, |
237 FROM_HERE, | 234 FROM_HERE, |
238 NewRunnableMethod( | 235 NewRunnableMethod( |
239 download_manager, | 236 download_manager, |
240 &DownloadManager::OnDownloadError, | 237 &DownloadManager::OnDownloadError, |
241 id, | 238 global_id.local(), |
242 download_file->bytes_so_far(), | 239 download_file->bytes_so_far(), |
243 net_error)); | 240 net_error)); |
244 } | 241 } |
245 // We need to keep the download around until the UI thread has finalized | 242 // We need to keep the download around until the UI thread has finalized |
246 // the name. | 243 // the name. |
247 } | 244 } |
248 | 245 |
249 // This method will be sent via a user action, or shutdown on the UI thread, and | 246 // This method will be sent via a user action, or shutdown on the UI thread, and |
250 // run on the download thread. Since this message has been sent from the UI | 247 // run on the download thread. Since this message has been sent from the UI |
251 // thread, the download may have already completed and won't exist in our map. | 248 // thread, the download may have already completed and won't exist in our map. |
252 void DownloadFileManager::CancelDownload(int id) { | 249 void DownloadFileManager::CancelDownload(DownloadId global_id) { |
253 VLOG(20) << __FUNCTION__ << "()" << " id = " << id; | 250 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id; |
254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
255 DownloadFileMap::iterator it = downloads_.find(id); | 252 DownloadFileMap::iterator it = downloads_.find(global_id); |
256 if (it == downloads_.end()) | 253 if (it == downloads_.end()) |
257 return; | 254 return; |
258 | 255 |
259 DownloadFile* download_file = it->second; | 256 DownloadFile* download_file = it->second; |
260 VLOG(20) << __FUNCTION__ << "()" | 257 VLOG(20) << __FUNCTION__ << "()" |
261 << " download_file = " << download_file->DebugString(); | 258 << " download_file = " << download_file->DebugString(); |
262 download_file->Cancel(); | 259 download_file->Cancel(); |
263 | 260 |
264 EraseDownload(id); | 261 EraseDownload(global_id); |
265 } | 262 } |
266 | 263 |
267 void DownloadFileManager::CompleteDownload(int id) { | 264 void DownloadFileManager::CompleteDownload(DownloadId global_id) { |
268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
269 | 266 |
270 if (!ContainsKey(downloads_, id)) | 267 if (!ContainsKey(downloads_, global_id)) |
271 return; | 268 return; |
272 | 269 |
273 DownloadFile* download_file = downloads_[id]; | 270 DownloadFile* download_file = downloads_[global_id]; |
274 | 271 |
275 VLOG(20) << " " << __FUNCTION__ << "()" | 272 VLOG(20) << " " << __FUNCTION__ << "()" |
276 << " id = " << id | 273 << " id = " << global_id |
277 << " download_file = " << download_file->DebugString(); | 274 << " download_file = " << download_file->DebugString(); |
278 | 275 |
279 download_file->Detach(); | 276 download_file->Detach(); |
280 | 277 |
281 EraseDownload(id); | 278 EraseDownload(global_id); |
282 } | 279 } |
283 | 280 |
284 void DownloadFileManager::OnDownloadManagerShutdown(DownloadManager* manager) { | 281 void DownloadFileManager::OnDownloadManagerShutdown(DownloadManager* manager) { |
285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
286 DCHECK(manager); | 283 DCHECK(manager); |
287 | 284 |
288 std::set<DownloadFile*> to_remove; | 285 std::set<DownloadFile*> to_remove; |
289 | 286 |
290 for (DownloadFileMap::iterator i = downloads_.begin(); | 287 for (DownloadFileMap::iterator i = downloads_.begin(); |
291 i != downloads_.end(); ++i) { | 288 i != downloads_.end(); ++i) { |
292 DownloadFile* download_file = i->second; | 289 DownloadFile* download_file = i->second; |
293 if (download_file->GetDownloadManager() == manager) { | 290 if (download_file->GetDownloadManager() == manager) { |
294 download_file->CancelDownloadRequest(); | 291 download_file->CancelDownloadRequest(); |
295 to_remove.insert(download_file); | 292 to_remove.insert(download_file); |
296 } | 293 } |
297 } | 294 } |
298 | 295 |
299 for (std::set<DownloadFile*>::iterator i = to_remove.begin(); | 296 for (std::set<DownloadFile*>::iterator i = to_remove.begin(); |
300 i != to_remove.end(); ++i) { | 297 i != to_remove.end(); ++i) { |
301 downloads_.erase((*i)->id()); | 298 downloads_.erase(DownloadId((*i)->GetDownloadManager(), (*i)->id())); |
302 delete *i; | 299 delete *i; |
303 } | 300 } |
304 } | 301 } |
305 | 302 |
306 // Actions from the UI thread and run on the download thread | 303 // Actions from the UI thread and run on the download thread |
307 | 304 |
308 // The DownloadManager in the UI thread has provided an intermediate .crdownload | 305 // The DownloadManager in the UI thread has provided an intermediate .crdownload |
309 // name for the download specified by 'id'. Rename the in progress download. | 306 // name for the download specified by 'id'. Rename the in progress download. |
310 // | 307 // |
311 // There are 2 possible rename cases where this method can be called: | 308 // There are 2 possible rename cases where this method can be called: |
312 // 1. tmp -> foo.crdownload (not final, safe) | 309 // 1. tmp -> foo.crdownload (not final, safe) |
313 // 2. tmp-> Unconfirmed.xxx.crdownload (not final, dangerous) | 310 // 2. tmp-> Unconfirmed.xxx.crdownload (not final, dangerous) |
314 void DownloadFileManager::RenameInProgressDownloadFile( | 311 void DownloadFileManager::RenameInProgressDownloadFile( |
315 int id, const FilePath& full_path) { | 312 DownloadId global_id, const FilePath& full_path) { |
316 VLOG(20) << __FUNCTION__ << "()" << " id = " << id | 313 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id |
317 << " full_path = \"" << full_path.value() << "\""; | 314 << " full_path = \"" << full_path.value() << "\""; |
318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 315 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
319 | 316 |
320 DownloadFile* download_file = GetDownloadFile(id); | 317 DownloadFile* download_file = GetDownloadFile(global_id); |
321 if (!download_file) | 318 if (!download_file) |
322 return; | 319 return; |
323 | 320 |
324 VLOG(20) << __FUNCTION__ << "()" | 321 VLOG(20) << __FUNCTION__ << "()" |
325 << " download_file = " << download_file->DebugString(); | 322 << " download_file = " << download_file->DebugString(); |
326 | 323 |
327 net::Error rename_error = download_file->Rename(full_path); | 324 net::Error rename_error = download_file->Rename(full_path); |
328 if (net::OK != rename_error) { | 325 if (net::OK != rename_error) { |
329 // Error. Between the time the UI thread generated 'full_path' to the time | 326 // Error. Between the time the UI thread generated 'full_path' to the time |
330 // this code runs, something happened that prevents us from renaming. | 327 // this code runs, something happened that prevents us from renaming. |
331 CancelDownloadOnRename(id, rename_error); | 328 CancelDownloadOnRename(global_id, rename_error); |
332 } | 329 } |
333 } | 330 } |
334 | 331 |
335 // The DownloadManager in the UI thread has provided a final name for the | 332 // The DownloadManager in the UI thread has provided a final name for the |
336 // download specified by 'id'. Rename the download that's in the process | 333 // download specified by 'id'. Rename the download that's in the process |
337 // of completing. | 334 // of completing. |
338 // | 335 // |
339 // There are 2 possible rename cases where this method can be called: | 336 // There are 2 possible rename cases where this method can be called: |
340 // 1. foo.crdownload -> foo (final, safe) | 337 // 1. foo.crdownload -> foo (final, safe) |
341 // 2. Unconfirmed.xxx.crdownload -> xxx (final, validated) | 338 // 2. Unconfirmed.xxx.crdownload -> xxx (final, validated) |
342 void DownloadFileManager::RenameCompletingDownloadFile( | 339 void DownloadFileManager::RenameCompletingDownloadFile( |
343 int id, const FilePath& full_path, bool overwrite_existing_file) { | 340 DownloadId global_id, |
344 VLOG(20) << __FUNCTION__ << "()" << " id = " << id | 341 const FilePath& full_path, |
| 342 bool overwrite_existing_file) { |
| 343 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id |
345 << " overwrite_existing_file = " << overwrite_existing_file | 344 << " overwrite_existing_file = " << overwrite_existing_file |
346 << " full_path = \"" << full_path.value() << "\""; | 345 << " full_path = \"" << full_path.value() << "\""; |
347 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
348 | 347 |
349 DownloadFile* download_file = GetDownloadFile(id); | 348 DownloadFile* download_file = GetDownloadFile(global_id); |
350 if (!download_file) | 349 if (!download_file) |
351 return; | 350 return; |
352 | 351 |
353 DCHECK(download_file->GetDownloadManager()); | 352 DCHECK(download_file->GetDownloadManager()); |
354 DownloadManager* download_manager = download_file->GetDownloadManager(); | 353 DownloadManager* download_manager = download_file->GetDownloadManager(); |
355 | 354 |
356 VLOG(20) << __FUNCTION__ << "()" | 355 VLOG(20) << __FUNCTION__ << "()" |
357 << " download_file = " << download_file->DebugString(); | 356 << " download_file = " << download_file->DebugString(); |
358 | 357 |
359 int uniquifier = 0; | 358 int uniquifier = 0; |
(...skipping 10 matching lines...) Expand all Loading... |
370 if (uniquifier > 0) { | 369 if (uniquifier > 0) { |
371 DownloadFile::AppendNumberToPath(&new_path, uniquifier); | 370 DownloadFile::AppendNumberToPath(&new_path, uniquifier); |
372 } | 371 } |
373 } | 372 } |
374 | 373 |
375 // Rename the file, overwriting if necessary. | 374 // Rename the file, overwriting if necessary. |
376 net::Error rename_error = download_file->Rename(full_path); | 375 net::Error rename_error = download_file->Rename(full_path); |
377 if (net::OK != rename_error) { | 376 if (net::OK != rename_error) { |
378 // Error. Between the time the UI thread generated 'full_path' to the time | 377 // Error. Between the time the UI thread generated 'full_path' to the time |
379 // this code runs, something happened that prevents us from renaming. | 378 // this code runs, something happened that prevents us from renaming. |
380 CancelDownloadOnRename(id, rename_error); | 379 CancelDownloadOnRename(global_id, rename_error); |
381 return; | 380 return; |
382 } | 381 } |
383 | 382 |
384 #if defined(OS_MACOSX) | 383 #if defined(OS_MACOSX) |
385 // Done here because we only want to do this once; see | 384 // Done here because we only want to do this once; see |
386 // http://crbug.com/13120 for details. | 385 // http://crbug.com/13120 for details. |
387 download_file->AnnotateWithSourceInformation(); | 386 download_file->AnnotateWithSourceInformation(); |
388 #endif | 387 #endif |
389 | 388 |
390 BrowserThread::PostTask( | 389 BrowserThread::PostTask( |
391 BrowserThread::UI, FROM_HERE, | 390 BrowserThread::UI, FROM_HERE, |
392 NewRunnableMethod( | 391 NewRunnableMethod( |
393 download_manager, &DownloadManager::OnDownloadRenamedToFinalName, id, | 392 download_manager, &DownloadManager::OnDownloadRenamedToFinalName, |
394 new_path, uniquifier)); | 393 global_id.local(), new_path, uniquifier)); |
395 } | 394 } |
396 | 395 |
397 // Called only from RenameInProgressDownloadFile and | 396 // Called only from RenameInProgressDownloadFile and |
398 // RenameCompletingDownloadFile on the FILE thread. | 397 // RenameCompletingDownloadFile on the FILE thread. |
399 void DownloadFileManager::CancelDownloadOnRename(int id, | 398 void DownloadFileManager::CancelDownloadOnRename( |
400 net::Error rename_error) { | 399 DownloadId global_id, net::Error rename_error) { |
401 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 400 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
402 | 401 |
403 DownloadFile* download_file = GetDownloadFile(id); | 402 DownloadFile* download_file = GetDownloadFile(global_id); |
404 if (!download_file) | 403 if (!download_file) |
405 return; | 404 return; |
406 | 405 |
407 DownloadManager* download_manager = download_file->GetDownloadManager(); | 406 DownloadManager* download_manager = download_file->GetDownloadManager(); |
408 if (!download_manager) { | 407 if (!download_manager) { |
409 // Without a download manager, we can't cancel the request normally, so we | 408 // Without a download manager, we can't cancel the request normally, so we |
410 // need to do it here. The normal path will also update the download | 409 // need to do it here. The normal path will also update the download |
411 // history before canceling the request. | 410 // history before canceling the request. |
412 download_file->CancelDownloadRequest(); | 411 download_file->CancelDownloadRequest(); |
413 return; | 412 return; |
414 } | 413 } |
415 | 414 |
416 BrowserThread::PostTask( | 415 BrowserThread::PostTask( |
417 BrowserThread::UI, FROM_HERE, | 416 BrowserThread::UI, FROM_HERE, |
418 NewRunnableMethod(download_manager, | 417 NewRunnableMethod(download_manager, |
419 &DownloadManager::OnDownloadError, | 418 &DownloadManager::OnDownloadError, |
420 id, | 419 global_id.local(), |
421 download_file->bytes_so_far(), | 420 download_file->bytes_so_far(), |
422 rename_error)); | 421 rename_error)); |
423 } | 422 } |
424 | 423 |
425 void DownloadFileManager::EraseDownload(int id) { | 424 void DownloadFileManager::EraseDownload(DownloadId global_id) { |
426 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 425 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
427 | 426 |
428 if (!ContainsKey(downloads_, id)) | 427 if (!ContainsKey(downloads_, global_id)) |
429 return; | 428 return; |
430 | 429 |
431 DownloadFile* download_file = downloads_[id]; | 430 DownloadFile* download_file = downloads_[global_id]; |
432 | 431 |
433 VLOG(20) << " " << __FUNCTION__ << "()" | 432 VLOG(20) << " " << __FUNCTION__ << "()" |
434 << " id = " << id | 433 << " id = " << global_id |
435 << " download_file = " << download_file->DebugString(); | 434 << " download_file = " << download_file->DebugString(); |
436 | 435 |
437 downloads_.erase(id); | 436 downloads_.erase(global_id); |
438 | 437 |
439 delete download_file; | 438 delete download_file; |
440 | 439 |
441 if (downloads_.empty()) | 440 if (downloads_.empty()) |
442 StopUpdateTimer(); | 441 StopUpdateTimer(); |
443 } | 442 } |
OLD | NEW |