| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/drive/file_write_watcher.h" | 5 #include "chrome/browser/chromeos/drive/file_write_watcher.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 | 73 |
| 74 // Note: This should remain the last member so it'll be destroyed and | 74 // Note: This should remain the last member so it'll be destroyed and |
| 75 // invalidate its weak pointers before any other members are destroyed. | 75 // invalidate its weak pointers before any other members are destroyed. |
| 76 base::WeakPtrFactory<FileWriteWatcherImpl> weak_ptr_factory_; | 76 base::WeakPtrFactory<FileWriteWatcherImpl> weak_ptr_factory_; |
| 77 DISALLOW_COPY_AND_ASSIGN(FileWriteWatcherImpl); | 77 DISALLOW_COPY_AND_ASSIGN(FileWriteWatcherImpl); |
| 78 }; | 78 }; |
| 79 | 79 |
| 80 FileWriteWatcher::FileWriteWatcherImpl::FileWriteWatcherImpl() | 80 FileWriteWatcher::FileWriteWatcherImpl::FileWriteWatcherImpl() |
| 81 : delay_(base::TimeDelta::FromSeconds(kWriteEventDelayInSeconds)), | 81 : delay_(base::TimeDelta::FromSeconds(kWriteEventDelayInSeconds)), |
| 82 weak_ptr_factory_(this) { | 82 weak_ptr_factory_(this) { |
| 83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 83 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 84 } | 84 } |
| 85 | 85 |
| 86 void FileWriteWatcher::FileWriteWatcherImpl::Destroy() { | 86 void FileWriteWatcher::FileWriteWatcherImpl::Destroy() { |
| 87 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 87 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 88 | 88 |
| 89 // Just forwarding the call to FILE thread. | 89 // Just forwarding the call to FILE thread. |
| 90 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)->PostTask( | 90 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)->PostTask( |
| 91 FROM_HERE, | 91 FROM_HERE, |
| 92 base::Bind(&FileWriteWatcherImpl::DestroyOnFileThread, | 92 base::Bind(&FileWriteWatcherImpl::DestroyOnFileThread, |
| 93 base::Unretained(this))); | 93 base::Unretained(this))); |
| 94 } | 94 } |
| 95 | 95 |
| 96 void FileWriteWatcher::FileWriteWatcherImpl::StartWatch( | 96 void FileWriteWatcher::FileWriteWatcherImpl::StartWatch( |
| 97 const base::FilePath& path, | 97 const base::FilePath& path, |
| 98 const StartWatchCallback& on_start_callback, | 98 const StartWatchCallback& on_start_callback, |
| 99 const base::Closure& on_write_callback) { | 99 const base::Closure& on_write_callback) { |
| 100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 100 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 101 | 101 |
| 102 // Forwarding the call to FILE thread and relaying the |callback|. | 102 // Forwarding the call to FILE thread and relaying the |callback|. |
| 103 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)->PostTask( | 103 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)->PostTask( |
| 104 FROM_HERE, | 104 FROM_HERE, |
| 105 base::Bind(&FileWriteWatcherImpl::StartWatchOnFileThread, | 105 base::Bind(&FileWriteWatcherImpl::StartWatchOnFileThread, |
| 106 base::Unretained(this), | 106 base::Unretained(this), |
| 107 path, | 107 path, |
| 108 google_apis::CreateRelayCallback(on_start_callback), | 108 google_apis::CreateRelayCallback(on_start_callback), |
| 109 google_apis::CreateRelayCallback(on_write_callback))); | 109 google_apis::CreateRelayCallback(on_write_callback))); |
| 110 } | 110 } |
| 111 | 111 |
| 112 FileWriteWatcher::FileWriteWatcherImpl::~FileWriteWatcherImpl() { | 112 FileWriteWatcher::FileWriteWatcherImpl::~FileWriteWatcherImpl() { |
| 113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 113 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 114 | 114 |
| 115 STLDeleteContainerPairSecondPointers(watchers_.begin(), watchers_.end()); | 115 STLDeleteContainerPairSecondPointers(watchers_.begin(), watchers_.end()); |
| 116 } | 116 } |
| 117 | 117 |
| 118 void FileWriteWatcher::FileWriteWatcherImpl::DestroyOnFileThread() { | 118 void FileWriteWatcher::FileWriteWatcherImpl::DestroyOnFileThread() { |
| 119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 119 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 120 | 120 |
| 121 delete this; | 121 delete this; |
| 122 } | 122 } |
| 123 | 123 |
| 124 void FileWriteWatcher::FileWriteWatcherImpl::StartWatchOnFileThread( | 124 void FileWriteWatcher::FileWriteWatcherImpl::StartWatchOnFileThread( |
| 125 const base::FilePath& path, | 125 const base::FilePath& path, |
| 126 const StartWatchCallback& on_start_callback, | 126 const StartWatchCallback& on_start_callback, |
| 127 const base::Closure& on_write_callback) { | 127 const base::Closure& on_write_callback) { |
| 128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 128 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 129 | 129 |
| 130 std::map<base::FilePath, PathWatchInfo*>::iterator it = watchers_.find(path); | 130 std::map<base::FilePath, PathWatchInfo*>::iterator it = watchers_.find(path); |
| 131 if (it != watchers_.end()) { | 131 if (it != watchers_.end()) { |
| 132 // We are already watching the path. | 132 // We are already watching the path. |
| 133 on_start_callback.Run(true); | 133 on_start_callback.Run(true); |
| 134 it->second->on_write_callbacks.push_back(on_write_callback); | 134 it->second->on_write_callbacks.push_back(on_write_callback); |
| 135 return; | 135 return; |
| 136 } | 136 } |
| 137 | 137 |
| 138 // Start watching |path|. | 138 // Start watching |path|. |
| 139 scoped_ptr<PathWatchInfo> info(new PathWatchInfo(on_write_callback)); | 139 scoped_ptr<PathWatchInfo> info(new PathWatchInfo(on_write_callback)); |
| 140 bool ok = info->watcher.Watch( | 140 bool ok = info->watcher.Watch( |
| 141 path, | 141 path, |
| 142 false, // recursive | 142 false, // recursive |
| 143 base::Bind(&FileWriteWatcherImpl::OnWriteEvent, | 143 base::Bind(&FileWriteWatcherImpl::OnWriteEvent, |
| 144 weak_ptr_factory_.GetWeakPtr())); | 144 weak_ptr_factory_.GetWeakPtr())); |
| 145 watchers_[path] = info.release(); | 145 watchers_[path] = info.release(); |
| 146 on_start_callback.Run(ok); | 146 on_start_callback.Run(ok); |
| 147 } | 147 } |
| 148 | 148 |
| 149 void FileWriteWatcher::FileWriteWatcherImpl::OnWriteEvent( | 149 void FileWriteWatcher::FileWriteWatcherImpl::OnWriteEvent( |
| 150 const base::FilePath& path, | 150 const base::FilePath& path, |
| 151 bool error) { | 151 bool error) { |
| 152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 152 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 153 | 153 |
| 154 if (error) | 154 if (error) |
| 155 return; | 155 return; |
| 156 | 156 |
| 157 std::map<base::FilePath, PathWatchInfo*>::iterator it = watchers_.find(path); | 157 std::map<base::FilePath, PathWatchInfo*>::iterator it = watchers_.find(path); |
| 158 DCHECK(it != watchers_.end()); | 158 DCHECK(it != watchers_.end()); |
| 159 | 159 |
| 160 // Heuristics for detecting the end of successive write operations. | 160 // Heuristics for detecting the end of successive write operations. |
| 161 // Delay running on_write_event_callback by |delay_| time, and if OnWriteEvent | 161 // Delay running on_write_event_callback by |delay_| time, and if OnWriteEvent |
| 162 // is called again in the period, the timer is reset. In other words, we | 162 // is called again in the period, the timer is reset. In other words, we |
| 163 // invoke callback when |delay_| has passed after the last OnWriteEvent(). | 163 // invoke callback when |delay_| has passed after the last OnWriteEvent(). |
| 164 it->second->timer.Start(FROM_HERE, | 164 it->second->timer.Start(FROM_HERE, |
| 165 delay_, | 165 delay_, |
| 166 base::Bind(&FileWriteWatcherImpl::InvokeCallback, | 166 base::Bind(&FileWriteWatcherImpl::InvokeCallback, |
| 167 weak_ptr_factory_.GetWeakPtr(), | 167 weak_ptr_factory_.GetWeakPtr(), |
| 168 path)); | 168 path)); |
| 169 } | 169 } |
| 170 | 170 |
| 171 void FileWriteWatcher::FileWriteWatcherImpl::InvokeCallback( | 171 void FileWriteWatcher::FileWriteWatcherImpl::InvokeCallback( |
| 172 const base::FilePath& path) { | 172 const base::FilePath& path) { |
| 173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 173 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 174 | 174 |
| 175 std::map<base::FilePath, PathWatchInfo*>::iterator it = watchers_.find(path); | 175 std::map<base::FilePath, PathWatchInfo*>::iterator it = watchers_.find(path); |
| 176 DCHECK(it != watchers_.end()); | 176 DCHECK(it != watchers_.end()); |
| 177 | 177 |
| 178 std::vector<base::Closure> callbacks; | 178 std::vector<base::Closure> callbacks; |
| 179 callbacks.swap(it->second->on_write_callbacks); | 179 callbacks.swap(it->second->on_write_callbacks); |
| 180 delete it->second; | 180 delete it->second; |
| 181 watchers_.erase(it); | 181 watchers_.erase(it); |
| 182 | 182 |
| 183 for (size_t i = 0; i < callbacks.size(); ++i) | 183 for (size_t i = 0; i < callbacks.size(); ++i) |
| 184 callbacks[i].Run(); | 184 callbacks[i].Run(); |
| 185 } | 185 } |
| 186 | 186 |
| 187 FileWriteWatcher::FileWriteWatcher() | 187 FileWriteWatcher::FileWriteWatcher() |
| 188 : watcher_impl_(new FileWriteWatcherImpl) { | 188 : watcher_impl_(new FileWriteWatcherImpl) { |
| 189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 189 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 190 } | 190 } |
| 191 | 191 |
| 192 FileWriteWatcher::~FileWriteWatcher() { | 192 FileWriteWatcher::~FileWriteWatcher() { |
| 193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 193 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 194 } | 194 } |
| 195 | 195 |
| 196 void FileWriteWatcher::StartWatch(const base::FilePath& file_path, | 196 void FileWriteWatcher::StartWatch(const base::FilePath& file_path, |
| 197 const StartWatchCallback& on_start_callback, | 197 const StartWatchCallback& on_start_callback, |
| 198 const base::Closure& on_write_callback) { | 198 const base::Closure& on_write_callback) { |
| 199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 199 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 200 watcher_impl_->StartWatch(file_path, on_start_callback, on_write_callback); | 200 watcher_impl_->StartWatch(file_path, on_start_callback, on_write_callback); |
| 201 } | 201 } |
| 202 | 202 |
| 203 void FileWriteWatcher::DisableDelayForTesting() { | 203 void FileWriteWatcher::DisableDelayForTesting() { |
| 204 watcher_impl_->set_delay(base::TimeDelta()); | 204 watcher_impl_->set_delay(base::TimeDelta()); |
| 205 } | 205 } |
| 206 | 206 |
| 207 } // namespace internal | 207 } // namespace internal |
| 208 } // namespace drive | 208 } // namespace drive |
| OLD | NEW |