OLD | NEW |
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_manager.h" | 5 #include "chrome/browser/download/download_manager.h" |
6 | 6 |
7 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
8 #include "app/resource_bundle.h" | 8 #include "app/resource_bundle.h" |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/path_service.h" | 12 #include "base/path_service.h" |
13 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
14 #include "base/sys_string_conversions.h" | 14 #include "base/sys_string_conversions.h" |
15 #include "base/task.h" | 15 #include "base/task.h" |
16 #include "build/build_config.h" | 16 #include "build/build_config.h" |
17 #include "chrome/browser/browser.h" | 17 #include "chrome/browser/browser.h" |
18 #include "chrome/browser/browser_list.h" | 18 #include "chrome/browser/browser_list.h" |
19 #include "chrome/browser/browser_process.h" | 19 #include "chrome/browser/browser_process.h" |
20 #include "chrome/browser/chrome_thread.h" | 20 #include "chrome/browser/chrome_thread.h" |
21 #include "chrome/browser/download/download_file_manager.h" | 21 #include "chrome/browser/download/download_file_manager.h" |
| 22 #include "chrome/browser/download/download_history.h" |
22 #include "chrome/browser/download/download_item.h" | 23 #include "chrome/browser/download/download_item.h" |
23 #include "chrome/browser/download/download_util.h" | 24 #include "chrome/browser/download/download_util.h" |
24 #include "chrome/browser/extensions/crx_installer.h" | 25 #include "chrome/browser/extensions/crx_installer.h" |
25 #include "chrome/browser/extensions/extension_install_ui.h" | 26 #include "chrome/browser/extensions/extension_install_ui.h" |
26 #include "chrome/browser/extensions/extensions_service.h" | 27 #include "chrome/browser/extensions/extensions_service.h" |
27 #include "chrome/browser/history/download_types.h" | 28 #include "chrome/browser/history/download_types.h" |
28 #include "chrome/browser/net/chrome_url_request_context.h" | 29 #include "chrome/browser/net/chrome_url_request_context.h" |
29 #include "chrome/browser/platform_util.h" | 30 #include "chrome/browser/platform_util.h" |
30 #include "chrome/browser/profile.h" | 31 #include "chrome/browser/profile.h" |
31 #include "chrome/browser/renderer_host/render_process_host.h" | 32 #include "chrome/browser/renderer_host/render_process_host.h" |
(...skipping 27 matching lines...) Expand all Loading... |
59 void DeleteDownloadedFile(const FilePath& path) { | 60 void DeleteDownloadedFile(const FilePath& path) { |
60 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); | 61 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
61 | 62 |
62 // Make sure we only delete files. | 63 // Make sure we only delete files. |
63 if (!file_util::DirectoryExists(path)) | 64 if (!file_util::DirectoryExists(path)) |
64 file_util::Delete(path, false); | 65 file_util::Delete(path, false); |
65 } | 66 } |
66 | 67 |
67 } // namespace | 68 } // namespace |
68 | 69 |
69 // Our download table ID starts at 1, so we use 0 to represent a download that | |
70 // has started, but has not yet had its data persisted in the table. We use fake | |
71 // database handles in incognito mode starting at -1 and progressively getting | |
72 // more negative. | |
73 // static | |
74 const int DownloadManager::kUninitializedHandle = 0; | |
75 | |
76 // static | 70 // static |
77 void DownloadManager::RegisterUserPrefs(PrefService* prefs) { | 71 void DownloadManager::RegisterUserPrefs(PrefService* prefs) { |
78 prefs->RegisterBooleanPref(prefs::kPromptForDownload, false); | 72 prefs->RegisterBooleanPref(prefs::kPromptForDownload, false); |
79 prefs->RegisterStringPref(prefs::kDownloadExtensionsToOpen, ""); | 73 prefs->RegisterStringPref(prefs::kDownloadExtensionsToOpen, ""); |
80 prefs->RegisterBooleanPref(prefs::kDownloadDirUpgraded, false); | 74 prefs->RegisterBooleanPref(prefs::kDownloadDirUpgraded, false); |
81 | 75 |
82 // The default download path is userprofile\download. | 76 // The default download path is userprofile\download. |
83 const FilePath& default_download_path = | 77 const FilePath& default_download_path = |
84 download_util::GetDefaultDownloadDirectory(); | 78 download_util::GetDefaultDownloadDirectory(); |
85 prefs->RegisterFilePathPref(prefs::kDownloadDefaultDirectory, | 79 prefs->RegisterFilePathPref(prefs::kDownloadDefaultDirectory, |
(...skipping 16 matching lines...) Expand all Loading... |
102 prefs->SetFilePath(prefs::kDownloadDefaultDirectory, | 96 prefs->SetFilePath(prefs::kDownloadDefaultDirectory, |
103 default_download_path); | 97 default_download_path); |
104 } | 98 } |
105 prefs->SetBoolean(prefs::kDownloadDirUpgraded, true); | 99 prefs->SetBoolean(prefs::kDownloadDirUpgraded, true); |
106 } | 100 } |
107 } | 101 } |
108 | 102 |
109 DownloadManager::DownloadManager() | 103 DownloadManager::DownloadManager() |
110 : shutdown_needed_(false), | 104 : shutdown_needed_(false), |
111 profile_(NULL), | 105 profile_(NULL), |
112 file_manager_(NULL), | 106 file_manager_(NULL) { |
113 fake_db_handle_(kUninitializedHandle - 1) { | |
114 } | 107 } |
115 | 108 |
116 DownloadManager::~DownloadManager() { | 109 DownloadManager::~DownloadManager() { |
117 FOR_EACH_OBSERVER(Observer, observers_, ManagerGoingDown()); | 110 FOR_EACH_OBSERVER(Observer, observers_, ManagerGoingDown()); |
118 | 111 |
119 if (shutdown_needed_) | 112 if (shutdown_needed_) |
120 Shutdown(); | 113 Shutdown(); |
121 } | 114 } |
122 | 115 |
123 void DownloadManager::Shutdown() { | 116 void DownloadManager::Shutdown() { |
124 DCHECK(shutdown_needed_) << "Shutdown called when not needed."; | 117 DCHECK(shutdown_needed_) << "Shutdown called when not needed."; |
125 | 118 |
126 // Stop receiving download updates | 119 // Stop receiving download updates |
127 if (file_manager_) | 120 if (file_manager_) |
128 file_manager_->RemoveDownloadManager(this); | 121 file_manager_->RemoveDownloadManager(this); |
129 | 122 |
130 // Stop making history service requests | |
131 cancelable_consumer_.CancelAllRequests(); | |
132 | |
133 // 'in_progress_' may contain DownloadItems that have not finished the start | 123 // 'in_progress_' may contain DownloadItems that have not finished the start |
134 // complete (from the history service) and thus aren't in downloads_. | 124 // complete (from the history service) and thus aren't in downloads_. |
135 DownloadMap::iterator it = in_progress_.begin(); | 125 DownloadMap::iterator it = in_progress_.begin(); |
136 std::set<DownloadItem*> to_remove; | 126 std::set<DownloadItem*> to_remove; |
137 for (; it != in_progress_.end(); ++it) { | 127 for (; it != in_progress_.end(); ++it) { |
138 DownloadItem* download = it->second; | 128 DownloadItem* download = it->second; |
139 if (download->safety_state() == DownloadItem::DANGEROUS) { | 129 if (download->safety_state() == DownloadItem::DANGEROUS) { |
140 // Forget about any download that the user did not approve. | 130 // Forget about any download that the user did not approve. |
141 // Note that we cannot call download->Remove() this would invalidate our | 131 // Note that we cannot call download->Remove() this would invalidate our |
142 // iterator. | 132 // iterator. |
143 to_remove.insert(download); | 133 to_remove.insert(download); |
144 continue; | 134 continue; |
145 } | 135 } |
146 DCHECK_EQ(DownloadItem::IN_PROGRESS, download->state()); | 136 DCHECK_EQ(DownloadItem::IN_PROGRESS, download->state()); |
147 download->Cancel(false); | 137 download->Cancel(false); |
148 UpdateHistoryForDownload(download); | 138 download_history_->UpdateEntry(download); |
149 if (download->db_handle() == kUninitializedHandle) { | 139 if (download->db_handle() == DownloadHistory::kUninitializedHandle) { |
150 // An invalid handle means that 'download' does not yet exist in | 140 // An invalid handle means that 'download' does not yet exist in |
151 // 'downloads_', so we have to delete it here. | 141 // 'downloads_', so we have to delete it here. |
152 delete download; | 142 delete download; |
153 } | 143 } |
154 } | 144 } |
155 | 145 |
156 // 'dangerous_finished_' contains all complete downloads that have not been | 146 // 'dangerous_finished_' contains all complete downloads that have not been |
157 // approved. They should be removed. | 147 // approved. They should be removed. |
158 it = dangerous_finished_.begin(); | 148 it = dangerous_finished_.begin(); |
159 for (; it != dangerous_finished_.end(); ++it) | 149 for (; it != dangerous_finished_.end(); ++it) |
160 to_remove.insert(it->second); | 150 to_remove.insert(it->second); |
161 | 151 |
162 // Remove the dangerous download that are not approved. | 152 // Remove the dangerous download that are not approved. |
163 for (std::set<DownloadItem*>::const_iterator rm_it = to_remove.begin(); | 153 for (std::set<DownloadItem*>::const_iterator rm_it = to_remove.begin(); |
164 rm_it != to_remove.end(); ++rm_it) { | 154 rm_it != to_remove.end(); ++rm_it) { |
165 DownloadItem* download = *rm_it; | 155 DownloadItem* download = *rm_it; |
166 int64 handle = download->db_handle(); | 156 int64 handle = download->db_handle(); |
167 download->Remove(true); | 157 download->Remove(true); |
168 // Same as above, delete the download if it is not in 'downloads_' (as the | 158 // Same as above, delete the download if it is not in 'downloads_' (as the |
169 // Remove() call above won't have deleted it). | 159 // Remove() call above won't have deleted it). |
170 if (handle == kUninitializedHandle) | 160 if (handle == DownloadHistory::kUninitializedHandle) |
171 delete download; | 161 delete download; |
172 } | 162 } |
173 to_remove.clear(); | 163 to_remove.clear(); |
174 | 164 |
175 in_progress_.clear(); | 165 in_progress_.clear(); |
176 dangerous_finished_.clear(); | 166 dangerous_finished_.clear(); |
177 STLDeleteValues(&downloads_); | 167 STLDeleteValues(&downloads_); |
178 | 168 |
179 file_manager_ = NULL; | 169 file_manager_ = NULL; |
180 | 170 |
181 // Save our file extensions to auto open. | 171 // Save our file extensions to auto open. |
182 SaveAutoOpens(); | 172 SaveAutoOpens(); |
183 | 173 |
184 // Make sure the save as dialog doesn't notify us back if we're gone before | 174 // Make sure the save as dialog doesn't notify us back if we're gone before |
185 // it returns. | 175 // it returns. |
186 if (select_file_dialog_.get()) | 176 if (select_file_dialog_.get()) |
187 select_file_dialog_->ListenerDestroyed(); | 177 select_file_dialog_->ListenerDestroyed(); |
188 | 178 |
| 179 download_history_.reset(); |
| 180 |
189 shutdown_needed_ = false; | 181 shutdown_needed_ = false; |
190 } | 182 } |
191 | 183 |
192 // Issue a history query for downloads matching 'search_text'. If 'search_text' | 184 void DownloadManager::GetTemporaryDownloads( |
193 // is empty, return all downloads that we know about. | 185 const FilePath& dir_path, std::vector<DownloadItem*>* result) { |
194 void DownloadManager::GetDownloads(Observer* observer, | 186 DCHECK(result); |
195 const std::wstring& search_text) { | |
196 std::vector<DownloadItem*> otr_downloads; | |
197 | |
198 if (profile_->IsOffTheRecord() && search_text.empty()) { | |
199 // List all incognito downloads and add that to the downloads the parent | |
200 // profile lists. | |
201 otr_downloads.reserve(downloads_.size()); | |
202 for (DownloadMap::iterator it = downloads_.begin(); | |
203 it != downloads_.end(); ++it) { | |
204 DownloadItem* download = it->second; | |
205 if (download->is_otr() && !download->is_extension_install() && | |
206 !download->is_temporary()) { | |
207 otr_downloads.push_back(download); | |
208 } | |
209 } | |
210 } | |
211 | |
212 profile_->GetOriginalProfile()->GetDownloadManager()-> | |
213 DoGetDownloads(observer, search_text, otr_downloads); | |
214 } | |
215 | |
216 void DownloadManager::DoGetDownloads( | |
217 Observer* observer, | |
218 const std::wstring& search_text, | |
219 std::vector<DownloadItem*>& otr_downloads) { | |
220 DCHECK(observer); | |
221 | |
222 // Return a empty list if we've not yet received the set of downloads from the | |
223 // history system (we'll update all observers once we get that list in | |
224 // OnQueryDownloadEntriesComplete), or if there are no downloads at all. | |
225 if (downloads_.empty()) { | |
226 observer->SetDownloads(otr_downloads); | |
227 return; | |
228 } | |
229 | |
230 std::vector<DownloadItem*> download_copy; | |
231 // We already know all the downloads and there is no filter, so just return a | |
232 // copy to the observer. | |
233 if (search_text.empty()) { | |
234 download_copy.reserve(downloads_.size()); | |
235 for (DownloadMap::iterator it = downloads_.begin(); | |
236 it != downloads_.end(); ++it) { | |
237 if (it->second->db_handle() > kUninitializedHandle) | |
238 download_copy.push_back(it->second); | |
239 } | |
240 | |
241 // Merge sort based on start time. | |
242 std::vector<DownloadItem*> merged_downloads; | |
243 std::merge(otr_downloads.begin(), otr_downloads.end(), | |
244 download_copy.begin(), download_copy.end(), | |
245 std::back_inserter(merged_downloads), | |
246 CompareStartTime); | |
247 | |
248 // We retain ownership of the DownloadItems. | |
249 observer->SetDownloads(merged_downloads); | |
250 return; | |
251 } | |
252 | |
253 DCHECK(otr_downloads.empty()); | |
254 | |
255 // Issue a request to the history service for a list of downloads matching | |
256 // our search text. | |
257 HistoryService* hs = | |
258 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); | |
259 if (hs) { | |
260 HistoryService::Handle h = | |
261 hs->SearchDownloads(WideToUTF16(search_text), | |
262 &cancelable_consumer_, | |
263 NewCallback(this, | |
264 &DownloadManager::OnSearchComplete)); | |
265 cancelable_consumer_.SetClientData(hs, h, observer); | |
266 } | |
267 } | |
268 | |
269 void DownloadManager::GetTemporaryDownloads(Observer* observer, | |
270 const FilePath& dir_path) { | |
271 DCHECK(observer); | |
272 | |
273 std::vector<DownloadItem*> download_copy; | |
274 | 187 |
275 for (DownloadMap::iterator it = downloads_.begin(); | 188 for (DownloadMap::iterator it = downloads_.begin(); |
276 it != downloads_.end(); ++it) { | 189 it != downloads_.end(); ++it) { |
277 if (it->second->is_temporary() && | 190 if (it->second->is_temporary() && |
278 it->second->full_path().DirName() == dir_path) | 191 it->second->full_path().DirName() == dir_path) |
279 download_copy.push_back(it->second); | 192 result->push_back(it->second); |
280 } | 193 } |
281 | |
282 observer->SetDownloads(download_copy); | |
283 } | 194 } |
284 | 195 |
285 void DownloadManager::GetAllDownloads(Observer* observer, | 196 void DownloadManager::GetAllDownloads( |
286 const FilePath& dir_path) { | 197 const FilePath& dir_path, std::vector<DownloadItem*>* result) { |
287 DCHECK(observer); | 198 DCHECK(result); |
288 | |
289 std::vector<DownloadItem*> download_copy; | |
290 | 199 |
291 for (DownloadMap::iterator it = downloads_.begin(); | 200 for (DownloadMap::iterator it = downloads_.begin(); |
292 it != downloads_.end(); ++it) { | 201 it != downloads_.end(); ++it) { |
293 if (!it->second->is_temporary() && | 202 if (!it->second->is_temporary() && |
294 (dir_path.empty() || it->second->full_path().DirName() == dir_path)) | 203 (dir_path.empty() || it->second->full_path().DirName() == dir_path)) |
295 download_copy.push_back(it->second); | 204 result->push_back(it->second); |
296 } | 205 } |
297 | |
298 observer->SetDownloads(download_copy); | |
299 } | 206 } |
300 | 207 |
301 void DownloadManager::GetCurrentDownloads(Observer* observer, | 208 void DownloadManager::GetCurrentDownloads( |
302 const FilePath& dir_path) { | 209 const FilePath& dir_path, std::vector<DownloadItem*>* result) { |
303 DCHECK(observer); | 210 DCHECK(result); |
304 | |
305 std::vector<DownloadItem*> download_copy; | |
306 | 211 |
307 for (DownloadMap::iterator it = downloads_.begin(); | 212 for (DownloadMap::iterator it = downloads_.begin(); |
308 it != downloads_.end(); ++it) { | 213 it != downloads_.end(); ++it) { |
309 if (!it->second->is_temporary() && | 214 if (!it->second->is_temporary() && |
310 (it->second->state() == DownloadItem::IN_PROGRESS || | 215 (it->second->state() == DownloadItem::IN_PROGRESS || |
311 it->second->safety_state() == DownloadItem::DANGEROUS) && | 216 it->second->safety_state() == DownloadItem::DANGEROUS) && |
312 (dir_path.empty() || it->second->full_path().DirName() == dir_path)) | 217 (dir_path.empty() || it->second->full_path().DirName() == dir_path)) |
313 download_copy.push_back(it->second); | 218 result->push_back(it->second); |
314 } | 219 } |
315 | |
316 observer->SetDownloads(download_copy); | |
317 } | 220 } |
318 | 221 |
319 // Query the history service for information about all persisted downloads. | 222 // Query the history service for information about all persisted downloads. |
320 bool DownloadManager::Init(Profile* profile) { | 223 bool DownloadManager::Init(Profile* profile) { |
321 DCHECK(profile); | 224 DCHECK(profile); |
322 DCHECK(!shutdown_needed_) << "DownloadManager already initialized."; | 225 DCHECK(!shutdown_needed_) << "DownloadManager already initialized."; |
323 shutdown_needed_ = true; | 226 shutdown_needed_ = true; |
324 | 227 |
325 profile_ = profile; | 228 profile_ = profile; |
326 request_context_getter_ = profile_->GetRequestContext(); | 229 request_context_getter_ = profile_->GetRequestContext(); |
327 | 230 download_history_.reset(new DownloadHistory(profile, this)); |
328 // 'incognito mode' will have access to past downloads, but we won't store | 231 download_history_->Load( |
329 // information about new downloads while in that mode. | 232 NewCallback(this, &DownloadManager::OnQueryDownloadEntriesComplete)); |
330 QueryHistoryForDownloads(); | |
331 | |
332 // Cleans up entries only when called for the first time. Subsequent calls are | |
333 // a no op. | |
334 CleanUpInProgressHistoryEntries(); | |
335 | 233 |
336 // In test mode, there may be no ResourceDispatcherHost. In this case it's | 234 // In test mode, there may be no ResourceDispatcherHost. In this case it's |
337 // safe to avoid setting |file_manager_| because we only call a small set of | 235 // safe to avoid setting |file_manager_| because we only call a small set of |
338 // functions, none of which need it. | 236 // functions, none of which need it. |
339 ResourceDispatcherHost* rdh = g_browser_process->resource_dispatcher_host(); | 237 ResourceDispatcherHost* rdh = g_browser_process->resource_dispatcher_host(); |
340 if (rdh) { | 238 if (rdh) { |
341 file_manager_ = rdh->download_file_manager(); | 239 file_manager_ = rdh->download_file_manager(); |
342 DCHECK(file_manager_); | 240 DCHECK(file_manager_); |
343 } | 241 } |
344 | 242 |
(...skipping 24 matching lines...) Expand all Loading... |
369 if (!extensions[i].empty() && !IsExecutableFile(path)) | 267 if (!extensions[i].empty() && !IsExecutableFile(path)) |
370 auto_open_.insert(path.value()); | 268 auto_open_.insert(path.value()); |
371 } | 269 } |
372 | 270 |
373 other_download_manager_observer_.reset( | 271 other_download_manager_observer_.reset( |
374 new OtherDownloadManagerObserver(this)); | 272 new OtherDownloadManagerObserver(this)); |
375 | 273 |
376 return true; | 274 return true; |
377 } | 275 } |
378 | 276 |
379 void DownloadManager::QueryHistoryForDownloads() { | |
380 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); | |
381 if (hs) { | |
382 hs->QueryDownloads( | |
383 &cancelable_consumer_, | |
384 NewCallback(this, &DownloadManager::OnQueryDownloadEntriesComplete)); | |
385 } | |
386 } | |
387 | |
388 void DownloadManager::CleanUpInProgressHistoryEntries() { | |
389 static bool already_cleaned_up = false; | |
390 | |
391 if (!already_cleaned_up) { | |
392 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); | |
393 if (hs) { | |
394 hs->CleanUpInProgressEntries(); | |
395 already_cleaned_up = true; | |
396 } | |
397 } | |
398 } | |
399 | |
400 // We have received a message from DownloadFileManager about a new download. We | 277 // We have received a message from DownloadFileManager about a new download. We |
401 // create a download item and store it in our download map, and inform the | 278 // create a download item and store it in our download map, and inform the |
402 // history system of a new download. Since this method can be called while the | 279 // history system of a new download. Since this method can be called while the |
403 // history service thread is still reading the persistent state, we do not | 280 // history service thread is still reading the persistent state, we do not |
404 // insert the new DownloadItem into 'downloads_' or inform our observers at this | 281 // insert the new DownloadItem into 'downloads_' or inform our observers at this |
405 // point. OnCreateDatabaseEntryComplete() handles that finalization of the the | 282 // point. OnCreateDatabaseEntryComplete() handles that finalization of the the |
406 // download creation as a callback from the history thread. | 283 // download creation as a callback from the history thread. |
407 void DownloadManager::StartDownload(DownloadCreateInfo* info) { | 284 void DownloadManager::StartDownload(DownloadCreateInfo* info) { |
408 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 285 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
409 DCHECK(info); | 286 DCHECK(info); |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 | 483 |
607 if (download_finished) { | 484 if (download_finished) { |
608 // If the download already completed by the time we reached this point, then | 485 // If the download already completed by the time we reached this point, then |
609 // notify observers that it did. | 486 // notify observers that it did. |
610 DownloadFinished(info->download_id, | 487 DownloadFinished(info->download_id, |
611 pending_finished_downloads_[info->download_id]); | 488 pending_finished_downloads_[info->download_id]); |
612 } | 489 } |
613 | 490 |
614 download->Rename(target_path); | 491 download->Rename(target_path); |
615 | 492 |
616 // Do not store the download in the history database for a few special cases: | 493 download_history_->AddEntry(*info, download, |
617 // - incognito mode (that is the point of this mode) | 494 NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete)); |
618 // - extensions (users don't think of extension installation as 'downloading') | |
619 // - temporary download, like in drag-and-drop | |
620 // - history service is not available (e.g. in tests) | |
621 // We have to make sure that these handles don't collide with normal db | |
622 // handles, so we use a negative value. Eventually, they could overlap, but | |
623 // you'd have to do enough downloading that your ISP would likely stab you in | |
624 // the neck first. YMMV. | |
625 // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. | |
626 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); | |
627 if (download->is_otr() || download->is_extension_install() || | |
628 download->is_temporary() || !hs) { | |
629 OnCreateDownloadEntryComplete(*info, fake_db_handle_.GetNext()); | |
630 } else { | |
631 // Update the history system with the new download. | |
632 hs->CreateDownload( | |
633 *info, &cancelable_consumer_, | |
634 NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete)); | |
635 } | |
636 | 495 |
637 UpdateAppIcon(); | 496 UpdateAppIcon(); |
638 } | 497 } |
639 | 498 |
640 // Convenience function for updating the history service for a download. | |
641 void DownloadManager::UpdateHistoryForDownload(DownloadItem* download) { | |
642 DCHECK(download); | |
643 | |
644 // Don't store info in the database if the download was initiated while in | |
645 // incognito mode or if it hasn't been initialized in our database table. | |
646 if (download->db_handle() <= kUninitializedHandle) | |
647 return; | |
648 | |
649 // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. | |
650 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); | |
651 if (hs) { | |
652 hs->UpdateDownload(download->received_bytes(), | |
653 download->state(), | |
654 download->db_handle()); | |
655 } | |
656 } | |
657 | |
658 void DownloadManager::RemoveDownloadFromHistory(DownloadItem* download) { | |
659 DCHECK(download); | |
660 // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. | |
661 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); | |
662 if (download->db_handle() > kUninitializedHandle && hs) | |
663 hs->RemoveDownload(download->db_handle()); | |
664 } | |
665 | |
666 void DownloadManager::RemoveDownloadsFromHistoryBetween( | |
667 const base::Time remove_begin, | |
668 const base::Time remove_end) { | |
669 // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. | |
670 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); | |
671 if (hs) | |
672 hs->RemoveDownloadsBetween(remove_begin, remove_end); | |
673 } | |
674 | |
675 void DownloadManager::UpdateDownload(int32 download_id, int64 size) { | 499 void DownloadManager::UpdateDownload(int32 download_id, int64 size) { |
676 DownloadMap::iterator it = in_progress_.find(download_id); | 500 DownloadMap::iterator it = in_progress_.find(download_id); |
677 if (it != in_progress_.end()) { | 501 if (it != in_progress_.end()) { |
678 DownloadItem* download = it->second; | 502 DownloadItem* download = it->second; |
679 download->Update(size); | 503 download->Update(size); |
680 UpdateHistoryForDownload(download); | 504 download_history_->UpdateEntry(download); |
681 } | 505 } |
682 UpdateAppIcon(); | 506 UpdateAppIcon(); |
683 } | 507 } |
684 | 508 |
685 void DownloadManager::DownloadFinished(int32 download_id, int64 size) { | 509 void DownloadManager::DownloadFinished(int32 download_id, int64 size) { |
686 DownloadMap::iterator it = in_progress_.find(download_id); | 510 DownloadMap::iterator it = in_progress_.find(download_id); |
687 if (it == in_progress_.end()) { | 511 if (it == in_progress_.end()) { |
688 // The download is done, but the user hasn't selected a final location for | 512 // The download is done, but the user hasn't selected a final location for |
689 // it yet (the Save As dialog box is probably still showing), so just keep | 513 // it yet (the Save As dialog box is probably still showing), so just keep |
690 // track of the fact that this download id is complete, when the | 514 // track of the fact that this download id is complete, when the |
691 // DownloadItem is constructed later we'll notify its completion then. | 515 // DownloadItem is constructed later we'll notify its completion then. |
692 PendingFinishedMap::iterator erase_it = | 516 PendingFinishedMap::iterator erase_it = |
693 pending_finished_downloads_.find(download_id); | 517 pending_finished_downloads_.find(download_id); |
694 DCHECK(erase_it == pending_finished_downloads_.end()); | 518 DCHECK(erase_it == pending_finished_downloads_.end()); |
695 pending_finished_downloads_[download_id] = size; | 519 pending_finished_downloads_[download_id] = size; |
696 return; | 520 return; |
697 } | 521 } |
698 | 522 |
699 // Remove the id from the list of pending ids. | 523 // Remove the id from the list of pending ids. |
700 PendingFinishedMap::iterator erase_it = | 524 PendingFinishedMap::iterator erase_it = |
701 pending_finished_downloads_.find(download_id); | 525 pending_finished_downloads_.find(download_id); |
702 if (erase_it != pending_finished_downloads_.end()) | 526 if (erase_it != pending_finished_downloads_.end()) |
703 pending_finished_downloads_.erase(erase_it); | 527 pending_finished_downloads_.erase(erase_it); |
704 | 528 |
705 DownloadItem* download = it->second; | 529 DownloadItem* download = it->second; |
706 download->Finished(size); | 530 download->Finished(size); |
707 | 531 |
708 // Clean up will happen when the history system create callback runs if we | 532 // Clean up will happen when the history system create callback runs if we |
709 // don't have a valid db_handle yet. | 533 // don't have a valid db_handle yet. |
710 if (download->db_handle() != kUninitializedHandle) { | 534 if (download->db_handle() != DownloadHistory::kUninitializedHandle) { |
711 in_progress_.erase(it); | 535 in_progress_.erase(it); |
712 UpdateHistoryForDownload(download); | 536 download_history_->UpdateEntry(download); |
713 } | 537 } |
714 | 538 |
715 UpdateAppIcon(); | 539 UpdateAppIcon(); |
716 | 540 |
717 // If this a dangerous download not yet validated by the user, don't do | 541 // If this a dangerous download not yet validated by the user, don't do |
718 // anything. When the user notifies us, it will trigger a call to | 542 // anything. When the user notifies us, it will trigger a call to |
719 // ProceedWithFinishedDangerousDownload. | 543 // ProceedWithFinishedDangerousDownload. |
720 if (download->safety_state() == DownloadItem::DANGEROUS) { | 544 if (download->safety_state() == DownloadItem::DANGEROUS) { |
721 dangerous_finished_[download_id] = download; | 545 dangerous_finished_[download_id] = download; |
722 return; | 546 return; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
854 } | 678 } |
855 | 679 |
856 void DownloadManager::DownloadCancelled(int32 download_id) { | 680 void DownloadManager::DownloadCancelled(int32 download_id) { |
857 DownloadMap::iterator it = in_progress_.find(download_id); | 681 DownloadMap::iterator it = in_progress_.find(download_id); |
858 if (it == in_progress_.end()) | 682 if (it == in_progress_.end()) |
859 return; | 683 return; |
860 DownloadItem* download = it->second; | 684 DownloadItem* download = it->second; |
861 | 685 |
862 // Clean up will happen when the history system create callback runs if we | 686 // Clean up will happen when the history system create callback runs if we |
863 // don't have a valid db_handle yet. | 687 // don't have a valid db_handle yet. |
864 if (download->db_handle() != kUninitializedHandle) { | 688 if (download->db_handle() != DownloadHistory::kUninitializedHandle) { |
865 in_progress_.erase(it); | 689 in_progress_.erase(it); |
866 UpdateHistoryForDownload(download); | 690 download_history_->UpdateEntry(download); |
867 } | 691 } |
868 | 692 |
869 DownloadCancelledInternal(download_id, | 693 DownloadCancelledInternal(download_id, |
870 download->render_process_id(), | 694 download->render_process_id(), |
871 download->request_id()); | 695 download->request_id()); |
872 UpdateAppIcon(); | 696 UpdateAppIcon(); |
873 } | 697 } |
874 | 698 |
875 void DownloadManager::DownloadCancelledInternal(int download_id, | 699 void DownloadManager::DownloadCancelledInternal(int download_id, |
876 int render_process_id, | 700 int render_process_id, |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
949 progress = (float)received_bytes / total_bytes; | 773 progress = (float)received_bytes / total_bytes; |
950 | 774 |
951 download_util::UpdateAppIconDownloadProgress(download_count, | 775 download_util::UpdateAppIconDownloadProgress(download_count, |
952 progress_known, | 776 progress_known, |
953 progress); | 777 progress); |
954 } | 778 } |
955 | 779 |
956 void DownloadManager::RenameDownload(DownloadItem* download, | 780 void DownloadManager::RenameDownload(DownloadItem* download, |
957 const FilePath& new_path) { | 781 const FilePath& new_path) { |
958 download->Rename(new_path); | 782 download->Rename(new_path); |
959 | 783 download_history_->UpdateDownloadPath(download, new_path); |
960 // Update the history. | |
961 | |
962 // No update necessary if the download was initiated while in incognito mode. | |
963 if (download->db_handle() <= kUninitializedHandle) | |
964 return; | |
965 | |
966 // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. | |
967 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); | |
968 if (hs) | |
969 hs->UpdateDownloadPath(new_path, download->db_handle()); | |
970 } | 784 } |
971 | 785 |
972 void DownloadManager::RemoveDownload(int64 download_handle) { | 786 void DownloadManager::RemoveDownload(int64 download_handle) { |
973 DownloadMap::iterator it = downloads_.find(download_handle); | 787 DownloadMap::iterator it = downloads_.find(download_handle); |
974 if (it == downloads_.end()) | 788 if (it == downloads_.end()) |
975 return; | 789 return; |
976 | 790 |
977 // Make history update. | 791 // Make history update. |
978 DownloadItem* download = it->second; | 792 DownloadItem* download = it->second; |
979 RemoveDownloadFromHistory(download); | 793 download_history_->RemoveEntry(download); |
980 | 794 |
981 // Remove from our tables and delete. | 795 // Remove from our tables and delete. |
982 downloads_.erase(it); | 796 downloads_.erase(it); |
983 it = dangerous_finished_.find(download->id()); | 797 it = dangerous_finished_.find(download->id()); |
984 if (it != dangerous_finished_.end()) | 798 if (it != dangerous_finished_.end()) |
985 dangerous_finished_.erase(it); | 799 dangerous_finished_.erase(it); |
986 | 800 |
987 // Tell observers to refresh their views. | 801 // Tell observers to refresh their views. |
988 NotifyModelChanged(); | 802 NotifyModelChanged(); |
989 | 803 |
990 delete download; | 804 delete download; |
991 } | 805 } |
992 | 806 |
993 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin, | 807 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin, |
994 const base::Time remove_end) { | 808 const base::Time remove_end) { |
995 RemoveDownloadsFromHistoryBetween(remove_begin, remove_end); | 809 download_history_->RemoveEntriesBetween(remove_begin, remove_end); |
996 | 810 |
997 DownloadMap::iterator it = downloads_.begin(); | 811 DownloadMap::iterator it = downloads_.begin(); |
998 std::vector<DownloadItem*> pending_deletes; | 812 std::vector<DownloadItem*> pending_deletes; |
999 while (it != downloads_.end()) { | 813 while (it != downloads_.end()) { |
1000 DownloadItem* download = it->second; | 814 DownloadItem* download = it->second; |
1001 DownloadItem::DownloadState state = download->state(); | 815 DownloadItem::DownloadState state = download->state(); |
1002 if (download->start_time() >= remove_begin && | 816 if (download->start_time() >= remove_begin && |
1003 (remove_end.is_null() || download->start_time() < remove_end) && | 817 (remove_end.is_null() || download->start_time() < remove_end) && |
1004 (state == DownloadItem::COMPLETE || | 818 (state == DownloadItem::COMPLETE || |
1005 state == DownloadItem::CANCELLED)) { | 819 state == DownloadItem::CANCELLED)) { |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1405 #endif | 1219 #endif |
1406 extensions += this_extension + ":"; | 1220 extensions += this_extension + ":"; |
1407 } | 1221 } |
1408 if (!extensions.empty()) | 1222 if (!extensions.empty()) |
1409 extensions.erase(extensions.size() - 1); | 1223 extensions.erase(extensions.size() - 1); |
1410 | 1224 |
1411 prefs->SetString(prefs::kDownloadExtensionsToOpen, extensions); | 1225 prefs->SetString(prefs::kDownloadExtensionsToOpen, extensions); |
1412 } | 1226 } |
1413 } | 1227 } |
1414 | 1228 |
| 1229 DownloadItem* DownloadManager::GetDownloadItemFromDbHandle(int64 db_handle) { |
| 1230 for (DownloadMap::iterator it = downloads_.begin(); |
| 1231 it != downloads_.end(); ++it) { |
| 1232 DownloadItem* item = it->second; |
| 1233 if (item->db_handle() == db_handle) |
| 1234 return item; |
| 1235 } |
| 1236 return NULL; |
| 1237 } |
| 1238 |
1415 void DownloadManager::FileSelected(const FilePath& path, | 1239 void DownloadManager::FileSelected(const FilePath& path, |
1416 int index, void* params) { | 1240 int index, void* params) { |
1417 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); | 1241 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); |
1418 if (info->prompt_user_for_save_location) | 1242 if (info->prompt_user_for_save_location) |
1419 last_download_path_ = path.DirName(); | 1243 last_download_path_ = path.DirName(); |
1420 ContinueStartDownload(info, path); | 1244 ContinueStartDownload(info, path); |
1421 } | 1245 } |
1422 | 1246 |
1423 void DownloadManager::FileSelectionCanceled(void* params) { | 1247 void DownloadManager::FileSelectionCanceled(void* params) { |
1424 // The user didn't pick a place to save the file, so need to cancel the | 1248 // The user didn't pick a place to save the file, so need to cancel the |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1498 DownloadMap::iterator it = in_progress_.find(info.download_id); | 1322 DownloadMap::iterator it = in_progress_.find(info.download_id); |
1499 DCHECK(it != in_progress_.end()); | 1323 DCHECK(it != in_progress_.end()); |
1500 | 1324 |
1501 DownloadItem* download = it->second; | 1325 DownloadItem* download = it->second; |
1502 | 1326 |
1503 // It's not immediately obvious, but HistoryBackend::CreateDownload() can | 1327 // It's not immediately obvious, but HistoryBackend::CreateDownload() can |
1504 // call this function with an invalid |db_handle|. For instance, this can | 1328 // call this function with an invalid |db_handle|. For instance, this can |
1505 // happen when the history database is offline. We cannot have multiple | 1329 // happen when the history database is offline. We cannot have multiple |
1506 // DownloadItems with the same invalid db_handle, so we need to assign a | 1330 // DownloadItems with the same invalid db_handle, so we need to assign a |
1507 // unique |db_handle| here. | 1331 // unique |db_handle| here. |
1508 if (db_handle == kUninitializedHandle) | 1332 if (db_handle == DownloadHistory::kUninitializedHandle) |
1509 db_handle = fake_db_handle_.GetNext(); | 1333 db_handle = download_history_->GetNextFakeDbHandle(); |
1510 | 1334 |
1511 DCHECK(download->db_handle() == kUninitializedHandle); | 1335 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); |
1512 download->set_db_handle(db_handle); | 1336 download->set_db_handle(db_handle); |
1513 | 1337 |
1514 // Insert into our full map. | 1338 // Insert into our full map. |
1515 DCHECK(downloads_.find(download->db_handle()) == downloads_.end()); | 1339 DCHECK(downloads_.find(download->db_handle()) == downloads_.end()); |
1516 downloads_[download->db_handle()] = download; | 1340 downloads_[download->db_handle()] = download; |
1517 | 1341 |
1518 // Show in the appropropriate browser UI. | 1342 // Show in the appropropriate browser UI. |
1519 ShowDownloadInBrowser(info, download); | 1343 ShowDownloadInBrowser(info, download); |
1520 | 1344 |
1521 // Inform interested objects about the new download. | 1345 // Inform interested objects about the new download. |
1522 NotifyModelChanged(); | 1346 NotifyModelChanged(); |
1523 | 1347 |
1524 // If this download has been completed before we've received the db handle, | 1348 // If this download has been completed before we've received the db handle, |
1525 // post one final message to the history service so that it can be properly | 1349 // post one final message to the history service so that it can be properly |
1526 // in sync with the DownloadItem's completion status, and also inform any | 1350 // in sync with the DownloadItem's completion status, and also inform any |
1527 // observers so that they get more than just the start notification. | 1351 // observers so that they get more than just the start notification. |
1528 if (download->state() != DownloadItem::IN_PROGRESS) { | 1352 if (download->state() != DownloadItem::IN_PROGRESS) { |
1529 in_progress_.erase(it); | 1353 in_progress_.erase(it); |
1530 UpdateHistoryForDownload(download); | 1354 download_history_->UpdateEntry(download); |
1531 download->UpdateObservers(); | 1355 download->UpdateObservers(); |
1532 } | 1356 } |
1533 | 1357 |
1534 UpdateAppIcon(); | 1358 UpdateAppIcon(); |
1535 } | 1359 } |
1536 | 1360 |
1537 // Called when the history service has retrieved the list of downloads that | |
1538 // match the search text. | |
1539 void DownloadManager::OnSearchComplete(HistoryService::Handle handle, | |
1540 std::vector<int64>* results) { | |
1541 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); | |
1542 Observer* requestor = cancelable_consumer_.GetClientData(hs, handle); | |
1543 if (!requestor) | |
1544 return; | |
1545 | |
1546 std::vector<DownloadItem*> searched_downloads; | |
1547 for (std::vector<int64>::iterator it = results->begin(); | |
1548 it != results->end(); ++it) { | |
1549 DownloadMap::iterator dit = downloads_.find(*it); | |
1550 if (dit != downloads_.end()) | |
1551 searched_downloads.push_back(dit->second); | |
1552 } | |
1553 | |
1554 requestor->SetDownloads(searched_downloads); | |
1555 } | |
1556 | |
1557 void DownloadManager::ShowDownloadInBrowser(const DownloadCreateInfo& info, | 1361 void DownloadManager::ShowDownloadInBrowser(const DownloadCreateInfo& info, |
1558 DownloadItem* download) { | 1362 DownloadItem* download) { |
1559 // The 'contents' may no longer exist if the user closed the tab before we | 1363 // The 'contents' may no longer exist if the user closed the tab before we |
1560 // get this start completion event. If it does, tell the origin TabContents | 1364 // get this start completion event. If it does, tell the origin TabContents |
1561 // to display its download shelf. | 1365 // to display its download shelf. |
1562 TabContents* contents = tab_util::GetTabContentsByID(info.child_id, | 1366 TabContents* contents = tab_util::GetTabContentsByID(info.child_id, |
1563 info.render_view_id); | 1367 info.render_view_id); |
1564 | 1368 |
1565 // If the contents no longer exists, we start the download in the last active | 1369 // If the contents no longer exists, we start the download in the last active |
1566 // browser. This is not ideal but better than fully hiding the download from | 1370 // browser. This is not ideal but better than fully hiding the download from |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1612 | 1416 |
1613 DownloadManager::OtherDownloadManagerObserver::~OtherDownloadManagerObserver() { | 1417 DownloadManager::OtherDownloadManagerObserver::~OtherDownloadManagerObserver() { |
1614 if (observed_download_manager_) | 1418 if (observed_download_manager_) |
1615 observed_download_manager_->RemoveObserver(this); | 1419 observed_download_manager_->RemoveObserver(this); |
1616 } | 1420 } |
1617 | 1421 |
1618 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { | 1422 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { |
1619 observing_download_manager_->NotifyModelChanged(); | 1423 observing_download_manager_->NotifyModelChanged(); |
1620 } | 1424 } |
1621 | 1425 |
1622 void DownloadManager::OtherDownloadManagerObserver::SetDownloads( | |
1623 std::vector<DownloadItem*>& downloads) { | |
1624 } | |
1625 | |
1626 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { | 1426 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { |
1627 observed_download_manager_ = NULL; | 1427 observed_download_manager_ = NULL; |
1628 } | 1428 } |
OLD | NEW |