Roll src/third_party/skia ce86687:b880d7f
[chromium-blink-merge.git] / extensions / browser / extension_user_script_loader.cc
blobdafcdd51a1b12d708c7f4d58edc1d11aa5746a95
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
3 // found in the LICENSE file.
5 #include "extensions/browser/extension_user_script_loader.h"
7 #include <set>
8 #include <string>
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h"
14 #include "base/version.h"
15 #include "content/public/browser/browser_context.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/notification_service.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "extensions/browser/component_extension_resource_manager.h"
20 #include "extensions/browser/content_verifier.h"
21 #include "extensions/browser/extension_registry.h"
22 #include "extensions/browser/extension_system.h"
23 #include "extensions/browser/extensions_browser_client.h"
24 #include "extensions/common/file_util.h"
25 #include "extensions/common/manifest_handlers/default_locale_handler.h"
26 #include "extensions/common/message_bundle.h"
27 #include "extensions/common/one_shot_event.h"
28 #include "ui/base/resource/resource_bundle.h"
30 using content::BrowserContext;
32 namespace extensions {
34 namespace {
36 // Verifies file contents as they are read.
37 void VerifyContent(const scoped_refptr<ContentVerifier>& verifier,
38 const std::string& extension_id,
39 const base::FilePath& extension_root,
40 const base::FilePath& relative_path,
41 const std::string& content) {
42 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
43 scoped_refptr<ContentVerifyJob> job(
44 verifier->CreateJobFor(extension_id, extension_root, relative_path));
45 if (job.get()) {
46 job->Start();
47 job->BytesRead(content.size(), content.data());
48 job->DoneReading();
52 // Loads user scripts from the extension who owns these scripts.
53 bool ExtensionLoadScriptContent(
54 const HostID& host_id,
55 UserScript::File* script_file,
56 const UserScriptLoader::SubstitutionMap* localization_messages,
57 const scoped_refptr<ContentVerifier>& verifier) {
58 DCHECK(script_file);
59 std::string content;
60 const base::FilePath& path = ExtensionResource::GetFilePath(
61 script_file->extension_root(), script_file->relative_path(),
62 ExtensionResource::SYMLINKS_MUST_RESOLVE_WITHIN_ROOT);
63 if (path.empty()) {
64 int resource_id = 0;
65 if (ExtensionsBrowserClient::Get()
66 ->GetComponentExtensionResourceManager()
67 ->IsComponentExtensionResource(script_file->extension_root(),
68 script_file->relative_path(),
69 &resource_id)) {
70 const ResourceBundle& rb = ResourceBundle::GetSharedInstance();
71 content = rb.GetRawDataResource(resource_id).as_string();
72 } else {
73 LOG(WARNING) << "Failed to get file path to "
74 << script_file->relative_path().value() << " from "
75 << script_file->extension_root().value();
76 return false;
78 } else {
79 if (!base::ReadFileToString(path, &content)) {
80 LOG(WARNING) << "Failed to load user script file: " << path.value();
81 return false;
83 if (verifier.get()) {
84 content::BrowserThread::PostTask(
85 content::BrowserThread::IO, FROM_HERE,
86 base::Bind(&VerifyContent, verifier, host_id.id(),
87 script_file->extension_root(),
88 script_file->relative_path(), content));
92 // Localize the content.
93 if (localization_messages) {
94 std::string error;
95 MessageBundle::ReplaceMessagesWithExternalDictionary(*localization_messages,
96 &content, &error);
97 if (!error.empty())
98 LOG(WARNING) << "Failed to replace messages in script: " << error;
101 // Remove BOM from the content.
102 std::string::size_type index = content.find(base::kUtf8ByteOrderMark);
103 if (index == 0)
104 script_file->set_content(content.substr(strlen(base::kUtf8ByteOrderMark)));
105 else
106 script_file->set_content(content);
108 return true;
111 } // namespace
113 ExtensionUserScriptLoader::ExtensionUserScriptLoader(
114 BrowserContext* browser_context,
115 const HostID& host_id,
116 bool listen_for_extension_system_loaded)
117 : UserScriptLoader(
118 browser_context,
119 host_id,
120 ExtensionSystem::Get(browser_context)->content_verifier()),
121 extension_registry_observer_(this),
122 weak_factory_(this) {
123 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context));
124 if (listen_for_extension_system_loaded) {
125 ExtensionSystem::Get(browser_context)
126 ->ready()
127 .Post(FROM_HERE,
128 base::Bind(&ExtensionUserScriptLoader::OnExtensionSystemReady,
129 weak_factory_.GetWeakPtr()));
130 } else {
131 SetReady(true);
135 ExtensionUserScriptLoader::~ExtensionUserScriptLoader() {
138 void ExtensionUserScriptLoader::UpdateHostsInfo(
139 const std::set<HostID>& changed_hosts) {
140 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
141 for (const HostID& host_id : changed_hosts) {
142 const Extension* extension =
143 registry->GetExtensionById(host_id.id(), ExtensionRegistry::ENABLED);
144 // |changed_hosts_| may include hosts that have been removed,
145 // which leads to the above lookup failing. In this case, just continue.
146 if (!extension)
147 continue;
148 AddHostInfo(host_id, ExtensionSet::ExtensionPathAndDefaultLocale(
149 extension->path(),
150 LocaleInfo::GetDefaultLocale(extension)));
154 UserScriptLoader::LoadUserScriptsContentFunction
155 ExtensionUserScriptLoader::GetLoadUserScriptsFunction() {
156 return base::Bind(&ExtensionLoadScriptContent);
159 void ExtensionUserScriptLoader::OnExtensionUnloaded(
160 content::BrowserContext* browser_context,
161 const Extension* extension,
162 UnloadedExtensionInfo::Reason reason) {
163 RemoveHostInfo(HostID(HostID::EXTENSIONS, extension->id()));
166 void ExtensionUserScriptLoader::OnExtensionSystemReady() {
167 SetReady(true);
170 } // namespace extensions