OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/extensions/shared_user_script_master.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/memory/shared_memory.h" | |
9 #include "chrome/browser/chrome_notification_types.h" | |
10 #include "chrome/browser/extensions/extension_util.h" | |
11 #include "chrome/browser/profiles/profile.h" | |
12 #include "chrome/common/extensions/api/i18n/default_locale_handler.h" | |
13 #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" | |
14 #include "content/public/browser/notification_service.h" | |
15 #include "content/public/browser/render_process_host.h" | |
16 #include "extensions/browser/content_verifier.h" | |
17 #include "extensions/browser/extension_system.h" | |
18 | |
19 namespace extensions { | |
20 | |
21 SharedUserScriptMaster::SharedUserScriptMaster(Profile* profile) | |
22 : UserScriptMaster(profile), extension_registry_observer_(this) { | |
23 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); | |
24 registrar_.Add(this, | |
25 chrome::NOTIFICATION_EXTENSIONS_READY, | |
26 content::Source<Profile>(profile_)); | |
27 registrar_.Add(this, | |
28 content::NOTIFICATION_RENDERER_PROCESS_CREATED, | |
29 content::NotificationService::AllBrowserContextsAndSources()); | |
30 } | |
31 | |
32 SharedUserScriptMaster::~SharedUserScriptMaster() { | |
33 } | |
34 | |
35 void SharedUserScriptMaster::OnExtensionLoaded( | |
36 content::BrowserContext* browser_context, | |
37 const Extension* extension) { | |
38 added_extensions_.insert(extension->id()); | |
39 removed_extensions_.erase(extension->id()); | |
40 extensions_info_[extension->id()] = | |
41 ExtensionSet::ExtensionPathAndDefaultLocale( | |
42 extension->path(), LocaleInfo::GetDefaultLocale(extension)); | |
43 if (extensions_service_ready_) { | |
44 changed_extensions_.insert(extension->id()); | |
45 if (is_loading()) | |
46 pending_load_ = true; | |
47 else | |
48 StartLoad(); | |
49 } | |
50 } | |
51 | |
52 void SharedUserScriptMaster::OnExtensionUnloaded( | |
53 content::BrowserContext* browser_context, | |
54 const Extension* extension, | |
55 UnloadedExtensionInfo::Reason reason) { | |
56 removed_extensions_.insert(extension->id()); | |
57 added_extensions_.erase(extension->id()); | |
58 // Remove any content scripts. | |
59 extensions_info_.erase(extension->id()); | |
60 changed_extensions_.insert(extension->id()); | |
61 if (is_loading()) | |
62 pending_load_ = true; | |
63 else | |
64 StartLoad(); | |
65 } | |
66 | |
67 void SharedUserScriptMaster::Observe( | |
68 int type, | |
69 const content::NotificationSource& source, | |
70 const content::NotificationDetails& details) { | |
71 bool should_start_load = false; | |
72 switch (type) { | |
73 case chrome::NOTIFICATION_EXTENSIONS_READY: | |
74 extensions_service_ready_ = true; | |
75 should_start_load = true; | |
76 break; | |
77 case content::NOTIFICATION_RENDERER_PROCESS_CREATED: { | |
78 content::RenderProcessHost* process = | |
79 content::Source<content::RenderProcessHost>(source).ptr(); | |
80 Profile* profile = | |
81 Profile::FromBrowserContext(process->GetBrowserContext()); | |
82 if (!profile_->IsSameProfile(profile)) | |
83 return; | |
84 if (ScriptsReady()) { | |
85 SendUpdate(process, | |
Devlin
2014/07/30 21:20:38
(This comment is in a random spot)
To me, this wh
| |
86 GetSharedMemory(), | |
87 std::set<std::string>()); // Include all extensions. | |
88 } | |
89 break; | |
90 } | |
91 default: | |
92 DCHECK(false); | |
93 } | |
94 | |
95 if (should_start_load) { | |
96 if (is_loading()) | |
97 pending_load_ = true; | |
98 else | |
99 StartLoad(); | |
100 } | |
101 } | |
102 | |
103 void SharedUserScriptMaster::StartLoad() { | |
104 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
105 DCHECK(!is_loading()); | |
106 | |
107 // Remove any user scripts belonging to any extension that was updated or | |
108 // removed. | |
109 for (UserScriptList::iterator iter = user_scripts_->begin(); | |
110 iter != user_scripts_->end();) { | |
111 if (removed_extensions_.count(iter->extension_id()) > 0 || | |
112 added_extensions_.count(iter->extension_id()) > 0) { | |
113 iter = user_scripts_->erase(iter); | |
114 } else { | |
115 ++iter; | |
116 } | |
117 } | |
118 | |
119 // Add any content scripts for extensions that were recently loaded. | |
120 const ExtensionSet& enabled_extensions = | |
121 ExtensionRegistry::Get(profile_)->enabled_extensions(); | |
122 for (std::set<std::string>::const_iterator iter = added_extensions_.begin(); | |
123 iter != added_extensions_.end(); | |
124 ++iter) { | |
125 const Extension* extension = enabled_extensions.GetByID(*iter); | |
126 if (!extension) | |
127 continue; | |
128 bool incognito_enabled = | |
129 util::IsIncognitoEnabled(extension->id(), profile_); | |
130 const UserScriptList& scripts = | |
131 ContentScriptsInfo::GetContentScripts(extension); | |
132 for (UserScriptList::const_iterator script = scripts.begin(); | |
133 script != scripts.end(); | |
134 ++script) { | |
135 user_scripts_->push_back(*script); | |
136 user_scripts_->back().set_incognito_enabled(incognito_enabled); | |
137 } | |
138 } | |
139 | |
140 content::BrowserThread::PostTask( | |
141 content::BrowserThread::FILE, | |
142 FROM_HERE, | |
143 base::Bind(&UserScriptMaster::LoadScriptsOnFileThread, | |
144 base::Passed(&user_scripts_), | |
145 extensions_info_, | |
146 added_extensions_, | |
147 make_scoped_refptr( | |
148 ExtensionSystem::Get(profile_)->content_verifier()), | |
149 base::Bind(&UserScriptMaster::OnScriptsLoaded, | |
150 weak_factory_.GetWeakPtr()))); | |
151 added_extensions_.clear(); | |
152 removed_extensions_.clear(); | |
153 user_scripts_.reset(NULL); | |
154 } | |
155 | |
156 } // namespace extensions | |
OLD | NEW |