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
3 // found in the LICENSE file.
5 #include "mojo/shell/application_instance.h"
8 #include "base/stl_util.h"
9 #include "mojo/application/public/interfaces/content_handler.mojom.h"
10 #include "mojo/common/common_type_converters.h"
11 #include "mojo/common/url_type_converters.h"
12 #include "mojo/shell/application_manager.h"
17 ApplicationInstance::QueuedClientRequest::QueuedClientRequest()
18 : originator(nullptr) {}
20 ApplicationInstance::QueuedClientRequest::~QueuedClientRequest() {
23 ApplicationInstance::ApplicationInstance(
24 ApplicationPtr application
,
25 ApplicationManager
* manager
,
26 const Identity
& originator_identity
,
27 const Identity
& identity
,
28 const CapabilityFilter
& filter
,
29 const base::Closure
& on_application_end
)
31 originator_identity_(originator_identity
),
34 allow_any_application_(filter
.size() == 1 && filter
.count("*") == 1),
35 on_application_end_(on_application_end
),
36 application_(application
.Pass()),
38 queue_requests_(false) {
39 binding_
.set_connection_error_handler([this]() { OnConnectionError(); });
42 ApplicationInstance::~ApplicationInstance() {
43 STLDeleteElements(&queued_client_requests_
);
46 void ApplicationInstance::InitializeApplication() {
48 binding_
.Bind(GetProxy(&shell
));
49 application_
->Initialize(shell
.Pass(), identity_
.url
.spec());
52 void ApplicationInstance::ConnectToClient(
53 ApplicationInstance
* originator
,
54 const GURL
& requested_url
,
55 const GURL
& requestor_url
,
56 InterfaceRequest
<ServiceProvider
> services
,
57 ServiceProviderPtr exposed_services
,
58 const CapabilityFilter
& filter
) {
59 if (queue_requests_
) {
60 QueuedClientRequest
* queued_request
= new QueuedClientRequest();
61 queued_request
->originator
= originator
;
62 queued_request
->requested_url
= requested_url
;
63 queued_request
->requestor_url
= requestor_url
;
64 queued_request
->services
= services
.Pass();
65 queued_request
->exposed_services
= exposed_services
.Pass();
66 queued_request
->filter
= filter
;
67 queued_client_requests_
.push_back(queued_request
);
71 CallAcceptConnection(originator
, requestor_url
, services
.Pass(),
72 exposed_services
.Pass(), requested_url
);
75 AllowedInterfaces
ApplicationInstance::GetAllowedInterfaces(
76 const Identity
& identity
) const {
77 // Start by looking for interfaces specific to the supplied identity.
78 auto it
= filter_
.find(identity
.url
.spec());
79 if (it
!= filter_
.end())
82 // Fall back to looking for a wildcard rule.
83 it
= filter_
.find("*");
84 if (filter_
.size() == 1 && it
!= filter_
.end())
87 // Finally, nothing is allowed.
88 return AllowedInterfaces();
91 // Shell implementation:
92 void ApplicationInstance::ConnectToApplication(
93 URLRequestPtr app_request
,
94 InterfaceRequest
<ServiceProvider
> services
,
95 ServiceProviderPtr exposed_services
,
96 CapabilityFilterPtr filter
) {
97 std::string url_string
= app_request
->url
.To
<std::string
>();
98 if (!GURL(url_string
).is_valid()) {
99 LOG(ERROR
) << "Error: invalid URL: " << url_string
;
102 if (allow_any_application_
|| filter_
.find(url_string
) != filter_
.end()) {
103 CapabilityFilter capability_filter
= GetPermissiveCapabilityFilter();
104 if (!filter
.is_null())
105 capability_filter
= filter
->filter
.To
<CapabilityFilter
>();
106 manager_
->ConnectToApplication(this, app_request
.Pass(), std::string(),
107 identity_
.url
, services
.Pass(),
108 exposed_services
.Pass(), capability_filter
,
111 DVLOG(1) << "CapabilityFilter prevented connection from: " <<
112 identity_
.url
<< " to: " << url_string
;
116 void ApplicationInstance::QuitApplication() {
117 queue_requests_
= true;
118 application_
->OnQuitRequested(
119 base::Bind(&ApplicationInstance::OnQuitRequestedResult
,
120 base::Unretained(this)));
123 void ApplicationInstance::CallAcceptConnection(
124 ApplicationInstance
* originator
,
125 const GURL
& requestor_url
,
126 InterfaceRequest
<ServiceProvider
> services
,
127 ServiceProviderPtr exposed_services
,
128 const GURL
& requested_url
) {
129 AllowedInterfaces interfaces
;
130 interfaces
.insert("*");
132 interfaces
= originator
->GetAllowedInterfaces(identity_
);
133 application_
->AcceptConnection(requestor_url
.spec(),
135 exposed_services
.Pass(),
136 Array
<String
>::From(interfaces
).Pass(),
137 requested_url
.spec());
140 void ApplicationInstance::OnConnectionError() {
141 std::vector
<QueuedClientRequest
*> queued_client_requests
;
142 queued_client_requests_
.swap(queued_client_requests
);
143 auto manager
= manager_
;
144 manager_
->OnApplicationInstanceError(this);
147 // If any queued requests came to shell during time it was shutting down,
149 for (auto request
: queued_client_requests
) {
150 mojo::URLRequestPtr
url(mojo::URLRequest::New());
151 url
->url
= mojo::String::From(request
->requested_url
.spec());
152 ApplicationInstance
* originator
=
153 manager
->GetApplicationInstance(originator_identity_
);
154 manager
->ConnectToApplication(originator
, url
.Pass(), std::string(),
155 request
->requestor_url
,
156 request
->services
.Pass(),
157 request
->exposed_services
.Pass(),
161 STLDeleteElements(&queued_client_requests
);
164 void ApplicationInstance::OnQuitRequestedResult(bool can_quit
) {
168 queue_requests_
= false;
169 for (auto request
: queued_client_requests_
) {
170 CallAcceptConnection(request
->originator
,
171 request
->requestor_url
,
172 request
->services
.Pass(),
173 request
->exposed_services
.Pass(),
174 request
->requested_url
);
176 STLDeleteElements(&queued_client_requests_
);