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