| 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/package_manager/package_manager.h" | 5 #include "mojo/services/package_manager/package_manager.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/json/json_file_value_serializer.h" |
| 9 #include "base/strings/string_split.h" | 9 #include "base/strings/string_split.h" |
| 10 #include "base/task_runner_util.h" | 10 #include "base/task_runner_util.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 return filter; | 36 return filter; |
| 37 } | 37 } |
| 38 | 38 |
| 39 ApplicationInfo BuildApplicationInfoFromDictionary( | 39 ApplicationInfo BuildApplicationInfoFromDictionary( |
| 40 const base::DictionaryValue& value) { | 40 const base::DictionaryValue& value) { |
| 41 ApplicationInfo info; | 41 ApplicationInfo info; |
| 42 std::string name_string; | 42 std::string name_string; |
| 43 CHECK(value.GetString(ApplicationCatalogStore::kNameKey, &name_string)); | 43 CHECK(value.GetString(ApplicationCatalogStore::kNameKey, &name_string)); |
| 44 CHECK(mojo::IsValidName(name_string)) << "Invalid Name: " << name_string; | 44 CHECK(mojo::IsValidName(name_string)) << "Invalid Name: " << name_string; |
| 45 info.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 } |
| 46 CHECK(value.GetString(ApplicationCatalogStore::kDisplayNameKey, | 52 CHECK(value.GetString(ApplicationCatalogStore::kDisplayNameKey, |
| 47 &info.display_name)); | 53 &info.display_name)); |
| 48 const base::DictionaryValue* capabilities = nullptr; | 54 const base::DictionaryValue* capabilities = nullptr; |
| 49 CHECK(value.GetDictionary(ApplicationCatalogStore::kCapabilitiesKey, | 55 CHECK(value.GetDictionary(ApplicationCatalogStore::kCapabilitiesKey, |
| 50 &capabilities)); | 56 &capabilities)); |
| 51 info.base_filter = BuildCapabilityFilterFromDictionary(*capabilities); | 57 info.base_filter = BuildCapabilityFilterFromDictionary(*capabilities); |
| 52 return info; | 58 return info; |
| 53 } | 59 } |
| 54 | 60 |
| 55 void SerializeEntry(const ApplicationInfo& entry, | 61 void SerializeEntry(const ApplicationInfo& entry, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 76 // TODO(beng): probably want to do more detailed error checking. This should | 82 // TODO(beng): probably want to do more detailed error checking. This should |
| 77 // be done when figuring out if to unblock connection completion. | 83 // be done when figuring out if to unblock connection completion. |
| 78 return deserializer.Deserialize(&error, &message); | 84 return deserializer.Deserialize(&error, &message); |
| 79 } | 85 } |
| 80 | 86 |
| 81 } // namespace | 87 } // namespace |
| 82 | 88 |
| 83 // static | 89 // static |
| 84 const char ApplicationCatalogStore::kNameKey[] = "name"; | 90 const char ApplicationCatalogStore::kNameKey[] = "name"; |
| 85 // static | 91 // static |
| 92 const char ApplicationCatalogStore::kQualifierKey[] = "process-group"; |
| 93 // static |
| 86 const char ApplicationCatalogStore::kDisplayNameKey[] = "display_name"; | 94 const char ApplicationCatalogStore::kDisplayNameKey[] = "display_name"; |
| 87 // static | 95 // static |
| 88 const char ApplicationCatalogStore::kCapabilitiesKey[] = "capabilities"; | 96 const char ApplicationCatalogStore::kCapabilitiesKey[] = "capabilities"; |
| 89 | 97 |
| 90 ApplicationInfo::ApplicationInfo() {} | 98 ApplicationInfo::ApplicationInfo() {} |
| 91 ApplicationInfo::ApplicationInfo(const ApplicationInfo& other) = default; | 99 ApplicationInfo::ApplicationInfo(const ApplicationInfo& other) = default; |
| 92 ApplicationInfo::~ApplicationInfo() {} | 100 ApplicationInfo::~ApplicationInfo() {} |
| 93 | 101 |
| 94 PackageManager::PackageManager(base::TaskRunner* blocking_pool, | 102 PackageManager::PackageManager(base::TaskRunner* blocking_pool, |
| 95 scoped_ptr<ApplicationCatalogStore> catalog) | 103 scoped_ptr<ApplicationCatalogStore> catalog) |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 void PackageManager::ResolveProtocolScheme( | 158 void PackageManager::ResolveProtocolScheme( |
| 151 const mojo::String& scheme, | 159 const mojo::String& scheme, |
| 152 const ResolveProtocolSchemeCallback& callback) { | 160 const ResolveProtocolSchemeCallback& callback) { |
| 153 // TODO(beng): implement. | 161 // TODO(beng): implement. |
| 154 } | 162 } |
| 155 | 163 |
| 156 void PackageManager::ResolveMojoName(const mojo::String& mojo_name, | 164 void PackageManager::ResolveMojoName(const mojo::String& mojo_name, |
| 157 const ResolveMojoNameCallback& callback) { | 165 const ResolveMojoNameCallback& callback) { |
| 158 std::string resolved_name = mojo_name; | 166 std::string resolved_name = mojo_name; |
| 159 auto alias_iter = mojo_name_aliases_.find(resolved_name); | 167 auto alias_iter = mojo_name_aliases_.find(resolved_name); |
| 160 std::string qualifier; | 168 if (alias_iter != mojo_name_aliases_.end()) |
| 161 if (alias_iter != mojo_name_aliases_.end()) { | |
| 162 resolved_name = alias_iter->second.first; | 169 resolved_name = alias_iter->second.first; |
| 163 qualifier = alias_iter->second.second; | |
| 164 } else { | |
| 165 qualifier = mojo::GetNamePath(resolved_name); | |
| 166 } | |
| 167 | 170 |
| 168 EnsureNameInCatalog(resolved_name, qualifier, callback); | 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); |
| 169 } | 180 } |
| 170 | 181 |
| 171 void PackageManager::GetEntries( | 182 void PackageManager::GetEntries( |
| 172 mojo::Array<mojo::String> names, | 183 mojo::Array<mojo::String> names, |
| 173 const GetEntriesCallback& callback) { | 184 const GetEntriesCallback& callback) { |
| 174 mojo::Map<mojo::String, mojom::CatalogEntryPtr> entries; | 185 mojo::Map<mojo::String, mojom::CatalogEntryPtr> entries; |
| 175 std::vector<mojo::String> names_vec = names.PassStorage(); | 186 std::vector<mojo::String> names_vec = names.PassStorage(); |
| 176 for (const std::string& name : names_vec) { | 187 for (const std::string& name : names_vec) { |
| 177 if (catalog_.find(name) == catalog_.end()) | 188 if (catalog_.find(name) == catalog_.end()) |
| 178 continue; | 189 continue; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 filter->filter.insert(entry.first, std::move(interfaces)); | 228 filter->filter.insert(entry.first, std::move(interfaces)); |
| 218 } | 229 } |
| 219 callback.Run(resolved_name, qualifier, std::move(filter), | 230 callback.Run(resolved_name, qualifier, std::move(filter), |
| 220 file_url.spec()); | 231 file_url.spec()); |
| 221 } | 232 } |
| 222 | 233 |
| 223 bool PackageManager::IsNameInCatalog(const std::string& name) const { | 234 bool PackageManager::IsNameInCatalog(const std::string& name) const { |
| 224 return catalog_.find(name) != catalog_.end(); | 235 return catalog_.find(name) != catalog_.end(); |
| 225 } | 236 } |
| 226 | 237 |
| 227 void PackageManager::EnsureNameInCatalog( | 238 void PackageManager::AddNameToCatalog( |
| 228 const std::string& name, | 239 const std::string& name, |
| 229 const std::string& qualifier, | |
| 230 const ResolveMojoNameCallback& callback) { | 240 const ResolveMojoNameCallback& callback) { |
| 231 if (IsNameInCatalog(name)) { | |
| 232 CompleteResolveMojoName(name, qualifier, callback); | |
| 233 return; | |
| 234 } | |
| 235 | |
| 236 GURL manifest_url = GetManifestURL(name); | 241 GURL manifest_url = GetManifestURL(name); |
| 237 if (manifest_url.is_empty()) { | 242 if (manifest_url.is_empty()) { |
| 238 // The name is of some form that can't be resolved to a manifest (e.g. some | 243 // The name is of some form that can't be resolved to a manifest (e.g. some |
| 239 // scheme used for tests). Just pass it back to the caller so it can be | 244 // scheme used for tests). Just pass it back to the caller so it can be |
| 240 // loaded with a custom loader. | 245 // loaded with a custom loader. |
| 241 callback.Run(name, name, nullptr, nullptr); | 246 callback.Run(name, mojo::GetNamePath(name), nullptr, nullptr); |
| 242 return; | 247 return; |
| 243 } | 248 } |
| 244 | 249 |
| 245 std::string type = mojo::GetNameType(name); | 250 std::string type = mojo::GetNameType(name); |
| 246 CHECK(type == "mojo" || type == "exe"); | 251 CHECK(type == "mojo" || type == "exe"); |
| 247 base::FilePath manifest_path; | 252 base::FilePath manifest_path; |
| 248 CHECK(net::FileURLToFilePath(manifest_url, &manifest_path)); | 253 CHECK(net::FileURLToFilePath(manifest_url, &manifest_path)); |
| 249 base::PostTaskAndReplyWithResult( | 254 base::PostTaskAndReplyWithResult( |
| 250 blocking_pool_, FROM_HERE, base::Bind(&ReadManifest, manifest_path), | 255 blocking_pool_, FROM_HERE, base::Bind(&ReadManifest, manifest_path), |
| 251 base::Bind(&PackageManager::OnReadManifest, weak_factory_.GetWeakPtr(), | 256 base::Bind(&PackageManager::OnReadManifest, weak_factory_.GetWeakPtr(), |
| 252 name, qualifier, callback)); | 257 name, callback)); |
| 253 } | 258 } |
| 254 | 259 |
| 255 void PackageManager::DeserializeCatalog() { | 260 void PackageManager::DeserializeCatalog() { |
| 256 if (!catalog_store_) | 261 if (!catalog_store_) |
| 257 return; | 262 return; |
| 258 const base::ListValue* catalog = catalog_store_->GetStore(); | 263 const base::ListValue* catalog = catalog_store_->GetStore(); |
| 259 CHECK(catalog); | 264 CHECK(catalog); |
| 260 // TODO(sky): make this handle aliases. | 265 // TODO(sky): make this handle aliases. |
| 261 for (auto it = catalog->begin(); it != catalog->end(); ++it) { | 266 for (auto it = catalog->begin(); it != catalog->end(); ++it) { |
| 262 const base::DictionaryValue* dictionary = nullptr; | 267 const base::DictionaryValue* dictionary = nullptr; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 286 catalog_[info.name] = info; | 291 catalog_[info.name] = info; |
| 287 | 292 |
| 288 if (dictionary->HasKey("applications")) { | 293 if (dictionary->HasKey("applications")) { |
| 289 const base::ListValue* applications = nullptr; | 294 const base::ListValue* applications = nullptr; |
| 290 dictionary->GetList("applications", &applications); | 295 dictionary->GetList("applications", &applications); |
| 291 for (size_t i = 0; i < applications->GetSize(); ++i) { | 296 for (size_t i = 0; i < applications->GetSize(); ++i) { |
| 292 const base::DictionaryValue* child = nullptr; | 297 const base::DictionaryValue* child = nullptr; |
| 293 applications->GetDictionary(i, &child); | 298 applications->GetDictionary(i, &child); |
| 294 const ApplicationInfo& child_info = DeserializeApplication(child); | 299 const ApplicationInfo& child_info = DeserializeApplication(child); |
| 295 mojo_name_aliases_[child_info.name] = | 300 mojo_name_aliases_[child_info.name] = |
| 296 std::make_pair(info.name, mojo::GetNamePath(child_info.name)); | 301 std::make_pair(info.name, child_info.qualifier); |
| 297 } | 302 } |
| 298 } | 303 } |
| 304 qualifiers_[info.name] = info.qualifier; |
| 299 } | 305 } |
| 300 return catalog_[info.name]; | 306 return catalog_[info.name]; |
| 301 } | 307 } |
| 302 | 308 |
| 303 GURL PackageManager::GetManifestURL(const std::string& name) { | 309 GURL PackageManager::GetManifestURL(const std::string& name) { |
| 304 // TODO(beng): think more about how this should be done for exe targets. | 310 // TODO(beng): think more about how this should be done for exe targets. |
| 305 std::string type = mojo::GetNameType(name); | 311 std::string type = mojo::GetNameType(name); |
| 306 std::string path = mojo::GetNamePath(name); | 312 std::string path = mojo::GetNamePath(name); |
| 307 if (type == "mojo") | 313 if (type == "mojo") |
| 308 return system_package_dir_.Resolve(path + "/manifest.json"); | 314 return system_package_dir_.Resolve(path + "/manifest.json"); |
| 309 else if (type == "exe") | 315 else if (type == "exe") |
| 310 return system_package_dir_.Resolve(path + "_manifest.json"); | 316 return system_package_dir_.Resolve(path + "_manifest.json"); |
| 311 return GURL(); | 317 return GURL(); |
| 312 } | 318 } |
| 313 | 319 |
| 314 // static | 320 // static |
| 315 void PackageManager::OnReadManifest(base::WeakPtr<PackageManager> pm, | 321 void PackageManager::OnReadManifest(base::WeakPtr<PackageManager> pm, |
| 316 const std::string& name, | 322 const std::string& name, |
| 317 const std::string& qualifier, | |
| 318 const ResolveMojoNameCallback& callback, | 323 const ResolveMojoNameCallback& callback, |
| 319 scoped_ptr<base::Value> manifest) { | 324 scoped_ptr<base::Value> manifest) { |
| 320 if (!pm) { | 325 if (!pm) { |
| 321 // The PackageManager was destroyed, we're likely in shutdown. Run the | 326 // The PackageManager was destroyed, we're likely in shutdown. Run the |
| 322 // callback so we don't trigger a DCHECK. | 327 // callback so we don't trigger a DCHECK. |
| 323 callback.Run(name, name, nullptr, nullptr); | 328 callback.Run(name, mojo::GetNamePath(name), nullptr, nullptr); |
| 324 return; | 329 return; |
| 325 } | 330 } |
| 326 pm->OnReadManifestImpl(name, qualifier, callback, std::move(manifest)); | 331 pm->OnReadManifestImpl(name, callback, std::move(manifest)); |
| 327 } | 332 } |
| 328 | 333 |
| 329 void PackageManager::OnReadManifestImpl(const std::string& name, | 334 void PackageManager::OnReadManifestImpl(const std::string& name, |
| 330 const std::string& qualifier, | |
| 331 const ResolveMojoNameCallback& callback, | 335 const ResolveMojoNameCallback& callback, |
| 332 scoped_ptr<base::Value> manifest) { | 336 scoped_ptr<base::Value> manifest) { |
| 333 if (manifest) { | 337 if (manifest) { |
| 334 base::DictionaryValue* dictionary = nullptr; | 338 base::DictionaryValue* dictionary = nullptr; |
| 335 CHECK(manifest->GetAsDictionary(&dictionary)); | 339 CHECK(manifest->GetAsDictionary(&dictionary)); |
| 336 DeserializeApplication(dictionary); | 340 DeserializeApplication(dictionary); |
| 337 } else { | 341 } else { |
| 338 ApplicationInfo info; | 342 ApplicationInfo info; |
| 339 info.name = name; | 343 info.name = name; |
| 340 info.display_name = name; | 344 info.display_name = name; |
| 341 catalog_[info.name] = info; | 345 catalog_[info.name] = info; |
| 346 qualifiers_[info.name] = mojo::GetNamePath(name); |
| 342 } | 347 } |
| 343 SerializeCatalog(); | 348 SerializeCatalog(); |
| 349 |
| 350 auto qualifier_iter = qualifiers_.find(name); |
| 351 DCHECK(qualifier_iter != qualifiers_.end()); |
| 352 std::string qualifier = qualifier_iter->second; |
| 344 CompleteResolveMojoName(name, qualifier, callback); | 353 CompleteResolveMojoName(name, qualifier, callback); |
| 345 } | 354 } |
| 346 | 355 |
| 347 } // namespace package_manager | 356 } // namespace package_manager |
| OLD | NEW |