OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_loader.h" | 5 #include "chrome/browser/extensions/user_script_loader.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
14 #include "base/memory/shared_memory.h" | |
15 #include "base/version.h" | 14 #include "base/version.h" |
16 #include "chrome/browser/chrome_notification_types.h" | 15 #include "chrome/browser/chrome_notification_types.h" |
17 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
18 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
19 #include "content/public/browser/notification_service.h" | 18 #include "content/public/browser/notification_service.h" |
20 #include "content/public/browser/render_process_host.h" | 19 #include "content/public/browser/render_process_host.h" |
21 #include "extensions/browser/component_extension_resource_manager.h" | |
22 #include "extensions/browser/content_verifier.h" | 20 #include "extensions/browser/content_verifier.h" |
23 #include "extensions/browser/extension_registry.h" | |
24 #include "extensions/browser/extension_system.h" | |
25 #include "extensions/browser/extensions_browser_client.h" | |
26 #include "extensions/common/extension_messages.h" | |
27 #include "extensions/common/file_util.h" | 21 #include "extensions/common/file_util.h" |
28 #include "extensions/common/manifest_handlers/default_locale_handler.h" | |
29 #include "extensions/common/message_bundle.h" | |
30 #include "extensions/common/one_shot_event.h" | |
31 #include "ui/base/resource/resource_bundle.h" | |
32 | 22 |
33 using content::BrowserThread; | 23 using content::BrowserThread; |
34 using extensions::ExtensionsBrowserClient; | |
35 | 24 |
36 namespace extensions { | 25 namespace extensions { |
37 | 26 |
38 namespace { | 27 namespace { |
39 | 28 |
40 typedef base::Callback< | 29 using LoadScriptsCallback = |
41 void(scoped_ptr<UserScriptList>, scoped_ptr<base::SharedMemory>)> | 30 base::Callback<void(scoped_ptr<UserScriptList>, |
42 LoadScriptsCallback; | 31 scoped_ptr<base::SharedMemory>)>; |
43 | 32 |
44 void VerifyContent(scoped_refptr<ContentVerifier> verifier, | 33 UserScriptLoader::SubstitutionMap* GetLocalizationMessages( |
45 const ExtensionId& extension_id, | 34 const UserScriptLoader::ConsumersInfo& consumers_info, |
46 const base::FilePath& extension_root, | 35 const ConsumerID& consumer_id) { |
47 const base::FilePath& relative_path, | 36 UserScriptLoader::ConsumersInfo::const_iterator iter = |
48 const std::string& content) { | 37 consumers_info.find(consumer_id); |
49 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 38 if (iter == consumers_info.end()) |
50 scoped_refptr<ContentVerifyJob> job( | 39 return nullptr; |
51 verifier->CreateJobFor(extension_id, extension_root, relative_path)); | 40 return file_util::LoadMessageBundleSubstitutionMap( |
52 if (job.get()) { | 41 iter->second.first, consumer_id.host_id(), iter->second.second); |
53 job->Start(); | |
54 job->BytesRead(content.size(), content.data()); | |
55 job->DoneReading(); | |
56 } | |
57 } | 42 } |
58 | 43 |
59 bool LoadScriptContent(const ExtensionId& extension_id, | 44 void LoadUserScripts( |
60 UserScript::File* script_file, | 45 UserScriptList* user_scripts, |
61 const SubstitutionMap* localization_messages, | 46 const UserScriptLoader::ConsumersInfo& consumers_info, |
62 scoped_refptr<ContentVerifier> verifier) { | 47 const std::set<int>& added_script_ids, |
63 std::string content; | 48 ContentVerifier* verifier, |
Devlin
2015/01/20 17:51:05
nit: Please update this to take a const scoped_ref
Xi Han
2015/01/21 21:30:16
Updated.
| |
64 const base::FilePath& path = ExtensionResource::GetFilePath( | 49 UserScriptLoader::LoadUserScriptsFunctionCallback callback) { |
Devlin
2015/01/20 17:51:05
nit: I think |load_script_content_function| is mor
Xi Han
2015/01/21 21:30:16
Done.
| |
65 script_file->extension_root(), | |
66 script_file->relative_path(), | |
67 ExtensionResource::SYMLINKS_MUST_RESOLVE_WITHIN_ROOT); | |
68 if (path.empty()) { | |
69 int resource_id; | |
70 if (ExtensionsBrowserClient::Get()->GetComponentExtensionResourceManager()-> | |
71 IsComponentExtensionResource(script_file->extension_root(), | |
72 script_file->relative_path(), | |
73 &resource_id)) { | |
74 const ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
75 content = rb.GetRawDataResource(resource_id).as_string(); | |
76 } else { | |
77 LOG(WARNING) << "Failed to get file path to " | |
78 << script_file->relative_path().value() << " from " | |
79 << script_file->extension_root().value(); | |
80 return false; | |
81 } | |
82 } else { | |
83 if (!base::ReadFileToString(path, &content)) { | |
84 LOG(WARNING) << "Failed to load user script file: " << path.value(); | |
85 return false; | |
86 } | |
87 if (verifier.get()) { | |
88 content::BrowserThread::PostTask(content::BrowserThread::IO, | |
89 FROM_HERE, | |
90 base::Bind(&VerifyContent, | |
91 verifier, | |
92 extension_id, | |
93 script_file->extension_root(), | |
94 script_file->relative_path(), | |
95 content)); | |
96 } | |
97 } | |
98 | |
99 // Localize the content. | |
100 if (localization_messages) { | |
101 std::string error; | |
102 MessageBundle::ReplaceMessagesWithExternalDictionary( | |
103 *localization_messages, &content, &error); | |
104 if (!error.empty()) { | |
105 LOG(WARNING) << "Failed to replace messages in script: " << error; | |
106 } | |
107 } | |
108 | |
109 // Remove BOM from the content. | |
110 std::string::size_type index = content.find(base::kUtf8ByteOrderMark); | |
111 if (index == 0) { | |
112 script_file->set_content(content.substr(strlen(base::kUtf8ByteOrderMark))); | |
113 } else { | |
114 script_file->set_content(content); | |
115 } | |
116 | |
117 return true; | |
118 } | |
119 | |
120 SubstitutionMap* GetLocalizationMessages(const ExtensionsInfo& extensions_info, | |
121 const ExtensionId& extension_id) { | |
122 ExtensionsInfo::const_iterator iter = extensions_info.find(extension_id); | |
123 if (iter == extensions_info.end()) | |
124 return NULL; | |
125 return file_util::LoadMessageBundleSubstitutionMap( | |
126 iter->second.first, extension_id, iter->second.second); | |
127 } | |
128 | |
129 void LoadUserScripts(UserScriptList* user_scripts, | |
130 const ExtensionsInfo& extensions_info, | |
131 const std::set<int>& added_script_ids, | |
132 ContentVerifier* verifier) { | |
133 for (UserScriptList::iterator script = user_scripts->begin(); | 50 for (UserScriptList::iterator script = user_scripts->begin(); |
134 script != user_scripts->end(); | 51 script != user_scripts->end(); |
135 ++script) { | 52 ++script) { |
136 if (added_script_ids.count(script->id()) == 0) | 53 if (added_script_ids.count(script->id()) == 0) |
137 continue; | 54 continue; |
138 scoped_ptr<SubstitutionMap> localization_messages( | 55 scoped_ptr<UserScriptLoader::SubstitutionMap> localization_messages( |
139 GetLocalizationMessages(extensions_info, script->extension_id())); | 56 GetLocalizationMessages(consumers_info, script->consumer_id())); |
140 for (size_t k = 0; k < script->js_scripts().size(); ++k) { | 57 for (size_t k = 0; k < script->js_scripts().size(); ++k) { |
141 UserScript::File& script_file = script->js_scripts()[k]; | 58 UserScript::File& script_file = script->js_scripts()[k]; |
142 if (script_file.GetContent().empty()) | 59 if (script_file.GetContent().empty()) |
143 LoadScriptContent(script->extension_id(), &script_file, NULL, verifier); | 60 callback.Run(script->consumer_id(), &script_file, NULL, verifier); |
144 } | 61 } |
145 for (size_t k = 0; k < script->css_scripts().size(); ++k) { | 62 for (size_t k = 0; k < script->css_scripts().size(); ++k) { |
146 UserScript::File& script_file = script->css_scripts()[k]; | 63 UserScript::File& script_file = script->css_scripts()[k]; |
147 if (script_file.GetContent().empty()) | 64 if (script_file.GetContent().empty()) |
148 LoadScriptContent(script->extension_id(), | 65 callback.Run(script->consumer_id(), &script_file, |
149 &script_file, | 66 localization_messages.get(), verifier); |
150 localization_messages.get(), | |
151 verifier); | |
152 } | 67 } |
153 } | 68 } |
154 } | 69 } |
155 | 70 |
156 // Pickle user scripts and return pointer to the shared memory. | 71 // Pickle user scripts and return pointer to the shared memory. |
157 scoped_ptr<base::SharedMemory> Serialize(const UserScriptList& scripts) { | 72 scoped_ptr<base::SharedMemory> Serialize(const UserScriptList& scripts) { |
158 Pickle pickle; | 73 Pickle pickle; |
159 pickle.WriteSizeT(scripts.size()); | 74 pickle.WriteSizeT(scripts.size()); |
160 for (UserScriptList::const_iterator script = scripts.begin(); | 75 for (UserScriptList::const_iterator script = scripts.begin(); |
161 script != scripts.end(); | 76 script != scripts.end(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
193 | 108 |
194 base::SharedMemoryHandle readonly_handle; | 109 base::SharedMemoryHandle readonly_handle; |
195 if (!shared_memory.ShareReadOnlyToProcess(base::GetCurrentProcessHandle(), | 110 if (!shared_memory.ShareReadOnlyToProcess(base::GetCurrentProcessHandle(), |
196 &readonly_handle)) | 111 &readonly_handle)) |
197 return scoped_ptr<base::SharedMemory>(); | 112 return scoped_ptr<base::SharedMemory>(); |
198 | 113 |
199 return make_scoped_ptr(new base::SharedMemory(readonly_handle, | 114 return make_scoped_ptr(new base::SharedMemory(readonly_handle, |
200 /*read_only=*/true)); | 115 /*read_only=*/true)); |
201 } | 116 } |
202 | 117 |
203 void LoadScriptsOnFileThread(scoped_ptr<UserScriptList> user_scripts, | 118 void LoadScriptsOnFileThread( |
204 const ExtensionsInfo& extensions_info, | 119 scoped_ptr<UserScriptList> user_scripts, |
205 const std::set<int>& added_script_ids, | 120 const UserScriptLoader::ConsumersInfo& consumers_info, |
206 scoped_refptr<ContentVerifier> verifier, | 121 const std::set<int>& added_script_ids, |
207 LoadScriptsCallback callback) { | 122 scoped_refptr<ContentVerifier> verifier, |
123 UserScriptLoader::LoadUserScriptsFunctionCallback function, | |
124 LoadScriptsCallback callback) { | |
208 DCHECK(user_scripts.get()); | 125 DCHECK(user_scripts.get()); |
209 LoadUserScripts( | 126 LoadUserScripts(user_scripts.get(), consumers_info, added_script_ids, |
210 user_scripts.get(), extensions_info, added_script_ids, verifier.get()); | 127 verifier.get(), function); |
211 scoped_ptr<base::SharedMemory> memory = Serialize(*user_scripts); | 128 scoped_ptr<base::SharedMemory> memory = Serialize(*user_scripts); |
212 BrowserThread::PostTask( | 129 BrowserThread::PostTask( |
213 BrowserThread::UI, | 130 BrowserThread::UI, |
214 FROM_HERE, | 131 FROM_HERE, |
215 base::Bind(callback, base::Passed(&user_scripts), base::Passed(&memory))); | 132 base::Bind(callback, base::Passed(&user_scripts), base::Passed(&memory))); |
216 } | 133 } |
217 | 134 |
218 // Helper function to parse greasesmonkey headers | 135 // Helper function to parse greasesmonkey headers |
219 bool GetDeclarationValue(const base::StringPiece& line, | 136 bool GetDeclarationValue(const base::StringPiece& line, |
220 const base::StringPiece& prefix, | 137 const base::StringPiece& prefix, |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
323 } | 240 } |
324 | 241 |
325 // If no patterns were specified, default to @include *. This is what | 242 // If no patterns were specified, default to @include *. This is what |
326 // Greasemonkey does. | 243 // Greasemonkey does. |
327 if (script->globs().empty() && script->url_patterns().is_empty()) | 244 if (script->globs().empty() && script->url_patterns().is_empty()) |
328 script->add_glob("*"); | 245 script->add_glob("*"); |
329 | 246 |
330 return true; | 247 return true; |
331 } | 248 } |
332 | 249 |
333 // static | |
334 void UserScriptLoader::LoadScriptsForTest(UserScriptList* user_scripts) { | 250 void UserScriptLoader::LoadScriptsForTest(UserScriptList* user_scripts) { |
335 ExtensionsInfo info; | 251 ConsumersInfo info; |
336 std::set<int> added_script_ids; | 252 std::set<int> added_script_ids; |
337 for (UserScriptList::iterator it = user_scripts->begin(); | 253 for (UserScriptList::iterator it = user_scripts->begin(); |
338 it != user_scripts->end(); | 254 it != user_scripts->end(); |
339 ++it) { | 255 ++it) { |
340 added_script_ids.insert(it->id()); | 256 added_script_ids.insert(it->id()); |
341 } | 257 } |
342 LoadUserScripts( | 258 LoadUserScripts(user_scripts, info, added_script_ids, |
343 user_scripts, info, added_script_ids, NULL /* no verifier for testing */); | 259 NULL /* no verifier for testing */, |
260 GetLoadUserScriptsFunction()); | |
344 } | 261 } |
345 | 262 |
346 UserScriptLoader::UserScriptLoader(Profile* profile, | 263 UserScriptLoader::UserScriptLoader(Profile* profile, |
347 const ExtensionId& owner_extension_id, | 264 const ConsumerID& consumer_id, |
348 bool listen_for_extension_system_loaded) | 265 ContentVerifier* content_verifier) |
Devlin
2015/01/20 17:51:05
Please update this to take a const scoped_refptr<C
Xi Han
2015/01/21 21:30:16
Done.
| |
349 : user_scripts_(new UserScriptList()), | 266 : user_scripts_(new UserScriptList()), |
350 clear_scripts_(false), | 267 clear_scripts_(false), |
351 extension_system_ready_(false), | 268 ready_(false), |
352 pending_load_(false), | 269 pending_load_(false), |
353 profile_(profile), | 270 profile_(profile), |
354 owner_extension_id_(owner_extension_id), | 271 consumer_id_(consumer_id), |
355 extension_registry_observer_(this), | 272 content_verifier_(content_verifier), |
356 weak_factory_(this) { | 273 weak_factory_(this) { |
357 extension_registry_observer_.Add(ExtensionRegistry::Get(profile)); | |
358 if (listen_for_extension_system_loaded) { | |
359 ExtensionSystem::Get(profile_)->ready().Post( | |
360 FROM_HERE, | |
361 base::Bind(&UserScriptLoader::OnExtensionSystemReady, | |
362 weak_factory_.GetWeakPtr())); | |
363 } else { | |
364 extension_system_ready_ = true; | |
365 } | |
366 registrar_.Add(this, | 274 registrar_.Add(this, |
367 content::NOTIFICATION_RENDERER_PROCESS_CREATED, | 275 content::NOTIFICATION_RENDERER_PROCESS_CREATED, |
368 content::NotificationService::AllBrowserContextsAndSources()); | 276 content::NotificationService::AllBrowserContextsAndSources()); |
369 } | 277 } |
370 | 278 |
371 UserScriptLoader::~UserScriptLoader() { | 279 UserScriptLoader::~UserScriptLoader() { |
372 } | 280 } |
373 | 281 |
374 void UserScriptLoader::AddScripts(const std::set<UserScript>& scripts) { | 282 void UserScriptLoader::AddScripts(const std::set<UserScript>& scripts) { |
375 for (std::set<UserScript>::const_iterator it = scripts.begin(); | 283 for (std::set<UserScript>::const_iterator it = scripts.begin(); |
(...skipping 25 matching lines...) Expand all Loading... | |
401 void UserScriptLoader::Observe(int type, | 309 void UserScriptLoader::Observe(int type, |
402 const content::NotificationSource& source, | 310 const content::NotificationSource& source, |
403 const content::NotificationDetails& details) { | 311 const content::NotificationDetails& details) { |
404 DCHECK_EQ(type, content::NOTIFICATION_RENDERER_PROCESS_CREATED); | 312 DCHECK_EQ(type, content::NOTIFICATION_RENDERER_PROCESS_CREATED); |
405 content::RenderProcessHost* process = | 313 content::RenderProcessHost* process = |
406 content::Source<content::RenderProcessHost>(source).ptr(); | 314 content::Source<content::RenderProcessHost>(source).ptr(); |
407 Profile* profile = Profile::FromBrowserContext(process->GetBrowserContext()); | 315 Profile* profile = Profile::FromBrowserContext(process->GetBrowserContext()); |
408 if (!profile_->IsSameProfile(profile)) | 316 if (!profile_->IsSameProfile(profile)) |
409 return; | 317 return; |
410 if (scripts_ready()) { | 318 if (scripts_ready()) { |
411 SendUpdate(process, | 319 SendUpdate(process, shared_memory_.get(), |
412 shared_memory_.get(), | 320 std::set<ConsumerID>()); // Include all consumers. |
413 std::set<ExtensionId>()); // Include all extensions. | |
414 } | 321 } |
415 } | 322 } |
416 | 323 |
417 void UserScriptLoader::OnExtensionUnloaded( | |
418 content::BrowserContext* browser_context, | |
419 const Extension* extension, | |
420 UnloadedExtensionInfo::Reason reason) { | |
421 extensions_info_.erase(extension->id()); | |
422 } | |
423 | |
424 void UserScriptLoader::OnExtensionSystemReady() { | |
425 extension_system_ready_ = true; | |
426 AttemptLoad(); | |
427 } | |
428 | |
429 bool UserScriptLoader::ScriptsMayHaveChanged() const { | 324 bool UserScriptLoader::ScriptsMayHaveChanged() const { |
430 // Scripts may have changed if there are scripts added, scripts removed, or | 325 // Scripts may have changed if there are scripts added, scripts removed, or |
431 // if scripts were cleared and either: | 326 // if scripts were cleared and either: |
432 // (1) A load is in progress (which may result in a non-zero number of | 327 // (1) A load is in progress (which may result in a non-zero number of |
433 // scripts that need to be cleared), or | 328 // scripts that need to be cleared), or |
434 // (2) The current set of scripts is non-empty (so they need to be cleared). | 329 // (2) The current set of scripts is non-empty (so they need to be cleared). |
435 return (added_scripts_.size() || | 330 return (added_scripts_.size() || |
436 removed_scripts_.size() || | 331 removed_scripts_.size() || |
437 (clear_scripts_ && | 332 (clear_scripts_ && |
438 (is_loading() || user_scripts_->size()))); | 333 (is_loading() || user_scripts_->size()))); |
439 } | 334 } |
440 | 335 |
441 void UserScriptLoader::AttemptLoad() { | 336 void UserScriptLoader::AttemptLoad() { |
442 if (extension_system_ready_ && ScriptsMayHaveChanged()) { | 337 if (ready_ && ScriptsMayHaveChanged()) { |
443 if (is_loading()) | 338 if (is_loading()) |
444 pending_load_ = true; | 339 pending_load_ = true; |
445 else | 340 else |
446 StartLoad(); | 341 StartLoad(); |
447 } | 342 } |
448 } | 343 } |
449 | 344 |
345 UserScriptLoader::LoadUserScriptsFunctionCallback | |
346 UserScriptLoader::GetLoadUserScriptsFunction() { | |
347 return base::Bind(&UserScriptLoader::LoadScriptContent); | |
348 } | |
349 | |
450 void UserScriptLoader::StartLoad() { | 350 void UserScriptLoader::StartLoad() { |
451 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 351 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
452 DCHECK(!is_loading()); | 352 DCHECK(!is_loading()); |
453 | 353 |
454 // If scripts were marked for clearing before adding and removing, then clear | 354 // If scripts were marked for clearing before adding and removing, then clear |
455 // them. | 355 // them. |
456 if (clear_scripts_) { | 356 if (clear_scripts_) { |
457 user_scripts_->clear(); | 357 user_scripts_->clear(); |
458 } else { | 358 } else { |
459 for (UserScriptList::iterator it = user_scripts_->begin(); | 359 for (UserScriptList::iterator it = user_scripts_->begin(); |
460 it != user_scripts_->end();) { | 360 it != user_scripts_->end();) { |
461 if (removed_scripts_.count(*it)) | 361 if (removed_scripts_.count(*it)) |
462 it = user_scripts_->erase(it); | 362 it = user_scripts_->erase(it); |
463 else | 363 else |
464 ++it; | 364 ++it; |
465 } | 365 } |
466 } | 366 } |
467 | 367 |
468 user_scripts_->insert( | 368 user_scripts_->insert( |
469 user_scripts_->end(), added_scripts_.begin(), added_scripts_.end()); | 369 user_scripts_->end(), added_scripts_.begin(), added_scripts_.end()); |
470 | 370 |
471 std::set<int> added_script_ids; | 371 std::set<int> added_script_ids; |
472 for (std::set<UserScript>::const_iterator it = added_scripts_.begin(); | 372 for (std::set<UserScript>::const_iterator it = added_scripts_.begin(); |
473 it != added_scripts_.end(); | 373 it != added_scripts_.end(); |
474 ++it) { | 374 ++it) { |
475 added_script_ids.insert(it->id()); | 375 added_script_ids.insert(it->id()); |
476 } | 376 } |
477 | 377 |
478 // Expand |changed_extensions_| for OnScriptsLoaded, which will use it in | 378 // Expand |changed_consumers_| for OnScriptsLoaded, which will use it in |
479 // its IPC message. This must be done before we clear |added_scripts_| and | 379 // its IPC message. This must be done before we clear |added_scripts_| and |
480 // |removed_scripts_| below. | 380 // |removed_scripts_| below. |
481 std::set<UserScript> changed_scripts(added_scripts_); | 381 std::set<UserScript> changed_scripts(added_scripts_); |
482 changed_scripts.insert(removed_scripts_.begin(), removed_scripts_.end()); | 382 changed_scripts.insert(removed_scripts_.begin(), removed_scripts_.end()); |
483 ExpandChangedExtensions(changed_scripts); | 383 ExpandChangedConsumers(changed_scripts); |
484 | 384 |
485 // Update |extensions_info_| to contain info from every extension in | 385 // |changed_consumers_| before passing it to LoadScriptsOnFileThread. |
486 // |changed_extensions_| before passing it to LoadScriptsOnFileThread. | 386 UpdateConsumersInfo(changed_consumers_); |
487 UpdateExtensionsInfo(); | |
488 | 387 |
489 BrowserThread::PostTask( | 388 BrowserThread::PostTask( |
490 BrowserThread::FILE, | 389 BrowserThread::FILE, FROM_HERE, |
491 FROM_HERE, | 390 base::Bind(&LoadScriptsOnFileThread, base::Passed(&user_scripts_), |
492 base::Bind(&LoadScriptsOnFileThread, | 391 consumers_info_, added_script_ids, |
493 base::Passed(&user_scripts_), | 392 make_scoped_refptr(content_verifier_), |
494 extensions_info_, | 393 GetLoadUserScriptsFunction(), |
495 added_script_ids, | |
496 make_scoped_refptr( | |
497 ExtensionSystem::Get(profile_)->content_verifier()), | |
498 base::Bind(&UserScriptLoader::OnScriptsLoaded, | 394 base::Bind(&UserScriptLoader::OnScriptsLoaded, |
499 weak_factory_.GetWeakPtr()))); | 395 weak_factory_.GetWeakPtr()))); |
500 | 396 |
501 clear_scripts_ = false; | 397 clear_scripts_ = false; |
502 added_scripts_.clear(); | 398 added_scripts_.clear(); |
503 removed_scripts_.clear(); | 399 removed_scripts_.clear(); |
504 user_scripts_.reset(NULL); | 400 user_scripts_.reset(NULL); |
505 } | 401 } |
506 | 402 |
403 // static | |
404 bool UserScriptLoader::LoadScriptContent( | |
Devlin
2015/01/20 17:51:05
Why can't we remove this method, remove the static
Xi Han
2015/01/21 21:30:17
Done.
| |
405 const ConsumerID& consumer_id, | |
406 UserScript::File* script_file, | |
407 const SubstitutionMap* localization_messages, | |
408 scoped_refptr<ContentVerifier> verifier) { | |
409 return false; | |
410 } | |
411 | |
412 void UserScriptLoader::AddConsumerInfo(const ConsumerID& consumer_id, | |
413 const PathAndDefaultLocale& location) { | |
414 if (consumers_info_.find(consumer_id) != consumers_info_.end()) | |
415 return; | |
416 consumers_info_[consumer_id] = location; | |
417 } | |
418 | |
419 void UserScriptLoader::RemoveConsumerInfo(const std::string& host_id) { | |
420 std::set<ConsumerID> ids_to_delete; | |
421 | |
422 for (ConsumersInfo::iterator it = consumers_info_.begin(); | |
423 it != consumers_info_.end(); ++it) { | |
424 const ConsumerID& id = it->first; | |
425 if (id.host_id() == host_id) | |
426 ids_to_delete.insert(id); | |
427 } | |
428 | |
429 for (std::set<ConsumerID>::iterator it = ids_to_delete.begin(); | |
430 it != ids_to_delete.end(); ++it) | |
431 consumers_info_.erase(*it); | |
432 } | |
433 | |
434 void UserScriptLoader::SetReady(bool ready) { | |
435 ready_ = ready; | |
436 if (ready_) | |
437 AttemptLoad(); | |
Devlin
2015/01/20 17:51:05
We should either:
DCHECK_NE(ready, ready_);
or
boo
Xi Han
2015/01/21 21:30:17
Done.
| |
438 } | |
439 | |
507 void UserScriptLoader::OnScriptsLoaded( | 440 void UserScriptLoader::OnScriptsLoaded( |
508 scoped_ptr<UserScriptList> user_scripts, | 441 scoped_ptr<UserScriptList> user_scripts, |
509 scoped_ptr<base::SharedMemory> shared_memory) { | 442 scoped_ptr<base::SharedMemory> shared_memory) { |
510 user_scripts_.reset(user_scripts.release()); | 443 user_scripts_.reset(user_scripts.release()); |
511 if (pending_load_) { | 444 if (pending_load_) { |
512 // While we were loading, there were further changes. Don't bother | 445 // While we were loading, there were further changes. Don't bother |
513 // notifying about these scripts and instead just immediately reload. | 446 // notifying about these scripts and instead just immediately reload. |
514 pending_load_ = false; | 447 pending_load_ = false; |
515 StartLoad(); | 448 StartLoad(); |
516 return; | 449 return; |
(...skipping 11 matching lines...) Expand all Loading... | |
528 return; | 461 return; |
529 } | 462 } |
530 | 463 |
531 // We've got scripts ready to go. | 464 // We've got scripts ready to go. |
532 shared_memory_.reset(shared_memory.release()); | 465 shared_memory_.reset(shared_memory.release()); |
533 | 466 |
534 for (content::RenderProcessHost::iterator i( | 467 for (content::RenderProcessHost::iterator i( |
535 content::RenderProcessHost::AllHostsIterator()); | 468 content::RenderProcessHost::AllHostsIterator()); |
536 !i.IsAtEnd(); | 469 !i.IsAtEnd(); |
537 i.Advance()) { | 470 i.Advance()) { |
538 SendUpdate(i.GetCurrentValue(), shared_memory_.get(), changed_extensions_); | 471 SendUpdate(i.GetCurrentValue(), shared_memory_.get(), changed_consumers_); |
539 } | 472 } |
540 changed_extensions_.clear(); | 473 changed_consumers_.clear(); |
541 | 474 |
542 content::NotificationService::current()->Notify( | 475 content::NotificationService::current()->Notify( |
543 extensions::NOTIFICATION_USER_SCRIPTS_UPDATED, | 476 extensions::NOTIFICATION_USER_SCRIPTS_UPDATED, |
544 content::Source<Profile>(profile_), | 477 content::Source<Profile>(profile_), |
545 content::Details<base::SharedMemory>(shared_memory_.get())); | 478 content::Details<base::SharedMemory>(shared_memory_.get())); |
546 } | 479 } |
547 | 480 |
548 void UserScriptLoader::SendUpdate( | 481 void UserScriptLoader::SendUpdate( |
549 content::RenderProcessHost* process, | 482 content::RenderProcessHost* process, |
550 base::SharedMemory* shared_memory, | 483 base::SharedMemory* shared_memory, |
551 const std::set<ExtensionId>& changed_extensions) { | 484 const std::set<ConsumerID>& changed_consumers) { |
552 // Don't allow injection of content scripts into <webview>. | 485 // Don't allow injection of content scripts into <webview>. |
553 if (process->IsIsolatedGuest()) | 486 if (process->IsIsolatedGuest()) |
554 return; | 487 return; |
555 | 488 |
556 Profile* profile = Profile::FromBrowserContext(process->GetBrowserContext()); | 489 Profile* profile = Profile::FromBrowserContext(process->GetBrowserContext()); |
557 // Make sure we only send user scripts to processes in our profile. | 490 // Make sure we only send user scripts to processes in our profile. |
558 if (!profile_->IsSameProfile(profile)) | 491 if (!profile_->IsSameProfile(profile)) |
559 return; | 492 return; |
560 | 493 |
561 // If the process is being started asynchronously, early return. We'll end up | 494 // If the process is being started asynchronously, early return. We'll end up |
562 // calling InitUserScripts when it's created which will call this again. | 495 // calling InitUserScripts when it's created which will call this again. |
563 base::ProcessHandle handle = process->GetHandle(); | 496 base::ProcessHandle handle = process->GetHandle(); |
564 if (!handle) | 497 if (!handle) |
565 return; | 498 return; |
566 | 499 |
567 base::SharedMemoryHandle handle_for_process; | 500 base::SharedMemoryHandle handle_for_process; |
568 if (!shared_memory->ShareToProcess(handle, &handle_for_process)) | 501 if (!shared_memory->ShareToProcess(handle, &handle_for_process)) |
569 return; // This can legitimately fail if the renderer asserts at startup. | 502 return; // This can legitimately fail if the renderer asserts at startup. |
570 | 503 |
571 if (base::SharedMemory::IsHandleValid(handle_for_process)) { | 504 SendUpdate(process, handle_for_process, changed_consumers); |
Devlin
2015/01/20 17:51:05
Why not keep this if here, so that subclasses don'
Xi Han
2015/01/21 21:30:17
Sure, move the code back.
| |
572 process->Send(new ExtensionMsg_UpdateUserScripts( | |
573 handle_for_process, owner_extension_id_, changed_extensions)); | |
574 } | |
575 } | 505 } |
576 | 506 |
577 void UserScriptLoader::ExpandChangedExtensions( | 507 void UserScriptLoader::ExpandChangedConsumers( |
578 const std::set<UserScript>& scripts) { | 508 const std::set<UserScript>& scripts) { |
579 for (std::set<UserScript>::const_iterator it = scripts.begin(); | 509 for (std::set<UserScript>::const_iterator it = scripts.begin(); |
Devlin
2015/01/20 17:51:05
let's C++11-ify this:
for (const UserScript& scrip
Xi Han
2015/01/21 21:30:16
Done.
| |
580 it != scripts.end(); | 510 it != scripts.end(); |
581 ++it) { | 511 ++it) { |
582 changed_extensions_.insert(it->extension_id()); | 512 changed_consumers_.insert(it->consumer_id()); |
583 } | 513 } |
584 } | 514 } |
585 | 515 |
586 void UserScriptLoader::UpdateExtensionsInfo() { | |
587 ExtensionRegistry* registry = ExtensionRegistry::Get(profile_); | |
588 for (std::set<ExtensionId>::const_iterator it = changed_extensions_.begin(); | |
589 it != changed_extensions_.end(); | |
590 ++it) { | |
591 if (extensions_info_.find(*it) == extensions_info_.end()) { | |
592 const Extension* extension = | |
593 registry->GetExtensionById(*it, ExtensionRegistry::EVERYTHING); | |
594 // |changed_extensions_| may include extensions that have been removed, | |
595 // which leads to the above lookup failing. In this case, just continue. | |
596 if (!extension) | |
597 continue; | |
598 extensions_info_[*it] = ExtensionSet::ExtensionPathAndDefaultLocale( | |
599 extension->path(), LocaleInfo::GetDefaultLocale(extension)); | |
600 } | |
601 } | |
602 } | |
603 | |
604 } // namespace extensions | 516 } // namespace extensions |
OLD | NEW |