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 |