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

Side by Side Diff: chrome/browser/devtools/devtools_file_watcher.cc

Issue 2384343002: DevTools: improve DevTools file watcher to send added and removed paths (Closed)
Patch Set: go above and beyond Created 4 years, 2 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
OLDNEW
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2015 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/devtools/devtools_file_watcher.h" 5 #include "chrome/browser/devtools/devtools_file_watcher.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map> 8 #include <map>
9 #include <memory> 9 #include <memory>
10 #include <set> 10 #include <set>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/files/file_enumerator.h" 13 #include "base/files/file_enumerator.h"
14 #include "base/files/file_path.h" 14 #include "base/files/file_path.h"
15 #include "base/files/file_path_watcher.h" 15 #include "base/files/file_path_watcher.h"
16 #include "base/files/file_util.h"
16 #include "base/memory/ref_counted.h" 17 #include "base/memory/ref_counted.h"
17 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
18 19
19 using content::BrowserThread; 20 using content::BrowserThread;
20 21
21 static int kFirstThrottleTimeout = 10; 22 static int kFirstThrottleTimeout = 10;
22 static int kDefaultThrottleTimeout = 200; 23 static int kDefaultThrottleTimeout = 200;
23 24
24 // DevToolsFileWatcher::SharedFileWatcher -------------------------------------- 25 // DevToolsFileWatcher::SharedFileWatcher --------------------------------------
25 26
26 class DevToolsFileWatcher::SharedFileWatcher : 27 class DevToolsFileWatcher::SharedFileWatcher :
27 public base::RefCounted<SharedFileWatcher> { 28 public base::RefCounted<SharedFileWatcher> {
28 public: 29 public:
29 SharedFileWatcher(); 30 SharedFileWatcher();
30 31
31 void AddListener(DevToolsFileWatcher* watcher); 32 void AddListener(DevToolsFileWatcher* watcher);
32 void RemoveListener(DevToolsFileWatcher* watcher); 33 void RemoveListener(DevToolsFileWatcher* watcher);
33 void AddWatch(const base::FilePath& path); 34 void AddWatch(const base::FilePath& path);
34 void RemoveWatch(const base::FilePath& path); 35 void RemoveWatch(const base::FilePath& path);
35 36
36 private: 37 private:
37 friend class base::RefCounted< 38 friend class base::RefCounted<
38 DevToolsFileWatcher::SharedFileWatcher>; 39 DevToolsFileWatcher::SharedFileWatcher>;
39 ~SharedFileWatcher(); 40 ~SharedFileWatcher();
40 41
42 using FilePathTimesMap = std::map<base::FilePath, base::Time>;
43 void GetModificationTimes(const base::FilePath& path,
44 FilePathTimesMap* file_path_times);
41 void DirectoryChanged(const base::FilePath& path, bool error); 45 void DirectoryChanged(const base::FilePath& path, bool error);
42 void DispatchNotifications(); 46 void DispatchNotifications();
43 47
44 std::vector<DevToolsFileWatcher*> listeners_; 48 std::vector<DevToolsFileWatcher*> listeners_;
45 std::map<base::FilePath, std::unique_ptr<base::FilePathWatcher>> watchers_; 49 std::map<base::FilePath, std::unique_ptr<base::FilePathWatcher>> watchers_;
46 using FilePathTimesMap = std::map<base::FilePath, base::Time>; 50 std::map<base::FilePath, FilePathTimesMap> file_path_times_;
47 FilePathTimesMap file_path_times_;
48 std::set<base::FilePath> pending_paths_; 51 std::set<base::FilePath> pending_paths_;
49 base::Time last_event_time_; 52 base::Time last_event_time_;
50 base::TimeDelta last_dispatch_cost_; 53 base::TimeDelta last_dispatch_cost_;
51 }; 54 };
52 55
53 DevToolsFileWatcher::SharedFileWatcher::SharedFileWatcher() 56 DevToolsFileWatcher::SharedFileWatcher::SharedFileWatcher()
54 : last_dispatch_cost_( 57 : last_dispatch_cost_(
55 base::TimeDelta::FromMilliseconds(kDefaultThrottleTimeout)) { 58 base::TimeDelta::FromMilliseconds(kDefaultThrottleTimeout)) {
56 DevToolsFileWatcher::s_shared_watcher_ = this; 59 DevToolsFileWatcher::s_shared_watcher_ = this;
57 } 60 }
(...skipping 19 matching lines...) Expand all
77 return; 80 return;
78 if (!base::FilePathWatcher::RecursiveWatchAvailable()) 81 if (!base::FilePathWatcher::RecursiveWatchAvailable())
79 return; 82 return;
80 watchers_[path].reset(new base::FilePathWatcher()); 83 watchers_[path].reset(new base::FilePathWatcher());
81 bool success = watchers_[path]->Watch( 84 bool success = watchers_[path]->Watch(
82 path, true, 85 path, true,
83 base::Bind(&SharedFileWatcher::DirectoryChanged, base::Unretained(this))); 86 base::Bind(&SharedFileWatcher::DirectoryChanged, base::Unretained(this)));
84 if (!success) 87 if (!success)
85 return; 88 return;
86 89
90 FilePathTimesMap times_map;
91 GetModificationTimes(path, &times_map);
dgozman 2016/10/04 02:26:41 One line, avoids copying: GetModificationTimes(pa
lushnikov 2016/10/04 02:51:59 Done.
92 file_path_times_[path] = times_map;
93 }
94
95 void DevToolsFileWatcher::SharedFileWatcher::GetModificationTimes(
96 const base::FilePath& path,
97 FilePathTimesMap* times_map) {
87 base::FileEnumerator enumerator(path, true, base::FileEnumerator::FILES); 98 base::FileEnumerator enumerator(path, true, base::FileEnumerator::FILES);
88 base::FilePath file_path = enumerator.Next(); 99 base::FilePath file_path = enumerator.Next();
89 while (!file_path.empty()) { 100 while (!file_path.empty()) {
90 base::FileEnumerator::FileInfo file_info = enumerator.GetInfo(); 101 base::FileEnumerator::FileInfo file_info = enumerator.GetInfo();
91 file_path_times_[file_path] = file_info.GetLastModifiedTime(); 102 (*times_map)[file_path] = file_info.GetLastModifiedTime();
92 file_path = enumerator.Next(); 103 file_path = enumerator.Next();
93 } 104 }
94 } 105 }
95 106
96 void DevToolsFileWatcher::SharedFileWatcher::RemoveWatch( 107 void DevToolsFileWatcher::SharedFileWatcher::RemoveWatch(
97 const base::FilePath& path) { 108 const base::FilePath& path) {
98 watchers_.erase(path); 109 watchers_.erase(path);
99 } 110 }
100 111
101 void DevToolsFileWatcher::SharedFileWatcher::DirectoryChanged( 112 void DevToolsFileWatcher::SharedFileWatcher::DirectoryChanged(
(...skipping 12 matching lines...) Expand all
114 last_dispatch_cost_ * 2; 125 last_dispatch_cost_ * 2;
115 126
116 BrowserThread::PostDelayedTask( 127 BrowserThread::PostDelayedTask(
117 BrowserThread::FILE, FROM_HERE, 128 BrowserThread::FILE, FROM_HERE,
118 base::Bind(&DevToolsFileWatcher::SharedFileWatcher::DispatchNotifications, 129 base::Bind(&DevToolsFileWatcher::SharedFileWatcher::DispatchNotifications,
119 this), shedule_for); 130 this), shedule_for);
120 last_event_time_ = now; 131 last_event_time_ = now;
121 } 132 }
122 133
123 void DevToolsFileWatcher::SharedFileWatcher::DispatchNotifications() { 134 void DevToolsFileWatcher::SharedFileWatcher::DispatchNotifications() {
135 if (!pending_paths_.size())
136 return;
124 base::Time start = base::Time::Now(); 137 base::Time start = base::Time::Now();
138 std::vector<std::string> added_paths;
139 std::vector<std::string> removed_paths;
125 std::vector<std::string> changed_paths; 140 std::vector<std::string> changed_paths;
126 for (auto path : pending_paths_) { 141
127 base::FileEnumerator enumerator(path, true, base::FileEnumerator::FILES); 142 for (const auto& path : pending_paths_) {
128 base::FilePath file_path = enumerator.Next(); 143 FilePathTimesMap& old_times = file_path_times_[path];
129 while (!file_path.empty()) { 144 FilePathTimesMap current_times;
130 base::FileEnumerator::FileInfo file_info = enumerator.GetInfo(); 145 GetModificationTimes(path, &current_times);
131 base::Time new_time = file_info.GetLastModifiedTime(); 146 for (auto it = current_times.begin(); it != current_times.end(); ++it) {
dgozman 2016/10/04 02:26:41 for (const auto& pair : current_times)
lushnikov 2016/10/04 02:51:59 Done.
132 if (file_path_times_[file_path] != new_time) { 147 auto old_timestamp = old_times.find(it->first);
133 file_path_times_[file_path] = new_time; 148 if (old_timestamp == old_times.end()) {
134 changed_paths.push_back(file_path.AsUTF8Unsafe()); 149 old_times[it->first] = it->second;
150 added_paths.push_back(it->first.AsUTF8Unsafe());
151 } else if (old_timestamp->second != it->second) {
152 old_timestamp->second = it->second;
153 changed_paths.push_back(it->first.AsUTF8Unsafe());
135 } 154 }
136 file_path = enumerator.Next(); 155 }
156 for (auto it = old_times.begin(); it != old_times.end();) {
dgozman 2016/10/04 02:26:41 ditto
lushnikov 2016/10/04 02:51:59 Done.
157 auto new_timestamp = current_times.find(it->first);
158 if (new_timestamp == current_times.end()) {
159 removed_paths.push_back(it->first.AsUTF8Unsafe());
160 old_times.erase(it++);
dgozman 2016/10/04 02:26:41 Don't do this. Just |old_times.swap(current_times)
lushnikov 2016/10/04 02:51:59 Done.
161 } else {
162 ++it;
163 }
137 } 164 }
138 } 165 }
139 pending_paths_.clear(); 166 pending_paths_.clear();
140 167
141 for (auto* watcher : listeners_) { 168 for (auto* watcher : listeners_) {
142 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 169 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
143 base::Bind(watcher->callback_, changed_paths)); 170 base::Bind(watcher->callback_, changed_paths,
171 added_paths, removed_paths));
144 } 172 }
145 last_dispatch_cost_ = base::Time::Now() - start; 173 last_dispatch_cost_ = base::Time::Now() - start;
146 } 174 }
147 175
148 // static 176 // static
149 DevToolsFileWatcher::SharedFileWatcher* 177 DevToolsFileWatcher::SharedFileWatcher*
150 DevToolsFileWatcher::s_shared_watcher_ = nullptr; 178 DevToolsFileWatcher::s_shared_watcher_ = nullptr;
151 179
152 // DevToolsFileWatcher --------------------------------------------------------- 180 // DevToolsFileWatcher ---------------------------------------------------------
153 181
(...skipping 19 matching lines...) Expand all
173 201
174 void DevToolsFileWatcher::AddWatch(const base::FilePath& path) { 202 void DevToolsFileWatcher::AddWatch(const base::FilePath& path) {
175 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 203 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
176 shared_watcher_->AddWatch(path); 204 shared_watcher_->AddWatch(path);
177 } 205 }
178 206
179 void DevToolsFileWatcher::RemoveWatch(const base::FilePath& path) { 207 void DevToolsFileWatcher::RemoveWatch(const base::FilePath& path) {
180 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 208 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
181 shared_watcher_->RemoveWatch(path); 209 shared_watcher_->RemoveWatch(path);
182 } 210 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698