| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/extensions/file_manager/event_router.h" | 5 #include "chrome/browser/chromeos/extensions/file_manager/event_router.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/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
| 10 #include "base/prefs/pref_change_registrar.h" | 10 #include "base/prefs/pref_change_registrar.h" |
| 11 #include "base/prefs/pref_service.h" | 11 #include "base/prefs/pref_service.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 13 #include "base/thread_task_runner_handle.h" |
| 13 #include "base/threading/sequenced_worker_pool.h" | 14 #include "base/threading/sequenced_worker_pool.h" |
| 14 #include "base/values.h" | 15 #include "base/values.h" |
| 15 #include "chrome/browser/app_mode/app_mode_utils.h" | 16 #include "chrome/browser/app_mode/app_mode_utils.h" |
| 16 #include "chrome/browser/chrome_notification_types.h" | 17 #include "chrome/browser/chrome_notification_types.h" |
| 17 #include "chrome/browser/chromeos/drive/drive_integration_service.h" | 18 #include "chrome/browser/chromeos/drive/drive_integration_service.h" |
| 18 #include "chrome/browser/chromeos/drive/file_change.h" | 19 #include "chrome/browser/chromeos/drive/file_change.h" |
| 19 #include "chrome/browser/chromeos/drive/file_system_interface.h" | 20 #include "chrome/browser/chromeos/drive/file_system_interface.h" |
| 20 #include "chrome/browser/chromeos/drive/file_system_util.h" | 21 #include "chrome/browser/chromeos/drive/file_system_util.h" |
| 21 #include "chrome/browser/chromeos/extensions/file_manager/device_event_router.h" | 22 #include "chrome/browser/chromeos/extensions/file_manager/device_event_router.h" |
| 22 #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h" | 23 #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h" |
| (...skipping 30 matching lines...) Expand all Loading... |
| 53 using drive::DriveIntegrationService; | 54 using drive::DriveIntegrationService; |
| 54 using drive::DriveIntegrationServiceFactory; | 55 using drive::DriveIntegrationServiceFactory; |
| 55 using file_manager::util::EntryDefinition; | 56 using file_manager::util::EntryDefinition; |
| 56 using file_manager::util::FileDefinition; | 57 using file_manager::util::FileDefinition; |
| 57 | 58 |
| 58 namespace file_browser_private = extensions::api::file_browser_private; | 59 namespace file_browser_private = extensions::api::file_browser_private; |
| 59 | 60 |
| 60 namespace file_manager { | 61 namespace file_manager { |
| 61 namespace { | 62 namespace { |
| 62 // Constants for the "transferState" field of onFileTransferUpdated event. | 63 // Constants for the "transferState" field of onFileTransferUpdated event. |
| 64 const char kFileTransferStateAdded[] = "added"; |
| 63 const char kFileTransferStateStarted[] = "started"; | 65 const char kFileTransferStateStarted[] = "started"; |
| 64 const char kFileTransferStateInProgress[] = "in_progress"; | 66 const char kFileTransferStateInProgress[] = "in_progress"; |
| 65 const char kFileTransferStateCompleted[] = "completed"; | 67 const char kFileTransferStateCompleted[] = "completed"; |
| 66 const char kFileTransferStateFailed[] = "failed"; | 68 const char kFileTransferStateFailed[] = "failed"; |
| 67 | 69 |
| 68 // Frequency of sending onFileTransferUpdated. | 70 // Frequency of sending onFileTransferUpdated. |
| 69 const int64 kProgressEventFrequencyInMilliseconds = 1000; | 71 const int64 kProgressEventFrequencyInMilliseconds = 1000; |
| 70 | 72 |
| 71 // Maximim size of detailed change info on directory change event. If the size | 73 // Maximim size of detailed change info on directory change event. If the size |
| 72 // exceeds the maximum size, the detailed info is omitted and the force refresh | 74 // exceeds the maximum size, the detailed info is omitted and the force refresh |
| 73 // is kicked. | 75 // is kicked. |
| 74 const size_t kDirectoryChangeEventMaxDetailInfoSize = 1000; | 76 const size_t kDirectoryChangeEventMaxDetailInfoSize = 1000; |
| 75 | 77 |
| 78 // This time(millisecond) is used for confirm following event exists. |
| 79 const int64 kFileTransferEventDelayTimeInMilliseconds = 300; |
| 80 |
| 76 // Utility function to check if |job_info| is a file uploading job. | 81 // Utility function to check if |job_info| is a file uploading job. |
| 77 bool IsUploadJob(drive::JobType type) { | 82 bool IsUploadJob(drive::JobType type) { |
| 78 return (type == drive::TYPE_UPLOAD_NEW_FILE || | 83 return (type == drive::TYPE_UPLOAD_NEW_FILE || |
| 79 type == drive::TYPE_UPLOAD_EXISTING_FILE); | 84 type == drive::TYPE_UPLOAD_EXISTING_FILE); |
| 80 } | 85 } |
| 81 | 86 |
| 87 size_t CountActiveFileTransferJobInfo( |
| 88 const std::vector<drive::JobInfo>& job_info_list) { |
| 89 size_t num_active_file_transfer_job_info = 0; |
| 90 for (size_t i = 0; i < job_info_list.size(); ++i) { |
| 91 if (IsActiveFileTransferJobInfo(job_info_list[i])) |
| 92 ++num_active_file_transfer_job_info; |
| 93 } |
| 94 return num_active_file_transfer_job_info; |
| 95 } |
| 96 |
| 82 // Converts the job info to a IDL generated type. | 97 // Converts the job info to a IDL generated type. |
| 83 void JobInfoToTransferStatus( | 98 void JobInfoToTransferStatus( |
| 84 Profile* profile, | 99 Profile* profile, |
| 85 const std::string& extension_id, | 100 const std::string& extension_id, |
| 86 const std::string& job_status, | 101 const std::string& job_status, |
| 87 const drive::JobInfo& job_info, | 102 const drive::JobInfo& job_info, |
| 88 file_browser_private::FileTransferStatus* status) { | 103 file_browser_private::FileTransferStatus* status) { |
| 89 DCHECK(IsActiveFileTransferJobInfo(job_info)); | 104 DCHECK(IsActiveFileTransferJobInfo(job_info)); |
| 90 | 105 |
| 91 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue); | 106 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue); |
| 92 GURL url = util::ConvertDrivePathToFileSystemUrl( | 107 GURL url = util::ConvertDrivePathToFileSystemUrl( |
| 93 profile, job_info.file_path, extension_id); | 108 profile, job_info.file_path, extension_id); |
| 94 status->file_url = url.spec(); | 109 status->file_url = url.spec(); |
| 95 status->transfer_state = file_browser_private::ParseTransferState(job_status); | 110 status->transfer_state = file_browser_private::ParseTransferState(job_status); |
| 96 status->transfer_type = | 111 status->transfer_type = |
| 97 IsUploadJob(job_info.job_type) ? | 112 IsUploadJob(job_info.job_type) ? |
| 98 file_browser_private::TRANSFER_TYPE_UPLOAD : | 113 file_browser_private::TRANSFER_TYPE_UPLOAD : |
| 99 file_browser_private::TRANSFER_TYPE_DOWNLOAD; | 114 file_browser_private::TRANSFER_TYPE_DOWNLOAD; |
| 115 DriveIntegrationService* const integration_service = |
| 116 DriveIntegrationServiceFactory::FindForProfile(profile); |
| 117 status->num_total_jobs = CountActiveFileTransferJobInfo( |
| 118 integration_service->job_list()->GetJobInfoList()); |
| 100 // JavaScript does not have 64-bit integers. Instead we use double, which | 119 // JavaScript does not have 64-bit integers. Instead we use double, which |
| 101 // is in IEEE 754 formant and accurate up to 52-bits in JS, and in practice | 120 // is in IEEE 754 formant and accurate up to 52-bits in JS, and in practice |
| 102 // in C++. Larger values are rounded. | 121 // in C++. Larger values are rounded. |
| 103 status->processed.reset( | 122 status->processed.reset( |
| 104 new double(static_cast<double>(job_info.num_completed_bytes))); | 123 new double(static_cast<double>(job_info.num_completed_bytes))); |
| 105 status->total.reset( | 124 status->total.reset( |
| 106 new double(static_cast<double>(job_info.num_total_bytes))); | 125 new double(static_cast<double>(job_info.num_total_bytes))); |
| 107 } | 126 } |
| 108 | 127 |
| 109 // Checks if the Recovery Tool is running. This is a temporary solution. | 128 // Checks if the Recovery Tool is running. This is a temporary solution. |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 } | 602 } |
| 584 | 603 |
| 585 BroadcastEvent( | 604 BroadcastEvent( |
| 586 profile_, | 605 profile_, |
| 587 file_browser_private::OnPreferencesChanged::kEventName, | 606 file_browser_private::OnPreferencesChanged::kEventName, |
| 588 file_browser_private::OnPreferencesChanged::Create()); | 607 file_browser_private::OnPreferencesChanged::Create()); |
| 589 } | 608 } |
| 590 | 609 |
| 591 void EventRouter::OnJobAdded(const drive::JobInfo& job_info) { | 610 void EventRouter::OnJobAdded(const drive::JobInfo& job_info) { |
| 592 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 611 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 593 OnJobUpdated(job_info); | 612 if (!drive::IsActiveFileTransferJobInfo(job_info)) |
| 613 return; |
| 614 ScheduleDriveFileTransferEvent( |
| 615 job_info, kFileTransferStateAdded, false /* immediate */); |
| 594 } | 616 } |
| 595 | 617 |
| 596 void EventRouter::OnJobUpdated(const drive::JobInfo& job_info) { | 618 void EventRouter::OnJobUpdated(const drive::JobInfo& job_info) { |
| 597 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 619 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 598 if (!drive::IsActiveFileTransferJobInfo(job_info)) | 620 if (!drive::IsActiveFileTransferJobInfo(job_info)) |
| 599 return; | 621 return; |
| 600 | 622 |
| 601 bool is_new_job = (drive_jobs_.find(job_info.job_id) == drive_jobs_.end()); | 623 bool is_new_job = (drive_jobs_.find(job_info.job_id) == drive_jobs_.end()); |
| 602 | 624 |
| 625 const std::string status = |
| 626 is_new_job ? kFileTransferStateStarted : kFileTransferStateInProgress; |
| 627 |
| 603 // Replace with the latest job info. | 628 // Replace with the latest job info. |
| 604 drive_jobs_[job_info.job_id] = DriveJobInfoWithStatus( | 629 drive_jobs_[job_info.job_id] = DriveJobInfoWithStatus(job_info, status); |
| 605 job_info, | |
| 606 is_new_job ? kFileTransferStateStarted : kFileTransferStateInProgress); | |
| 607 | 630 |
| 608 // Fire event if needed. | 631 ScheduleDriveFileTransferEvent(job_info, status, false /* immediate */); |
| 609 bool always = is_new_job; | |
| 610 SendDriveFileTransferEvent(always); | |
| 611 } | 632 } |
| 612 | 633 |
| 613 void EventRouter::OnJobDone(const drive::JobInfo& job_info, | 634 void EventRouter::OnJobDone(const drive::JobInfo& job_info, |
| 614 drive::FileError error) { | 635 drive::FileError error) { |
| 615 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 636 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 616 if (!drive::IsActiveFileTransferJobInfo(job_info)) | 637 if (!drive::IsActiveFileTransferJobInfo(job_info)) |
| 617 return; | 638 return; |
| 618 | 639 |
| 619 // Replace with the latest job info. | 640 const std::string status = error == drive::FILE_ERROR_OK |
| 620 drive_jobs_[job_info.job_id] = DriveJobInfoWithStatus( | 641 ? kFileTransferStateCompleted |
| 621 job_info, | 642 : kFileTransferStateFailed; |
| 622 error == drive::FILE_ERROR_OK ? kFileTransferStateCompleted | |
| 623 : kFileTransferStateFailed); | |
| 624 | 643 |
| 625 // Fire event if needed. | 644 ScheduleDriveFileTransferEvent(job_info, status, true /* immediate */); |
| 626 bool always = true; | |
| 627 SendDriveFileTransferEvent(always); | |
| 628 | 645 |
| 629 // Forget about the job. | 646 // Forget about the job. |
| 630 drive_jobs_.erase(job_info.job_id); | 647 drive_jobs_.erase(job_info.job_id); |
| 631 } | 648 } |
| 632 | 649 |
| 633 void EventRouter::SendDriveFileTransferEvent(bool always) { | 650 void EventRouter::ScheduleDriveFileTransferEvent(const drive::JobInfo& job_info, |
| 634 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 651 const std::string& status, |
| 652 bool immediate) { |
| 653 const bool no_pending_task = !drive_job_info_for_scheduled_event_; |
| 654 // Update the latest event. |
| 655 drive_job_info_for_scheduled_event_.reset( |
| 656 new DriveJobInfoWithStatus(job_info, status)); |
| 657 if (immediate) { |
| 658 SendDriveFileTransferEvent(); |
| 659 } else if (no_pending_task) { |
| 660 const base::TimeDelta delay = base::TimeDelta::FromMilliseconds( |
| 661 kFileTransferEventDelayTimeInMilliseconds); |
| 662 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 663 FROM_HERE, |
| 664 base::Bind(&EventRouter::SendDriveFileTransferEvent, |
| 665 weak_factory_.GetWeakPtr()), |
| 666 delay); |
| 667 } |
| 668 } |
| 635 | 669 |
| 636 // When |always| flag is not set, we don't send the event until certain | 670 void EventRouter::SendDriveFileTransferEvent() { |
| 637 // amount of time passes after the previous one. This is to avoid | 671 if (!drive_job_info_for_scheduled_event_) |
| 638 // flooding the IPC between extensions by many onFileTransferUpdated events. | |
| 639 if (!ShouldSendProgressEvent(always, &last_file_transfer_event_)) | |
| 640 return; | 672 return; |
| 641 | 673 |
| 642 // Convert the current |drive_jobs_| to IDL type. | 674 // Convert the drive_job_info_for_scheduled_event_ to IDL type. |
| 643 std::vector<linked_ptr<file_browser_private::FileTransferStatus> > | 675 std::vector<linked_ptr<file_browser_private::FileTransferStatus> > |
| 644 status_list; | 676 status_list; |
| 645 for (std::map<drive::JobID, DriveJobInfoWithStatus>::iterator | 677 |
| 646 iter = drive_jobs_.begin(); iter != drive_jobs_.end(); ++iter) { | 678 linked_ptr<file_browser_private::FileTransferStatus> status( |
| 647 linked_ptr<file_browser_private::FileTransferStatus> status( | 679 new file_browser_private::FileTransferStatus()); |
| 648 new file_browser_private::FileTransferStatus()); | 680 JobInfoToTransferStatus(profile_, |
| 649 JobInfoToTransferStatus(profile_, | 681 kFileManagerAppId, |
| 650 kFileManagerAppId, | 682 drive_job_info_for_scheduled_event_->status, |
| 651 iter->second.status, | 683 drive_job_info_for_scheduled_event_->job_info, |
| 652 iter->second.job_info, | 684 status.get()); |
| 653 status.get()); | 685 status_list.push_back(status); |
| 654 status_list.push_back(status); | 686 |
| 655 } | 687 drive_job_info_for_scheduled_event_.reset(); |
| 688 |
| 656 BroadcastEvent( | 689 BroadcastEvent( |
| 657 profile_, | 690 profile_, |
| 658 file_browser_private::OnFileTransfersUpdated::kEventName, | 691 file_browser_private::OnFileTransfersUpdated::kEventName, |
| 659 file_browser_private::OnFileTransfersUpdated::Create(status_list)); | 692 file_browser_private::OnFileTransfersUpdated::Create(status_list)); |
| 660 } | 693 } |
| 661 | 694 |
| 662 void EventRouter::OnDirectoryChanged(const base::FilePath& drive_path) { | 695 void EventRouter::OnDirectoryChanged(const base::FilePath& drive_path) { |
| 663 HandleFileWatchNotification(NULL, drive_path, false); | 696 HandleFileWatchNotification(NULL, drive_path, false); |
| 664 } | 697 } |
| 665 | 698 |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 904 // Do nothing. | 937 // Do nothing. |
| 905 } | 938 } |
| 906 | 939 |
| 907 void EventRouter::OnFormatCompleted(const std::string& device_path, | 940 void EventRouter::OnFormatCompleted(const std::string& device_path, |
| 908 bool success) { | 941 bool success) { |
| 909 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 942 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 910 // Do nothing. | 943 // Do nothing. |
| 911 } | 944 } |
| 912 | 945 |
| 913 } // namespace file_manager | 946 } // namespace file_manager |
| OLD | NEW |