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

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

Issue 1422463007: DevTools: use inotify to pick changes on the filesystem. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: build fix Created 5 years, 1 month 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/devtools/devtools_file_watcher.h"
6
7 #include <map>
8 #include <set>
9
10 #include "base/bind.h"
11 #include "base/files/file_enumerator.h"
12 #include "base/files/file_path.h"
13 #include "base/files/file_path_watcher.h"
14 #include "base/memory/ref_counted.h"
15 #include "content/public/browser/browser_thread.h"
16
17 using content::BrowserThread;
18
19 static int kFirstThrottleTimeout = 10;
20 static int kDefaultThrottleTimeout = 200;
21
22 // DevToolsFileWatcher::SharedFileWatcher --------------------------------------
23
24 class DevToolsFileWatcher::SharedFileWatcher :
25 public base::RefCounted<SharedFileWatcher> {
26 public:
27 SharedFileWatcher();
28
29 void AddListener(DevToolsFileWatcher* watcher);
30 void RemoveListener(DevToolsFileWatcher* watcher);
31 void AddWatch(const base::FilePath& path);
32 void RemoveWatch(const base::FilePath& path);
33
34 private:
35 friend class base::RefCounted<
36 DevToolsFileWatcher::SharedFileWatcher>;
37 ~SharedFileWatcher();
38
39 void DirectoryChanged(const base::FilePath& path, bool error);
40 void DispatchNotifications();
41
42 std::vector<DevToolsFileWatcher*> listeners_;
43 std::map<base::FilePath, scoped_ptr<base::FilePathWatcher>> watchers_;
44 using FilePathTimesMap = std::map<base::FilePath, base::Time>;
45 FilePathTimesMap file_path_times_;
46 std::set<base::FilePath> pending_paths_;
47 base::Time last_event_time_;
48 base::TimeDelta last_dispatch_cost_;
49 };
50
51 DevToolsFileWatcher::SharedFileWatcher::SharedFileWatcher()
52 : last_dispatch_cost_(
53 base::TimeDelta::FromMilliseconds(kDefaultThrottleTimeout)) {
54 DevToolsFileWatcher::s_shared_watcher_ = this;
55 }
56
57 DevToolsFileWatcher::SharedFileWatcher::~SharedFileWatcher() {
58 DevToolsFileWatcher::s_shared_watcher_ = nullptr;
59 }
60
61 void DevToolsFileWatcher::SharedFileWatcher::AddListener(
62 DevToolsFileWatcher* watcher) {
63 listeners_.push_back(watcher);
64 }
65
66 void DevToolsFileWatcher::SharedFileWatcher::RemoveListener(
67 DevToolsFileWatcher* watcher) {
68 auto it = std::find(listeners_.begin(), listeners_.end(), watcher);
69 listeners_.erase(it);
70 }
71
72 void DevToolsFileWatcher::SharedFileWatcher::AddWatch(
73 const base::FilePath& path) {
74 if (watchers_.find(path) != watchers_.end())
75 return;
76 if (!base::FilePathWatcher::RecursiveWatchAvailable())
77 return;
78 watchers_[path].reset(new base::FilePathWatcher());
79 bool success = watchers_[path]->Watch(
80 path, true,
81 base::Bind(&SharedFileWatcher::DirectoryChanged, base::Unretained(this)));
82 if (!success)
83 return;
84
85 base::FileEnumerator enumerator(path, true, base::FileEnumerator::FILES);
86 base::FilePath file_path = enumerator.Next();
87 while (!file_path.empty()) {
88 base::FileEnumerator::FileInfo file_info = enumerator.GetInfo();
89 file_path_times_[file_path] = file_info.GetLastModifiedTime();
90 file_path = enumerator.Next();
91 }
92 }
93
94 void DevToolsFileWatcher::SharedFileWatcher::RemoveWatch(
95 const base::FilePath& path) {
96 watchers_.erase(path);
97 }
98
99 void DevToolsFileWatcher::SharedFileWatcher::DirectoryChanged(
100 const base::FilePath& path,
101 bool error) {
102 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
103 pending_paths_.insert(path);
104 if (pending_paths_.size() > 1)
105 return; // PostDelayedTask is already pending.
106
107 base::Time now = base::Time::Now();
108 // Quickly dispatch first chunk.
109 base::TimeDelta shedule_for =
110 now - last_event_time_ > last_dispatch_cost_ ?
111 base::TimeDelta::FromMilliseconds(kFirstThrottleTimeout) :
112 last_dispatch_cost_ * 2;
113
114 BrowserThread::PostDelayedTask(
115 BrowserThread::FILE, FROM_HERE,
116 base::Bind(&DevToolsFileWatcher::SharedFileWatcher::DispatchNotifications,
117 this), shedule_for);
118 last_event_time_ = now;
119 }
120
121 void DevToolsFileWatcher::SharedFileWatcher::DispatchNotifications() {
122 base::Time start = base::Time::Now();
123 std::vector<std::string> changed_paths;
124 for (auto path : pending_paths_) {
125 base::FileEnumerator enumerator(path, true, base::FileEnumerator::FILES);
126 base::FilePath file_path = enumerator.Next();
127 while (!file_path.empty()) {
128 base::FileEnumerator::FileInfo file_info = enumerator.GetInfo();
129 base::Time new_time = file_info.GetLastModifiedTime();
130 if (file_path_times_[file_path] != new_time) {
131 file_path_times_[file_path] = new_time;
132 changed_paths.push_back(file_path.AsUTF8Unsafe());
133 }
134 file_path = enumerator.Next();
135 }
136 }
137 pending_paths_.clear();
138
139 for (auto watcher : listeners_) {
140 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
141 base::Bind(watcher->callback_, changed_paths));
142 }
143 last_dispatch_cost_ = base::Time::Now() - start;
144 }
145
146 // static
147 DevToolsFileWatcher::SharedFileWatcher*
148 DevToolsFileWatcher::s_shared_watcher_ = nullptr;
149
150 // DevToolsFileWatcher ---------------------------------------------------------
151
152 DevToolsFileWatcher::DevToolsFileWatcher(const WatchCallback& callback)
153 : callback_(callback) {
154 DCHECK_CURRENTLY_ON(BrowserThread::UI);
155 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
156 base::Bind(&DevToolsFileWatcher::InitSharedWatcher,
157 base::Unretained(this)));
158 }
159
160 DevToolsFileWatcher::~DevToolsFileWatcher() {
161 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
162 shared_watcher_->RemoveListener(this);
163 }
164
165 void DevToolsFileWatcher::InitSharedWatcher() {
166 if (!DevToolsFileWatcher::s_shared_watcher_)
167 new SharedFileWatcher();
168 shared_watcher_ = DevToolsFileWatcher::s_shared_watcher_;
169 shared_watcher_->AddListener(this);
170 }
171
172 void DevToolsFileWatcher::AddWatch(const base::FilePath& path) {
173 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
174 shared_watcher_->AddWatch(path);
175 }
176
177 void DevToolsFileWatcher::RemoveWatch(const base::FilePath& path) {
178 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
179 shared_watcher_->RemoveWatch(path);
180 }
OLDNEW
« no previous file with comments | « chrome/browser/devtools/devtools_file_watcher.h ('k') | chrome/browser/devtools/devtools_ui_bindings.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698