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

Side by Side Diff: services/catalog/catalog.cc

Issue 2645973006: [Service Manager] Get rid of dynamic service discovery (Closed)
Patch Set: . Created 3 years, 11 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
« no previous file with comments | « services/catalog/catalog.h ('k') | services/catalog/entry.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "services/catalog/catalog.h" 5 #include "services/catalog/catalog.h"
6 6
7 #include "base/bind.h" 7 #include <memory>
8 #include <string>
9
10 #include "base/base_paths.h"
8 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
9 #include "base/files/scoped_temp_dir.h" 12 #include "base/files/file_util.h"
13 #include "base/json/json_reader.h"
14 #include "base/lazy_instance.h"
10 #include "base/macros.h" 15 #include "base/macros.h"
11 #include "base/memory/ptr_util.h" 16 #include "base/memory/ptr_util.h"
12 #include "base/path_service.h" 17 #include "base/path_service.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h"
15 #include "components/filesystem/directory_impl.h" 20 #include "components/filesystem/directory_impl.h"
16 #include "components/filesystem/lock_table.h" 21 #include "components/filesystem/lock_table.h"
17 #include "components/filesystem/public/interfaces/types.mojom.h" 22 #include "components/filesystem/public/interfaces/types.mojom.h"
18 #include "mojo/public/cpp/bindings/strong_binding.h" 23 #include "mojo/public/cpp/bindings/strong_binding.h"
19 #include "services/catalog/constants.h" 24 #include "services/catalog/constants.h"
20 #include "services/catalog/entry_cache.h" 25 #include "services/catalog/entry_cache.h"
21 #include "services/catalog/instance.h" 26 #include "services/catalog/instance.h"
22 #include "services/catalog/reader.h"
23 #include "services/service_manager/public/cpp/connection.h" 27 #include "services/service_manager/public/cpp/connection.h"
24 #include "services/service_manager/public/cpp/interface_registry.h" 28 #include "services/service_manager/public/cpp/interface_registry.h"
25 #include "services/service_manager/public/cpp/service_context.h" 29 #include "services/service_manager/public/cpp/service_context.h"
26 30
27 namespace catalog { 31 namespace catalog {
32
28 namespace { 33 namespace {
29 34
30 bool IsPathNameValid(const std::string& name) { 35 const char kCatalogServicesKey[] = "services";
31 if (name.empty() || name == "." || name == "..") 36 const char kCatalogServiceEmbeddedKey[] = "embedded";
32 return false; 37 const char kCatalogServiceExecutableKey[] = "executable";
38 const char kCatalogServiceManifestKey[] = "manifest";
33 39
34 for (auto c : name) { 40 base::LazyInstance<std::unique_ptr<base::Value>> g_default_static_manifest =
35 if (!base::IsAsciiAlpha(c) && !base::IsAsciiDigit(c) && 41 LAZY_INSTANCE_INITIALIZER;
36 c != '_' && c != '.') 42
37 return false; 43 void LoadCatalogManifestIntoCache(const base::Value* root, EntryCache* cache) {
44 DCHECK(root);
45 const base::DictionaryValue* catalog = nullptr;
46 if (!root->GetAsDictionary(&catalog)) {
47 LOG(ERROR) << "Catalog manifest is not a dictionary value.";
48 return;
38 } 49 }
39 return true; 50 DCHECK(catalog);
40 }
41 51
42 base::FilePath GetPathForApplicationName(const std::string& application_name) { 52 const base::DictionaryValue* services = nullptr;
43 static const char kServicePrefix[] = ""; 53 if (!catalog->GetDictionary(kCatalogServicesKey, &services)) {
44 std::string path = application_name; 54 LOG(ERROR) << "Catalog manifest \"services\" is not a dictionary value.";
45 const bool is_service = base::StartsWith( 55 return;
46 path, kServicePrefix, base::CompareCase::INSENSITIVE_ASCII); 56 }
47 if (!is_service)
48 return base::FilePath();
49 if (path.find('.') != std::string::npos)
50 return base::FilePath();
51 path.erase(path.begin(), path.begin() + strlen(kServicePrefix));
52 base::TrimString(path, "/", &path);
53 size_t end_of_name = path.find('/');
54 if (end_of_name != std::string::npos)
55 path.erase(path.begin() + end_of_name, path.end());
56 57
57 if (!IsPathNameValid(path)) 58 for (base::DictionaryValue::Iterator it(*services); !it.IsAtEnd();
58 return base::FilePath(); 59 it.Advance()) {
60 const base::DictionaryValue* service_entry = nullptr;
61 if (!it.value().GetAsDictionary(&service_entry)) {
62 LOG(ERROR) << "Catalog service entry for \"" << it.key()
63 << "\" is not a dictionary value.";
64 continue;
65 }
59 66
60 base::FilePath base_path; 67 bool is_embedded = false;
61 PathService::Get(base::DIR_EXE, &base_path); 68 service_entry->GetBoolean(kCatalogServiceEmbeddedKey, &is_embedded);
62 // TODO(beng): this won't handle user-specific components. 69
63 return base_path.AppendASCII(kPackagesDirName).AppendASCII(path). 70 base::FilePath executable_path;
64 AppendASCII("resources"); 71 std::string executable_path_string;
72 if (service_entry->GetString(kCatalogServiceExecutableKey,
73 &executable_path_string)) {
74 base::FilePath exe_dir;
75 CHECK(base::PathService::Get(base::DIR_EXE, &exe_dir));
76 #if defined(OS_WIN)
77 executable_path_string += ".exe";
78 base::ReplaceFirstSubstringAfterOffset(
79 &executable_path_string, 0, "@EXE_DIR",
80 base::UTF16ToUTF8(exe_dir.value()));
81 executable_path =
82 base::FilePath(base::UTF8ToUTF16(executable_path_string));
83 #else
84 base::ReplaceFirstSubstringAfterOffset(
85 &executable_path_string, 0, "@EXE_DIR", exe_dir.value());
86 executable_path = base::FilePath(executable_path_string);
87 #endif
88 }
89
90 const base::DictionaryValue* manifest = nullptr;
91 if (!service_entry->GetDictionary(kCatalogServiceManifestKey, &manifest)) {
92 LOG(ERROR) << "Catalog entry for \"" << it.key() << "\" has an invalid "
93 << "\"manifest\" value.";
94 continue;
95 }
96
97 DCHECK(!(is_embedded && !executable_path.empty()));
98
99 auto entry = Entry::Deserialize(*manifest);
100 if (entry) {
101 if (!executable_path.empty())
102 entry->set_path(executable_path);
103 bool added = cache->AddRootEntry(std::move(entry));
104 DCHECK(added);
105 } else {
106 LOG(ERROR) << "Failed to read manifest entry for \"" << it.key() << "\".";
107 }
108 }
65 } 109 }
66 110
67 } // namespace 111 } // namespace
68 112
69 class Catalog::ServiceImpl : public service_manager::Service { 113 class Catalog::ServiceImpl : public service_manager::Service {
70 public: 114 public:
71 explicit ServiceImpl(Catalog* catalog) : catalog_(catalog) {} 115 explicit ServiceImpl(Catalog* catalog) : catalog_(catalog) {}
72 ~ServiceImpl() override {} 116 ~ServiceImpl() override {}
73 117
74 // service_manager::Service: 118 // service_manager::Service:
75 bool OnConnect(const service_manager::ServiceInfo& remote_info, 119 bool OnConnect(const service_manager::ServiceInfo& remote_info,
76 service_manager::InterfaceRegistry* registry) override { 120 service_manager::InterfaceRegistry* registry) override {
77 registry->AddInterface<mojom::Catalog>(catalog_); 121 registry->AddInterface<mojom::Catalog>(catalog_);
78 registry->AddInterface<mojom::CatalogControl>(catalog_);
79 registry->AddInterface<filesystem::mojom::Directory>(catalog_); 122 registry->AddInterface<filesystem::mojom::Directory>(catalog_);
80 registry->AddInterface<service_manager::mojom::Resolver>(catalog_); 123 registry->AddInterface<service_manager::mojom::Resolver>(catalog_);
81 return true; 124 return true;
82 } 125 }
83 126
84 private: 127 private:
85 Catalog* const catalog_; 128 Catalog* const catalog_;
86 129
87 DISALLOW_COPY_AND_ASSIGN(ServiceImpl); 130 DISALLOW_COPY_AND_ASSIGN(ServiceImpl);
88 }; 131 };
89 132
90 Catalog::Catalog(std::unique_ptr<base::Value> static_manifest) : Catalog() { 133 Catalog::Catalog(std::unique_ptr<base::Value> static_manifest,
91 system_reader_.reset(new Reader(std::move(static_manifest), 134 ManifestProvider* service_manifest_provider)
92 system_cache_.get())); 135 : service_context_(new service_manager::ServiceContext(
93 loaded_ = true; 136 base::MakeUnique<ServiceImpl>(this),
94 } 137 service_manager::mojom::ServiceRequest(&service_))),
95 138 service_manifest_provider_(service_manifest_provider),
96 Catalog::Catalog(base::SequencedWorkerPool* worker_pool, 139 weak_factory_(this) {
97 ManifestProvider* manifest_provider) : Catalog() { 140 if (static_manifest) {
98 system_reader_.reset(new Reader(worker_pool, manifest_provider)); 141 LoadCatalogManifestIntoCache(static_manifest.get(), &system_cache_);
99 ScanSystemPackageDir(); 142 } else if (g_default_static_manifest.Get()) {
100 } 143 LoadCatalogManifestIntoCache(
101 144 g_default_static_manifest.Get().get(), &system_cache_);
102 Catalog::Catalog(base::SingleThreadTaskRunner* task_runner, 145 }
103 ManifestProvider* manifest_provider) : Catalog() {
104 system_reader_.reset(new Reader(task_runner, manifest_provider));
105 ScanSystemPackageDir();
106 } 146 }
107 147
108 Catalog::~Catalog() {} 148 Catalog::~Catalog() {}
109 149
110 void Catalog::OverridePackageName(const std::string& service_name,
111 const std::string& package_name) {
112 system_reader_->OverridePackageName(service_name, package_name);
113 }
114
115 service_manager::mojom::ServicePtr Catalog::TakeService() { 150 service_manager::mojom::ServicePtr Catalog::TakeService() {
116 return std::move(service_); 151 return std::move(service_);
117 } 152 }
118 153
119 Catalog::Catalog() : system_cache_(new EntryCache), weak_factory_(this) { 154 // static
120 service_context_.reset(new service_manager::ServiceContext( 155 void Catalog::SetDefaultCatalogManifest(
121 base::MakeUnique<ServiceImpl>(this), 156 std::unique_ptr<base::Value> static_manifest) {
122 service_manager::mojom::ServiceRequest(&service_))); 157 g_default_static_manifest.Get() = std::move(static_manifest);
123 } 158 }
124 159
125 void Catalog::ScanSystemPackageDir() { 160 // static
126 base::FilePath system_package_dir; 161 void Catalog::LoadDefaultCatalogManifest(const base::FilePath& path) {
127 PathService::Get(base::DIR_MODULE, &system_package_dir); 162 std::string catalog_contents;
128 system_package_dir = system_package_dir.AppendASCII(kPackagesDirName); 163 base::FilePath exe_path;
129 system_reader_->Read(system_package_dir, system_cache_.get(), 164 base::PathService::Get(base::DIR_EXE, &exe_path);
130 base::Bind(&Catalog::SystemPackageDirScanned, 165 base::FilePath catalog_path = exe_path.Append(path);
131 weak_factory_.GetWeakPtr())); 166 bool result = base::ReadFileToString(catalog_path, &catalog_contents);
167 DCHECK(result);
168 std::unique_ptr<base::Value> manifest_value =
169 base::JSONReader::Read(catalog_contents);
170 DCHECK(manifest_value);
171 catalog::Catalog::SetDefaultCatalogManifest(std::move(manifest_value));
132 } 172 }
133 173
134 void Catalog::Create(const service_manager::Identity& remote_identity, 174 void Catalog::Create(const service_manager::Identity& remote_identity,
135 service_manager::mojom::ResolverRequest request) { 175 service_manager::mojom::ResolverRequest request) {
136 Instance* instance = GetInstanceForUserId(remote_identity.user_id()); 176 Instance* instance = GetInstanceForUserId(remote_identity.user_id());
137 instance->BindResolver(std::move(request)); 177 instance->BindResolver(std::move(request));
138 } 178 }
139 179
140 void Catalog::Create(const service_manager::Identity& remote_identity, 180 void Catalog::Create(const service_manager::Identity& remote_identity,
141 mojom::CatalogRequest request) { 181 mojom::CatalogRequest request) {
142 Instance* instance = GetInstanceForUserId(remote_identity.user_id()); 182 Instance* instance = GetInstanceForUserId(remote_identity.user_id());
143 instance->BindCatalog(std::move(request)); 183 instance->BindCatalog(std::move(request));
144 } 184 }
145 185
146 void Catalog::Create(const service_manager::Identity& remote_identity, 186 void Catalog::Create(const service_manager::Identity& remote_identity,
147 filesystem::mojom::DirectoryRequest request) { 187 filesystem::mojom::DirectoryRequest request) {
148 if (!lock_table_) 188 if (!lock_table_)
149 lock_table_ = new filesystem::LockTable; 189 lock_table_ = new filesystem::LockTable;
150 base::FilePath resources_path = 190
151 GetPathForApplicationName(remote_identity.name()); 191 base::FilePath resources_path;
192 base::PathService::Get(base::DIR_MODULE, &resources_path);
152 mojo::MakeStrongBinding( 193 mojo::MakeStrongBinding(
153 base::MakeUnique<filesystem::DirectoryImpl>( 194 base::MakeUnique<filesystem::DirectoryImpl>(
154 resources_path, scoped_refptr<filesystem::SharedTempDir>(), 195 resources_path, scoped_refptr<filesystem::SharedTempDir>(),
155 lock_table_), 196 lock_table_),
156 std::move(request)); 197 std::move(request));
157 } 198 }
158 199
159 void Catalog::Create(const service_manager::Identity& remote_identity,
160 mojom::CatalogControlRequest request) {
161 control_bindings_.AddBinding(this, std::move(request));
162 }
163
164 void Catalog::OverrideManifestPath(
165 const std::string& service_name,
166 const base::FilePath& path,
167 const OverrideManifestPathCallback& callback) {
168 system_reader_->OverrideManifestPath(service_name, path);
169 callback.Run();
170 }
171
172 Instance* Catalog::GetInstanceForUserId(const std::string& user_id) { 200 Instance* Catalog::GetInstanceForUserId(const std::string& user_id) {
173 auto it = instances_.find(user_id); 201 auto it = instances_.find(user_id);
174 if (it != instances_.end()) 202 if (it != instances_.end())
175 return it->second.get(); 203 return it->second.get();
176 204
177 Instance* instance = new Instance(system_reader_.get()); 205 auto result = instances_.insert(std::make_pair(
178 instances_[user_id] = base::WrapUnique(instance); 206 user_id,
179 if (loaded_) 207 base::MakeUnique<Instance>(&system_cache_, service_manifest_provider_)));
180 instance->CacheReady(system_cache_.get()); 208 return result.first->second.get();
181
182 return instance;
183 }
184
185 void Catalog::SystemPackageDirScanned() {
186 loaded_ = true;
187 for (auto& instance : instances_)
188 instance.second->CacheReady(system_cache_.get());
189 } 209 }
190 210
191 } // namespace catalog 211 } // namespace catalog
OLDNEW
« no previous file with comments | « services/catalog/catalog.h ('k') | services/catalog/entry.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698