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

Side by Side Diff: chrome/browser/download/download_file_manager.cc

Issue 3348010: Revert 58196 - GTTF: Clean up DownloadFileManager... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 3 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/download/download_file_manager.h" 5 #include "chrome/browser/download/download_file_manager.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/stl_util-inl.h" 8 #include "base/stl_util-inl.h"
9 #include "base/task.h" 9 #include "base/task.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
(...skipping 17 matching lines...) Expand all
28 #elif defined(OS_MACOSX) 28 #elif defined(OS_MACOSX)
29 #include "chrome/browser/cocoa/file_metadata.h" 29 #include "chrome/browser/cocoa/file_metadata.h"
30 #endif 30 #endif
31 31
32 namespace { 32 namespace {
33 33
34 // Throttle updates to the UI thread so that a fast moving download doesn't 34 // Throttle updates to the UI thread so that a fast moving download doesn't
35 // cause it to become unresponsive (in milliseconds). 35 // cause it to become unresponsive (in milliseconds).
36 const int kUpdatePeriodMs = 500; 36 const int kUpdatePeriodMs = 500;
37 37
38 DownloadManager* DownloadManagerForRenderViewHost(int render_process_id,
39 int render_view_id) {
40 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
41
42 TabContents* contents = tab_util::GetTabContentsByID(render_process_id,
43 render_view_id);
44 if (contents) {
45 Profile* profile = contents->profile();
46 if (profile)
47 return profile->GetDownloadManager();
48 }
49
50 return NULL;
51 }
52
53 } // namespace 38 } // namespace
54 39
55 DownloadFileManager::DownloadFileManager(ResourceDispatcherHost* rdh) 40 DownloadFileManager::DownloadFileManager(ResourceDispatcherHost* rdh)
56 : next_id_(0), 41 : next_id_(0),
57 resource_dispatcher_host_(rdh) { 42 resource_dispatcher_host_(rdh) {
58 } 43 }
59 44
60 DownloadFileManager::~DownloadFileManager() { 45 DownloadFileManager::~DownloadFileManager() {
46 // Check for clean shutdown.
61 DCHECK(downloads_.empty()); 47 DCHECK(downloads_.empty());
62 } 48 }
63 49
50 // Called during the browser shutdown process to clean up any state (open files,
51 // timers) that live on the download_thread_.
64 void DownloadFileManager::Shutdown() { 52 void DownloadFileManager::Shutdown() {
65 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 53 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
54 StopUpdateTimer();
66 ChromeThread::PostTask( 55 ChromeThread::PostTask(
67 ChromeThread::FILE, FROM_HERE, 56 ChromeThread::FILE, FROM_HERE,
68 NewRunnableMethod(this, &DownloadFileManager::OnShutdown)); 57 NewRunnableMethod(this, &DownloadFileManager::OnShutdown));
69 } 58 }
70 59
60 // Cease download thread operations.
71 void DownloadFileManager::OnShutdown() { 61 void DownloadFileManager::OnShutdown() {
72 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 62 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
73 StopUpdateTimer();
74 STLDeleteValues(&downloads_); 63 STLDeleteValues(&downloads_);
75 } 64 }
76 65
77 void DownloadFileManager::CreateDownloadFile( 66 // Notifications sent from the download thread and run on the UI thread.
78 DownloadCreateInfo* info, DownloadManager* download_manager) {
79 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
80 67
81 scoped_ptr<DownloadFile> download_file( 68 // Lookup the DownloadManager for this TabContents' profile and inform it of
82 new DownloadFile(info, download_manager)); 69 // a new download.
83 if (!download_file->Initialize()) { 70 // TODO(paulg): When implementing download restart via the Downloads tab,
71 // there will be no 'render_process_id' or 'render_view_id'.
72 void DownloadFileManager::OnStartDownload(DownloadCreateInfo* info) {
73 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
74 DownloadManager* manager = DownloadManagerFromRenderIds(info->child_id,
75 info->render_view_id);
76 if (!manager) {
84 ChromeThread::PostTask( 77 ChromeThread::PostTask(
85 ChromeThread::IO, FROM_HERE, 78 ChromeThread::IO, FROM_HERE,
86 NewRunnableFunction(&download_util::CancelDownloadRequest, 79 NewRunnableFunction(&download_util::CancelDownloadRequest,
87 resource_dispatcher_host_, 80 resource_dispatcher_host_,
88 info->child_id, 81 info->child_id,
89 info->request_id)); 82 info->request_id));
90 delete info; 83 delete info;
91 return; 84 return;
92 } 85 }
93 86
94 DCHECK(GetDownloadFile(info->download_id) == NULL);
95 downloads_[info->download_id] = download_file.release();
96 // TODO(phajdan.jr): fix the duplication of path info below.
97 info->path = info->save_info.file_path;
98
99 StartUpdateTimer(); 87 StartUpdateTimer();
100 88
101 ChromeThread::PostTask( 89 // Add the download manager to our request maps for future updates. We want to
102 ChromeThread::UI, FROM_HERE, 90 // be able to cancel all in progress downloads when a DownloadManager is
103 NewRunnableMethod(download_manager, 91 // deleted, such as when a profile is closed. We also want to be able to look
104 &DownloadManager::StartDownload, info)); 92 // up the DownloadManager associated with a given request without having to
93 // rely on using tab information, since a tab may be closed while a download
94 // initiated from that tab is still in progress.
95 DownloadRequests& downloads = requests_[manager];
96 downloads.insert(info->download_id);
97
98 // TODO(paulg): The manager will exist when restarts are implemented.
99 DownloadManagerMap::iterator dit = managers_.find(info->download_id);
100 if (dit == managers_.end())
101 managers_[info->download_id] = manager;
102 else
103 NOTREACHED();
104
105 // StartDownload will clean up |info|.
106 manager->StartDownload(info);
105 } 107 }
106 108
109 // Update the Download Manager with the finish state, and remove the request
110 // tracking entries.
111 void DownloadFileManager::OnDownloadFinished(int id,
112 int64 bytes_so_far) {
113 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
114 DownloadManager* manager = GetDownloadManager(id);
115 if (manager)
116 manager->DownloadFinished(id, bytes_so_far);
117 RemoveDownload(id, manager);
118 RemoveDownloadFromUIProgress(id);
119 }
120
121 // Lookup one in-progress download.
107 DownloadFile* DownloadFileManager::GetDownloadFile(int id) { 122 DownloadFile* DownloadFileManager::GetDownloadFile(int id) {
108 DownloadFileMap::iterator it = downloads_.find(id); 123 DownloadFileMap::iterator it = downloads_.find(id);
109 return it == downloads_.end() ? NULL : it->second; 124 return it == downloads_.end() ? NULL : it->second;
110 } 125 }
111 126
127 // The UI progress is updated on the file thread and removed on the UI thread.
128 void DownloadFileManager::RemoveDownloadFromUIProgress(int id) {
129 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
130 AutoLock lock(progress_lock_);
131 if (ui_progress_.find(id) != ui_progress_.end())
132 ui_progress_.erase(id);
133 }
134
135 // Throttle updates to the UI thread by only posting update notifications at a
136 // regularly controlled interval.
112 void DownloadFileManager::StartUpdateTimer() { 137 void DownloadFileManager::StartUpdateTimer() {
113 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 138 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
114 if (!update_timer_.IsRunning()) { 139 if (!update_timer_.IsRunning()) {
115 update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), 140 update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdatePeriodMs),
116 this, &DownloadFileManager::UpdateInProgressDownloads); 141 this, &DownloadFileManager::UpdateInProgressDownloads);
117 } 142 }
118 } 143 }
119 144
120 void DownloadFileManager::StopUpdateTimer() { 145 void DownloadFileManager::StopUpdateTimer() {
121 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 146 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
122 update_timer_.Stop(); 147 update_timer_.Stop();
123 } 148 }
124 149
150 // Our periodic timer has fired so send the UI thread updates on all in progress
151 // downloads.
125 void DownloadFileManager::UpdateInProgressDownloads() { 152 void DownloadFileManager::UpdateInProgressDownloads() {
126 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 153 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
127 for (DownloadFileMap::iterator i = downloads_.begin(); 154 AutoLock lock(progress_lock_);
128 i != downloads_.end(); ++i) { 155 ProgressMap::iterator it = ui_progress_.begin();
129 int id = i->first; 156 for (; it != ui_progress_.end(); ++it) {
130 DownloadFile* download_file = i->second; 157 const int id = it->first;
131 DownloadManager* manager = download_file->GetDownloadManager(); 158 DownloadManager* manager = GetDownloadManager(id);
132 if (manager) { 159 if (manager)
133 ChromeThread::PostTask(ChromeThread::UI, FROM_HERE, 160 manager->UpdateDownload(id, it->second);
134 NewRunnableMethod(manager, &DownloadManager::UpdateDownload,
135 id, download_file->bytes_so_far()));
136 }
137 } 161 }
138 } 162 }
139 163
140 // Called on the IO thread once the ResourceDispatcherHost has decided that a 164 // Called on the IO thread once the ResourceDispatcherHost has decided that a
141 // request is a download. 165 // request is a download.
142 int DownloadFileManager::GetNextId() { 166 int DownloadFileManager::GetNextId() {
143 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); 167 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
144 return next_id_++; 168 return next_id_++;
145 } 169 }
146 170
171 // Notifications sent from the IO thread and run on the download thread:
172
173 // The IO thread created 'info', but the download thread (this method) uses it
174 // to create a DownloadFile, then passes 'info' to the UI thread where it is
175 // finally consumed and deleted.
147 void DownloadFileManager::StartDownload(DownloadCreateInfo* info) { 176 void DownloadFileManager::StartDownload(DownloadCreateInfo* info) {
148 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 177 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
149 DCHECK(info); 178 DCHECK(info);
150 179
151 DownloadManager* manager = DownloadManagerForRenderViewHost( 180 DownloadFile* download = new DownloadFile(info);
152 info->child_id, info->render_view_id); 181 if (!download->Initialize()) {
153 if (!manager) { 182 // Couldn't open, cancel the operation. The UI thread does not yet know
183 // about this download so we have to clean up 'info'. We need to get back
184 // to the IO thread to cancel the network request and CancelDownloadRequest
185 // on the UI thread is the safe way to do that.
154 ChromeThread::PostTask( 186 ChromeThread::PostTask(
155 ChromeThread::IO, FROM_HERE, 187 ChromeThread::IO, FROM_HERE,
156 NewRunnableFunction(&download_util::CancelDownloadRequest, 188 NewRunnableFunction(&download_util::CancelDownloadRequest,
157 resource_dispatcher_host_, 189 resource_dispatcher_host_,
158 info->child_id, 190 info->child_id,
159 info->request_id)); 191 info->request_id));
160 delete info; 192 delete info;
193 delete download;
161 return; 194 return;
162 } 195 }
163 196
164 ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE, 197 DCHECK(GetDownloadFile(info->download_id) == NULL);
165 NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile, 198 downloads_[info->download_id] = download;
166 info, manager)); 199 // TODO(phajdan.jr): fix the duplication of path info below.
200 info->path = info->save_info.file_path;
201 {
202 AutoLock lock(progress_lock_);
203 ui_progress_[info->download_id] = info->received_bytes;
204 }
205
206 ChromeThread::PostTask(
207 ChromeThread::UI, FROM_HERE,
208 NewRunnableMethod(this, &DownloadFileManager::OnStartDownload, info));
167 } 209 }
168 210
169 // We don't forward an update to the UI thread here, since we want to throttle 211 // We don't forward an update to the UI thread here, since we want to throttle
170 // the UI update rate via a periodic timer. If the user has cancelled the 212 // the UI update rate via a periodic timer. If the user has cancelled the
171 // download (in the UI thread), we may receive a few more updates before the IO 213 // download (in the UI thread), we may receive a few more updates before the IO
172 // thread gets the cancel message: we just delete the data since the 214 // thread gets the cancel message: we just delete the data since the
173 // DownloadFile has been deleted. 215 // DownloadFile has been deleted.
174 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) { 216 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) {
175 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 217 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
176 std::vector<DownloadBuffer::Contents> contents; 218 std::vector<DownloadBuffer::Contents> contents;
177 { 219 {
178 AutoLock auto_lock(buffer->lock); 220 AutoLock auto_lock(buffer->lock);
179 contents.swap(buffer->contents); 221 contents.swap(buffer->contents);
180 } 222 }
181 223
224 // Keep track of how many bytes we have successfully saved to update
225 // our progress status in the UI.
226 int64 progress_bytes = 0;
227
182 DownloadFile* download = GetDownloadFile(id); 228 DownloadFile* download = GetDownloadFile(id);
183 for (size_t i = 0; i < contents.size(); ++i) { 229 for (size_t i = 0; i < contents.size(); ++i) {
184 net::IOBuffer* data = contents[i].first; 230 net::IOBuffer* data = contents[i].first;
185 const int data_len = contents[i].second; 231 const int data_len = contents[i].second;
186 if (download) 232 if (download) {
187 download->AppendDataToFile(data->data(), data_len); 233 if (download->AppendDataToFile(data->data(), data_len))
234 progress_bytes += data_len;
235 }
188 data->Release(); 236 data->Release();
189 } 237 }
238
239 if (download) {
240 AutoLock lock(progress_lock_);
241 ui_progress_[download->id()] += progress_bytes;
242 }
190 } 243 }
191 244
192 void DownloadFileManager::DownloadFinished(int id, DownloadBuffer* buffer) { 245 void DownloadFileManager::DownloadFinished(int id, DownloadBuffer* buffer) {
193 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 246 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
194 delete buffer; 247 delete buffer;
195 DownloadFileMap::iterator it = downloads_.find(id); 248 DownloadFileMap::iterator it = downloads_.find(id);
196 if (it != downloads_.end()) { 249 if (it != downloads_.end()) {
197 DownloadFile* download = it->second; 250 DownloadFile* download = it->second;
198 download->Finish(); 251 download->Finish();
199 252
200 DownloadManager* download_manager = download->GetDownloadManager(); 253 int64 download_size = -1;
201 if (download_manager) { 254 {
202 ChromeThread::PostTask( 255 AutoLock lock(progress_lock_);
203 ChromeThread::UI, FROM_HERE, 256 download_size = ui_progress_[download->id()];
204 NewRunnableMethod(
205 download_manager, &DownloadManager::DownloadFinished,
206 id, download->bytes_so_far()));
207 } 257 }
208 258
259 ChromeThread::PostTask(
260 ChromeThread::UI, FROM_HERE,
261 NewRunnableMethod(
262 this, &DownloadFileManager::OnDownloadFinished,
263 id, download_size));
264
209 // We need to keep the download around until the UI thread has finalized 265 // We need to keep the download around until the UI thread has finalized
210 // the name. 266 // the name.
211 if (download->path_renamed()) { 267 if (download->path_renamed()) {
212 downloads_.erase(it); 268 downloads_.erase(it);
213 delete download; 269 delete download;
214 } 270 }
215 } 271 }
216 272
217 if (downloads_.empty()) 273 if (downloads_.empty())
218 StopUpdateTimer(); 274 ChromeThread::PostTask(
275 ChromeThread::UI, FROM_HERE,
276 NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer));
219 } 277 }
220 278
221 // This method will be sent via a user action, or shutdown on the UI thread, and 279 // This method will be sent via a user action, or shutdown on the UI thread, and
222 // run on the download thread. Since this message has been sent from the UI 280 // run on the download thread. Since this message has been sent from the UI
223 // thread, the download may have already completed and won't exist in our map. 281 // thread, the download may have already completed and won't exist in our map.
224 void DownloadFileManager::CancelDownload(int id) { 282 void DownloadFileManager::CancelDownload(int id) {
225 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 283 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
226 DownloadFileMap::iterator it = downloads_.find(id); 284 DownloadFileMap::iterator it = downloads_.find(id);
227 if (it != downloads_.end()) { 285 if (it != downloads_.end()) {
228 DownloadFile* download = it->second; 286 DownloadFile* download = it->second;
229 download->Cancel(); 287 download->Cancel();
230 288
289 ChromeThread::PostTask(
290 ChromeThread::UI, FROM_HERE,
291 NewRunnableMethod(
292 this, &DownloadFileManager::RemoveDownloadFromUIProgress,
293 download->id()));
294
231 if (download->path_renamed()) { 295 if (download->path_renamed()) {
232 downloads_.erase(it); 296 downloads_.erase(it);
233 delete download; 297 delete download;
234 } 298 }
235 } 299 }
236 300
237 if (downloads_.empty()) 301 if (downloads_.empty()) {
238 StopUpdateTimer(); 302 ChromeThread::PostTask(
239 } 303 ChromeThread::UI, FROM_HERE,
240 304 NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer));
241 void DownloadFileManager::OnDownloadManagerShutdown(DownloadManager* manager) {
242 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
243 DCHECK(manager);
244
245 for (DownloadFileMap::iterator i = downloads_.begin();
246 i != downloads_.end(); ++i) {
247 DownloadFile* download_file = i->second;
248 if (download_file->GetDownloadManager() == manager)
249 download_file->OnDownloadManagerShutdown();
250 } 305 }
251 } 306 }
252 307
308 // Relate a download ID to its owning DownloadManager.
309 DownloadManager* DownloadFileManager::GetDownloadManager(int download_id) {
310 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
311 DownloadManagerMap::iterator it = managers_.find(download_id);
312 if (it != managers_.end())
313 return it->second;
314 return NULL;
315 }
316
317 // Utility function for look up table maintenance, called on the UI thread.
318 // A manager may have multiple downloads in progress, so we just look up the
319 // one download (id) and remove it from the set, and remove the set if it
320 // becomes empty.
321 void DownloadFileManager::RemoveDownload(int id, DownloadManager* manager) {
322 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
323 if (manager) {
324 RequestMap::iterator it = requests_.find(manager);
325 if (it != requests_.end()) {
326 DownloadRequests& downloads = it->second;
327 DownloadRequests::iterator rit = downloads.find(id);
328 if (rit != downloads.end())
329 downloads.erase(rit);
330 if (downloads.empty())
331 requests_.erase(it);
332 }
333 }
334
335 // A download can only have one manager, so remove it if it exists.
336 DownloadManagerMap::iterator dit = managers_.find(id);
337 if (dit != managers_.end())
338 managers_.erase(dit);
339 }
340
341 // Utility function for converting request IDs to a TabContents. Must be called
342 // only on the UI thread since Profile operations may create UI objects, such as
343 // the first call to profile->GetDownloadManager().
344 // static
345 DownloadManager* DownloadFileManager::DownloadManagerFromRenderIds(
346 int render_process_id, int render_view_id) {
347 TabContents* contents = tab_util::GetTabContentsByID(render_process_id,
348 render_view_id);
349 if (contents) {
350 Profile* profile = contents->profile();
351 if (profile)
352 return profile->GetDownloadManager();
353 }
354
355 return NULL;
356 }
357
358 // Called by DownloadManagers in their destructor, and only on the UI thread.
359 void DownloadFileManager::RemoveDownloadManager(DownloadManager* manager) {
360 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
361 DCHECK(manager);
362 RequestMap::iterator it = requests_.find(manager);
363 if (it == requests_.end())
364 return;
365
366 const DownloadRequests& requests = it->second;
367 DownloadRequests::const_iterator i = requests.begin();
368 for (; i != requests.end(); ++i) {
369 DownloadManagerMap::iterator dit = managers_.find(*i);
370 if (dit != managers_.end()) {
371 DCHECK(dit->second == manager);
372 managers_.erase(dit);
373 }
374 }
375
376 requests_.erase(it);
377 }
378
253 // Actions from the UI thread and run on the download thread 379 // Actions from the UI thread and run on the download thread
254 380
255 // Open a download, or show it in a file explorer window. We run on this 381 // Open a download, or show it in a file explorer window. We run on this
256 // thread to avoid blocking the UI with (potentially) slow Shell operations. 382 // thread to avoid blocking the UI with (potentially) slow Shell operations.
257 // TODO(paulg): File 'stat' operations. 383 // TODO(paulg): File 'stat' operations.
258 #if !defined(OS_MACOSX) 384 #if !defined(OS_MACOSX)
259 void DownloadFileManager::OnShowDownloadInShell(const FilePath& full_path) { 385 void DownloadFileManager::OnShowDownloadInShell(const FilePath& full_path) {
260 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 386 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
261 platform_util::ShowItemInFolder(full_path); 387 platform_util::ShowItemInFolder(full_path);
262 } 388 }
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 if (need_delete_crdownload) 465 if (need_delete_crdownload)
340 download->DeleteCrDownload(); 466 download->DeleteCrDownload();
341 467
342 // If the download has completed before we got this final name, we remove it 468 // If the download has completed before we got this final name, we remove it
343 // from our in progress map. 469 // from our in progress map.
344 if (!download->in_progress()) { 470 if (!download->in_progress()) {
345 downloads_.erase(id); 471 downloads_.erase(id);
346 delete download; 472 delete download;
347 } 473 }
348 474
349 if (downloads_.empty()) 475 if (downloads_.empty()) {
350 StopUpdateTimer(); 476 ChromeThread::PostTask(
477 ChromeThread::UI, FROM_HERE,
478 NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer));
479 }
351 } 480 }
352 481
353 // Called only from OnFinalDownloadName or OnIntermediateDownloadName 482 // Called only from OnFinalDownloadName or OnIntermediateDownloadName
354 // on the FILE thread. 483 // on the FILE thread.
355 void DownloadFileManager::CancelDownloadOnRename(int id) { 484 void DownloadFileManager::CancelDownloadOnRename(int id) {
356 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 485 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
357 486
358 DownloadFile* download = GetDownloadFile(id); 487 DownloadFile* download = GetDownloadFile(id);
359 if (!download) 488 if (!download)
360 return; 489 return;
361 490
362 DownloadManager* download_manager = download->GetDownloadManager(); 491 DownloadManagerMap::iterator dmit = managers_.find(download->id());
363 if (!download_manager) { 492 if (dmit != managers_.end()) {
493 DownloadManager* dlm = dmit->second;
494 ChromeThread::PostTask(
495 ChromeThread::UI, FROM_HERE,
496 NewRunnableMethod(dlm, &DownloadManager::DownloadCancelled, id));
497 } else {
364 download->CancelDownloadRequest(resource_dispatcher_host_); 498 download->CancelDownloadRequest(resource_dispatcher_host_);
365 return;
366 } 499 }
367
368 ChromeThread::PostTask(
369 ChromeThread::UI, FROM_HERE,
370 NewRunnableMethod(download_manager,
371 &DownloadManager::DownloadCancelled, id));
372 } 500 }
OLDNEW
« no previous file with comments | « chrome/browser/download/download_file_manager.h ('k') | chrome/browser/download/download_manager.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698