OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "extensions/browser/extension_user_script_loader.h" | 5 #include "extensions/browser/extension_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" |
(...skipping 15 matching lines...) Expand all Loading... | |
26 #include "extensions/common/message_bundle.h" | 26 #include "extensions/common/message_bundle.h" |
27 #include "extensions/common/one_shot_event.h" | 27 #include "extensions/common/one_shot_event.h" |
28 #include "ui/base/resource/resource_bundle.h" | 28 #include "ui/base/resource/resource_bundle.h" |
29 | 29 |
30 using content::BrowserContext; | 30 using content::BrowserContext; |
31 | 31 |
32 namespace extensions { | 32 namespace extensions { |
33 | 33 |
34 namespace { | 34 namespace { |
35 | 35 |
36 using LoadScriptsCallback = | |
37 base::Callback<void(scoped_ptr<UserScriptList>, | |
38 scoped_ptr<base::SharedMemory>)>; | |
39 | |
36 // Verifies file contents as they are read. | 40 // Verifies file contents as they are read. |
37 void VerifyContent(const scoped_refptr<ContentVerifier>& verifier, | 41 void VerifyContent(const scoped_refptr<ContentVerifier>& verifier, |
38 const std::string& extension_id, | 42 const std::string& extension_id, |
39 const base::FilePath& extension_root, | 43 const base::FilePath& extension_root, |
40 const base::FilePath& relative_path, | 44 const base::FilePath& relative_path, |
41 const std::string& content) { | 45 const std::string& content) { |
42 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 46 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
43 scoped_refptr<ContentVerifyJob> job( | 47 scoped_refptr<ContentVerifyJob> job( |
44 verifier->CreateJobFor(extension_id, extension_root, relative_path)); | 48 verifier->CreateJobFor(extension_id, extension_root, relative_path)); |
45 if (job.get()) { | 49 if (job.get()) { |
46 job->Start(); | 50 job->Start(); |
47 job->BytesRead(content.size(), content.data()); | 51 job->BytesRead(content.size(), content.data()); |
48 job->DoneReading(); | 52 job->DoneReading(); |
49 } | 53 } |
50 } | 54 } |
51 | 55 |
52 // Loads user scripts from the extension who owns these scripts. | 56 // Loads user scripts from the extension who owns these scripts. |
53 bool ExtensionLoadScriptContent( | 57 bool LoadScriptContent( |
54 const HostID& host_id, | 58 const HostID& host_id, |
55 UserScript::File* script_file, | 59 UserScript::File* script_file, |
56 const UserScriptLoader::SubstitutionMap* localization_messages, | 60 const UserScriptLoader::SubstitutionMap* localization_messages, |
57 const scoped_refptr<ContentVerifier>& verifier) { | 61 const scoped_refptr<ContentVerifier>& verifier) { |
58 DCHECK(script_file); | 62 DCHECK(script_file); |
59 std::string content; | 63 std::string content; |
60 const base::FilePath& path = ExtensionResource::GetFilePath( | 64 const base::FilePath& path = ExtensionResource::GetFilePath( |
61 script_file->extension_root(), script_file->relative_path(), | 65 script_file->extension_root(), script_file->relative_path(), |
62 ExtensionResource::SYMLINKS_MUST_RESOLVE_WITHIN_ROOT); | 66 ExtensionResource::SYMLINKS_MUST_RESOLVE_WITHIN_ROOT); |
63 if (path.empty()) { | 67 if (path.empty()) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
101 // Remove BOM from the content. | 105 // Remove BOM from the content. |
102 std::string::size_type index = content.find(base::kUtf8ByteOrderMark); | 106 std::string::size_type index = content.find(base::kUtf8ByteOrderMark); |
103 if (index == 0) | 107 if (index == 0) |
104 script_file->set_content(content.substr(strlen(base::kUtf8ByteOrderMark))); | 108 script_file->set_content(content.substr(strlen(base::kUtf8ByteOrderMark))); |
105 else | 109 else |
106 script_file->set_content(content); | 110 script_file->set_content(content); |
107 | 111 |
108 return true; | 112 return true; |
109 } | 113 } |
110 | 114 |
115 UserScriptLoader::SubstitutionMap* GetLocalizationMessages( | |
116 const UserScriptLoader::HostsInfo& hosts_info, | |
117 const HostID& host_id) { | |
118 UserScriptLoader::HostsInfo::const_iterator iter = hosts_info.find(host_id); | |
119 if (iter == hosts_info.end()) | |
120 return nullptr; | |
121 return file_util::LoadMessageBundleSubstitutionMap( | |
122 iter->second.first, host_id.id(), iter->second.second); | |
123 } | |
124 | |
125 void LoadUserScripts(UserScriptList* user_scripts, | |
126 const UserScriptLoader::HostsInfo& hosts_info, | |
127 const std::set<int>& added_script_ids, | |
128 const scoped_refptr<ContentVerifier>& verifier) { | |
129 for (UserScriptList::iterator script = user_scripts->begin(); | |
130 script != user_scripts->end(); ++script) { | |
131 if (added_script_ids.count(script->id()) == 0) | |
132 continue; | |
133 scoped_ptr<UserScriptLoader::SubstitutionMap> localization_messages( | |
134 GetLocalizationMessages(hosts_info, script->host_id())); | |
135 for (size_t k = 0; k < script->js_scripts().size(); ++k) { | |
136 UserScript::File& script_file = script->js_scripts()[k]; | |
137 if (script_file.GetContent().empty()) | |
138 LoadScriptContent(script->host_id(), &script_file, NULL, verifier); | |
139 } | |
140 for (size_t k = 0; k < script->css_scripts().size(); ++k) { | |
141 UserScript::File& script_file = script->css_scripts()[k]; | |
142 if (script_file.GetContent().empty()) | |
143 LoadScriptContent(script->host_id(), &script_file, | |
144 localization_messages.get(), verifier); | |
145 } | |
146 } | |
147 } | |
148 | |
149 void LoadScriptsOnFileThread(scoped_ptr<UserScriptList> user_scripts, | |
150 const UserScriptLoader::HostsInfo& hosts_info, | |
151 const std::set<int>& added_script_ids, | |
152 const scoped_refptr<ContentVerifier>& verifier, | |
153 LoadScriptsCallback callback) { | |
154 DCHECK(user_scripts.get()); | |
155 LoadUserScripts(user_scripts.get(), hosts_info, added_script_ids, verifier); | |
156 scoped_ptr<base::SharedMemory> memory = | |
157 UserScriptLoader::Serialize(*user_scripts); | |
158 content::BrowserThread::PostTask( | |
159 content::BrowserThread::UI, FROM_HERE, | |
160 base::Bind(callback, base::Passed(&user_scripts), base::Passed(&memory))); | |
161 } | |
162 | |
111 } // namespace | 163 } // namespace |
112 | 164 |
113 ExtensionUserScriptLoader::ExtensionUserScriptLoader( | 165 ExtensionUserScriptLoader::ExtensionUserScriptLoader( |
114 BrowserContext* browser_context, | 166 BrowserContext* browser_context, |
115 const HostID& host_id, | 167 const HostID& host_id, |
116 bool listen_for_extension_system_loaded) | 168 bool listen_for_extension_system_loaded) |
117 : UserScriptLoader( | 169 : UserScriptLoader(browser_context, host_id), |
118 browser_context, | 170 content_verifier_( |
119 host_id, | |
120 ExtensionSystem::Get(browser_context)->content_verifier()), | 171 ExtensionSystem::Get(browser_context)->content_verifier()), |
121 extension_registry_observer_(this), | 172 extension_registry_observer_(this), |
122 weak_factory_(this) { | 173 weak_factory_(this) { |
123 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context)); | 174 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context)); |
124 if (listen_for_extension_system_loaded) { | 175 if (listen_for_extension_system_loaded) { |
125 ExtensionSystem::Get(browser_context) | 176 ExtensionSystem::Get(browser_context) |
126 ->ready() | 177 ->ready() |
127 .Post(FROM_HERE, | 178 .Post(FROM_HERE, |
128 base::Bind(&ExtensionUserScriptLoader::OnExtensionSystemReady, | 179 base::Bind(&ExtensionUserScriptLoader::OnExtensionSystemReady, |
129 weak_factory_.GetWeakPtr())); | 180 weak_factory_.GetWeakPtr())); |
130 } else { | 181 } else { |
131 SetReady(true); | 182 SetReady(true); |
132 } | 183 } |
133 } | 184 } |
134 | 185 |
135 ExtensionUserScriptLoader::~ExtensionUserScriptLoader() { | 186 ExtensionUserScriptLoader::~ExtensionUserScriptLoader() { |
136 } | 187 } |
137 | 188 |
189 void ExtensionUserScriptLoader::LoadScriptsForTest( | |
190 UserScriptList* user_scripts) { | |
191 HostsInfo info; | |
192 std::set<int> added_script_ids; | |
193 for (UserScriptList::iterator it = user_scripts->begin(); | |
194 it != user_scripts->end(); ++it) { | |
195 added_script_ids.insert(it->id()); | |
196 } | |
197 LoadUserScripts(user_scripts, info, added_script_ids, | |
198 NULL /* no verifier for testing */); | |
199 } | |
200 | |
201 void ExtensionUserScriptLoader::LoadScripts( | |
Devlin
2015/04/20 23:48:25
This would be cleaner if we kept the |user_scripts
Xi Han
2015/04/21 21:18:58
Change |user_scripts_| to a private member of base
| |
202 const std::set<HostID>& changed_hosts, | |
203 const std::set<int>& added_script_ids) { | |
204 UpdateHostsInfo(changed_hosts); | |
205 | |
206 content::BrowserThread::PostTask( | |
207 content::BrowserThread::FILE, FROM_HERE, | |
208 base::Bind(&LoadScriptsOnFileThread, base::Passed(&user_scripts_), | |
209 hosts_info_, added_script_ids, content_verifier_, | |
210 base::Bind(&ExtensionUserScriptLoader::OnScriptsLoaded, | |
211 weak_factory_.GetWeakPtr()))); | |
212 ClearScripts(false); | |
213 user_scripts_.reset(NULL); | |
214 } | |
215 | |
138 void ExtensionUserScriptLoader::UpdateHostsInfo( | 216 void ExtensionUserScriptLoader::UpdateHostsInfo( |
139 const std::set<HostID>& changed_hosts) { | 217 const std::set<HostID>& changed_hosts) { |
140 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context()); | 218 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context()); |
141 for (const HostID& host_id : changed_hosts) { | 219 for (const HostID& host_id : changed_hosts) { |
142 const Extension* extension = | 220 const Extension* extension = |
143 registry->GetExtensionById(host_id.id(), ExtensionRegistry::ENABLED); | 221 registry->GetExtensionById(host_id.id(), ExtensionRegistry::ENABLED); |
144 // |changed_hosts_| may include hosts that have been removed, | 222 // |changed_hosts_| may include hosts that have been removed, |
145 // which leads to the above lookup failing. In this case, just continue. | 223 // which leads to the above lookup failing. In this case, just continue. |
146 if (!extension) | 224 if (!extension) |
147 continue; | 225 continue; |
148 AddHostInfo(host_id, ExtensionSet::ExtensionPathAndDefaultLocale( | 226 if (hosts_info_.find(host_id) != hosts_info_.end()) |
149 extension->path(), | 227 return; |
Devlin
2015/04/20 23:48:25
Why return? Shouldn't it be continue?
Xi Han
2015/04/21 21:18:58
Good catch, thanks.
| |
150 LocaleInfo::GetDefaultLocale(extension))); | 228 hosts_info_[host_id] = ExtensionSet::ExtensionPathAndDefaultLocale( |
229 extension->path(), LocaleInfo::GetDefaultLocale(extension)); | |
151 } | 230 } |
152 } | 231 } |
153 | 232 |
154 UserScriptLoader::LoadUserScriptsContentFunction | |
155 ExtensionUserScriptLoader::GetLoadUserScriptsFunction() { | |
156 return base::Bind(&ExtensionLoadScriptContent); | |
157 } | |
158 | |
159 void ExtensionUserScriptLoader::OnExtensionUnloaded( | 233 void ExtensionUserScriptLoader::OnExtensionUnloaded( |
160 content::BrowserContext* browser_context, | 234 content::BrowserContext* browser_context, |
161 const Extension* extension, | 235 const Extension* extension, |
162 UnloadedExtensionInfo::Reason reason) { | 236 UnloadedExtensionInfo::Reason reason) { |
163 RemoveHostInfo(HostID(HostID::EXTENSIONS, extension->id())); | 237 hosts_info_.erase(HostID(HostID::EXTENSIONS, extension->id())); |
164 } | 238 } |
165 | 239 |
166 void ExtensionUserScriptLoader::OnExtensionSystemReady() { | 240 void ExtensionUserScriptLoader::OnExtensionSystemReady() { |
167 SetReady(true); | 241 SetReady(true); |
168 } | 242 } |
169 | 243 |
170 } // namespace extensions | 244 } // namespace extensions |
OLD | NEW |