Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: mojo/services/package_manager/package_manager.cc

Issue 1775243002: Rename PackageManager->Catalog. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@42cpi
Patch Set: . Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "mojo/services/package_manager/package_manager.h"
6
7 #include "base/bind.h"
8 #include "base/json/json_file_value_serializer.h"
9 #include "base/strings/string_split.h"
10 #include "base/task_runner_util.h"
11 #include "mojo/common/url_type_converters.h"
12 #include "mojo/shell/public/cpp/names.h"
13 #include "mojo/util/filename_util.h"
14 #include "net/base/filename_util.h"
15 #include "url/url_util.h"
16
17 namespace package_manager {
18 namespace {
19
20 CapabilityFilter BuildCapabilityFilterFromDictionary(
21 const base::DictionaryValue& value) {
22 CapabilityFilter filter;
23 base::DictionaryValue::Iterator it(value);
24 for (; !it.IsAtEnd(); it.Advance()) {
25 const base::ListValue* values = nullptr;
26 CHECK(it.value().GetAsList(&values));
27 AllowedInterfaces interfaces;
28 for (auto i = values->begin(); i != values->end(); ++i) {
29 std::string iface_name;
30 const base::Value* v = *i;
31 CHECK(v->GetAsString(&iface_name));
32 interfaces.insert(iface_name);
33 }
34 filter[it.key()] = interfaces;
35 }
36 return filter;
37 }
38
39 ApplicationInfo BuildApplicationInfoFromDictionary(
40 const base::DictionaryValue& value) {
41 ApplicationInfo info;
42 std::string name_string;
43 CHECK(value.GetString(ApplicationCatalogStore::kNameKey, &name_string));
44 CHECK(mojo::IsValidName(name_string)) << "Invalid Name: " << name_string;
45 info.name = name_string;
46 if (value.HasKey(ApplicationCatalogStore::kQualifierKey)) {
47 CHECK(value.GetString(ApplicationCatalogStore::kQualifierKey,
48 &info.qualifier));
49 } else {
50 info.qualifier = mojo::GetNamePath(name_string);
51 }
52 CHECK(value.GetString(ApplicationCatalogStore::kDisplayNameKey,
53 &info.display_name));
54 const base::DictionaryValue* capabilities = nullptr;
55 CHECK(value.GetDictionary(ApplicationCatalogStore::kCapabilitiesKey,
56 &capabilities));
57 info.base_filter = BuildCapabilityFilterFromDictionary(*capabilities);
58 return info;
59 }
60
61 void SerializeEntry(const ApplicationInfo& entry,
62 base::DictionaryValue** value) {
63 *value = new base::DictionaryValue;
64 (*value)->SetString(ApplicationCatalogStore::kNameKey, entry.name);
65 (*value)->SetString(ApplicationCatalogStore::kDisplayNameKey,
66 entry.display_name);
67 base::DictionaryValue* capabilities = new base::DictionaryValue;
68 for (const auto& pair : entry.base_filter) {
69 scoped_ptr<base::ListValue> interfaces(new base::ListValue);
70 for (const auto& iface_name : pair.second)
71 interfaces->AppendString(iface_name);
72 capabilities->Set(pair.first, std::move(interfaces));
73 }
74 (*value)->Set(ApplicationCatalogStore::kCapabilitiesKey,
75 make_scoped_ptr(capabilities));
76 }
77
78 scoped_ptr<base::Value> ReadManifest(const base::FilePath& manifest_path) {
79 JSONFileValueDeserializer deserializer(manifest_path);
80 int error = 0;
81 std::string message;
82 // TODO(beng): probably want to do more detailed error checking. This should
83 // be done when figuring out if to unblock connection completion.
84 return deserializer.Deserialize(&error, &message);
85 }
86
87 } // namespace
88
89 // static
90 const char ApplicationCatalogStore::kNameKey[] = "name";
91 // static
92 const char ApplicationCatalogStore::kQualifierKey[] = "process-group";
93 // static
94 const char ApplicationCatalogStore::kDisplayNameKey[] = "display_name";
95 // static
96 const char ApplicationCatalogStore::kCapabilitiesKey[] = "capabilities";
97
98 ApplicationInfo::ApplicationInfo() {}
99 ApplicationInfo::ApplicationInfo(const ApplicationInfo& other) = default;
100 ApplicationInfo::~ApplicationInfo() {}
101
102 PackageManager::PackageManager(base::TaskRunner* blocking_pool,
103 scoped_ptr<ApplicationCatalogStore> catalog)
104 : blocking_pool_(blocking_pool),
105 catalog_store_(std::move(catalog)),
106 weak_factory_(this) {
107 base::FilePath shell_dir;
108 PathService::Get(base::DIR_MODULE, &shell_dir);
109
110 system_package_dir_ =
111 mojo::util::FilePathToFileURL(shell_dir).Resolve(std::string());
112 system_package_dir_ =
113 mojo::util::AddTrailingSlashIfNeeded(system_package_dir_);
114
115 DeserializeCatalog();
116 }
117 PackageManager::~PackageManager() {}
118
119 bool PackageManager::AcceptConnection(mojo::Connection* connection) {
120 connection->AddInterface<mojom::Catalog>(this);
121 connection->AddInterface<mojom::Resolver>(this);
122 if (connection->GetRemoteIdentity().name() == "mojo:shell")
123 connection->AddInterface<mojo::shell::mojom::ShellResolver>(this);
124 return true;
125 }
126
127 void PackageManager::Create(mojo::Connection* connection,
128 mojom::ResolverRequest request) {
129 resolver_bindings_.AddBinding(this, std::move(request));
130 }
131
132 void PackageManager::Create(mojo::Connection* connection,
133 mojo::shell::mojom::ShellResolverRequest request) {
134 shell_resolver_bindings_.AddBinding(this, std::move(request));
135 }
136
137 void PackageManager::Create(mojo::Connection* connection,
138 mojom::CatalogRequest request) {
139 catalog_bindings_.AddBinding(this, std::move(request));
140 }
141
142 void PackageManager::ResolveResponse(mojo::URLResponsePtr response,
143 const ResolveResponseCallback& callback) {
144 // TODO(beng): implement.
145 }
146
147 void PackageManager::ResolveInterfaces(
148 mojo::Array<mojo::String> interfaces,
149 const ResolveInterfacesCallback& callback) {
150 // TODO(beng): implement.
151 }
152
153 void PackageManager::ResolveMIMEType(const mojo::String& mime_type,
154 const ResolveMIMETypeCallback& callback) {
155 // TODO(beng): implement.
156 }
157
158 void PackageManager::ResolveProtocolScheme(
159 const mojo::String& scheme,
160 const ResolveProtocolSchemeCallback& callback) {
161 // TODO(beng): implement.
162 }
163
164 void PackageManager::ResolveMojoName(const mojo::String& mojo_name,
165 const ResolveMojoNameCallback& callback) {
166 std::string resolved_name = mojo_name;
167 auto alias_iter = mojo_name_aliases_.find(resolved_name);
168 if (alias_iter != mojo_name_aliases_.end())
169 resolved_name = alias_iter->second.first;
170
171 std::string qualifier = mojo::GetNamePath(resolved_name);
172 auto qualifier_iter = qualifiers_.find(resolved_name);
173 if (qualifier_iter != qualifiers_.end())
174 qualifier = qualifier_iter->second;
175
176 if (IsNameInCatalog(resolved_name))
177 CompleteResolveMojoName(resolved_name, qualifier, callback);
178 else
179 AddNameToCatalog(resolved_name, callback);
180 }
181
182 void PackageManager::GetEntries(
183 mojo::Array<mojo::String> names,
184 const GetEntriesCallback& callback) {
185 mojo::Map<mojo::String, mojom::CatalogEntryPtr> entries;
186 std::vector<mojo::String> names_vec = names.PassStorage();
187 for (const std::string& name : names_vec) {
188 if (catalog_.find(name) == catalog_.end())
189 continue;
190 const ApplicationInfo& info = catalog_[name];
191 mojom::CatalogEntryPtr entry(mojom::CatalogEntry::New());
192 entry->display_name = info.display_name;
193 entries[info.name] = std::move(entry);
194 }
195 callback.Run(std::move(entries));
196 }
197
198 void PackageManager::CompleteResolveMojoName(
199 const std::string& resolved_name,
200 const std::string& qualifier,
201 const ResolveMojoNameCallback& callback) {
202 auto info_iter = catalog_.find(resolved_name);
203 CHECK(info_iter != catalog_.end());
204
205 GURL file_url;
206 std::string type = mojo::GetNameType(resolved_name);
207 if (type == "mojo") {
208 // It's still a mojo: URL, use the default mapping scheme.
209 const std::string host = mojo::GetNamePath(resolved_name);
210 file_url = system_package_dir_.Resolve(host + "/" + host + ".mojo");
211 } else if (type == "exe") {
212 #if defined OS_WIN
213 std::string extension = ".exe";
214 #else
215 std::string extension;
216 #endif
217 file_url = system_package_dir_.Resolve(
218 mojo::GetNamePath(resolved_name) + extension);
219 }
220
221 mojo::shell::mojom::CapabilityFilterPtr filter(
222 mojo::shell::mojom::CapabilityFilter::New());
223 filter->filter = mojo::Map<mojo::String, mojo::Array<mojo::String>>();
224 for (const auto& entry : info_iter->second.base_filter) {
225 mojo::Array<mojo::String> interfaces;
226 for (auto interface_name : entry.second)
227 interfaces.push_back(interface_name);
228 filter->filter.insert(entry.first, std::move(interfaces));
229 }
230 callback.Run(resolved_name, qualifier, std::move(filter),
231 file_url.spec());
232 }
233
234 bool PackageManager::IsNameInCatalog(const std::string& name) const {
235 return catalog_.find(name) != catalog_.end();
236 }
237
238 void PackageManager::AddNameToCatalog(
239 const std::string& name,
240 const ResolveMojoNameCallback& callback) {
241 GURL manifest_url = GetManifestURL(name);
242 if (manifest_url.is_empty()) {
243 // The name is of some form that can't be resolved to a manifest (e.g. some
244 // scheme used for tests). Just pass it back to the caller so it can be
245 // loaded with a custom loader.
246 callback.Run(name, mojo::GetNamePath(name), nullptr, nullptr);
247 return;
248 }
249
250 std::string type = mojo::GetNameType(name);
251 CHECK(type == "mojo" || type == "exe");
252 base::FilePath manifest_path;
253 CHECK(net::FileURLToFilePath(manifest_url, &manifest_path));
254 base::PostTaskAndReplyWithResult(
255 blocking_pool_, FROM_HERE, base::Bind(&ReadManifest, manifest_path),
256 base::Bind(&PackageManager::OnReadManifest, weak_factory_.GetWeakPtr(),
257 name, callback));
258 }
259
260 void PackageManager::DeserializeCatalog() {
261 if (!catalog_store_)
262 return;
263 const base::ListValue* catalog = catalog_store_->GetStore();
264 CHECK(catalog);
265 // TODO(sky): make this handle aliases.
266 for (auto it = catalog->begin(); it != catalog->end(); ++it) {
267 const base::DictionaryValue* dictionary = nullptr;
268 const base::Value* v = *it;
269 CHECK(v->GetAsDictionary(&dictionary));
270 const ApplicationInfo app_info =
271 BuildApplicationInfoFromDictionary(*dictionary);
272 catalog_[app_info.name] = app_info;
273 }
274 }
275
276 void PackageManager::SerializeCatalog() {
277 scoped_ptr<base::ListValue> catalog(new base::ListValue);
278 for (const auto& info : catalog_) {
279 base::DictionaryValue* dictionary = nullptr;
280 SerializeEntry(info.second, &dictionary);
281 catalog->Append(make_scoped_ptr(dictionary));
282 }
283 if (catalog_store_)
284 catalog_store_->UpdateStore(std::move(catalog));
285 }
286
287 const ApplicationInfo& PackageManager::DeserializeApplication(
288 const base::DictionaryValue* dictionary) {
289 ApplicationInfo info = BuildApplicationInfoFromDictionary(*dictionary);
290 if (catalog_.find(info.name) == catalog_.end()) {
291 catalog_[info.name] = info;
292
293 if (dictionary->HasKey("applications")) {
294 const base::ListValue* applications = nullptr;
295 dictionary->GetList("applications", &applications);
296 for (size_t i = 0; i < applications->GetSize(); ++i) {
297 const base::DictionaryValue* child = nullptr;
298 applications->GetDictionary(i, &child);
299 const ApplicationInfo& child_info = DeserializeApplication(child);
300 mojo_name_aliases_[child_info.name] =
301 std::make_pair(info.name, child_info.qualifier);
302 }
303 }
304 qualifiers_[info.name] = info.qualifier;
305 }
306 return catalog_[info.name];
307 }
308
309 GURL PackageManager::GetManifestURL(const std::string& name) {
310 // TODO(beng): think more about how this should be done for exe targets.
311 std::string type = mojo::GetNameType(name);
312 std::string path = mojo::GetNamePath(name);
313 if (type == "mojo")
314 return system_package_dir_.Resolve(path + "/manifest.json");
315 else if (type == "exe")
316 return system_package_dir_.Resolve(path + "_manifest.json");
317 return GURL();
318 }
319
320 // static
321 void PackageManager::OnReadManifest(base::WeakPtr<PackageManager> pm,
322 const std::string& name,
323 const ResolveMojoNameCallback& callback,
324 scoped_ptr<base::Value> manifest) {
325 if (!pm) {
326 // The PackageManager was destroyed, we're likely in shutdown. Run the
327 // callback so we don't trigger a DCHECK.
328 callback.Run(name, mojo::GetNamePath(name), nullptr, nullptr);
329 return;
330 }
331 pm->OnReadManifestImpl(name, callback, std::move(manifest));
332 }
333
334 void PackageManager::OnReadManifestImpl(const std::string& name,
335 const ResolveMojoNameCallback& callback,
336 scoped_ptr<base::Value> manifest) {
337 if (manifest) {
338 base::DictionaryValue* dictionary = nullptr;
339 CHECK(manifest->GetAsDictionary(&dictionary));
340 DeserializeApplication(dictionary);
341 } else {
342 ApplicationInfo info;
343 info.name = name;
344 info.display_name = name;
345 catalog_[info.name] = info;
346 qualifiers_[info.name] = mojo::GetNamePath(name);
347 }
348 SerializeCatalog();
349
350 auto qualifier_iter = qualifiers_.find(name);
351 DCHECK(qualifier_iter != qualifiers_.end());
352 std::string qualifier = qualifier_iter->second;
353 CompleteResolveMojoName(name, qualifier, callback);
354 }
355
356 } // namespace package_manager
OLDNEW
« no previous file with comments | « mojo/services/package_manager/package_manager.h ('k') | mojo/services/package_manager/public/interfaces/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698