| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "services/catalog/instance.h" |
| |
| #include "base/bind.h" |
| #include "services/catalog/entry.h" |
| #include "services/catalog/manifest_provider.h" |
| #include "services/catalog/reader.h" |
| #include "services/catalog/store.h" |
| #include "services/shell/public/cpp/names.h" |
| |
| namespace catalog { |
| namespace { |
| |
| void AddEntry(const Entry& entry, std::vector<mojom::EntryPtr>* ary) { |
| mojom::EntryPtr entry_ptr(mojom::Entry::New()); |
| entry_ptr->name = entry.name(); |
| entry_ptr->display_name = entry.display_name(); |
| ary->push_back(std::move(entry_ptr)); |
| } |
| |
| } // namespace |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // Instance, public: |
| |
| Instance::Instance(std::unique_ptr<Store> store, Reader* system_reader) |
| : store_(std::move(store)), |
| system_reader_(system_reader), |
| weak_factory_(this) {} |
| Instance::~Instance() {} |
| |
| void Instance::BindResolver(shell::mojom::ResolverRequest request) { |
| if (system_cache_) |
| resolver_bindings_.AddBinding(this, std::move(request)); |
| else |
| pending_resolver_requests_.push_back(std::move(request)); |
| } |
| |
| void Instance::BindCatalog(mojom::CatalogRequest request) { |
| if (system_cache_) |
| catalog_bindings_.AddBinding(this, std::move(request)); |
| else |
| pending_catalog_requests_.push_back(std::move(request)); |
| } |
| |
| void Instance::CacheReady(EntryCache* cache) { |
| system_cache_ = cache; |
| DeserializeCatalog(); |
| for (auto& request : pending_resolver_requests_) |
| BindResolver(std::move(request)); |
| for (auto& request : pending_catalog_requests_) |
| BindCatalog(std::move(request)); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // Instance, shell::mojom::Resolver: |
| |
| void Instance::ResolveMojoName(const std::string& mojo_name, |
| const ResolveMojoNameCallback& callback) { |
| DCHECK(system_cache_); |
| |
| std::string type = shell::GetNameType(mojo_name); |
| if (type != shell::kNameType_Mojo && type != shell::kNameType_Exe) { |
| std::unique_ptr<Entry> entry(new Entry(mojo_name)); |
| shell::mojom::ResolveResultPtr result = |
| shell::mojom::ResolveResult::From(*entry); |
| result->capabilities = base::nullopt; |
| callback.Run(std::move(result)); |
| return; |
| } |
| |
| // TODO(beng): per-user catalogs. |
| auto entry = system_cache_->find(mojo_name); |
| if (entry != system_cache_->end()) { |
| callback.Run(shell::mojom::ResolveResult::From(*entry->second)); |
| return; |
| } |
| |
| // Manifests for mojo: names should always be in the catalog by this point. |
| //DCHECK(type == shell::kNameType_Exe); |
| system_reader_->CreateEntryForName( |
| mojo_name, system_cache_, |
| base::Bind(&Instance::OnReadManifest, weak_factory_.GetWeakPtr(), |
| mojo_name, callback)); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // Instance, mojom::Catalog: |
| |
| void Instance::GetEntries(const base::Optional<std::vector<std::string>>& names, |
| const GetEntriesCallback& callback) { |
| DCHECK(system_cache_); |
| |
| std::vector<mojom::EntryPtr> entries; |
| if (!names.has_value()) { |
| // TODO(beng): user catalog. |
| for (const auto& entry : *system_cache_) |
| AddEntry(*entry.second, &entries); |
| } else { |
| for (const std::string& name : names.value()) { |
| Entry* entry = nullptr; |
| // TODO(beng): user catalog. |
| if (system_cache_->find(name) != system_cache_->end()) |
| entry = (*system_cache_)[name].get(); |
| else |
| continue; |
| AddEntry(*entry, &entries); |
| } |
| } |
| callback.Run(std::move(entries)); |
| } |
| |
| void Instance::GetEntriesProvidingClass( |
| const std::string& clazz, |
| const GetEntriesProvidingClassCallback& callback) { |
| std::vector<mojom::EntryPtr> entries; |
| for (const auto& entry : *system_cache_) |
| if (entry.second->ProvidesClass(clazz)) |
| entries.push_back(mojom::Entry::From(*entry.second)); |
| callback.Run(std::move(entries)); |
| } |
| |
| void Instance::GetEntriesConsumingMIMEType( |
| const std::string& mime_type, |
| const GetEntriesConsumingMIMETypeCallback& callback) { |
| // TODO(beng): implement. |
| } |
| |
| void Instance::GetEntriesSupportingScheme( |
| const std::string& scheme, |
| const GetEntriesSupportingSchemeCallback& callback) { |
| // TODO(beng): implement. |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // Instance, private: |
| |
| void Instance::DeserializeCatalog() { |
| DCHECK(system_cache_); |
| if (!store_) |
| return; |
| const base::ListValue* catalog = store_->GetStore(); |
| CHECK(catalog); |
| // TODO(sky): make this handle aliases. |
| // TODO(beng): implement this properly! |
| for (const auto& v : *catalog) { |
| const base::DictionaryValue* dictionary = nullptr; |
| CHECK(v->GetAsDictionary(&dictionary)); |
| std::unique_ptr<Entry> entry = Entry::Deserialize(*dictionary); |
| // TODO(beng): user catalog. |
| if (entry) |
| (*system_cache_)[entry->name()] = std::move(entry); |
| } |
| } |
| |
| void Instance::SerializeCatalog() { |
| DCHECK(system_cache_); |
| std::unique_ptr<base::ListValue> catalog(new base::ListValue); |
| // TODO(beng): user catalog. |
| for (const auto& entry : *system_cache_) |
| catalog->Append(entry.second->Serialize()); |
| if (store_) |
| store_->UpdateStore(std::move(catalog)); |
| } |
| |
| // static |
| void Instance::OnReadManifest(base::WeakPtr<Instance> instance, |
| const std::string& mojo_name, |
| const ResolveMojoNameCallback& callback, |
| shell::mojom::ResolveResultPtr result) { |
| callback.Run(std::move(result)); |
| if (instance) |
| instance->SerializeCatalog(); |
| } |
| |
| } // namespace catalog |