OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/package_manager/package_manager_impl.h" | 5 #include "mojo/package_manager/package_manager_impl.h" |
6 | 6 |
| 7 #include "base/bind.h" |
| 8 #include "mojo/application/public/interfaces/content_handler.mojom.h" |
7 #include "mojo/fetcher/about_fetcher.h" | 9 #include "mojo/fetcher/about_fetcher.h" |
8 #include "mojo/fetcher/data_fetcher.h" | 10 #include "mojo/fetcher/data_fetcher.h" |
9 #include "mojo/fetcher/local_fetcher.h" | 11 #include "mojo/fetcher/local_fetcher.h" |
10 #include "mojo/fetcher/network_fetcher.h" | 12 #include "mojo/fetcher/network_fetcher.h" |
11 #include "mojo/fetcher/switches.h" | 13 #include "mojo/fetcher/switches.h" |
12 #include "mojo/fetcher/update_fetcher.h" | 14 #include "mojo/fetcher/update_fetcher.h" |
| 15 #include "mojo/package_manager/content_handler_connection.h" |
13 #include "mojo/shell/application_manager.h" | 16 #include "mojo/shell/application_manager.h" |
14 #include "mojo/shell/connect_util.h" | 17 #include "mojo/shell/connect_util.h" |
15 #include "mojo/shell/query_util.h" | 18 #include "mojo/shell/query_util.h" |
16 #include "mojo/shell/switches.h" | 19 #include "mojo/shell/switches.h" |
17 #include "mojo/util/filename_util.h" | 20 #include "mojo/util/filename_util.h" |
18 #include "url/gurl.h" | 21 #include "url/gurl.h" |
19 | 22 |
20 namespace mojo { | 23 namespace mojo { |
21 namespace package_manager { | 24 namespace package_manager { |
22 | 25 |
23 PackageManagerImpl::PackageManagerImpl( | 26 PackageManagerImpl::PackageManagerImpl( |
24 const base::FilePath& shell_file_root) | 27 const base::FilePath& shell_file_root, |
| 28 base::TaskRunner* task_runner) |
25 : application_manager_(nullptr), | 29 : application_manager_(nullptr), |
26 disable_cache_(base::CommandLine::ForCurrentProcess()->HasSwitch( | 30 disable_cache_(base::CommandLine::ForCurrentProcess()->HasSwitch( |
27 switches::kDisableCache)) { | 31 switches::kDisableCache)), |
| 32 content_handler_id_counter_(0u), |
| 33 task_runner_(task_runner) { |
28 if (!shell_file_root.empty()) { | 34 if (!shell_file_root.empty()) { |
29 GURL mojo_root_file_url = | 35 GURL mojo_root_file_url = |
30 util::FilePathToFileURL(shell_file_root).Resolve(std::string()); | 36 util::FilePathToFileURL(shell_file_root).Resolve(std::string()); |
31 url_resolver_.reset(new fetcher::URLResolver(mojo_root_file_url)); | 37 url_resolver_.reset(new fetcher::URLResolver(mojo_root_file_url)); |
32 } | 38 } |
33 } | 39 } |
34 | 40 |
35 PackageManagerImpl::~PackageManagerImpl() { | 41 PackageManagerImpl::~PackageManagerImpl() { |
| 42 IdentityToContentHandlerMap identity_to_content_handler( |
| 43 identity_to_content_handler_); |
| 44 for (auto& pair : identity_to_content_handler) |
| 45 pair.second->CloseConnection(); |
36 } | 46 } |
37 | 47 |
38 void PackageManagerImpl::RegisterContentHandler( | 48 void PackageManagerImpl::RegisterContentHandler( |
39 const std::string& mime_type, | 49 const std::string& mime_type, |
40 const GURL& content_handler_url) { | 50 const GURL& content_handler_url) { |
41 DCHECK(content_handler_url.is_valid()) | 51 DCHECK(content_handler_url.is_valid()) |
42 << "Content handler URL is invalid for mime type " << mime_type; | 52 << "Content handler URL is invalid for mime type " << mime_type; |
43 mime_type_to_url_[mime_type] = content_handler_url; | 53 mime_type_to_url_[mime_type] = content_handler_url; |
44 } | 54 } |
45 | 55 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 shell::ConnectToService(application_manager_, GURL("mojo:network_service"), | 118 shell::ConnectToService(application_manager_, GURL("mojo:network_service"), |
109 &url_loader_factory_); | 119 &url_loader_factory_); |
110 } | 120 } |
111 | 121 |
112 // Ownership of this object is transferred to |loader_callback|. | 122 // Ownership of this object is transferred to |loader_callback|. |
113 // TODO(beng): this is eff'n weird. | 123 // TODO(beng): this is eff'n weird. |
114 new fetcher::NetworkFetcher(disable_cache_, request.Pass(), | 124 new fetcher::NetworkFetcher(disable_cache_, request.Pass(), |
115 url_loader_factory_.get(), loader_callback); | 125 url_loader_factory_.get(), loader_callback); |
116 } | 126 } |
117 | 127 |
118 bool PackageManagerImpl::HandleWithContentHandler(shell::Fetcher* fetcher, | 128 uint32_t PackageManagerImpl::HandleWithContentHandler( |
119 const GURL& url, | 129 shell::Fetcher* fetcher, |
120 base::TaskRunner* task_runner, | 130 const shell::Identity& source, |
121 URLResponsePtr* new_response, | 131 const GURL& target_url, |
122 GURL* content_handler_url, | 132 const shell::CapabilityFilter& target_filter, |
123 std::string* qualifier) { | 133 InterfaceRequest<Application>* application_request) { |
| 134 shell::Identity content_handler_identity; |
| 135 URLResponsePtr response; |
| 136 if (ShouldHandleWithContentHandler(fetcher, |
| 137 target_url, |
| 138 target_filter, |
| 139 &content_handler_identity, |
| 140 &response)) { |
| 141 ContentHandlerConnection* connection = |
| 142 GetContentHandler(content_handler_identity, source); |
| 143 connection->content_handler()->StartApplication(application_request->Pass(), |
| 144 response.Pass()); |
| 145 return connection->id(); |
| 146 } |
| 147 return Shell::kInvalidContentHandlerID; |
| 148 } |
| 149 |
| 150 GURL PackageManagerImpl::ResolveURL(const GURL& url) { |
| 151 return url_resolver_.get() ? url_resolver_->ResolveMojoURL(url) : url; |
| 152 } |
| 153 |
| 154 bool PackageManagerImpl::ShouldHandleWithContentHandler( |
| 155 shell::Fetcher* fetcher, |
| 156 const GURL& target_url, |
| 157 const shell::CapabilityFilter& target_filter, |
| 158 shell::Identity* content_handler_identity, |
| 159 URLResponsePtr* response) const { |
124 // TODO(beng): it seems like some delegate should/would want to have a say in | 160 // TODO(beng): it seems like some delegate should/would want to have a say in |
125 // configuring the qualifier also. | 161 // configuring the qualifier also. |
126 bool enable_multi_process = base::CommandLine::ForCurrentProcess()->HasSwitch( | 162 // Why can't we use the real qualifier in single process mode? Because of |
| 163 // base::AtExitManager. If you link in ApplicationRunner into your code, and |
| 164 // then we make initialize multiple copies of the application, we end up |
| 165 // with multiple AtExitManagers and will check on the second one being |
| 166 // created. |
| 167 // |
| 168 // Why doesn't that happen when running different apps? Because |
| 169 // your_thing.mojo!base::AtExitManager and |
| 170 // my_thing.mojo!base::AtExitManager are different symbols. |
| 171 bool use_real_qualifier = base::CommandLine::ForCurrentProcess()->HasSwitch( |
127 switches::kEnableMultiprocess); | 172 switches::kEnableMultiprocess); |
128 | 173 |
| 174 GURL content_handler_url; |
129 // The response begins with a #!mojo <content-handler-url>. | 175 // The response begins with a #!mojo <content-handler-url>. |
130 std::string shebang; | 176 std::string shebang; |
131 if (fetcher->PeekContentHandler(&shebang, content_handler_url)) { | 177 if (fetcher->PeekContentHandler(&shebang, &content_handler_url)) { |
132 *new_response = fetcher->AsURLResponse( | 178 *response = fetcher->AsURLResponse(task_runner_, |
133 task_runner, static_cast<int>(shebang.size())); | 179 static_cast<int>(shebang.size())); |
134 *qualifier = enable_multi_process ? (*new_response)->site.To<std::string>() | 180 *content_handler_identity = shell::Identity( |
135 : std::string(); | 181 content_handler_url, |
| 182 use_real_qualifier ? (*response)->site.To<std::string>() |
| 183 : std::string(), |
| 184 target_filter); |
136 return true; | 185 return true; |
137 } | 186 } |
138 | 187 |
139 // The response MIME type matches a registered content handler. | 188 // The response MIME type matches a registered content handler. |
140 MimeTypeToURLMap::iterator iter = mime_type_to_url_.find(fetcher->MimeType()); | 189 auto iter = mime_type_to_url_.find(fetcher->MimeType()); |
141 if (iter != mime_type_to_url_.end()) { | 190 if (iter != mime_type_to_url_.end()) { |
142 *new_response = fetcher->AsURLResponse(task_runner, 0); | 191 *response = fetcher->AsURLResponse(task_runner_, 0); |
143 *content_handler_url = iter->second; | 192 *content_handler_identity = shell::Identity( |
144 *qualifier = enable_multi_process ? (*new_response)->site.To<std::string>() | 193 iter->second, |
145 : std::string(); | 194 use_real_qualifier ? (*response)->site.To<std::string>() |
| 195 : std::string(), |
| 196 target_filter); |
146 return true; | 197 return true; |
147 } | 198 } |
148 | 199 |
149 // The response URL matches a registered content handler. | 200 // The response URL matches a registered content handler. |
150 auto alias_iter = application_package_alias_.find(url); | 201 auto alias_iter = application_package_alias_.find(target_url); |
151 if (alias_iter != application_package_alias_.end()) { | 202 if (alias_iter != application_package_alias_.end()) { |
152 // We replace the qualifier with the one our package alias requested. | 203 // We replace the qualifier with the one our package alias requested. |
153 *new_response = URLResponse::New(); | 204 *response = URLResponse::New(); |
154 (*new_response)->url = url.spec(); | 205 (*response)->url = target_url.spec(); |
155 | 206 *content_handler_identity = shell::Identity( |
156 // Why can't we use this in single process mode? Because of | 207 alias_iter->second.first, |
157 // base::AtExitManager. If you link in ApplicationRunner into your code, and | 208 use_real_qualifier ? alias_iter->second.second : std::string(), |
158 // then we make initialize multiple copies of the application, we end up | 209 target_filter); |
159 // with multiple AtExitManagers and will check on the second one being | |
160 // created. | |
161 // | |
162 // Why doesn't that happen when running different apps? Because | |
163 // your_thing.mojo!base::AtExitManager and | |
164 // my_thing.mojo!base::AtExitManager are different symbols. | |
165 *qualifier = enable_multi_process ? alias_iter->second.second | |
166 : std::string(); | |
167 *content_handler_url = alias_iter->second.first; | |
168 return true; | 210 return true; |
169 } | 211 } |
170 | 212 |
171 return false; | 213 return false; |
172 } | 214 } |
173 | 215 |
174 GURL PackageManagerImpl::ResolveURL(const GURL& url) { | 216 ContentHandlerConnection* PackageManagerImpl::GetContentHandler( |
175 return url_resolver_.get() ? url_resolver_->ResolveMojoURL(url) : url; | 217 const shell::Identity& content_handler_identity, |
| 218 const shell::Identity& source_identity) { |
| 219 auto it = identity_to_content_handler_.find(content_handler_identity); |
| 220 if (it != identity_to_content_handler_.end()) |
| 221 return it->second; |
| 222 |
| 223 ContentHandlerConnection* connection = new ContentHandlerConnection( |
| 224 application_manager_, source_identity, |
| 225 content_handler_identity, |
| 226 ++content_handler_id_counter_, |
| 227 base::Bind(&PackageManagerImpl::OnContentHandlerConnectionClosed, |
| 228 base::Unretained(this))); |
| 229 identity_to_content_handler_[content_handler_identity] = connection; |
| 230 return connection; |
| 231 } |
| 232 |
| 233 void PackageManagerImpl::OnContentHandlerConnectionClosed( |
| 234 ContentHandlerConnection* connection) { |
| 235 // Remove the mapping. |
| 236 auto it = identity_to_content_handler_.find(connection->identity()); |
| 237 DCHECK(it != identity_to_content_handler_.end()); |
| 238 identity_to_content_handler_.erase(it); |
176 } | 239 } |
177 | 240 |
178 } // namespace package_manager | 241 } // namespace package_manager |
179 } // namespace mojo | 242 } // namespace mojo |
OLD | NEW |