Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/chromeos/drive/download_handler.h" | 5 #include "chrome/browser/chromeos/drive/download_handler.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 10 #include "base/supports_user_data.h" | 10 #include "base/supports_user_data.h" |
| 11 #include "base/thread_task_runner_handle.h" | |
| 11 #include "base/threading/sequenced_worker_pool.h" | 12 #include "base/threading/sequenced_worker_pool.h" |
| 12 #include "chrome/browser/chromeos/drive/drive_integration_service.h" | 13 #include "chrome/browser/chromeos/drive/drive_integration_service.h" |
| 13 #include "chrome/browser/chromeos/drive/file_system_util.h" | 14 #include "chrome/browser/chromeos/drive/file_system_util.h" |
| 14 #include "chrome/browser/chromeos/drive/write_on_cache_file.h" | 15 #include "chrome/browser/chromeos/drive/write_on_cache_file.h" |
| 15 #include "chrome/browser/download/download_history.h" | 16 #include "chrome/browser/download/download_history.h" |
| 16 #include "chrome/browser/download/download_service.h" | 17 #include "chrome/browser/download/download_service.h" |
| 17 #include "chrome/browser/download/download_service_factory.h" | 18 #include "chrome/browser/download/download_service_factory.h" |
| 18 #include "components/drive/drive.pb.h" | 19 #include "components/drive/drive.pb.h" |
| 19 #include "components/drive/file_system_interface.h" | 20 #include "components/drive/file_system_interface.h" |
| 20 #include "content/public/browser/browser_thread.h" | 21 #include "content/public/browser/browser_thread.h" |
| 21 | 22 |
| 22 using content::BrowserThread; | 23 using content::BrowserThread; |
| 23 using content::DownloadManager; | 24 using content::DownloadManager; |
| 24 using content::DownloadItem; | 25 using content::DownloadItem; |
| 25 | 26 |
| 26 namespace drive { | 27 namespace drive { |
| 27 namespace { | 28 namespace { |
| 28 | 29 |
| 29 // Key for base::SupportsUserData::Data. | 30 // Key for base::SupportsUserData::Data. |
| 30 const char kDrivePathKey[] = "DrivePath"; | 31 const char kDrivePathKey[] = "DrivePath"; |
| 31 | 32 |
| 32 // Mime types that we better not trust. If the file was downloade with these | 33 // Mime types that we better not trust. If the file was downloade with these |
| 33 // mime types, while uploading to Drive we ignore it at guess by our own logic. | 34 // mime types, while uploading to Drive we ignore it at guess by our own logic. |
| 34 const char* kGenericMimeTypes[] = {"text/html", "text/plain", | 35 const char* kGenericMimeTypes[] = {"text/html", "text/plain", |
| 35 "application/octet-stream"}; | 36 "application/octet-stream"}; |
| 36 | 37 |
| 38 // Longer is better. But at the same time, this value should be short enough as | |
| 39 // drive::internal::kMinFreeSpaceInBytes is not used up by file download in this | |
| 40 // interval. | |
| 41 const base::TimeDelta kFreeDiskSpaceDelay = base::TimeDelta::FromSeconds(3); | |
| 42 | |
| 37 // User Data stored in DownloadItem for drive path. | 43 // User Data stored in DownloadItem for drive path. |
| 38 class DriveUserData : public base::SupportsUserData::Data { | 44 class DriveUserData : public base::SupportsUserData::Data { |
| 39 public: | 45 public: |
| 40 explicit DriveUserData(const base::FilePath& path) : file_path_(path), | 46 explicit DriveUserData(const base::FilePath& path) : file_path_(path), |
| 41 is_complete_(false) {} | 47 is_complete_(false) {} |
| 42 ~DriveUserData() override {} | 48 ~DriveUserData() override {} |
| 43 | 49 |
| 44 const base::FilePath& file_path() const { return file_path_; } | 50 const base::FilePath& file_path() const { return file_path_; } |
| 45 const base::FilePath& cache_file_path() const { return cache_file_path_; } | 51 const base::FilePath& cache_file_path() const { return cache_file_path_; } |
| 46 void set_cache_file_path(const base::FilePath& path) { | 52 void set_cache_file_path(const base::FilePath& path) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 118 // 'default' fallback choice on the HTTP server. In such a case, we ignore the | 124 // 'default' fallback choice on the HTTP server. In such a case, we ignore the |
| 119 // type so that our logic can guess by its own while uploading to Drive. | 125 // type so that our logic can guess by its own while uploading to Drive. |
| 120 std::string FilterOutGenericMimeType(const std::string& mime_type) { | 126 std::string FilterOutGenericMimeType(const std::string& mime_type) { |
| 121 for (size_t i = 0; i < arraysize(kGenericMimeTypes); ++i) { | 127 for (size_t i = 0; i < arraysize(kGenericMimeTypes); ++i) { |
| 122 if (base::LowerCaseEqualsASCII(mime_type, kGenericMimeTypes[i])) | 128 if (base::LowerCaseEqualsASCII(mime_type, kGenericMimeTypes[i])) |
| 123 return std::string(); | 129 return std::string(); |
| 124 } | 130 } |
| 125 return mime_type; | 131 return mime_type; |
| 126 } | 132 } |
| 127 | 133 |
| 134 void IgnoreFreeDiskSpaceIfNeededForCallback(bool /*result*/) {} | |
| 135 | |
| 128 } // namespace | 136 } // namespace |
| 129 | 137 |
| 130 DownloadHandler::DownloadHandler(FileSystemInterface* file_system) | 138 DownloadHandler::DownloadHandler(FileSystemInterface* file_system) |
| 131 : file_system_(file_system), | 139 : file_system_(file_system), |
| 132 weak_ptr_factory_(this) { | 140 has_pending_free_disk_space_(false), |
| 133 } | 141 free_disk_space_delay_(kFreeDiskSpaceDelay), |
| 142 weak_ptr_factory_(this) {} | |
| 134 | 143 |
| 135 DownloadHandler::~DownloadHandler() { | 144 DownloadHandler::~DownloadHandler() { |
| 136 } | 145 } |
| 137 | 146 |
| 138 // static | 147 // static |
| 139 DownloadHandler* DownloadHandler::GetForProfile(Profile* profile) { | 148 DownloadHandler* DownloadHandler::GetForProfile(Profile* profile) { |
| 140 DriveIntegrationService* service = | 149 DriveIntegrationService* service = |
| 141 DriveIntegrationServiceFactory::FindForProfile(profile); | 150 DriveIntegrationServiceFactory::FindForProfile(profile); |
| 142 if (!service || !service->IsMounted()) | 151 if (!service || !service->IsMounted()) |
| 143 return NULL; | 152 return NULL; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 | 239 |
| 231 void DownloadHandler::CheckForFileExistence( | 240 void DownloadHandler::CheckForFileExistence( |
| 232 const DownloadItem* download, | 241 const DownloadItem* download, |
| 233 const content::CheckForFileExistenceCallback& callback) { | 242 const content::CheckForFileExistenceCallback& callback) { |
| 234 file_system_->GetResourceEntry( | 243 file_system_->GetResourceEntry( |
| 235 util::ExtractDrivePath(GetTargetPath(download)), | 244 util::ExtractDrivePath(GetTargetPath(download)), |
| 236 base::Bind(&ContinueCheckingForFileExistence, | 245 base::Bind(&ContinueCheckingForFileExistence, |
| 237 callback)); | 246 callback)); |
| 238 } | 247 } |
| 239 | 248 |
| 249 void DownloadHandler::SetFreeDiskSpaceDelayForTesting( | |
| 250 const base::TimeDelta& delay) { | |
| 251 free_disk_space_delay_ = delay; | |
| 252 } | |
| 253 | |
| 254 int64 DownloadHandler::CalculateRequestSpace( | |
| 255 const DownloadManager::DownloadVector& downloads) { | |
| 256 int64 request_space = 0; | |
| 257 | |
| 258 for (const auto* download : downloads) { | |
| 259 if (download->IsDone()) | |
| 260 continue; | |
| 261 | |
| 262 const int64 total_bytes = download->GetTotalBytes(); | |
| 263 // Skip unknown size download. Since drive cache tries to keep | |
| 264 // drive::internal::kMinFreeSpaceInBytes, we can continue download with | |
| 265 // using the space temporally. | |
| 266 if (total_bytes == 0) | |
| 267 continue; | |
| 268 | |
| 269 request_space += total_bytes - download->GetReceivedBytes(); | |
| 270 } | |
| 271 | |
| 272 return request_space; | |
| 273 } | |
| 274 | |
| 275 void DownloadHandler::FreeDiskSpaceIfNeeded() { | |
| 276 if (has_pending_free_disk_space_) | |
| 277 return; | |
| 278 | |
| 279 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 280 FROM_HERE, base::Bind(&DownloadHandler::FreeDiskSpaceIfNeededImmediately, | |
| 281 weak_ptr_factory_.GetWeakPtr()), | |
| 282 free_disk_space_delay_); | |
| 283 | |
| 284 has_pending_free_disk_space_ = true; | |
| 285 } | |
| 286 | |
| 287 void DownloadHandler::FreeDiskSpaceIfNeededImmediately() { | |
| 288 DownloadManager::DownloadVector downloads; | |
| 289 | |
| 290 // Get all downloads of current profile and its off-the-record profile. | |
| 291 // TODO(yawano): support multi profiles. | |
| 292 if (notifier_ != nullptr && notifier_->GetManager() != nullptr) { | |
|
hashimoto
2015/11/02 20:57:59
nit: You can write "if (notifier_ && notifier_->Ge
yawano
2015/11/05 03:51:25
Done.
| |
| 293 notifier_->GetManager()->GetAllDownloads(&downloads); | |
| 294 } | |
| 295 if (notifier_incognito_ != nullptr && | |
| 296 notifier_incognito_->GetManager() != nullptr) { | |
| 297 notifier_incognito_->GetManager()->GetAllDownloads(&downloads); | |
| 298 } | |
| 299 | |
| 300 // Free disk space even if request size is 0 byte in order to make drive cache | |
| 301 // keep drive::internal::kMinFreeSpaceInBytes. | |
| 302 file_system_->FreeDiskSpaceIfNeededFor( | |
| 303 CalculateRequestSpace(downloads), | |
| 304 base::Bind(&IgnoreFreeDiskSpaceIfNeededForCallback)); | |
| 305 | |
| 306 has_pending_free_disk_space_ = false; | |
| 307 } | |
| 308 | |
| 240 void DownloadHandler::OnDownloadCreated(DownloadManager* manager, | 309 void DownloadHandler::OnDownloadCreated(DownloadManager* manager, |
| 241 DownloadItem* download) { | 310 DownloadItem* download) { |
| 311 FreeDiskSpaceIfNeededImmediately(); | |
| 312 | |
| 242 // Remove any persisted Drive DownloadItem. crbug.com/171384 | 313 // Remove any persisted Drive DownloadItem. crbug.com/171384 |
| 243 if (IsPersistedDriveDownload(drive_tmp_download_path_, download)) { | 314 if (IsPersistedDriveDownload(drive_tmp_download_path_, download)) { |
| 244 // Remove download later, since doing it here results in a crash. | 315 // Remove download later, since doing it here results in a crash. |
| 245 BrowserThread::PostTask(BrowserThread::UI, | 316 BrowserThread::PostTask(BrowserThread::UI, |
| 246 FROM_HERE, | 317 FROM_HERE, |
| 247 base::Bind(&DownloadHandler::RemoveDownload, | 318 base::Bind(&DownloadHandler::RemoveDownload, |
| 248 weak_ptr_factory_.GetWeakPtr(), | 319 weak_ptr_factory_.GetWeakPtr(), |
| 249 static_cast<void*>(manager), | 320 static_cast<void*>(manager), |
| 250 download->GetId())); | 321 download->GetId())); |
| 251 } | 322 } |
| 252 } | 323 } |
| 253 | 324 |
| 254 void DownloadHandler::RemoveDownload(void* manager_id, int id) { | 325 void DownloadHandler::RemoveDownload(void* manager_id, int id) { |
| 255 DownloadManager* manager = GetDownloadManager(manager_id); | 326 DownloadManager* manager = GetDownloadManager(manager_id); |
| 256 if (!manager) | 327 if (!manager) |
| 257 return; | 328 return; |
| 258 DownloadItem* download = manager->GetDownload(id); | 329 DownloadItem* download = manager->GetDownload(id); |
| 259 if (!download) | 330 if (!download) |
| 260 return; | 331 return; |
| 261 download->Remove(); | 332 download->Remove(); |
| 262 } | 333 } |
| 263 | 334 |
| 264 void DownloadHandler::OnDownloadUpdated( | 335 void DownloadHandler::OnDownloadUpdated( |
| 265 DownloadManager* manager, DownloadItem* download) { | 336 DownloadManager* manager, DownloadItem* download) { |
| 266 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 337 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 267 | 338 |
| 339 FreeDiskSpaceIfNeeded(); | |
| 340 | |
| 268 // Only accept downloads that have the Drive meta data associated with them. | 341 // Only accept downloads that have the Drive meta data associated with them. |
| 269 DriveUserData* data = GetDriveUserData(download); | 342 DriveUserData* data = GetDriveUserData(download); |
| 270 if (!drive_tmp_download_path_.IsParent(download->GetTargetFilePath()) || | 343 if (!drive_tmp_download_path_.IsParent(download->GetTargetFilePath()) || |
| 271 !data || | 344 !data || |
| 272 data->is_complete()) | 345 data->is_complete()) |
| 273 return; | 346 return; |
| 274 | 347 |
| 275 switch (download->GetState()) { | 348 switch (download->GetState()) { |
| 276 case DownloadItem::IN_PROGRESS: | 349 case DownloadItem::IN_PROGRESS: |
| 277 break; | 350 break; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 347 | 420 |
| 348 DownloadManager* DownloadHandler::GetDownloadManager(void* manager_id) { | 421 DownloadManager* DownloadHandler::GetDownloadManager(void* manager_id) { |
| 349 if (manager_id == notifier_->GetManager()) | 422 if (manager_id == notifier_->GetManager()) |
| 350 return notifier_->GetManager(); | 423 return notifier_->GetManager(); |
| 351 if (notifier_incognito_ && manager_id == notifier_incognito_->GetManager()) | 424 if (notifier_incognito_ && manager_id == notifier_incognito_->GetManager()) |
| 352 return notifier_incognito_->GetManager(); | 425 return notifier_incognito_->GetManager(); |
| 353 return NULL; | 426 return NULL; |
| 354 } | 427 } |
| 355 | 428 |
| 356 } // namespace drive | 429 } // namespace drive |
| OLD | NEW |