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

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: 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);
dgozman 2016/10/04 00:17:02 Out parameters must be passed by pointer.
lushnikov 2016/10/04 01:04:18 Done.
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>;
47 FilePathTimesMap file_path_times_; 50 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;
(...skipping 20 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 GetModificationTimes(path, file_path_times_);
91 }
92
93 void DevToolsFileWatcher::SharedFileWatcher::GetModificationTimes(
94 const base::FilePath& path,
95 FilePathTimesMap& file_path_times) {
87 base::FileEnumerator enumerator(path, true, base::FileEnumerator::FILES); 96 base::FileEnumerator enumerator(path, true, base::FileEnumerator::FILES);
88 base::FilePath file_path = enumerator.Next(); 97 base::FilePath file_path = enumerator.Next();
89 while (!file_path.empty()) { 98 while (!file_path.empty()) {
90 base::FileEnumerator::FileInfo file_info = enumerator.GetInfo(); 99 base::FileEnumerator::FileInfo file_info = enumerator.GetInfo();
91 file_path_times_[file_path] = file_info.GetLastModifiedTime(); 100 file_path_times[file_path] = file_info.GetLastModifiedTime();
92 file_path = enumerator.Next(); 101 file_path = enumerator.Next();
93 } 102 }
94 } 103 }
95 104
96 void DevToolsFileWatcher::SharedFileWatcher::RemoveWatch( 105 void DevToolsFileWatcher::SharedFileWatcher::RemoveWatch(
97 const base::FilePath& path) { 106 const base::FilePath& path) {
98 watchers_.erase(path); 107 watchers_.erase(path);
99 } 108 }
100 109
101 void DevToolsFileWatcher::SharedFileWatcher::DirectoryChanged( 110 void DevToolsFileWatcher::SharedFileWatcher::DirectoryChanged(
(...skipping 12 matching lines...) Expand all
114 last_dispatch_cost_ * 2; 123 last_dispatch_cost_ * 2;
115 124
116 BrowserThread::PostDelayedTask( 125 BrowserThread::PostDelayedTask(
117 BrowserThread::FILE, FROM_HERE, 126 BrowserThread::FILE, FROM_HERE,
118 base::Bind(&DevToolsFileWatcher::SharedFileWatcher::DispatchNotifications, 127 base::Bind(&DevToolsFileWatcher::SharedFileWatcher::DispatchNotifications,
119 this), shedule_for); 128 this), shedule_for);
120 last_event_time_ = now; 129 last_event_time_ = now;
121 } 130 }
122 131
123 void DevToolsFileWatcher::SharedFileWatcher::DispatchNotifications() { 132 void DevToolsFileWatcher::SharedFileWatcher::DispatchNotifications() {
133 if (!pending_paths_.size())
134 return;
124 base::Time start = base::Time::Now(); 135 base::Time start = base::Time::Now();
136 std::vector<std::string> added_paths;
137 std::vector<std::string> removed_paths;
125 std::vector<std::string> changed_paths; 138 std::vector<std::string> changed_paths;
126 for (auto path : pending_paths_) { 139
140 for (auto iterator = file_path_times_.begin();
141 iterator != file_path_times_.end();) {
dgozman 2016/10/04 00:17:02 Looks to be expensive to check all files on any si
lushnikov 2016/10/04 01:04:18 This method is actually throttled, so should be fi
142 if (!base::PathExists(iterator->first)) {
143 removed_paths.push_back(iterator->first.AsUTF8Unsafe());
144 file_path_times_.erase(iterator++);
145 } else {
146 ++iterator;
147 }
148 }
149
150 for (const auto& path : pending_paths_) {
127 base::FileEnumerator enumerator(path, true, base::FileEnumerator::FILES); 151 base::FileEnumerator enumerator(path, true, base::FileEnumerator::FILES);
128 base::FilePath file_path = enumerator.Next(); 152 base::FilePath file_path = enumerator.Next();
129 while (!file_path.empty()) { 153 FilePathTimesMap new_file_times;
130 base::FileEnumerator::FileInfo file_info = enumerator.GetInfo(); 154 GetModificationTimes(path, new_file_times);
131 base::Time new_time = file_info.GetLastModifiedTime(); 155 for (auto it = new_file_times.begin(); it != new_file_times.end(); ++it) {
132 if (file_path_times_[file_path] != new_time) { 156 auto old_timestamp = file_path_times_.find(it->first);
133 file_path_times_[file_path] = new_time; 157 if (old_timestamp == file_path_times_.end()) {
134 changed_paths.push_back(file_path.AsUTF8Unsafe()); 158 file_path_times_[it->first] = it->second;
159 added_paths.push_back(it->first.AsUTF8Unsafe());
160 } else if (old_timestamp->second != it->second) {
161 old_timestamp->second = it->second;
162 changed_paths.push_back(it->first.AsUTF8Unsafe());
135 } 163 }
136 file_path = enumerator.Next();
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