OLD | NEW |
---|---|
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 "chrome/browser/extensions/user_script_master.h" | 5 #include "chrome/browser/extensions/user_script_master.h" |
6 | 6 |
7 #include <map> | |
7 #include <string> | 8 #include <string> |
8 #include <vector> | 9 #include <vector> |
9 | 10 |
10 #include "base/file_path.h" | 11 #include "base/file_path.h" |
11 #include "base/file_util.h" | 12 #include "base/file_util.h" |
12 #include "base/pickle.h" | 13 #include "base/pickle.h" |
13 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
14 #include "base/string_util.h" | 15 #include "base/string_util.h" |
15 #include "base/threading/thread.h" | 16 #include "base/threading/thread.h" |
16 #include "base/version.h" | 17 #include "base/version.h" |
17 #include "chrome/browser/extensions/extension_service.h" | 18 #include "chrome/browser/extensions/extension_service.h" |
18 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
19 #include "chrome/common/chrome_notification_types.h" | 20 #include "chrome/common/chrome_notification_types.h" |
20 #include "chrome/common/extensions/extension.h" | 21 #include "chrome/common/extensions/extension.h" |
21 #include "chrome/common/extensions/extension_messages.h" | 22 #include "chrome/common/extensions/extension_file_util.h" |
23 #include "chrome/common/extensions/extension_message_bundle.h" | |
22 #include "chrome/common/extensions/extension_resource.h" | 24 #include "chrome/common/extensions/extension_resource.h" |
25 #include "chrome/common/extensions/extension_set.h" | |
23 #include "content/browser/renderer_host/render_process_host.h" | 26 #include "content/browser/renderer_host/render_process_host.h" |
24 #include "content/common/notification_service.h" | 27 #include "content/common/notification_service.h" |
25 | 28 |
26 // Helper function to parse greasesmonkey headers | 29 // Helper function to parse greasesmonkey headers |
27 static bool GetDeclarationValue(const base::StringPiece& line, | 30 static bool GetDeclarationValue(const base::StringPiece& line, |
28 const base::StringPiece& prefix, | 31 const base::StringPiece& prefix, |
29 std::string* value) { | 32 std::string* value) { |
30 base::StringPiece::size_type index = line.find(prefix); | 33 base::StringPiece::size_type index = line.find(prefix); |
31 if (index == base::StringPiece::npos) | 34 if (index == base::StringPiece::npos) |
32 return false; | 35 return false; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
134 script->add_glob("*"); | 137 script->add_glob("*"); |
135 | 138 |
136 return true; | 139 return true; |
137 } | 140 } |
138 | 141 |
139 void UserScriptMaster::ScriptReloader::StartLoad( | 142 void UserScriptMaster::ScriptReloader::StartLoad( |
140 const UserScriptList& user_scripts) { | 143 const UserScriptList& user_scripts) { |
141 // Add a reference to ourselves to keep ourselves alive while we're running. | 144 // Add a reference to ourselves to keep ourselves alive while we're running. |
142 // Balanced by NotifyMaster(). | 145 // Balanced by NotifyMaster(). |
143 AddRef(); | 146 AddRef(); |
147 | |
148 const ExtensionInfoMap* info_map = NULL; | |
149 // Gather extensions information needed for localization. | |
150 if (master_ && master_->profile_ && | |
151 master_->profile_->GetExtensionInfoMap()) { | |
152 info_map = master_->profile_->GetExtensionInfoMap(); | |
153 // Add a reference to the info_map to keep it alive while we're in the IO | |
154 // thread iterating through the available extensions set. | |
155 // Balanced by GatherExtensionsInfo(). | |
156 info_map->AddRef(); | |
157 } | |
144 BrowserThread::PostTask( | 158 BrowserThread::PostTask( |
145 BrowserThread::FILE, FROM_HERE, | 159 BrowserThread::IO, FROM_HERE, |
146 NewRunnableMethod( | 160 NewRunnableMethod( |
147 this, &UserScriptMaster::ScriptReloader::RunLoad, user_scripts)); | 161 this, &UserScriptMaster::ScriptReloader::GatherExtensionsInfo, |
162 info_map, user_scripts)); | |
148 } | 163 } |
149 | 164 |
165 | |
150 void UserScriptMaster::ScriptReloader::NotifyMaster( | 166 void UserScriptMaster::ScriptReloader::NotifyMaster( |
151 base::SharedMemory* memory) { | 167 base::SharedMemory* memory) { |
152 // The master went away, so these new scripts aren't useful anymore. | 168 // The master went away, so these new scripts aren't useful anymore. |
153 if (!master_) | 169 if (!master_) |
154 delete memory; | 170 delete memory; |
155 else | 171 else |
156 master_->NewScriptsAvailable(memory); | 172 master_->NewScriptsAvailable(memory); |
157 | 173 |
158 // Drop our self-reference. | 174 // Drop our self-reference. |
159 // Balances StartLoad(). | 175 // Balances StartLoad(). |
160 Release(); | 176 Release(); |
161 } | 177 } |
162 | 178 |
163 static bool LoadScriptContent(UserScript::File* script_file) { | 179 static bool LoadScriptContent(UserScript::File* script_file, |
180 const SubstitutionMap* localization_messages) { | |
164 std::string content; | 181 std::string content; |
165 const FilePath& path = ExtensionResource::GetFilePath( | 182 const FilePath& path = ExtensionResource::GetFilePath( |
166 script_file->extension_root(), script_file->relative_path()); | 183 script_file->extension_root(), script_file->relative_path()); |
167 if (path.empty()) { | 184 if (path.empty()) { |
168 LOG(WARNING) << "Failed to get file path to " | 185 LOG(WARNING) << "Failed to get file path to " |
169 << script_file->relative_path().value() << " from " | 186 << script_file->relative_path().value() << " from " |
170 << script_file->extension_root().value(); | 187 << script_file->extension_root().value(); |
171 return false; | 188 return false; |
172 } | 189 } |
173 if (!file_util::ReadFileToString(path, &content)) { | 190 if (!file_util::ReadFileToString(path, &content)) { |
174 LOG(WARNING) << "Failed to load user script file: " << path.value(); | 191 LOG(WARNING) << "Failed to load user script file: " << path.value(); |
175 return false; | 192 return false; |
176 } | 193 } |
177 | 194 |
195 // Localize the content. | |
196 if (localization_messages) { | |
197 std::string error; | |
198 ExtensionMessageBundle::ReplaceMessagesWithExternalDictionary( | |
199 *localization_messages, &content, &error); | |
200 if (!error.empty()) { | |
201 LOG(WARNING) << "Failed to replace messages in script: " << error; | |
202 } | |
203 } | |
204 | |
178 // Remove BOM from the content. | 205 // Remove BOM from the content. |
179 std::string::size_type index = content.find(kUtf8ByteOrderMark); | 206 std::string::size_type index = content.find(kUtf8ByteOrderMark); |
180 if (index == 0) { | 207 if (index == 0) { |
181 script_file->set_content(content.substr(strlen(kUtf8ByteOrderMark))); | 208 script_file->set_content(content.substr(strlen(kUtf8ByteOrderMark))); |
182 } else { | 209 } else { |
183 script_file->set_content(content); | 210 script_file->set_content(content); |
184 } | 211 } |
185 | 212 |
186 return true; | 213 return true; |
187 } | 214 } |
188 | 215 |
189 // static | |
190 void UserScriptMaster::ScriptReloader::LoadUserScripts( | 216 void UserScriptMaster::ScriptReloader::LoadUserScripts( |
191 UserScriptList* user_scripts) { | 217 UserScriptList* user_scripts) { |
192 for (size_t i = 0; i < user_scripts->size(); ++i) { | 218 for (size_t i = 0; i < user_scripts->size(); ++i) { |
193 UserScript& script = user_scripts->at(i); | 219 UserScript& script = user_scripts->at(i); |
220 scoped_ptr<SubstitutionMap> localization_messages( | |
221 GetLocalizationMessages(script.extension_id())); | |
194 for (size_t k = 0; k < script.js_scripts().size(); ++k) { | 222 for (size_t k = 0; k < script.js_scripts().size(); ++k) { |
195 UserScript::File& script_file = script.js_scripts()[k]; | 223 UserScript::File& script_file = script.js_scripts()[k]; |
196 if (script_file.GetContent().empty()) | 224 if (script_file.GetContent().empty()) |
197 LoadScriptContent(&script_file); | 225 LoadScriptContent(&script_file, NULL); |
198 } | 226 } |
199 for (size_t k = 0; k < script.css_scripts().size(); ++k) { | 227 for (size_t k = 0; k < script.css_scripts().size(); ++k) { |
200 UserScript::File& script_file = script.css_scripts()[k]; | 228 UserScript::File& script_file = script.css_scripts()[k]; |
201 if (script_file.GetContent().empty()) | 229 if (script_file.GetContent().empty()) |
202 LoadScriptContent(&script_file); | 230 LoadScriptContent(&script_file, localization_messages.get()); |
203 } | 231 } |
204 } | 232 } |
205 } | 233 } |
206 | 234 |
235 SubstitutionMap* UserScriptMaster::ScriptReloader::GetLocalizationMessages( | |
236 std::string extension_id) { | |
237 if (extensions_info_.find(extension_id) == extensions_info_.end()) { | |
238 return NULL; | |
239 } | |
240 | |
241 return extension_file_util::LoadExtensionMessageBundleSubstitutionMap( | |
242 extensions_info_[extension_id].first, | |
243 extension_id, | |
244 extensions_info_[extension_id].second); | |
245 } | |
246 | |
207 // Pickle user scripts and return pointer to the shared memory. | 247 // Pickle user scripts and return pointer to the shared memory. |
208 static base::SharedMemory* Serialize(const UserScriptList& scripts) { | 248 static base::SharedMemory* Serialize(const UserScriptList& scripts) { |
209 Pickle pickle; | 249 Pickle pickle; |
210 pickle.WriteSize(scripts.size()); | 250 pickle.WriteSize(scripts.size()); |
211 for (size_t i = 0; i < scripts.size(); i++) { | 251 for (size_t i = 0; i < scripts.size(); i++) { |
212 const UserScript& script = scripts[i]; | 252 const UserScript& script = scripts[i]; |
213 // TODO(aa): This can be replaced by sending content script metadata to | 253 // TODO(aa): This can be replaced by sending content script metadata to |
214 // renderers along with other extension data in ExtensionMsg_Loaded. | 254 // renderers along with other extension data in ExtensionMsg_Loaded. |
215 // See crbug.com/70516. | 255 // See crbug.com/70516. |
216 script.Pickle(&pickle); | 256 script.Pickle(&pickle); |
(...skipping 14 matching lines...) Expand all Loading... | |
231 | 271 |
232 if (!shared_memory->CreateAndMapAnonymous(pickle.size())) | 272 if (!shared_memory->CreateAndMapAnonymous(pickle.size())) |
233 return NULL; | 273 return NULL; |
234 | 274 |
235 // Copy the pickle to shared memory. | 275 // Copy the pickle to shared memory. |
236 memcpy(shared_memory->memory(), pickle.data(), pickle.size()); | 276 memcpy(shared_memory->memory(), pickle.data(), pickle.size()); |
237 | 277 |
238 return shared_memory.release(); | 278 return shared_memory.release(); |
239 } | 279 } |
240 | 280 |
281 // This method will be called on the IO thread | |
282 void UserScriptMaster::ScriptReloader::GatherExtensionsInfo( | |
Nebojša Ćirić
2011/08/19 22:02:25
Maybe:
CollectExtensionsInfo, GetExtensionsInfo?
| |
283 const ExtensionInfoMap* const info_map, | |
284 const UserScriptList& user_scripts) { | |
285 if (info_map) { | |
286 info_map->extensions().GetExtensionsPathAndDefaultLocale(&extensions_info_); | |
287 // Drop the reference on the ExtensionInfoMap object after reading from it. | |
288 // Balances StartLoad(). | |
289 info_map->Release(); | |
290 } | |
291 BrowserThread::PostTask( | |
292 BrowserThread::FILE, FROM_HERE, | |
293 NewRunnableMethod( | |
294 this, &UserScriptMaster::ScriptReloader::RunLoad, user_scripts)); | |
295 } | |
296 | |
241 // This method will be called from the file thread | 297 // This method will be called from the file thread |
242 void UserScriptMaster::ScriptReloader::RunLoad( | 298 void UserScriptMaster::ScriptReloader::RunLoad( |
243 const UserScriptList& user_scripts) { | 299 const UserScriptList& user_scripts) { |
244 LoadUserScripts(const_cast<UserScriptList*>(&user_scripts)); | 300 LoadUserScripts(const_cast<UserScriptList*>(&user_scripts)); |
245 | 301 |
246 // Scripts now contains list of up-to-date scripts. Load the content in the | 302 // Scripts now contains list of up-to-date scripts. Load the content in the |
247 // shared memory and let the master know it's ready. We need to post the task | 303 // shared memory and let the master know it's ready. We need to post the task |
248 // back even if no scripts ware found to balance the AddRef/Release calls | 304 // back even if no scripts ware found to balance the AddRef/Release calls |
249 BrowserThread::PostTask( | 305 BrowserThread::PostTask( |
250 master_thread_id_, FROM_HERE, | 306 master_thread_id_, FROM_HERE, |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
380 if (!handle) | 436 if (!handle) |
381 return; | 437 return; |
382 | 438 |
383 base::SharedMemoryHandle handle_for_process; | 439 base::SharedMemoryHandle handle_for_process; |
384 if (!shared_memory->ShareToProcess(handle, &handle_for_process)) | 440 if (!shared_memory->ShareToProcess(handle, &handle_for_process)) |
385 return; // This can legitimately fail if the renderer asserts at startup. | 441 return; // This can legitimately fail if the renderer asserts at startup. |
386 | 442 |
387 if (base::SharedMemory::IsHandleValid(handle_for_process)) | 443 if (base::SharedMemory::IsHandleValid(handle_for_process)) |
388 process->Send(new ExtensionMsg_UpdateUserScripts(handle_for_process)); | 444 process->Send(new ExtensionMsg_UpdateUserScripts(handle_for_process)); |
389 } | 445 } |
OLD | NEW |