| 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 |