| 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 |