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 std::vector<drive::JobInfo> GetActiveFileTransferJobInfo( | |
kinaba
2014/09/03 15:54:18
You can simply return only the number of jobs
size
iseki
2014/09/04 00:50:06
Done.
| |
88 std::vector<drive::JobInfo> job_info_list) { | |
kinaba
2014/09/03 15:54:18
const std::vector<drive::JobInfo>& job_info_list
iseki
2014/09/04 00:50:07
Done.
| |
89 std::vector<drive::JobInfo> active_job_info_list; | |
90 for (std::vector<drive::JobInfo>::iterator iter = job_info_list.begin(), | |
91 end = job_info_list.end(); | |
kinaba
2014/09/03 15:54:18
(Though I personally prefer iterators :)), we are
iseki
2014/09/04 00:50:07
Done.
| |
92 iter != end; | |
93 ++iter) { | |
94 if (IsActiveFileTransferJobInfo(*iter)) | |
95 active_job_info_list.push_back(*iter); | |
96 } | |
97 return active_job_info_list; | |
98 } | |
99 | |
82 // Converts the job info to a IDL generated type. | 100 // Converts the job info to a IDL generated type. |
83 void JobInfoToTransferStatus( | 101 void JobInfoToTransferStatus( |
84 Profile* profile, | 102 Profile* profile, |
85 const std::string& extension_id, | 103 const std::string& extension_id, |
86 const std::string& job_status, | 104 const std::string& job_status, |
87 const drive::JobInfo& job_info, | 105 const drive::JobInfo& job_info, |
88 file_browser_private::FileTransferStatus* status) { | 106 file_browser_private::FileTransferStatus* status) { |
89 DCHECK(IsActiveFileTransferJobInfo(job_info)); | 107 DCHECK(IsActiveFileTransferJobInfo(job_info)); |
90 | 108 |
91 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue); | 109 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue); |
92 GURL url = util::ConvertDrivePathToFileSystemUrl( | 110 GURL url = util::ConvertDrivePathToFileSystemUrl( |
93 profile, job_info.file_path, extension_id); | 111 profile, job_info.file_path, extension_id); |
94 status->file_url = url.spec(); | 112 status->file_url = url.spec(); |
95 status->transfer_state = file_browser_private::ParseTransferState(job_status); | 113 status->transfer_state = file_browser_private::ParseTransferState(job_status); |
96 status->transfer_type = | 114 status->transfer_type = |
97 IsUploadJob(job_info.job_type) ? | 115 IsUploadJob(job_info.job_type) ? |
98 file_browser_private::TRANSFER_TYPE_UPLOAD : | 116 file_browser_private::TRANSFER_TYPE_UPLOAD : |
99 file_browser_private::TRANSFER_TYPE_DOWNLOAD; | 117 file_browser_private::TRANSFER_TYPE_DOWNLOAD; |
118 DriveIntegrationService* const integration_service = | |
119 DriveIntegrationServiceFactory::FindForProfile(profile); | |
120 status->num_total_jobs = | |
121 GetActiveFileTransferJobInfo( | |
122 integration_service->job_list()->GetJobInfoList()).size(); | |
100 // JavaScript does not have 64-bit integers. Instead we use double, which | 123 // 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 | 124 // is in IEEE 754 formant and accurate up to 52-bits in JS, and in practice |
102 // in C++. Larger values are rounded. | 125 // in C++. Larger values are rounded. |
103 status->processed.reset( | 126 status->processed.reset( |
104 new double(static_cast<double>(job_info.num_completed_bytes))); | 127 new double(static_cast<double>(job_info.num_completed_bytes))); |
105 status->total.reset( | 128 status->total.reset( |
106 new double(static_cast<double>(job_info.num_total_bytes))); | 129 new double(static_cast<double>(job_info.num_total_bytes))); |
107 } | 130 } |
108 | 131 |
109 // Checks if the Recovery Tool is running. This is a temporary solution. | 132 // 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 } | 606 } |
584 | 607 |
585 BroadcastEvent( | 608 BroadcastEvent( |
586 profile_, | 609 profile_, |
587 file_browser_private::OnPreferencesChanged::kEventName, | 610 file_browser_private::OnPreferencesChanged::kEventName, |
588 file_browser_private::OnPreferencesChanged::Create()); | 611 file_browser_private::OnPreferencesChanged::Create()); |
589 } | 612 } |
590 | 613 |
591 void EventRouter::OnJobAdded(const drive::JobInfo& job_info) { | 614 void EventRouter::OnJobAdded(const drive::JobInfo& job_info) { |
592 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 615 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
593 OnJobUpdated(job_info); | 616 if (!drive::IsActiveFileTransferJobInfo(job_info)) |
617 return; | |
618 ScheduleDriveFileTransferEvent( | |
619 job_info, kFileTransferStateAdded, false /* immediate */); | |
594 } | 620 } |
595 | 621 |
596 void EventRouter::OnJobUpdated(const drive::JobInfo& job_info) { | 622 void EventRouter::OnJobUpdated(const drive::JobInfo& job_info) { |
597 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 623 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
598 if (!drive::IsActiveFileTransferJobInfo(job_info)) | 624 if (!drive::IsActiveFileTransferJobInfo(job_info)) |
599 return; | 625 return; |
600 | 626 |
601 bool is_new_job = (drive_jobs_.find(job_info.job_id) == drive_jobs_.end()); | 627 bool is_new_job = (drive_jobs_.find(job_info.job_id) == drive_jobs_.end()); |
602 | 628 |
629 const std::string status = | |
630 is_new_job ? kFileTransferStateStarted : kFileTransferStateInProgress; | |
kinaba
2014/09/03 15:54:18
Just a question, do we need to distinguish these t
iseki
2014/09/04 00:50:07
Now, kFileTransferStateInProgress is not necessary
| |
631 | |
603 // Replace with the latest job info. | 632 // Replace with the latest job info. |
604 drive_jobs_[job_info.job_id] = DriveJobInfoWithStatus( | 633 drive_jobs_[job_info.job_id] = DriveJobInfoWithStatus(job_info, status); |
605 job_info, | |
606 is_new_job ? kFileTransferStateStarted : kFileTransferStateInProgress); | |
607 | 634 |
608 // Fire event if needed. | 635 ScheduleDriveFileTransferEvent(job_info, status, false /* immediate */); |
609 bool always = is_new_job; | |
610 SendDriveFileTransferEvent(always); | |
611 } | 636 } |
612 | 637 |
613 void EventRouter::OnJobDone(const drive::JobInfo& job_info, | 638 void EventRouter::OnJobDone(const drive::JobInfo& job_info, |
614 drive::FileError error) { | 639 drive::FileError error) { |
615 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 640 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
616 if (!drive::IsActiveFileTransferJobInfo(job_info)) | 641 if (!drive::IsActiveFileTransferJobInfo(job_info)) |
617 return; | 642 return; |
618 | 643 |
619 // Replace with the latest job info. | 644 const std::string status = error == drive::FILE_ERROR_OK |
620 drive_jobs_[job_info.job_id] = DriveJobInfoWithStatus( | 645 ? kFileTransferStateCompleted |
621 job_info, | 646 : kFileTransferStateFailed; |
622 error == drive::FILE_ERROR_OK ? kFileTransferStateCompleted | |
623 : kFileTransferStateFailed); | |
624 | 647 |
625 // Fire event if needed. | 648 ScheduleDriveFileTransferEvent(job_info, status, true /* immediate */); |
626 bool always = true; | |
627 SendDriveFileTransferEvent(always); | |
628 | 649 |
629 // Forget about the job. | 650 // Forget about the job. |
630 drive_jobs_.erase(job_info.job_id); | 651 drive_jobs_.erase(job_info.job_id); |
631 } | 652 } |
632 | 653 |
633 void EventRouter::SendDriveFileTransferEvent(bool always) { | 654 void EventRouter::ScheduleDriveFileTransferEvent(const drive::JobInfo& job_info, |
634 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 655 const std::string& status, |
656 bool immediate) { | |
657 const bool no_pending_task = !drive_job_info_for_scheduled_event_; | |
658 // Update the latest event. | |
659 drive_job_info_for_scheduled_event_.reset( | |
660 new DriveJobInfoWithStatus(job_info, status)); | |
661 if (immediate) { | |
662 SendDriveFileTransferEvent(); | |
663 } else if (no_pending_task) { | |
664 const base::TimeDelta delay = base::TimeDelta::FromMilliseconds( | |
665 kFileTransferEventDelayTimeInMilliseconds); | |
666 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
667 FROM_HERE, | |
668 base::Bind(&EventRouter::SendDriveFileTransferEvent, | |
669 weak_factory_.GetWeakPtr()), | |
670 delay); | |
671 } | |
672 } | |
635 | 673 |
636 // When |always| flag is not set, we don't send the event until certain | 674 void EventRouter::SendDriveFileTransferEvent() { |
637 // amount of time passes after the previous one. This is to avoid | 675 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; | 676 return; |
641 | 677 |
642 // Convert the current |drive_jobs_| to IDL type. | 678 // Convert the drive_job_info_for_scheduled_event_ to IDL type. |
643 std::vector<linked_ptr<file_browser_private::FileTransferStatus> > | 679 std::vector<linked_ptr<file_browser_private::FileTransferStatus> > |
644 status_list; | 680 status_list; |
645 for (std::map<drive::JobID, DriveJobInfoWithStatus>::iterator | 681 |
646 iter = drive_jobs_.begin(); iter != drive_jobs_.end(); ++iter) { | 682 linked_ptr<file_browser_private::FileTransferStatus> status( |
647 linked_ptr<file_browser_private::FileTransferStatus> status( | 683 new file_browser_private::FileTransferStatus()); |
648 new file_browser_private::FileTransferStatus()); | 684 JobInfoToTransferStatus(profile_, |
649 JobInfoToTransferStatus(profile_, | 685 kFileManagerAppId, |
650 kFileManagerAppId, | 686 drive_job_info_for_scheduled_event_->status, |
651 iter->second.status, | 687 drive_job_info_for_scheduled_event_->job_info, |
652 iter->second.job_info, | 688 status.get()); |
653 status.get()); | 689 status_list.push_back(status); |
654 status_list.push_back(status); | 690 |
655 } | 691 drive_job_info_for_scheduled_event_.reset(); |
692 | |
656 BroadcastEvent( | 693 BroadcastEvent( |
657 profile_, | 694 profile_, |
658 file_browser_private::OnFileTransfersUpdated::kEventName, | 695 file_browser_private::OnFileTransfersUpdated::kEventName, |
659 file_browser_private::OnFileTransfersUpdated::Create(status_list)); | 696 file_browser_private::OnFileTransfersUpdated::Create(status_list)); |
660 } | 697 } |
661 | 698 |
662 void EventRouter::OnDirectoryChanged(const base::FilePath& drive_path) { | 699 void EventRouter::OnDirectoryChanged(const base::FilePath& drive_path) { |
663 HandleFileWatchNotification(NULL, drive_path, false); | 700 HandleFileWatchNotification(NULL, drive_path, false); |
664 } | 701 } |
665 | 702 |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
904 // Do nothing. | 941 // Do nothing. |
905 } | 942 } |
906 | 943 |
907 void EventRouter::OnFormatCompleted(const std::string& device_path, | 944 void EventRouter::OnFormatCompleted(const std::string& device_path, |
908 bool success) { | 945 bool success) { |
909 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 946 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
910 // Do nothing. | 947 // Do nothing. |
911 } | 948 } |
912 | 949 |
913 } // namespace file_manager | 950 } // namespace file_manager |
OLD | NEW |