Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 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 "mojo/services/catalog/catalog.h" | 5 #include "mojo/services/catalog/catalog.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/json/json_file_value_serializer.h" | |
| 8 #include "base/strings/string_split.h" | 9 #include "base/strings/string_split.h" |
| 9 #include "base/task_runner_util.h" | 10 #include "base/task_runner_util.h" |
| 10 #include "mojo/common/url_type_converters.h" | 11 #include "mojo/common/url_type_converters.h" |
| 11 #include "mojo/services/catalog/entry.h" | 12 #include "mojo/services/catalog/entry.h" |
| 12 #include "mojo/services/catalog/store.h" | 13 #include "mojo/services/catalog/store.h" |
| 13 #include "mojo/shell/public/cpp/names.h" | 14 #include "mojo/shell/public/cpp/names.h" |
| 14 #include "mojo/util/filename_util.h" | |
| 15 #include "url/gurl.h" | 15 #include "url/gurl.h" |
| 16 #include "url/url_util.h" | 16 #include "url/url_util.h" |
| 17 | 17 |
| 18 namespace catalog { | 18 namespace catalog { |
| 19 namespace { | |
| 20 | |
| 21 base::FilePath GetManifestPath(const base::FilePath& package_dir, | |
| 22 const std::string& name) { | |
| 23 // TODO(beng): think more about how this should be done for exe targets. | |
| 24 std::string type = mojo::GetNameType(name); | |
| 25 std::string path = mojo::GetNamePath(name); | |
| 26 if (type == "mojo") | |
| 27 return package_dir.AppendASCII(path + "/manifest.json"); | |
| 28 else if (type == "exe") | |
|
sky
2016/03/23 23:42:37
nit: no need for else.
| |
| 29 return package_dir.AppendASCII(path + "_manifest.json"); | |
| 30 return base::FilePath(); | |
| 31 } | |
| 32 | |
| 33 base::FilePath GetPackagePath(const base::FilePath& package_dir, | |
| 34 const std::string& name) { | |
| 35 std::string type = mojo::GetNameType(name); | |
| 36 if (type == "mojo") { | |
|
sky
2016/03/23 23:42:37
nit: would be nice to have these constants defined
| |
| 37 // It's still a mojo: URL, use the default mapping scheme. | |
| 38 const std::string host = mojo::GetNamePath(name); | |
| 39 return package_dir.AppendASCII(host + "/" + host + ".mojo"); | |
| 40 } else if (type == "exe") { | |
|
sky
2016/03/23 23:42:37
nit: no else.
| |
| 41 #if defined OS_WIN | |
| 42 std::string extension = ".exe"; | |
| 43 #else | |
| 44 std::string extension; | |
| 45 #endif | |
| 46 return package_dir.AppendASCII(mojo::GetNamePath(name) + extension); | |
| 47 } | |
| 48 return base::FilePath(); | |
| 49 } | |
| 50 | |
| 51 scoped_ptr<ReadManifestResult> ReadManifest(const base::FilePath& package_dir, | |
| 52 const std::string& name) { | |
| 53 base::FilePath manifest_path = GetManifestPath(package_dir, name); | |
| 54 JSONFileValueDeserializer deserializer(manifest_path); | |
| 55 int error = 0; | |
| 56 std::string message; | |
| 57 // TODO(beng): probably want to do more detailed error checking. This should | |
| 58 // be done when figuring out if to unblock connection completion. | |
| 59 ReadManifestResult* result = new ReadManifestResult; | |
| 60 result->manifest_root = deserializer.Deserialize(&error, &message); | |
| 61 result->package_dir = package_dir; | |
| 62 return make_scoped_ptr(result); | |
|
sky
2016/03/23 23:42:37
nit: use scoped_ptr at 59 and return said scoped_p
| |
| 63 } | |
| 64 | |
| 65 } // namespace | |
| 66 | |
| 67 ReadManifestResult::ReadManifestResult() {} | |
| 68 ReadManifestResult::~ReadManifestResult() {} | |
| 19 | 69 |
| 20 //////////////////////////////////////////////////////////////////////////////// | 70 //////////////////////////////////////////////////////////////////////////////// |
| 21 // Catalog, public: | 71 // Catalog, public: |
| 22 | 72 |
| 23 Catalog::Catalog(base::TaskRunner* blocking_pool, scoped_ptr<Store> store) | 73 Catalog::Catalog(scoped_ptr<Store> store, base::TaskRunner* file_task_runner) |
| 24 : store_(std::move(store)), | 74 : store_(std::move(store)), |
| 75 file_task_runner_(file_task_runner), | |
| 25 weak_factory_(this) { | 76 weak_factory_(this) { |
| 26 PathService::Get(base::DIR_MODULE, &package_path_); | 77 PathService::Get(base::DIR_MODULE, &system_package_dir_); |
| 27 reader_.reset(new Reader(package_path_, blocking_pool)); | |
| 28 DeserializeCatalog(); | 78 DeserializeCatalog(); |
| 29 } | 79 } |
| 30 | 80 |
| 31 Catalog::~Catalog() {} | 81 Catalog::~Catalog() {} |
| 32 | 82 |
| 33 void Catalog::BindResolver(mojom::ResolverRequest request) { | 83 void Catalog::BindResolver(mojom::ResolverRequest request) { |
| 34 resolver_bindings_.AddBinding(this, std::move(request)); | 84 resolver_bindings_.AddBinding(this, std::move(request)); |
| 35 } | 85 } |
| 36 | 86 |
| 37 void Catalog::BindShellResolver( | 87 void Catalog::BindShellResolver( |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 65 const mojo::String& scheme, | 115 const mojo::String& scheme, |
| 66 const ResolveProtocolSchemeCallback& callback) { | 116 const ResolveProtocolSchemeCallback& callback) { |
| 67 // TODO(beng): implement. | 117 // TODO(beng): implement. |
| 68 } | 118 } |
| 69 | 119 |
| 70 //////////////////////////////////////////////////////////////////////////////// | 120 //////////////////////////////////////////////////////////////////////////////// |
| 71 // Catalog, mojo::shell::mojom::ShellResolver: | 121 // Catalog, mojo::shell::mojom::ShellResolver: |
| 72 | 122 |
| 73 void Catalog::ResolveMojoName(const mojo::String& mojo_name, | 123 void Catalog::ResolveMojoName(const mojo::String& mojo_name, |
| 74 const ResolveMojoNameCallback& callback) { | 124 const ResolveMojoNameCallback& callback) { |
| 75 std::string resolved_name = mojo_name; | 125 std::string type = mojo::GetNameType(mojo_name); |
| 76 auto alias_iter = mojo_name_aliases_.find(resolved_name); | 126 if (type != "mojo" && type != "exe") { |
| 77 if (alias_iter != mojo_name_aliases_.end()) | 127 scoped_ptr<Entry> entry(new Entry(mojo_name)); |
| 78 resolved_name = alias_iter->second.first; | 128 callback.Run(mojo::shell::mojom::ResolveResult::From(*entry)); |
| 129 return; | |
| 130 } | |
| 79 | 131 |
| 80 std::string qualifier = mojo::GetNamePath(resolved_name); | 132 auto entry = catalog_.find(mojo_name); |
| 81 auto qualifier_iter = qualifiers_.find(resolved_name); | 133 if (entry != catalog_.end()) { |
| 82 if (qualifier_iter != qualifiers_.end()) | 134 callback.Run(mojo::shell::mojom::ResolveResult::From(*entry->second)); |
| 83 qualifier = qualifier_iter->second; | |
| 84 | |
| 85 if (IsNameInCatalog(resolved_name)) { | |
| 86 CompleteResolveMojoName(resolved_name, qualifier, callback); | |
| 87 } else { | 135 } else { |
| 88 reader_->Read(resolved_name, | 136 base::PostTaskAndReplyWithResult( |
| 89 base::Bind(&Catalog::OnReadEntry, weak_factory_.GetWeakPtr(), | 137 file_task_runner_, FROM_HERE, |
| 90 resolved_name, callback)); | 138 base::Bind(&ReadManifest, system_package_dir_, mojo_name), |
| 139 base::Bind(&Catalog::OnReadManifest, weak_factory_.GetWeakPtr(), | |
| 140 mojo_name, callback)); | |
| 91 } | 141 } |
| 92 } | 142 } |
| 93 | 143 |
| 94 //////////////////////////////////////////////////////////////////////////////// | 144 //////////////////////////////////////////////////////////////////////////////// |
| 95 // Catalog, mojom::Catalog: | 145 // Catalog, mojom::Catalog: |
| 96 | 146 |
| 97 void Catalog::GetEntries(mojo::Array<mojo::String> names, | 147 void Catalog::GetEntries(mojo::Array<mojo::String> names, |
| 98 const GetEntriesCallback& callback) { | 148 const GetEntriesCallback& callback) { |
| 99 mojo::Map<mojo::String, mojom::CatalogEntryPtr> entries; | 149 mojo::Map<mojo::String, mojom::CatalogEntryPtr> entries; |
| 100 std::vector<mojo::String> names_vec = names.PassStorage(); | 150 std::vector<mojo::String> names_vec = names.PassStorage(); |
| 101 for (const std::string& name : names_vec) { | 151 for (const std::string& name : names_vec) { |
| 102 if (catalog_.find(name) == catalog_.end()) | 152 if (catalog_.find(name) == catalog_.end()) |
| 103 continue; | 153 continue; |
| 104 const Entry& entry = catalog_[name]; | 154 const Entry& entry = *catalog_[name]; |
| 105 mojom::CatalogEntryPtr entry_ptr(mojom::CatalogEntry::New()); | 155 mojom::CatalogEntryPtr entry_ptr(mojom::CatalogEntry::New()); |
| 106 entry_ptr->display_name = entry.display_name(); | 156 entry_ptr->display_name = entry.display_name(); |
| 107 entries[entry.name()] = std::move(entry_ptr); | 157 entries[entry.name()] = std::move(entry_ptr); |
| 108 } | 158 } |
| 109 callback.Run(std::move(entries)); | 159 callback.Run(std::move(entries)); |
| 110 } | 160 } |
| 111 | 161 |
| 112 //////////////////////////////////////////////////////////////////////////////// | 162 //////////////////////////////////////////////////////////////////////////////// |
| 113 // Catalog, private: | 163 // Catalog, private: |
| 114 | 164 |
| 115 void Catalog::CompleteResolveMojoName( | |
| 116 const std::string& resolved_name, | |
| 117 const std::string& qualifier, | |
| 118 const ResolveMojoNameCallback& callback) { | |
| 119 auto entry_iter = catalog_.find(resolved_name); | |
| 120 CHECK(entry_iter != catalog_.end()); | |
| 121 | |
| 122 GURL package_url = mojo::util::AddTrailingSlashIfNeeded( | |
| 123 mojo::util::FilePathToFileURL(package_path_)); | |
| 124 GURL file_url; | |
| 125 std::string type = mojo::GetNameType(resolved_name); | |
| 126 if (type == "mojo") { | |
| 127 // It's still a mojo: URL, use the default mapping scheme. | |
| 128 const std::string host = mojo::GetNamePath(resolved_name); | |
| 129 file_url = package_url.Resolve(host + "/" + host + ".mojo"); | |
| 130 } else if (type == "exe") { | |
| 131 #if defined OS_WIN | |
| 132 std::string extension = ".exe"; | |
| 133 #else | |
| 134 std::string extension; | |
| 135 #endif | |
| 136 file_url = package_url.Resolve( | |
| 137 mojo::GetNamePath(resolved_name) + extension); | |
| 138 } | |
| 139 | |
| 140 mojo::shell::mojom::CapabilitySpecPtr capabilities_ptr = | |
| 141 mojo::shell::mojom::CapabilitySpec::From( | |
| 142 entry_iter->second.capabilities()); | |
| 143 | |
| 144 callback.Run(resolved_name, qualifier, std::move(capabilities_ptr), | |
| 145 file_url.spec()); | |
| 146 } | |
| 147 | |
| 148 bool Catalog::IsNameInCatalog(const std::string& name) const { | |
| 149 return catalog_.find(name) != catalog_.end(); | |
| 150 } | |
| 151 | |
| 152 void Catalog::DeserializeCatalog() { | 165 void Catalog::DeserializeCatalog() { |
| 153 if (!store_) | 166 if (!store_) |
| 154 return; | 167 return; |
| 155 const base::ListValue* catalog = store_->GetStore(); | 168 const base::ListValue* catalog = store_->GetStore(); |
| 156 CHECK(catalog); | 169 CHECK(catalog); |
| 157 // TODO(sky): make this handle aliases. | 170 // TODO(sky): make this handle aliases. |
| 158 for (auto it = catalog->begin(); it != catalog->end(); ++it) { | 171 for (auto it = catalog->begin(); it != catalog->end(); ++it) { |
| 159 const base::DictionaryValue* dictionary = nullptr; | 172 const base::DictionaryValue* dictionary = nullptr; |
| 160 const base::Value* v = *it; | 173 const base::Value* v = *it; |
| 161 CHECK(v->GetAsDictionary(&dictionary)); | 174 CHECK(v->GetAsDictionary(&dictionary)); |
| 162 scoped_ptr<Entry> entry = Entry::Deserialize(*dictionary); | 175 scoped_ptr<Entry> entry = Entry::Deserialize(*dictionary); |
| 163 if (entry) | 176 if (entry) |
| 164 catalog_[entry->name()] = *entry; | 177 catalog_[entry->name()] = std::move(entry); |
| 165 } | 178 } |
| 166 } | 179 } |
| 167 | 180 |
| 168 void Catalog::SerializeCatalog() { | 181 void Catalog::SerializeCatalog() { |
| 169 scoped_ptr<base::ListValue> catalog(new base::ListValue); | 182 scoped_ptr<base::ListValue> catalog(new base::ListValue); |
| 170 for (const auto& entry : catalog_) | 183 for (const auto& entry : catalog_) |
| 171 catalog->Append(entry.second.Serialize()); | 184 catalog->Append(entry.second->Serialize()); |
| 172 if (store_) | 185 if (store_) |
| 173 store_->UpdateStore(std::move(catalog)); | 186 store_->UpdateStore(std::move(catalog)); |
| 174 } | 187 } |
| 175 | 188 |
| 176 // static | 189 // static |
| 177 void Catalog::OnReadEntry(base::WeakPtr<Catalog> catalog, | 190 void Catalog::OnReadManifest(base::WeakPtr<Catalog> catalog, |
| 178 const std::string& name, | 191 const std::string& name, |
| 179 const ResolveMojoNameCallback& callback, | 192 const ResolveMojoNameCallback& callback, |
| 180 scoped_ptr<Entry> entry) { | 193 scoped_ptr<ReadManifestResult> result) { |
| 181 if (!catalog) { | 194 scoped_ptr<Entry> entry(new Entry(name)); |
| 182 callback.Run(name, mojo::GetNamePath(name), nullptr, nullptr); | 195 if (result->manifest_root) { |
| 183 return; | 196 const base::DictionaryValue* dictionary = nullptr; |
| 197 CHECK(result->manifest_root->GetAsDictionary(&dictionary)); | |
| 198 entry = Entry::Deserialize(*dictionary); | |
| 184 } | 199 } |
| 185 catalog->OnReadEntryImpl(name, callback, std::move(entry)); | 200 entry->set_path(GetPackagePath(result->package_dir, name)); |
| 201 | |
| 202 callback.Run(mojo::shell::mojom::ResolveResult::From(*entry)); | |
| 203 if (catalog) | |
| 204 catalog->AddEntryToCatalog(std::move(entry)); | |
| 186 } | 205 } |
| 187 | 206 |
| 188 void Catalog::OnReadEntryImpl(const std::string& name, | 207 void Catalog::AddEntryToCatalog(scoped_ptr<Entry> entry) { |
| 189 const ResolveMojoNameCallback& callback, | 208 DCHECK(entry); |
| 190 scoped_ptr<Entry> entry) { | 209 DCHECK(catalog_.end() == catalog_.find(entry->name())); |
| 191 // TODO(beng): evaluate the conditions under which entry is null. | 210 for (auto child : entry->applications()) |
| 192 if (!entry) { | 211 AddEntryToCatalog(make_scoped_ptr(child)); |
| 193 entry.reset(new Entry); | 212 catalog_[entry->name()] = std::move(entry); |
| 194 entry->set_name(name); | |
| 195 entry->set_display_name(name); | |
| 196 entry->set_qualifier(mojo::GetNamePath(name)); | |
| 197 } | |
| 198 | |
| 199 if (catalog_.find(entry->name()) == catalog_.end()) { | |
| 200 catalog_[entry->name()] = *entry; | |
| 201 | |
| 202 if (!entry->applications().empty()) { | |
| 203 for (const auto& child : entry->applications()) { | |
| 204 mojo_name_aliases_[child.name()] = | |
| 205 std::make_pair(entry->name(), child.qualifier()); | |
| 206 } | |
| 207 } | |
| 208 qualifiers_[entry->name()] = entry->qualifier(); | |
|
sky
2016/03/23 23:42:37
How come the qualifiers_ is getting removed? Isn't
Ben Goodger (Google)
2016/03/23 23:52:49
The qualifier is stored in the Entry, and passed b
| |
| 209 } | |
| 210 | |
| 211 SerializeCatalog(); | 213 SerializeCatalog(); |
| 212 | |
| 213 auto qualifier_iter = qualifiers_.find(name); | |
| 214 DCHECK(qualifier_iter != qualifiers_.end()); | |
| 215 std::string qualifier = qualifier_iter->second; | |
| 216 CompleteResolveMojoName(name, qualifier, callback); | |
| 217 } | 214 } |
| 218 | 215 |
| 219 } // namespace catalog | 216 } // namespace catalog |
| OLD | NEW |