OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <string> | 7 #include <string> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
11 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
12 #include "base/version.h" | 12 #include "base/version.h" |
13 #include "chrome/browser/chrome_notification_types.h" | 13 #include "chrome/browser/chrome_notification_types.h" |
14 #include "chrome/browser/extensions/extension_service.h" | 14 #include "chrome/browser/extensions/extension_service.h" |
15 #include "chrome/browser/extensions/extension_util.h" | 15 #include "chrome/browser/extensions/extension_util.h" |
16 #include "chrome/browser/extensions/image_loader.h" | 16 #include "chrome/browser/extensions/image_loader.h" |
17 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
18 #include "chrome/common/extensions/api/i18n/default_locale_handler.h" | 18 #include "chrome/common/extensions/api/i18n/default_locale_handler.h" |
19 #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" | 19 #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" |
20 #include "content/public/browser/notification_service.h" | 20 #include "content/public/browser/notification_service.h" |
21 #include "content/public/browser/render_process_host.h" | 21 #include "content/public/browser/render_process_host.h" |
| 22 #include "extensions/browser/content_verifier.h" |
22 #include "extensions/browser/extension_registry.h" | 23 #include "extensions/browser/extension_registry.h" |
| 24 #include "extensions/browser/extension_system.h" |
23 #include "extensions/common/file_util.h" | 25 #include "extensions/common/file_util.h" |
24 #include "extensions/common/message_bundle.h" | 26 #include "extensions/common/message_bundle.h" |
25 #include "ui/base/resource/resource_bundle.h" | 27 #include "ui/base/resource/resource_bundle.h" |
26 | 28 |
27 using content::BrowserThread; | 29 using content::BrowserThread; |
28 | 30 |
29 namespace extensions { | 31 namespace extensions { |
30 | 32 |
31 // Helper function to parse greasesmonkey headers | 33 // Helper function to parse greasesmonkey headers |
32 static bool GetDeclarationValue(const base::StringPiece& line, | 34 static bool GetDeclarationValue(const base::StringPiece& line, |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 // If no patterns were specified, default to @include *. This is what | 143 // If no patterns were specified, default to @include *. This is what |
142 // Greasemonkey does. | 144 // Greasemonkey does. |
143 if (script->globs().empty() && script->url_patterns().is_empty()) | 145 if (script->globs().empty() && script->url_patterns().is_empty()) |
144 script->add_glob("*"); | 146 script->add_glob("*"); |
145 | 147 |
146 return true; | 148 return true; |
147 } | 149 } |
148 | 150 |
149 void UserScriptMaster::ScriptReloader::StartLoad( | 151 void UserScriptMaster::ScriptReloader::StartLoad( |
150 const UserScriptList& user_scripts, | 152 const UserScriptList& user_scripts, |
151 const ExtensionsInfo& extensions_info_) { | 153 const ExtensionsInfo& extensions_info) { |
152 // Add a reference to ourselves to keep ourselves alive while we're running. | 154 // Add a reference to ourselves to keep ourselves alive while we're running. |
153 // Balanced by NotifyMaster(). | 155 // Balanced by NotifyMaster(). |
154 AddRef(); | 156 AddRef(); |
155 | 157 |
156 this->extensions_info_ = extensions_info_; | 158 verifier_ = master_->content_verifier(); |
| 159 this->extensions_info_ = extensions_info; |
157 BrowserThread::PostTask( | 160 BrowserThread::PostTask( |
158 BrowserThread::FILE, FROM_HERE, | 161 BrowserThread::FILE, FROM_HERE, |
159 base::Bind( | 162 base::Bind( |
160 &UserScriptMaster::ScriptReloader::RunLoad, this, user_scripts)); | 163 &UserScriptMaster::ScriptReloader::RunLoad, this, user_scripts)); |
161 } | 164 } |
162 | 165 |
163 UserScriptMaster::ScriptReloader::~ScriptReloader() {} | 166 UserScriptMaster::ScriptReloader::~ScriptReloader() {} |
164 | 167 |
165 void UserScriptMaster::ScriptReloader::NotifyMaster( | 168 void UserScriptMaster::ScriptReloader::NotifyMaster( |
166 base::SharedMemory* memory) { | 169 base::SharedMemory* memory) { |
167 // The master went away, so these new scripts aren't useful anymore. | 170 // The master went away, so these new scripts aren't useful anymore. |
168 if (!master_) | 171 if (!master_) |
169 delete memory; | 172 delete memory; |
170 else | 173 else |
171 master_->NewScriptsAvailable(memory); | 174 master_->NewScriptsAvailable(memory); |
172 | 175 |
173 // Drop our self-reference. | 176 // Drop our self-reference. |
174 // Balances StartLoad(). | 177 // Balances StartLoad(). |
175 Release(); | 178 Release(); |
176 } | 179 } |
177 | 180 |
178 static bool LoadScriptContent(UserScript::File* script_file, | 181 static void VerifyContent(ContentVerifier* verifier, |
179 const SubstitutionMap* localization_messages) { | 182 const std::string& extension_id, |
| 183 const base::FilePath& extension_root, |
| 184 const base::FilePath& relative_path, |
| 185 const std::string& content) { |
| 186 scoped_refptr<ContentVerifyJob> job( |
| 187 verifier->CreateJobFor(extension_id, extension_root, relative_path)); |
| 188 if (job.get()) { |
| 189 job->Start(); |
| 190 job->BytesRead(content.size(), content.data()); |
| 191 job->DoneReading(); |
| 192 } |
| 193 } |
| 194 |
| 195 static bool LoadScriptContent(const std::string& extension_id, |
| 196 UserScript::File* script_file, |
| 197 const SubstitutionMap* localization_messages, |
| 198 ContentVerifier* verifier) { |
180 std::string content; | 199 std::string content; |
181 const base::FilePath& path = ExtensionResource::GetFilePath( | 200 const base::FilePath& path = ExtensionResource::GetFilePath( |
182 script_file->extension_root(), script_file->relative_path(), | 201 script_file->extension_root(), script_file->relative_path(), |
183 ExtensionResource::SYMLINKS_MUST_RESOLVE_WITHIN_ROOT); | 202 ExtensionResource::SYMLINKS_MUST_RESOLVE_WITHIN_ROOT); |
184 if (path.empty()) { | 203 if (path.empty()) { |
185 int resource_id; | 204 int resource_id; |
186 if (extensions::ImageLoader::IsComponentExtensionResource( | 205 if (extensions::ImageLoader::IsComponentExtensionResource( |
187 script_file->extension_root(), script_file->relative_path(), | 206 script_file->extension_root(), script_file->relative_path(), |
188 &resource_id)) { | 207 &resource_id)) { |
189 const ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 208 const ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
190 content = rb.GetRawDataResource(resource_id).as_string(); | 209 content = rb.GetRawDataResource(resource_id).as_string(); |
191 } else { | 210 } else { |
192 LOG(WARNING) << "Failed to get file path to " | 211 LOG(WARNING) << "Failed to get file path to " |
193 << script_file->relative_path().value() << " from " | 212 << script_file->relative_path().value() << " from " |
194 << script_file->extension_root().value(); | 213 << script_file->extension_root().value(); |
195 return false; | 214 return false; |
196 } | 215 } |
197 } else { | 216 } else { |
198 if (!base::ReadFileToString(path, &content)) { | 217 if (!base::ReadFileToString(path, &content)) { |
199 LOG(WARNING) << "Failed to load user script file: " << path.value(); | 218 LOG(WARNING) << "Failed to load user script file: " << path.value(); |
200 return false; | 219 return false; |
201 } | 220 } |
| 221 if (verifier) { |
| 222 VerifyContent(verifier, |
| 223 extension_id, |
| 224 script_file->extension_root(), |
| 225 script_file->relative_path(), |
| 226 content); |
| 227 } |
202 } | 228 } |
203 | 229 |
204 // Localize the content. | 230 // Localize the content. |
205 if (localization_messages) { | 231 if (localization_messages) { |
206 std::string error; | 232 std::string error; |
207 MessageBundle::ReplaceMessagesWithExternalDictionary( | 233 MessageBundle::ReplaceMessagesWithExternalDictionary( |
208 *localization_messages, &content, &error); | 234 *localization_messages, &content, &error); |
209 if (!error.empty()) { | 235 if (!error.empty()) { |
210 LOG(WARNING) << "Failed to replace messages in script: " << error; | 236 LOG(WARNING) << "Failed to replace messages in script: " << error; |
211 } | 237 } |
(...skipping 12 matching lines...) Expand all Loading... |
224 | 250 |
225 void UserScriptMaster::ScriptReloader::LoadUserScripts( | 251 void UserScriptMaster::ScriptReloader::LoadUserScripts( |
226 UserScriptList* user_scripts) { | 252 UserScriptList* user_scripts) { |
227 for (size_t i = 0; i < user_scripts->size(); ++i) { | 253 for (size_t i = 0; i < user_scripts->size(); ++i) { |
228 UserScript& script = user_scripts->at(i); | 254 UserScript& script = user_scripts->at(i); |
229 scoped_ptr<SubstitutionMap> localization_messages( | 255 scoped_ptr<SubstitutionMap> localization_messages( |
230 GetLocalizationMessages(script.extension_id())); | 256 GetLocalizationMessages(script.extension_id())); |
231 for (size_t k = 0; k < script.js_scripts().size(); ++k) { | 257 for (size_t k = 0; k < script.js_scripts().size(); ++k) { |
232 UserScript::File& script_file = script.js_scripts()[k]; | 258 UserScript::File& script_file = script.js_scripts()[k]; |
233 if (script_file.GetContent().empty()) | 259 if (script_file.GetContent().empty()) |
234 LoadScriptContent(&script_file, NULL); | 260 LoadScriptContent( |
| 261 script.extension_id(), &script_file, NULL, verifier_.get()); |
235 } | 262 } |
236 for (size_t k = 0; k < script.css_scripts().size(); ++k) { | 263 for (size_t k = 0; k < script.css_scripts().size(); ++k) { |
237 UserScript::File& script_file = script.css_scripts()[k]; | 264 UserScript::File& script_file = script.css_scripts()[k]; |
238 if (script_file.GetContent().empty()) | 265 if (script_file.GetContent().empty()) |
239 LoadScriptContent(&script_file, localization_messages.get()); | 266 LoadScriptContent(script.extension_id(), |
| 267 &script_file, |
| 268 localization_messages.get(), |
| 269 verifier_.get()); |
240 } | 270 } |
241 } | 271 } |
242 } | 272 } |
243 | 273 |
244 SubstitutionMap* UserScriptMaster::ScriptReloader::GetLocalizationMessages( | 274 SubstitutionMap* UserScriptMaster::ScriptReloader::GetLocalizationMessages( |
245 const std::string& extension_id) { | 275 const std::string& extension_id) { |
246 if (extensions_info_.find(extension_id) == extensions_info_.end()) { | 276 if (extensions_info_.find(extension_id) == extensions_info_.end()) { |
247 return NULL; | 277 return NULL; |
248 } | 278 } |
249 | 279 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 SendUpdate(i.GetCurrentValue(), handle); | 393 SendUpdate(i.GetCurrentValue(), handle); |
364 } | 394 } |
365 | 395 |
366 content::NotificationService::current()->Notify( | 396 content::NotificationService::current()->Notify( |
367 chrome::NOTIFICATION_USER_SCRIPTS_UPDATED, | 397 chrome::NOTIFICATION_USER_SCRIPTS_UPDATED, |
368 content::Source<Profile>(profile_), | 398 content::Source<Profile>(profile_), |
369 content::Details<base::SharedMemory>(handle)); | 399 content::Details<base::SharedMemory>(handle)); |
370 } | 400 } |
371 } | 401 } |
372 | 402 |
| 403 ContentVerifier* UserScriptMaster::content_verifier() { |
| 404 ExtensionSystem* system = ExtensionSystem::Get(profile_); |
| 405 return system->content_verifier(); |
| 406 } |
| 407 |
373 void UserScriptMaster::OnExtensionLoaded( | 408 void UserScriptMaster::OnExtensionLoaded( |
374 content::BrowserContext* browser_context, | 409 content::BrowserContext* browser_context, |
375 const Extension* extension) { | 410 const Extension* extension) { |
376 // Add any content scripts inside the extension. | 411 // Add any content scripts inside the extension. |
377 extensions_info_[extension->id()] = | 412 extensions_info_[extension->id()] = |
378 ExtensionSet::ExtensionPathAndDefaultLocale( | 413 ExtensionSet::ExtensionPathAndDefaultLocale( |
379 extension->path(), LocaleInfo::GetDefaultLocale(extension)); | 414 extension->path(), LocaleInfo::GetDefaultLocale(extension)); |
380 bool incognito_enabled = util::IsIncognitoEnabled(extension->id(), profile_); | 415 bool incognito_enabled = util::IsIncognitoEnabled(extension->id(), profile_); |
381 const UserScriptList& scripts = | 416 const UserScriptList& scripts = |
382 ContentScriptsInfo::GetContentScripts(extension); | 417 ContentScriptsInfo::GetContentScripts(extension); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 | 510 |
476 base::SharedMemoryHandle handle_for_process; | 511 base::SharedMemoryHandle handle_for_process; |
477 if (!shared_memory->ShareToProcess(handle, &handle_for_process)) | 512 if (!shared_memory->ShareToProcess(handle, &handle_for_process)) |
478 return; // This can legitimately fail if the renderer asserts at startup. | 513 return; // This can legitimately fail if the renderer asserts at startup. |
479 | 514 |
480 if (base::SharedMemory::IsHandleValid(handle_for_process)) | 515 if (base::SharedMemory::IsHandleValid(handle_for_process)) |
481 process->Send(new ExtensionMsg_UpdateUserScripts(handle_for_process)); | 516 process->Send(new ExtensionMsg_UpdateUserScripts(handle_for_process)); |
482 } | 517 } |
483 | 518 |
484 } // namespace extensions | 519 } // namespace extensions |
OLD | NEW |