Chromium Code Reviews| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 54 using drive::DriveIntegrationService; | 55 using drive::DriveIntegrationService; |
| 55 using drive::DriveIntegrationServiceFactory; | 56 using drive::DriveIntegrationServiceFactory; |
| 56 using file_manager::util::EntryDefinition; | 57 using file_manager::util::EntryDefinition; |
| 57 using file_manager::util::FileDefinition; | 58 using file_manager::util::FileDefinition; |
| 58 | 59 |
| 59 namespace file_browser_private = extensions::api::file_browser_private; | 60 namespace file_browser_private = extensions::api::file_browser_private; |
| 60 | 61 |
| 61 namespace file_manager { | 62 namespace file_manager { |
| 62 namespace { | 63 namespace { |
| 63 // Constants for the "transferState" field of onFileTransferUpdated event. | 64 // Constants for the "transferState" field of onFileTransferUpdated event. |
| 65 const char kFileTransferStateAdded[] = "added"; | |
| 64 const char kFileTransferStateStarted[] = "started"; | 66 const char kFileTransferStateStarted[] = "started"; |
| 65 const char kFileTransferStateInProgress[] = "in_progress"; | 67 const char kFileTransferStateInProgress[] = "in_progress"; |
| 66 const char kFileTransferStateCompleted[] = "completed"; | 68 const char kFileTransferStateCompleted[] = "completed"; |
| 67 const char kFileTransferStateFailed[] = "failed"; | 69 const char kFileTransferStateFailed[] = "failed"; |
| 68 | 70 |
| 69 // Frequency of sending onFileTransferUpdated. | 71 // Frequency of sending onFileTransferUpdated. |
| 70 const int64 kProgressEventFrequencyInMilliseconds = 1000; | 72 const int64 kProgressEventFrequencyInMilliseconds = 1000; |
| 71 | 73 |
| 72 // Maximim size of detailed change info on directory change event. If the size | 74 // Maximim size of detailed change info on directory change event. If the size |
| 73 // exceeds the maximum size, the detailed info is omitted and the force refresh | 75 // exceeds the maximum size, the detailed info is omitted and the force refresh |
| 74 // is kicked. | 76 // is kicked. |
| 75 const size_t kDirectoryChangeEventMaxDetailInfoSize = 1000; | 77 const size_t kDirectoryChangeEventMaxDetailInfoSize = 1000; |
| 76 | 78 |
| 79 // This time is used for confirm following event exists. | |
| 80 const int64 kFileTransferEventDelayTime = 100; | |
|
kinaba
2014/09/02 05:01:39
Could you add the uint (millisecond?) of the value
iseki
2014/09/02 10:01:42
Done.
| |
| 81 // This time is used for sending a event forcely. | |
| 82 const int64 kFileTransferEventForceSendInterval = 500; | |
|
kinaba
2014/09/02 05:01:39
ditto
iseki
2014/09/02 10:01:42
Done.
| |
| 83 | |
| 77 // Utility function to check if |job_info| is a file uploading job. | 84 // Utility function to check if |job_info| is a file uploading job. |
| 78 bool IsUploadJob(drive::JobType type) { | 85 bool IsUploadJob(drive::JobType type) { |
| 79 return (type == drive::TYPE_UPLOAD_NEW_FILE || | 86 return (type == drive::TYPE_UPLOAD_NEW_FILE || |
| 80 type == drive::TYPE_UPLOAD_EXISTING_FILE); | 87 type == drive::TYPE_UPLOAD_EXISTING_FILE); |
| 81 } | 88 } |
| 82 | 89 |
| 83 // Converts the job info to a IDL generated type. | 90 // Converts the job info to a IDL generated type. |
| 84 void JobInfoToTransferStatus( | 91 void JobInfoToTransferStatus( |
| 85 Profile* profile, | 92 Profile* profile, |
| 86 const std::string& extension_id, | 93 const std::string& extension_id, |
| 87 const std::string& job_status, | 94 const std::string& job_status, |
| 88 const drive::JobInfo& job_info, | 95 const drive::JobInfo& job_info, |
| 89 file_browser_private::FileTransferStatus* status) { | 96 file_browser_private::FileTransferStatus* status) { |
| 90 DCHECK(IsActiveFileTransferJobInfo(job_info)); | 97 DCHECK(IsActiveFileTransferJobInfo(job_info)); |
| 91 | 98 |
| 92 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue); | 99 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue); |
| 93 GURL url = util::ConvertDrivePathToFileSystemUrl( | 100 GURL url = util::ConvertDrivePathToFileSystemUrl( |
| 94 profile, job_info.file_path, extension_id); | 101 profile, job_info.file_path, extension_id); |
| 95 status->file_url = url.spec(); | 102 status->file_url = url.spec(); |
| 96 status->transfer_state = file_browser_private::ParseTransferState(job_status); | 103 status->transfer_state = file_browser_private::ParseTransferState(job_status); |
| 97 status->transfer_type = | 104 status->transfer_type = |
| 98 IsUploadJob(job_info.job_type) ? | 105 IsUploadJob(job_info.job_type) ? |
| 99 file_browser_private::TRANSFER_TYPE_UPLOAD : | 106 file_browser_private::TRANSFER_TYPE_UPLOAD : |
| 100 file_browser_private::TRANSFER_TYPE_DOWNLOAD; | 107 file_browser_private::TRANSFER_TYPE_DOWNLOAD; |
| 108 status->num_total_jobs = job_info.num_total_jobs; | |
| 101 // JavaScript does not have 64-bit integers. Instead we use double, which | 109 // JavaScript does not have 64-bit integers. Instead we use double, which |
| 102 // is in IEEE 754 formant and accurate up to 52-bits in JS, and in practice | 110 // is in IEEE 754 formant and accurate up to 52-bits in JS, and in practice |
| 103 // in C++. Larger values are rounded. | 111 // in C++. Larger values are rounded. |
| 104 status->processed.reset( | 112 status->processed.reset( |
| 105 new double(static_cast<double>(job_info.num_completed_bytes))); | 113 new double(static_cast<double>(job_info.num_completed_bytes))); |
| 106 status->total.reset( | 114 status->total.reset( |
| 107 new double(static_cast<double>(job_info.num_total_bytes))); | 115 new double(static_cast<double>(job_info.num_total_bytes))); |
| 108 } | 116 } |
| 109 | 117 |
| 110 // Checks if the Recovery Tool is running. This is a temporary solution. | 118 // Checks if the Recovery Tool is running. This is a temporary solution. |
| (...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 613 } | 621 } |
| 614 | 622 |
| 615 BroadcastEvent( | 623 BroadcastEvent( |
| 616 profile_, | 624 profile_, |
| 617 file_browser_private::OnPreferencesChanged::kEventName, | 625 file_browser_private::OnPreferencesChanged::kEventName, |
| 618 file_browser_private::OnPreferencesChanged::Create()); | 626 file_browser_private::OnPreferencesChanged::Create()); |
| 619 } | 627 } |
| 620 | 628 |
| 621 void EventRouter::OnJobAdded(const drive::JobInfo& job_info) { | 629 void EventRouter::OnJobAdded(const drive::JobInfo& job_info) { |
| 622 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 630 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 623 OnJobUpdated(job_info); | 631 if (!drive::IsActiveFileTransferJobInfo(job_info)) |
| 632 return; | |
| 633 ScheduleDriveFileTransferEvent( | |
| 634 job_info, kFileTransferStateAdded, false /* immediate */); | |
| 624 } | 635 } |
| 625 | 636 |
| 626 void EventRouter::OnJobUpdated(const drive::JobInfo& job_info) { | 637 void EventRouter::OnJobUpdated(const drive::JobInfo& job_info) { |
| 627 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 638 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 628 if (!drive::IsActiveFileTransferJobInfo(job_info)) | 639 if (!drive::IsActiveFileTransferJobInfo(job_info)) |
| 629 return; | 640 return; |
| 630 | 641 |
| 631 bool is_new_job = (drive_jobs_.find(job_info.job_id) == drive_jobs_.end()); | 642 bool is_new_job = (drive_jobs_.find(job_info.job_id) == drive_jobs_.end()); |
| 632 | 643 |
| 644 const std::string status = | |
| 645 is_new_job ? kFileTransferStateStarted : kFileTransferStateInProgress; | |
| 646 | |
| 633 // Replace with the latest job info. | 647 // Replace with the latest job info. |
| 634 drive_jobs_[job_info.job_id] = DriveJobInfoWithStatus( | 648 drive_jobs_[job_info.job_id] = DriveJobInfoWithStatus(job_info, status); |
| 635 job_info, | |
| 636 is_new_job ? kFileTransferStateStarted : kFileTransferStateInProgress); | |
| 637 | 649 |
| 638 // Fire event if needed. | 650 ScheduleDriveFileTransferEvent(job_info, status, false /* immediate */); |
| 639 bool always = is_new_job; | |
| 640 SendDriveFileTransferEvent(always); | |
| 641 } | 651 } |
| 642 | 652 |
| 643 void EventRouter::OnJobDone(const drive::JobInfo& job_info, | 653 void EventRouter::OnJobDone(const drive::JobInfo& job_info, |
| 644 drive::FileError error) { | 654 drive::FileError error) { |
| 645 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 655 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 646 if (!drive::IsActiveFileTransferJobInfo(job_info)) | 656 if (!drive::IsActiveFileTransferJobInfo(job_info)) |
| 647 return; | 657 return; |
| 648 | 658 |
| 649 // Replace with the latest job info. | 659 const std::string status = error == drive::FILE_ERROR_OK |
| 650 drive_jobs_[job_info.job_id] = DriveJobInfoWithStatus( | 660 ? kFileTransferStateCompleted |
| 651 job_info, | 661 : kFileTransferStateFailed; |
| 652 error == drive::FILE_ERROR_OK ? kFileTransferStateCompleted | |
| 653 : kFileTransferStateFailed); | |
| 654 | 662 |
| 655 // Fire event if needed. | 663 ScheduleDriveFileTransferEvent(job_info, status, true /* immediate */); |
| 656 bool always = true; | |
| 657 SendDriveFileTransferEvent(always); | |
| 658 | 664 |
| 659 // Forget about the job. | 665 // Forget about the job. |
| 660 drive_jobs_.erase(job_info.job_id); | 666 drive_jobs_.erase(job_info.job_id); |
| 661 } | 667 } |
| 662 | 668 |
| 663 void EventRouter::SendDriveFileTransferEvent(bool always) { | 669 void EventRouter::ScheduleDriveFileTransferEvent(const drive::JobInfo& job_info, |
| 664 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 670 const std::string& status, |
| 671 bool immediate) { | |
| 672 // Update next send time. | |
| 673 const base::Time now = base::Time::Now(); | |
| 674 if (immediate) { | |
| 675 next_send_file_transfer_event_ = now; | |
| 676 } else if (!drive_job_info_with_status_) { | |
| 677 // The first job is delayed to confirm whether only job or many jobs. | |
| 678 next_send_file_transfer_event_ = std::max( | |
| 679 now + base::TimeDelta::FromMilliseconds(kFileTransferEventDelayTime), | |
| 680 next_send_file_transfer_event_); | |
| 681 } | |
| 665 | 682 |
| 666 // When |always| flag is not set, we don't send the event until certain | 683 // Update the latest event. |
| 667 // amount of time passes after the previous one. This is to avoid | 684 drive_job_info_with_status_.reset( |
| 668 // flooding the IPC between extensions by many onFileTransferUpdated events. | 685 new DriveJobInfoWithStatus(job_info, status)); |
| 669 if (!ShouldSendProgressEvent(always, &last_file_transfer_event_)) | 686 |
| 687 // Schedule event. | |
| 688 if (next_send_file_transfer_event_ < now) { | |
| 689 SendDriveFileTransferEvent(); | |
| 690 } else { | |
| 691 const base::TimeDelta delta = next_send_file_transfer_event_ - now; | |
| 692 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 693 FROM_HERE, | |
| 694 base::Bind(&EventRouter::SendDriveFileTransferEvent, | |
| 695 weak_factory_.GetWeakPtr()), | |
| 696 delta); | |
| 697 } | |
| 698 } | |
| 699 | |
| 700 void EventRouter::SendDriveFileTransferEvent() { | |
| 701 const base::Time now = base::Time::Now(); | |
| 702 if (now < next_send_file_transfer_event_ || !drive_job_info_with_status_) | |
|
kinaba
2014/09/02 05:01:39
This may be fragile due to reasons.
First, accord
iseki
2014/09/02 10:01:42
Done.
| |
| 670 return; | 703 return; |
| 671 | 704 |
| 672 // Convert the current |drive_jobs_| to IDL type. | 705 // Convert the drive_job_info_with_status_ to IDL type. |
| 673 std::vector<linked_ptr<file_browser_private::FileTransferStatus> > | 706 std::vector<linked_ptr<file_browser_private::FileTransferStatus> > |
| 674 status_list; | 707 status_list; |
| 675 for (std::map<drive::JobID, DriveJobInfoWithStatus>::iterator | 708 |
| 676 iter = drive_jobs_.begin(); iter != drive_jobs_.end(); ++iter) { | 709 linked_ptr<file_browser_private::FileTransferStatus> status( |
| 677 linked_ptr<file_browser_private::FileTransferStatus> status( | 710 new file_browser_private::FileTransferStatus()); |
| 678 new file_browser_private::FileTransferStatus()); | 711 JobInfoToTransferStatus(profile_, |
| 679 JobInfoToTransferStatus(profile_, | 712 kFileManagerAppId, |
| 680 kFileManagerAppId, | 713 drive_job_info_with_status_->status, |
| 681 iter->second.status, | 714 drive_job_info_with_status_->job_info, |
| 682 iter->second.job_info, | 715 status.get()); |
| 683 status.get()); | 716 status_list.push_back(status); |
|
kinaba
2014/09/02 05:01:39
Previously the onFileTransferUpdated event sent al
iseki
2014/09/02 10:01:42
I make the clean up issue(crbug.com/408482) and tr
| |
| 684 status_list.push_back(status); | 717 |
| 685 } | 718 drive_job_info_with_status_.reset(); |
| 719 | |
| 686 BroadcastEvent( | 720 BroadcastEvent( |
| 687 profile_, | 721 profile_, |
| 688 file_browser_private::OnFileTransfersUpdated::kEventName, | 722 file_browser_private::OnFileTransfersUpdated::kEventName, |
| 689 file_browser_private::OnFileTransfersUpdated::Create(status_list)); | 723 file_browser_private::OnFileTransfersUpdated::Create(status_list)); |
| 724 // To avoid terriable delay due to dense consecutive event, set the | |
| 725 // force send time. | |
|
kinaba
2014/09/02 05:01:39
I couldn't see how it works, or what is it for.
I
iseki
2014/09/02 10:01:42
Done.
| |
| 726 next_send_file_transfer_event_ = | |
| 727 now + | |
| 728 base::TimeDelta::FromMilliseconds(kFileTransferEventForceSendInterval); | |
| 690 } | 729 } |
| 691 | 730 |
| 692 void EventRouter::OnDirectoryChanged(const base::FilePath& drive_path) { | 731 void EventRouter::OnDirectoryChanged(const base::FilePath& drive_path) { |
| 693 HandleFileWatchNotification(NULL, drive_path, false); | 732 HandleFileWatchNotification(NULL, drive_path, false); |
| 694 } | 733 } |
| 695 | 734 |
| 696 void EventRouter::OnFileChanged(const drive::FileChange& changed_files) { | 735 void EventRouter::OnFileChanged(const drive::FileChange& changed_files) { |
| 697 typedef std::map<base::FilePath, drive::FileChange> FileChangeMap; | 736 typedef std::map<base::FilePath, drive::FileChange> FileChangeMap; |
| 698 | 737 |
| 699 FileChangeMap map; | 738 FileChangeMap map; |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 965 } | 1004 } |
| 966 } | 1005 } |
| 967 | 1006 |
| 968 void EventRouter::OnOwnerEntryChanged(aura::Window* window) { | 1007 void EventRouter::OnOwnerEntryChanged(aura::Window* window) { |
| 969 BroadcastEvent(profile_, | 1008 BroadcastEvent(profile_, |
| 970 file_browser_private::OnDesktopChanged::kEventName, | 1009 file_browser_private::OnDesktopChanged::kEventName, |
| 971 file_browser_private::OnDesktopChanged::Create()); | 1010 file_browser_private::OnDesktopChanged::Create()); |
| 972 } | 1011 } |
| 973 | 1012 |
| 974 } // namespace file_manager | 1013 } // namespace file_manager |
| OLD | NEW |