| 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 |