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

Side by Side Diff: base/files/file_path_watcher_win.cc

Issue 105293002: Move more file_util functions to base namespace. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years 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 | Annotate | Revision Log
« no previous file with comments | « base/files/file_path_watcher_linux.cc ('k') | base/files/file_util_proxy.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "base/files/file_path_watcher.h" 5 #include "base/files/file_path_watcher.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 HANDLE handle_; 69 HANDLE handle_;
70 70
71 // ObjectWatcher to watch handle_ for events. 71 // ObjectWatcher to watch handle_ for events.
72 base::win::ObjectWatcher watcher_; 72 base::win::ObjectWatcher watcher_;
73 73
74 // Set to true to watch the sub trees of the specified directory file path. 74 // Set to true to watch the sub trees of the specified directory file path.
75 bool recursive_watch_; 75 bool recursive_watch_;
76 76
77 // Keep track of the last modified time of the file. We use nulltime 77 // Keep track of the last modified time of the file. We use nulltime
78 // to represent the file not existing. 78 // to represent the file not existing.
79 base::Time last_modified_; 79 Time last_modified_;
80 80
81 // The time at which we processed the first notification with the 81 // The time at which we processed the first notification with the
82 // |last_modified_| time stamp. 82 // |last_modified_| time stamp.
83 base::Time first_notification_; 83 Time first_notification_;
84 84
85 DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl); 85 DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl);
86 }; 86 };
87 87
88 bool FilePathWatcherImpl::Watch(const FilePath& path, 88 bool FilePathWatcherImpl::Watch(const FilePath& path,
89 bool recursive, 89 bool recursive,
90 const FilePathWatcher::Callback& callback) { 90 const FilePathWatcher::Callback& callback) {
91 DCHECK(target_.value().empty()); // Can only watch one path. 91 DCHECK(target_.value().empty()); // Can only watch one path.
92 92
93 set_message_loop(base::MessageLoopProxy::current()); 93 set_message_loop(MessageLoopProxy::current());
94 callback_ = callback; 94 callback_ = callback;
95 target_ = path; 95 target_ = path;
96 recursive_watch_ = recursive; 96 recursive_watch_ = recursive;
97 MessageLoop::current()->AddDestructionObserver(this); 97 MessageLoop::current()->AddDestructionObserver(this);
98 98
99 if (!UpdateWatch()) 99 if (!UpdateWatch())
100 return false; 100 return false;
101 101
102 watcher_.StartWatching(handle_, this); 102 watcher_.StartWatching(handle_, this);
103 103
104 return true; 104 return true;
105 } 105 }
106 106
107 void FilePathWatcherImpl::Cancel() { 107 void FilePathWatcherImpl::Cancel() {
108 if (callback_.is_null()) { 108 if (callback_.is_null()) {
109 // Watch was never called, or the |message_loop_| has already quit. 109 // Watch was never called, or the |message_loop_| has already quit.
110 set_cancelled(); 110 set_cancelled();
111 return; 111 return;
112 } 112 }
113 113
114 // Switch to the file thread if necessary so we can stop |watcher_|. 114 // Switch to the file thread if necessary so we can stop |watcher_|.
115 if (!message_loop()->BelongsToCurrentThread()) { 115 if (!message_loop()->BelongsToCurrentThread()) {
116 message_loop()->PostTask(FROM_HERE, 116 message_loop()->PostTask(FROM_HERE,
117 base::Bind(&FilePathWatcher::CancelWatch, 117 Bind(&FilePathWatcher::CancelWatch,
118 make_scoped_refptr(this))); 118 make_scoped_refptr(this)));
119 } else { 119 } else {
120 CancelOnMessageLoopThread(); 120 CancelOnMessageLoopThread();
121 } 121 }
122 } 122 }
123 123
124 void FilePathWatcherImpl::CancelOnMessageLoopThread() { 124 void FilePathWatcherImpl::CancelOnMessageLoopThread() {
125 set_cancelled(); 125 set_cancelled();
126 126
127 if (handle_ != INVALID_HANDLE_VALUE) 127 if (handle_ != INVALID_HANDLE_VALUE)
128 DestroyWatch(); 128 DestroyWatch();
(...skipping 12 matching lines...) Expand all
141 DCHECK(object == handle_); 141 DCHECK(object == handle_);
142 // Make sure we stay alive through the body of this function. 142 // Make sure we stay alive through the body of this function.
143 scoped_refptr<FilePathWatcherImpl> keep_alive(this); 143 scoped_refptr<FilePathWatcherImpl> keep_alive(this);
144 144
145 if (!UpdateWatch()) { 145 if (!UpdateWatch()) {
146 callback_.Run(target_, true /* error */); 146 callback_.Run(target_, true /* error */);
147 return; 147 return;
148 } 148 }
149 149
150 // Check whether the event applies to |target_| and notify the callback. 150 // Check whether the event applies to |target_| and notify the callback.
151 base::PlatformFileInfo file_info; 151 PlatformFileInfo file_info;
152 bool file_exists = file_util::GetFileInfo(target_, &file_info); 152 bool file_exists = GetFileInfo(target_, &file_info);
153 if (file_exists && (last_modified_.is_null() || 153 if (file_exists && (last_modified_.is_null() ||
154 last_modified_ != file_info.last_modified)) { 154 last_modified_ != file_info.last_modified)) {
155 last_modified_ = file_info.last_modified; 155 last_modified_ = file_info.last_modified;
156 first_notification_ = base::Time::Now(); 156 first_notification_ = Time::Now();
157 callback_.Run(target_, false); 157 callback_.Run(target_, false);
158 } else if (file_exists && !first_notification_.is_null()) { 158 } else if (file_exists && !first_notification_.is_null()) {
159 // The target's last modification time is equal to what's on record. This 159 // The target's last modification time is equal to what's on record. This
160 // means that either an unrelated event occurred, or the target changed 160 // means that either an unrelated event occurred, or the target changed
161 // again (file modification times only have a resolution of 1s). Comparing 161 // again (file modification times only have a resolution of 1s). Comparing
162 // file modification times against the wall clock is not reliable to find 162 // file modification times against the wall clock is not reliable to find
163 // out whether the change is recent, since this code might just run too 163 // out whether the change is recent, since this code might just run too
164 // late. Moreover, there's no guarantee that file modification time and wall 164 // late. Moreover, there's no guarantee that file modification time and wall
165 // clock times come from the same source. 165 // clock times come from the same source.
166 // 166 //
167 // Instead, the time at which the first notification carrying the current 167 // Instead, the time at which the first notification carrying the current
168 // |last_notified_| time stamp is recorded. Later notifications that find 168 // |last_notified_| time stamp is recorded. Later notifications that find
169 // the same file modification time only need to be forwarded until wall 169 // the same file modification time only need to be forwarded until wall
170 // clock has advanced one second from the initial notification. After that 170 // clock has advanced one second from the initial notification. After that
171 // interval, client code is guaranteed to having seen the current revision 171 // interval, client code is guaranteed to having seen the current revision
172 // of the file. 172 // of the file.
173 if (base::Time::Now() - first_notification_ > 173 if (Time::Now() - first_notification_ > TimeDelta::FromSeconds(1)) {
174 base::TimeDelta::FromSeconds(1)) {
175 // Stop further notifications for this |last_modification_| time stamp. 174 // Stop further notifications for this |last_modification_| time stamp.
176 first_notification_ = base::Time(); 175 first_notification_ = Time();
177 } 176 }
178 callback_.Run(target_, false); 177 callback_.Run(target_, false);
179 } else if (!file_exists && !last_modified_.is_null()) { 178 } else if (!file_exists && !last_modified_.is_null()) {
180 last_modified_ = base::Time(); 179 last_modified_ = Time();
181 callback_.Run(target_, false); 180 callback_.Run(target_, false);
182 } 181 }
183 182
184 // The watch may have been cancelled by the callback. 183 // The watch may have been cancelled by the callback.
185 if (handle_ != INVALID_HANDLE_VALUE) 184 if (handle_ != INVALID_HANDLE_VALUE)
186 watcher_.StartWatching(handle_, this); 185 watcher_.StartWatching(handle_, this);
187 } 186 }
188 187
189 // static 188 // static
190 bool FilePathWatcherImpl::SetupWatchHandle(const FilePath& dir, 189 bool FilePathWatcherImpl::SetupWatchHandle(const FilePath& dir,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 return false; 222 return false;
224 } 223 }
225 224
226 return true; 225 return true;
227 } 226 }
228 227
229 bool FilePathWatcherImpl::UpdateWatch() { 228 bool FilePathWatcherImpl::UpdateWatch() {
230 if (handle_ != INVALID_HANDLE_VALUE) 229 if (handle_ != INVALID_HANDLE_VALUE)
231 DestroyWatch(); 230 DestroyWatch();
232 231
233 base::PlatformFileInfo file_info; 232 PlatformFileInfo file_info;
234 if (file_util::GetFileInfo(target_, &file_info)) { 233 if (GetFileInfo(target_, &file_info)) {
235 last_modified_ = file_info.last_modified; 234 last_modified_ = file_info.last_modified;
236 first_notification_ = base::Time::Now(); 235 first_notification_ = Time::Now();
237 } 236 }
238 237
239 // Start at the target and walk up the directory chain until we succesfully 238 // Start at the target and walk up the directory chain until we succesfully
240 // create a watch handle in |handle_|. |child_dirs| keeps a stack of child 239 // create a watch handle in |handle_|. |child_dirs| keeps a stack of child
241 // directories stripped from target, in reverse order. 240 // directories stripped from target, in reverse order.
242 std::vector<FilePath> child_dirs; 241 std::vector<FilePath> child_dirs;
243 FilePath watched_path(target_); 242 FilePath watched_path(target_);
244 while (true) { 243 while (true) {
245 if (!SetupWatchHandle(watched_path, recursive_watch_, &handle_)) 244 if (!SetupWatchHandle(watched_path, recursive_watch_, &handle_))
246 return false; 245 return false;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 handle_ = INVALID_HANDLE_VALUE; 282 handle_ = INVALID_HANDLE_VALUE;
284 } 283 }
285 284
286 } // namespace 285 } // namespace
287 286
288 FilePathWatcher::FilePathWatcher() { 287 FilePathWatcher::FilePathWatcher() {
289 impl_ = new FilePathWatcherImpl(); 288 impl_ = new FilePathWatcherImpl();
290 } 289 }
291 290
292 } // namespace base 291 } // namespace base
OLDNEW
« no previous file with comments | « base/files/file_path_watcher_linux.cc ('k') | base/files/file_util_proxy.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698