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

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

Issue 2573283002: Use a static catalog manifest for the standalone Mash runner (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/reader.h ('k') | services/catalog/store.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/reader.h" 5 #include "services/catalog/reader.h"
6 6
7 #include "base/base_paths.h"
7 #include "base/bind.h" 8 #include "base/bind.h"
8 #include "base/files/file_enumerator.h" 9 #include "base/files/file_enumerator.h"
9 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
10 #include "base/json/json_file_value_serializer.h" 11 #include "base/json/json_file_value_serializer.h"
11 #include "base/json/json_reader.h" 12 #include "base/json/json_reader.h"
12 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
13 #include "base/path_service.h" 14 #include "base/path_service.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h"
14 #include "base/task_runner_util.h" 17 #include "base/task_runner_util.h"
15 #include "base/threading/thread_task_runner_handle.h" 18 #include "base/threading/thread_task_runner_handle.h"
19 #include "base/values.h"
16 #include "services/catalog/constants.h" 20 #include "services/catalog/constants.h"
17 #include "services/catalog/entry.h" 21 #include "services/catalog/entry.h"
18 #include "services/catalog/manifest_provider.h" 22 #include "services/catalog/manifest_provider.h"
19 #include "services/catalog/public/interfaces/constants.mojom.h" 23 #include "services/catalog/public/interfaces/constants.mojom.h"
20 #include "services/service_manager/public/interfaces/constants.mojom.h" 24 #include "services/service_manager/public/interfaces/constants.mojom.h"
21 25
22 namespace catalog { 26 namespace catalog {
23 namespace { 27 namespace {
24 28
25 #if defined(OS_WIN) 29 #if defined(OS_WIN)
26 const char kServiceExecutableExtension[] = ".service.exe"; 30 const char kServiceExecutableExtension[] = ".service.exe";
27 #else 31 #else
28 const char kServiceExecutableExtension[] = ".service"; 32 const char kServiceExecutableExtension[] = ".service";
29 #endif 33 #endif
30 34
35 const char kCatalogServicesKey[] = "services";
36 const char kCatalogServiceEmbeddedKey[] = "embedded";
37 const char kCatalogServiceExecutableKey[] = "executable";
38 const char kCatalogServiceManifestKey[] = "manifest";
39
31 base::FilePath GetManifestPath(const base::FilePath& package_dir, 40 base::FilePath GetManifestPath(const base::FilePath& package_dir,
32 const std::string& name, 41 const std::string& name,
33 const std::string& package_name_override) { 42 const std::string& package_name_override) {
34 // TODO(beng): think more about how this should be done for exe targets. 43 // TODO(beng): think more about how this should be done for exe targets.
35 std::string package_name = 44 std::string package_name =
36 package_name_override.empty() ? name : package_name_override; 45 package_name_override.empty() ? name : package_name_override;
37 return package_dir.AppendASCII(kPackagesDirName).AppendASCII( 46 return package_dir.AppendASCII(kPackagesDirName).AppendASCII(
38 package_name + "/manifest.json"); 47 package_name + "/manifest.json");
39 } 48 }
40 49
41 base::FilePath GetExecutablePath(const base::FilePath& package_dir, 50 base::FilePath GetExecutablePath(const base::FilePath& package_dir,
42 const std::string& name) { 51 const std::string& name) {
43 return package_dir.AppendASCII( 52 return package_dir.AppendASCII(
44 name + "/" + name + kServiceExecutableExtension); 53 name + "/" + name + kServiceExecutableExtension);
45 } 54 }
46 55
47 std::unique_ptr<Entry> ProcessManifest( 56 std::unique_ptr<Entry> ProcessManifest(const base::Value* manifest_root,
48 std::unique_ptr<base::Value> manifest_root, 57 const base::FilePath& package_dir,
49 const base::FilePath& package_dir) { 58 const base::FilePath& executable_path) {
59
50 // Manifest was malformed or did not exist. 60 // Manifest was malformed or did not exist.
51 if (!manifest_root) 61 if (!manifest_root)
52 return nullptr; 62 return nullptr;
53 63
54 const base::DictionaryValue* dictionary = nullptr; 64 const base::DictionaryValue* dictionary = nullptr;
55 if (!manifest_root->GetAsDictionary(&dictionary)) 65 if (!manifest_root->GetAsDictionary(&dictionary))
56 return nullptr; 66 return nullptr;
57 67
58 std::unique_ptr<Entry> entry = Entry::Deserialize(*dictionary); 68 std::unique_ptr<Entry> entry = Entry::Deserialize(*dictionary);
59 if (!entry) 69 if (!entry)
60 return nullptr; 70 return nullptr;
61 entry->set_path(GetExecutablePath(package_dir, entry->name())); 71 if (!executable_path.empty())
72 entry->set_path(executable_path);
73 else
74 entry->set_path(GetExecutablePath(package_dir, entry->name()));
62 return entry; 75 return entry;
63 } 76 }
64 77
78 std::unique_ptr<Entry> ProcessUniqueManifest(
79 std::unique_ptr<base::Value> manifest_root,
80 const base::FilePath& package_dir) {
81 return ProcessManifest(manifest_root.get(), package_dir, base::FilePath());
82 }
83
65 std::unique_ptr<Entry> CreateEntryForManifestAt( 84 std::unique_ptr<Entry> CreateEntryForManifestAt(
66 const base::FilePath& manifest_path, 85 const base::FilePath& manifest_path,
67 const base::FilePath& package_dir) { 86 const base::FilePath& package_dir) {
68 JSONFileValueDeserializer deserializer(manifest_path); 87 JSONFileValueDeserializer deserializer(manifest_path);
69 int error = 0; 88 int error = 0;
70 std::string message; 89 std::string message;
71 90
72 // TODO(beng): probably want to do more detailed error checking. This should 91 // TODO(beng): probably want to do more detailed error checking. This should
73 // be done when figuring out if to unblock connection completion. 92 // be done when figuring out if to unblock connection completion.
74 return ProcessManifest(deserializer.Deserialize(&error, &message), 93 return ProcessUniqueManifest(deserializer.Deserialize(&error, &message),
75 package_dir); 94 package_dir);
76 } 95 }
77 96
78 void ScanDir( 97 void ScanDir(
79 const base::FilePath& package_dir, 98 const base::FilePath& package_dir,
80 const Reader::ReadManifestCallback& read_manifest_callback, 99 const Reader::ReadManifestCallback& read_manifest_callback,
81 scoped_refptr<base::SingleThreadTaskRunner> original_thread_task_runner, 100 scoped_refptr<base::SingleThreadTaskRunner> original_thread_task_runner,
82 const base::Closure& read_complete_closure) { 101 const base::Closure& read_complete_closure) {
83 base::FileEnumerator enumerator(package_dir, false, 102 base::FileEnumerator enumerator(package_dir, false,
84 base::FileEnumerator::DIRECTORIES); 103 base::FileEnumerator::DIRECTORIES);
85 while (1) { 104 while (1) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 154
136 void AddEntryToCache(EntryCache* cache, std::unique_ptr<Entry> entry) { 155 void AddEntryToCache(EntryCache* cache, std::unique_ptr<Entry> entry) {
137 std::vector<std::unique_ptr<Entry>> children = entry->TakeChildren(); 156 std::vector<std::unique_ptr<Entry>> children = entry->TakeChildren();
138 for (auto& child : children) 157 for (auto& child : children)
139 AddEntryToCache(cache, std::move(child)); 158 AddEntryToCache(cache, std::move(child));
140 (*cache)[entry->name()] = std::move(entry); 159 (*cache)[entry->name()] = std::move(entry);
141 } 160 }
142 161
143 void DoNothing(service_manager::mojom::ResolveResultPtr) {} 162 void DoNothing(service_manager::mojom::ResolveResultPtr) {}
144 163
164 void LoadCatalogManifestIntoCache(const base::Value* root,
165 const base::FilePath& package_dir,
166 EntryCache* cache) {
167 DCHECK(root);
168 const base::DictionaryValue* catalog = nullptr;
169 if (!root->GetAsDictionary(&catalog)) {
170 LOG(ERROR) << "Catalog manifest is not a dictionary value.";
171 return;
172 }
173 DCHECK(catalog);
174
175 const base::DictionaryValue* services = nullptr;
176 if (!catalog->GetDictionary(kCatalogServicesKey, &services)) {
177 LOG(ERROR) << "Catalog manifest \"services\" is not a dictionary value.";
178 return;
179 }
180
181 for (base::DictionaryValue::Iterator it(*services); !it.IsAtEnd();
182 it.Advance()) {
183 const base::DictionaryValue* service_entry = nullptr;
184 if (!it.value().GetAsDictionary(&service_entry)) {
185 LOG(ERROR) << "Catalog service entry for \"" << it.key()
186 << "\" is not a dictionary value.";
187 continue;
188 }
189
190 bool is_embedded = false;
191 service_entry->GetBoolean(kCatalogServiceEmbeddedKey, &is_embedded);
192
193 base::FilePath executable_path;
194 std::string executable_path_string;
195 if (service_entry->GetString(kCatalogServiceExecutableKey,
196 &executable_path_string)) {
197 base::FilePath exe_dir;
198 CHECK(base::PathService::Get(base::DIR_EXE, &exe_dir));
199 #if defined(OS_WIN)
200 executable_path_string += ".exe";
201 base::ReplaceFirstSubstringAfterOffset(
202 &executable_path_string, 0, "@EXE_DIR",
203 base::UTF16ToUTF8(exe_dir.value()));
204 executable_path =
205 base::FilePath(base::UTF8ToUTF16(executable_path_string));
206 #else
207 base::ReplaceFirstSubstringAfterOffset(
208 &executable_path_string, 0, "@EXE_DIR", exe_dir.value());
209 executable_path = base::FilePath(executable_path_string);
210 #endif
211 }
212
213 const base::DictionaryValue* manifest = nullptr;
214 if (!service_entry->GetDictionary(kCatalogServiceManifestKey, &manifest)) {
215 LOG(ERROR) << "Catalog entry for \"" << it.key() << "\" has an invalid "
216 << "\"manifest\" value.";
217 continue;
218 }
219
220 DCHECK(!(is_embedded && !executable_path.empty()));
221
222 auto entry = ProcessManifest(
223 manifest, is_embedded ? base::FilePath() : package_dir,
224 executable_path);
225 if (entry)
226 AddEntryToCache(cache, std::move(entry));
227 else
228 LOG(ERROR) << "Failed to read manifest entry for \"" << it.key() << "\".";
229 }
230 }
231
145 } // namespace 232 } // namespace
146 233
234 Reader::Reader(std::unique_ptr<base::Value> static_manifest,
235 EntryCache* cache)
236 : using_static_catalog_(true),
237 manifest_provider_(nullptr),
238 weak_factory_(this) {
239 PathService::Get(base::DIR_MODULE, &system_package_dir_);
240 LoadCatalogManifestIntoCache(
241 static_manifest.get(), system_package_dir_.AppendASCII(kPackagesDirName),
242 cache);
243 }
244
147 // A sequenced task runner is used to guarantee requests are serviced in the 245 // A sequenced task runner is used to guarantee requests are serviced in the
148 // order requested. To do otherwise means we may run callbacks in an 246 // order requested. To do otherwise means we may run callbacks in an
149 // unpredictable order, leading to flake. 247 // unpredictable order, leading to flake.
150 Reader::Reader(base::SequencedWorkerPool* worker_pool, 248 Reader::Reader(base::SequencedWorkerPool* worker_pool,
151 ManifestProvider* manifest_provider) 249 ManifestProvider* manifest_provider)
152 : Reader(manifest_provider) { 250 : Reader(manifest_provider) {
153 file_task_runner_ = worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( 251 file_task_runner_ = worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
154 base::SequencedWorkerPool::GetSequenceToken(), 252 base::SequencedWorkerPool::GetSequenceToken(),
155 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 253 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
156 } 254 }
(...skipping 21 matching lines...) Expand all
178 void Reader::CreateEntryForName( 276 void Reader::CreateEntryForName(
179 const std::string& mojo_name, 277 const std::string& mojo_name,
180 EntryCache* cache, 278 EntryCache* cache,
181 const CreateEntryForNameCallback& entry_created_callback) { 279 const CreateEntryForNameCallback& entry_created_callback) {
182 if (manifest_provider_) { 280 if (manifest_provider_) {
183 std::unique_ptr<base::Value> manifest_root = 281 std::unique_ptr<base::Value> manifest_root =
184 manifest_provider_->GetManifest(mojo_name); 282 manifest_provider_->GetManifest(mojo_name);
185 if (manifest_root) { 283 if (manifest_root) {
186 base::PostTaskAndReplyWithResult( 284 base::PostTaskAndReplyWithResult(
187 file_task_runner_.get(), FROM_HERE, 285 file_task_runner_.get(), FROM_HERE,
188 base::Bind(&ProcessManifest, base::Passed(&manifest_root), 286 base::Bind(&ProcessUniqueManifest, base::Passed(&manifest_root),
189 system_package_dir_), 287 system_package_dir_),
190 base::Bind(&Reader::OnReadManifest, weak_factory_.GetWeakPtr(), cache, 288 base::Bind(&Reader::OnReadManifest, weak_factory_.GetWeakPtr(), cache,
191 entry_created_callback)); 289 entry_created_callback));
192 return; 290 return;
193 } 291 }
292 } else if (using_static_catalog_) {
293 // A Reader using a static catalog manifest does not support dynamic
294 // discovery or introduction of new catalog entries.
295 entry_created_callback.Run(service_manager::mojom::ResolveResultPtr());
296 return;
194 } 297 }
195 298
196 base::FilePath manifest_path_override; 299 base::FilePath manifest_path_override;
197 { 300 {
198 auto override_iter = manifest_path_overrides_.find(mojo_name); 301 auto override_iter = manifest_path_overrides_.find(mojo_name);
199 if (override_iter != manifest_path_overrides_.end()) 302 if (override_iter != manifest_path_overrides_.end())
200 manifest_path_override = override_iter->second; 303 manifest_path_override = override_iter->second;
201 } 304 }
202 305
203 std::string package_name_override; 306 std::string package_name_override;
(...skipping 14 matching lines...) Expand all
218 const std::string& package_name) { 321 const std::string& package_name) {
219 package_name_overrides_.insert(std::make_pair(service_name, package_name)); 322 package_name_overrides_.insert(std::make_pair(service_name, package_name));
220 } 323 }
221 324
222 void Reader::OverrideManifestPath(const std::string& service_name, 325 void Reader::OverrideManifestPath(const std::string& service_name,
223 const base::FilePath& path) { 326 const base::FilePath& path) {
224 manifest_path_overrides_.insert(std::make_pair(service_name, path)); 327 manifest_path_overrides_.insert(std::make_pair(service_name, path));
225 } 328 }
226 329
227 Reader::Reader(ManifestProvider* manifest_provider) 330 Reader::Reader(ManifestProvider* manifest_provider)
228 : manifest_provider_(manifest_provider), weak_factory_(this) { 331 : using_static_catalog_(false),
332 manifest_provider_(manifest_provider),
333 weak_factory_(this) {
229 PathService::Get(base::DIR_MODULE, &system_package_dir_); 334 PathService::Get(base::DIR_MODULE, &system_package_dir_);
230 } 335 }
231 336
232 void Reader::OnReadManifest( 337 void Reader::OnReadManifest(
233 EntryCache* cache, 338 EntryCache* cache,
234 const CreateEntryForNameCallback& entry_created_callback, 339 const CreateEntryForNameCallback& entry_created_callback,
235 std::unique_ptr<Entry> entry) { 340 std::unique_ptr<Entry> entry) {
236 if (!entry) 341 if (!entry)
237 return; 342 return;
238 service_manager::mojom::ResolveResultPtr result = 343 service_manager::mojom::ResolveResultPtr result =
239 service_manager::mojom::ResolveResult::From(*entry); 344 service_manager::mojom::ResolveResult::From(*entry);
240 AddEntryToCache(cache, std::move(entry)); 345 AddEntryToCache(cache, std::move(entry));
241 entry_created_callback.Run(std::move(result)); 346 entry_created_callback.Run(std::move(result));
242 } 347 }
243 348
244 } // namespace catalog 349 } // namespace catalog
OLDNEW
« no previous file with comments | « services/catalog/reader.h ('k') | services/catalog/store.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698