Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(430)

Side by Side Diff: chrome/browser/chromeos/arc/arc_downloads_watcher_service.cc

Issue 2304523002: arc: Fix thread unsafe behavior of ArcDownloadsWatcherService (Closed)
Patch Set: Less busy UI thread Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/chromeos/arc/arc_downloads_watcher_service.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/arc/arc_downloads_watcher_service.h" 5 #include "chrome/browser/chromeos/arc/arc_downloads_watcher_service.h"
6 6
7 #include <map> 7 #include <map>
8 #include <memory> 8 #include <memory>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 17 matching lines...) Expand all
28 28
29 namespace arc { 29 namespace arc {
30 30
31 namespace { 31 namespace {
32 32
33 const base::FilePath::CharType kAndroidDownloadDir[] = 33 const base::FilePath::CharType kAndroidDownloadDir[] =
34 FILE_PATH_LITERAL("/storage/emulated/0/Download"); 34 FILE_PATH_LITERAL("/storage/emulated/0/Download");
35 35
36 // Compares two TimestampMaps and returns the list of file paths added/removed 36 // Compares two TimestampMaps and returns the list of file paths added/removed
37 // or whose timestamp have changed. 37 // or whose timestamp have changed.
38 std::vector<base::FilePath> CollectChangedPaths( 38 std::vector<std::string> CollectChangedPaths(
hashimoto 2016/09/01 07:34:20 Semantically, base::FilePath suits better than std
hidehiko 2016/09/01 17:05:45 Is it measurable? If so, it's good to note. If not
hashimoto 2016/09/02 03:56:00 I just thought it might be nice to do as there is
39 const TimestampMap& timestamp_map_a, 39 const TimestampMap& timestamp_map_a,
40 const TimestampMap& timestamp_map_b) { 40 const TimestampMap& timestamp_map_b) {
41 std::vector<base::FilePath> changed_paths; 41 std::vector<std::string> changed_paths;
42 42
43 TimestampMap::const_iterator iter_a = timestamp_map_a.begin(); 43 TimestampMap::const_iterator iter_a = timestamp_map_a.begin();
44 TimestampMap::const_iterator iter_b = timestamp_map_b.begin(); 44 TimestampMap::const_iterator iter_b = timestamp_map_b.begin();
45 while (iter_a != timestamp_map_a.end() && iter_b != timestamp_map_b.end()) { 45 while (iter_a != timestamp_map_a.end() && iter_b != timestamp_map_b.end()) {
46 if (iter_a->first == iter_b->first) { 46 if (iter_a->first == iter_b->first) {
47 if (iter_a->second != iter_b->second) { 47 if (iter_a->second != iter_b->second) {
48 changed_paths.emplace_back(iter_a->first); 48 changed_paths.emplace_back(iter_a->first.value());
49 } 49 }
50 ++iter_a; 50 ++iter_a;
51 ++iter_b; 51 ++iter_b;
52 } else if (iter_a->first < iter_b->first) { 52 } else if (iter_a->first < iter_b->first) {
53 changed_paths.emplace_back(iter_a->first); 53 changed_paths.emplace_back(iter_a->first.value());
54 ++iter_a; 54 ++iter_a;
55 } else { // iter_a->first > iter_b->first 55 } else { // iter_a->first > iter_b->first
56 changed_paths.emplace_back(iter_b->first); 56 changed_paths.emplace_back(iter_b->first.value());
57 ++iter_b; 57 ++iter_b;
58 } 58 }
59 } 59 }
60 60
61 while (iter_a != timestamp_map_a.end()) { 61 while (iter_a != timestamp_map_a.end()) {
62 changed_paths.emplace_back(iter_a->first); 62 changed_paths.emplace_back(iter_a->first.value());
63 ++iter_a; 63 ++iter_a;
64 } 64 }
65 while (iter_b != timestamp_map_b.end()) { 65 while (iter_b != timestamp_map_b.end()) {
66 changed_paths.emplace_back(iter_b->first); 66 changed_paths.emplace_back(iter_b->first.value());
67 ++iter_b; 67 ++iter_b;
68 } 68 }
69 69
70 return changed_paths; 70 return changed_paths;
71 } 71 }
72 72
73 } // namespace 73 } // namespace
74 74
75 // The core part of ArcDownloadsWatcherService to watch for file changes in 75 // The core part of ArcDownloadsWatcherService to watch for file changes in
76 // Downloads directory. 76 // Downloads directory.
77 class ArcDownloadsWatcherService::DownloadsWatcher { 77 class ArcDownloadsWatcherService::DownloadsWatcher {
78 public: 78 public:
79 using Callback = 79 using Callback =
80 base::Callback<void(const std::vector<base::FilePath>& paths)>; 80 base::Callback<void(std::unique_ptr<mojo::Array<mojo::String>> paths)>;
81 81
82 explicit DownloadsWatcher(const Callback& callback); 82 explicit DownloadsWatcher(const Callback& callback);
83 ~DownloadsWatcher(); 83 ~DownloadsWatcher();
84 84
85 // Starts watching Downloads directory. 85 // Starts watching Downloads directory.
86 void Start(); 86 void Start();
87 87
88 private: 88 private:
89 // Called by base::FilePathWatcher to notify file changes. 89 // Called by base::FilePathWatcher to notify file changes.
90 void OnFilePathChanged(const base::FilePath& path, bool error); 90 void OnFilePathChanged(const base::FilePath& path, bool error);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 135
136 void ArcDownloadsWatcherService::DownloadsWatcher::OnFilePathChanged( 136 void ArcDownloadsWatcherService::DownloadsWatcher::OnFilePathChanged(
137 const base::FilePath& path, 137 const base::FilePath& path,
138 bool error) { 138 bool error) {
139 // On Linux, |error| is always false. Also, |path| is always the same path 139 // On Linux, |error| is always false. Also, |path| is always the same path
140 // as one given to FilePathWatcher::Watch(). 140 // as one given to FilePathWatcher::Watch().
141 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 141 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
142 142
143 TimestampMap current_timestamp_map = BuildTimestampMap(); 143 TimestampMap current_timestamp_map = BuildTimestampMap();
144 144
145 std::vector<base::FilePath> changed_paths = 145 std::vector<std::string> changed_paths =
146 CollectChangedPaths(last_timestamp_map_, current_timestamp_map); 146 CollectChangedPaths(last_timestamp_map_, current_timestamp_map);
147 147
148 last_timestamp_map_ = std::move(current_timestamp_map); 148 last_timestamp_map_ = std::move(current_timestamp_map);
149 149
150 callback_.Run(changed_paths); 150 auto mojo_paths =
151 base::MakeUnique<mojo::Array<mojo::String>>(changed_paths.size());
hidehiko 2016/09/01 17:05:45 Is it necessary to be unique_ptr? I thought mojo::
hashimoto 2016/09/02 03:56:00 Thank you for pointing this out. I wasn't aware of
152 for (size_t i = 0; i < changed_paths.size(); ++i) {
153 (*mojo_paths)[i] = std::move(changed_paths[i]);
154 }
155 BrowserThread::PostTask(
156 BrowserThread::UI, FROM_HERE,
157 base::Bind(callback_, base::Passed(std::move(mojo_paths))));
151 } 158 }
152 159
153 TimestampMap ArcDownloadsWatcherService::DownloadsWatcher::BuildTimestampMap() 160 TimestampMap ArcDownloadsWatcherService::DownloadsWatcher::BuildTimestampMap()
154 const { 161 const {
155 DCHECK(!downloads_dir_.EndsWithSeparator()); 162 DCHECK(!downloads_dir_.EndsWithSeparator());
156 TimestampMap timestamp_map; 163 TimestampMap timestamp_map;
157 164
158 // Enumerate normal files only; directories and symlinks are skipped. 165 // Enumerate normal files only; directories and symlinks are skipped.
159 base::FileEnumerator enumerator(downloads_dir_, true, 166 base::FileEnumerator enumerator(downloads_dir_, true,
160 base::FileEnumerator::FILES); 167 base::FileEnumerator::FILES);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 217
211 void ArcDownloadsWatcherService::StopWatchingDownloads() { 218 void ArcDownloadsWatcherService::StopWatchingDownloads() {
212 DCHECK_CURRENTLY_ON(BrowserThread::UI); 219 DCHECK_CURRENTLY_ON(BrowserThread::UI);
213 if (watcher_) { 220 if (watcher_) {
214 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, 221 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE,
215 watcher_.release()); 222 watcher_.release());
216 } 223 }
217 } 224 }
218 225
219 void ArcDownloadsWatcherService::OnDownloadsChanged( 226 void ArcDownloadsWatcherService::OnDownloadsChanged(
220 const std::vector<base::FilePath>& paths) { 227 std::unique_ptr<mojo::Array<mojo::String>> paths) {
221 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 228 DCHECK_CURRENTLY_ON(BrowserThread::UI);
222 229
223 auto* instance = arc_bridge_service()->file_system()->instance(); 230 auto* instance = arc_bridge_service()->file_system()->instance();
224 if (!instance) 231 if (!instance)
225 return; 232 return;
226 233 instance->RequestMediaScan(std::move(*paths));
227 mojo::Array<mojo::String> mojo_paths(paths.size());
228 for (size_t i = 0; i < paths.size(); ++i) {
229 mojo_paths[i] = paths[i].value();
230 }
231 instance->RequestMediaScan(std::move(mojo_paths));
232 } 234 }
233 235
234 } // namespace arc 236 } // namespace arc
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/arc/arc_downloads_watcher_service.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698