OLD | NEW |
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 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/greasemonkey_master.h" | 5 #include "chrome/browser/extensions/user_script_master.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/file_path.h" | 9 #include "base/file_path.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
13 #include "base/path_service.h" | 13 #include "base/path_service.h" |
14 #include "base/pickle.h" | 14 #include "base/pickle.h" |
15 #include "base/string_util.h" | 15 #include "base/string_util.h" |
16 #include "chrome/common/notification_service.h" | 16 #include "chrome/common/notification_service.h" |
17 #include "googleurl/src/gurl.h" | 17 #include "googleurl/src/gurl.h" |
18 #include "net/base/net_util.h" | 18 #include "net/base/net_util.h" |
19 | 19 |
20 // We reload user scripts on the file thread to prevent blocking the UI. | 20 // We reload user scripts on the file thread to prevent blocking the UI. |
21 // ScriptReloader lives on the file thread and does the reload | 21 // ScriptReloader lives on the file thread and does the reload |
22 // work, and then sends a message back to its master with a new SharedMemory*. | 22 // work, and then sends a message back to its master with a new SharedMemory*. |
23 | 23 |
24 // ScriptReloader is the worker that manages running the script scan | 24 // ScriptReloader is the worker that manages running the script scan |
25 // on the file thread. | 25 // on the file thread. |
26 // It must be created on, and its public API must only be called from, | 26 // It must be created on, and its public API must only be called from, |
27 // the master's thread. | 27 // the master's thread. |
28 class GreasemonkeyMaster::ScriptReloader | 28 class UserScriptMaster::ScriptReloader |
29 : public base::RefCounted<GreasemonkeyMaster::ScriptReloader> { | 29 : public base::RefCounted<UserScriptMaster::ScriptReloader> { |
30 public: | 30 public: |
31 ScriptReloader(GreasemonkeyMaster* master) | 31 ScriptReloader(UserScriptMaster* master) |
32 : master_(master), master_message_loop_(MessageLoop::current()) {} | 32 : master_(master), master_message_loop_(MessageLoop::current()) {} |
33 | 33 |
34 // Start a scan for scripts. | 34 // Start a scan for scripts. |
35 // Will always send a message to the master upon completion. | 35 // Will always send a message to the master upon completion. |
36 void StartScan(MessageLoop* work_loop, const FilePath& script_dir); | 36 void StartScan(MessageLoop* work_loop, const FilePath& script_dir); |
37 | 37 |
38 // The master is going away; don't call it back. | 38 // The master is going away; don't call it back. |
39 void DisownMaster() { | 39 void DisownMaster() { |
40 master_ = NULL; | 40 master_ = NULL; |
41 } | 41 } |
(...skipping 15 matching lines...) Expand all Loading... |
57 // to the caller. | 57 // to the caller. |
58 void RunScan(const FilePath script_dir); | 58 void RunScan(const FilePath script_dir); |
59 | 59 |
60 // Runs on the File thread. | 60 // Runs on the File thread. |
61 // Scan the script directory for scripts, returning either a new SharedMemory | 61 // Scan the script directory for scripts, returning either a new SharedMemory |
62 // or NULL on error. | 62 // or NULL on error. |
63 base::SharedMemory* GetNewScripts(const FilePath& script_dir); | 63 base::SharedMemory* GetNewScripts(const FilePath& script_dir); |
64 | 64 |
65 // A pointer back to our master. | 65 // A pointer back to our master. |
66 // May be NULL if DisownMaster() is called. | 66 // May be NULL if DisownMaster() is called. |
67 GreasemonkeyMaster* master_; | 67 UserScriptMaster* master_; |
68 | 68 |
69 // The message loop to call our master back on. | 69 // The message loop to call our master back on. |
70 // Expected to always outlive us. | 70 // Expected to always outlive us. |
71 MessageLoop* master_message_loop_; | 71 MessageLoop* master_message_loop_; |
72 | 72 |
73 DISALLOW_COPY_AND_ASSIGN(ScriptReloader); | 73 DISALLOW_COPY_AND_ASSIGN(ScriptReloader); |
74 }; | 74 }; |
75 | 75 |
76 void GreasemonkeyMaster::ScriptReloader::StartScan( | 76 void UserScriptMaster::ScriptReloader::StartScan( |
77 MessageLoop* work_loop, | 77 MessageLoop* work_loop, |
78 const FilePath& script_dir) { | 78 const FilePath& script_dir) { |
79 // Add a reference to ourselves to keep ourselves alive while we're running. | 79 // Add a reference to ourselves to keep ourselves alive while we're running. |
80 // Balanced by NotifyMaster(). | 80 // Balanced by NotifyMaster(). |
81 AddRef(); | 81 AddRef(); |
82 work_loop->PostTask(FROM_HERE, | 82 work_loop->PostTask(FROM_HERE, |
83 NewRunnableMethod(this, | 83 NewRunnableMethod(this, |
84 &GreasemonkeyMaster::ScriptReloader::RunScan, | 84 &UserScriptMaster::ScriptReloader::RunScan, |
85 script_dir)); | 85 script_dir)); |
86 } | 86 } |
87 | 87 |
88 void GreasemonkeyMaster::ScriptReloader::NotifyMaster( | 88 void UserScriptMaster::ScriptReloader::NotifyMaster( |
89 base::SharedMemory* memory) { | 89 base::SharedMemory* memory) { |
90 if (!master_) { | 90 if (!master_) { |
91 // The master went away, so these new scripts aren't useful anymore. | 91 // The master went away, so these new scripts aren't useful anymore. |
92 delete memory; | 92 delete memory; |
93 } else { | 93 } else { |
94 master_->NewScriptsAvailable(memory); | 94 master_->NewScriptsAvailable(memory); |
95 } | 95 } |
96 | 96 |
97 // Drop our self-reference. | 97 // Drop our self-reference. |
98 // Balances StartScan(). | 98 // Balances StartScan(). |
99 Release(); | 99 Release(); |
100 } | 100 } |
101 | 101 |
102 void GreasemonkeyMaster::ScriptReloader::RunScan(const FilePath script_dir) { | 102 void UserScriptMaster::ScriptReloader::RunScan(const FilePath script_dir) { |
103 base::SharedMemory* shared_memory = GetNewScripts(script_dir); | 103 base::SharedMemory* shared_memory = GetNewScripts(script_dir); |
104 | 104 |
105 // Post the new scripts back to the master's message loop. | 105 // Post the new scripts back to the master's message loop. |
106 master_message_loop_->PostTask(FROM_HERE, | 106 master_message_loop_->PostTask(FROM_HERE, |
107 NewRunnableMethod(this, | 107 NewRunnableMethod(this, |
108 &GreasemonkeyMaster::ScriptReloader::NotifyMaster, | 108 &UserScriptMaster::ScriptReloader::NotifyMaster, |
109 shared_memory)); | 109 shared_memory)); |
110 } | 110 } |
111 | 111 |
112 base::SharedMemory* GreasemonkeyMaster::ScriptReloader::GetNewScripts( | 112 base::SharedMemory* UserScriptMaster::ScriptReloader::GetNewScripts( |
113 const FilePath& script_dir) { | 113 const FilePath& script_dir) { |
114 std::vector<std::wstring> scripts; | 114 std::vector<std::wstring> scripts; |
115 | 115 |
116 file_util::FileEnumerator enumerator(script_dir, false, | 116 file_util::FileEnumerator enumerator(script_dir, false, |
117 file_util::FileEnumerator::FILES, | 117 file_util::FileEnumerator::FILES, |
118 FILE_PATH_LITERAL("*.user.js")); | 118 FILE_PATH_LITERAL("*.user.js")); |
119 for (FilePath file = enumerator.Next(); !file.value().empty(); | 119 for (FilePath file = enumerator.Next(); !file.value().empty(); |
120 file = enumerator.Next()) { | 120 file = enumerator.Next()) { |
121 scripts.push_back(file.ToWStringHack()); | 121 scripts.push_back(file.ToWStringHack()); |
122 } | 122 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 if (!shared_memory->Map(pickle.size())) | 154 if (!shared_memory->Map(pickle.size())) |
155 return NULL; | 155 return NULL; |
156 | 156 |
157 // Copy the pickle to shared memory. | 157 // Copy the pickle to shared memory. |
158 memcpy(shared_memory->memory(), pickle.data(), pickle.size()); | 158 memcpy(shared_memory->memory(), pickle.data(), pickle.size()); |
159 | 159 |
160 return shared_memory.release(); | 160 return shared_memory.release(); |
161 } | 161 } |
162 | 162 |
163 | 163 |
164 GreasemonkeyMaster::GreasemonkeyMaster(MessageLoop* worker_loop, | 164 UserScriptMaster::UserScriptMaster(MessageLoop* worker_loop, |
165 const FilePath& script_dir) | 165 const FilePath& script_dir) |
166 : user_script_dir_(new FilePath(script_dir)), | 166 : user_script_dir_(new FilePath(script_dir)), |
167 dir_watcher_(new DirectoryWatcher), | 167 dir_watcher_(new DirectoryWatcher), |
168 worker_loop_(worker_loop), | 168 worker_loop_(worker_loop), |
169 pending_scan_(false) { | 169 pending_scan_(false) { |
170 // Watch our scripts directory for modifications. | 170 // Watch our scripts directory for modifications. |
171 if (dir_watcher_->Watch(script_dir, this)) { | 171 if (dir_watcher_->Watch(script_dir, this)) { |
172 // (Asynchronously) scan for our initial set of scripts. | 172 // (Asynchronously) scan for our initial set of scripts. |
173 StartScan(); | 173 StartScan(); |
174 } | 174 } |
175 } | 175 } |
176 | 176 |
177 GreasemonkeyMaster::~GreasemonkeyMaster() { | 177 UserScriptMaster::~UserScriptMaster() { |
178 if (script_reloader_) | 178 if (script_reloader_) |
179 script_reloader_->DisownMaster(); | 179 script_reloader_->DisownMaster(); |
180 } | 180 } |
181 | 181 |
182 void GreasemonkeyMaster::NewScriptsAvailable(base::SharedMemory* handle) { | 182 void UserScriptMaster::NewScriptsAvailable(base::SharedMemory* handle) { |
183 // Ensure handle is deleted or released. | 183 // Ensure handle is deleted or released. |
184 scoped_ptr<base::SharedMemory> handle_deleter(handle); | 184 scoped_ptr<base::SharedMemory> handle_deleter(handle); |
185 | 185 |
186 if (pending_scan_) { | 186 if (pending_scan_) { |
187 // While we were scanning, there were further changes. Don't bother | 187 // While we were scanning, there were further changes. Don't bother |
188 // notifying about these scripts and instead just immediately rescan. | 188 // notifying about these scripts and instead just immediately rescan. |
189 pending_scan_ = false; | 189 pending_scan_ = false; |
190 StartScan(); | 190 StartScan(); |
191 } else { | 191 } else { |
192 // We're no longer scanning. | 192 // We're no longer scanning. |
193 script_reloader_ = NULL; | 193 script_reloader_ = NULL; |
194 // We've got scripts ready to go. | 194 // We've got scripts ready to go. |
195 shared_memory_.swap(handle_deleter); | 195 shared_memory_.swap(handle_deleter); |
196 | 196 |
197 NotificationService::current()->Notify(NOTIFY_GREASEMONKEY_SCRIPTS_LOADED, | 197 NotificationService::current()->Notify(NOTIFY_USER_SCRIPTS_LOADED, |
198 NotificationService::AllSources(), | 198 NotificationService::AllSources(), |
199 Details<base::SharedMemory>(handle)); | 199 Details<base::SharedMemory>(handle)); |
200 } | 200 } |
201 } | 201 } |
202 | 202 |
203 void GreasemonkeyMaster::OnDirectoryChanged(const FilePath& path) { | 203 void UserScriptMaster::OnDirectoryChanged(const FilePath& path) { |
204 if (script_reloader_.get()) { | 204 if (script_reloader_.get()) { |
205 // We're already scanning for scripts. We note that we should rescan when | 205 // We're already scanning for scripts. We note that we should rescan when |
206 // we get the chance. | 206 // we get the chance. |
207 pending_scan_ = true; | 207 pending_scan_ = true; |
208 return; | 208 return; |
209 } | 209 } |
210 | 210 |
211 StartScan(); | 211 StartScan(); |
212 } | 212 } |
213 | 213 |
214 void GreasemonkeyMaster::StartScan() { | 214 void UserScriptMaster::StartScan() { |
215 if (!script_reloader_) | 215 if (!script_reloader_) |
216 script_reloader_ = new ScriptReloader(this); | 216 script_reloader_ = new ScriptReloader(this); |
217 | 217 |
218 script_reloader_->StartScan(worker_loop_, *user_script_dir_); | 218 script_reloader_->StartScan(worker_loop_, *user_script_dir_); |
219 } | 219 } |
OLD | NEW |