Add ICU message format support
[chromium-blink-merge.git] / mojo / shell / application_instance.cc
blob45d3e4b05c97326e6b5de9c78dc6eabd5d063a7e
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"
7 #include "base/bind.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"
14 namespace mojo {
15 namespace shell {
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)
30 : manager_(manager),
31 originator_identity_(originator_identity),
32 identity_(identity),
33 filter_(filter),
34 allow_any_application_(filter.size() == 1 && filter.count("*") == 1),
35 on_application_end_(on_application_end),
36 application_(application.Pass()),
37 binding_(this),
38 queue_requests_(false) {
39 binding_.set_connection_error_handler([this]() { OnConnectionError(); });
42 ApplicationInstance::~ApplicationInstance() {
43 STLDeleteElements(&queued_client_requests_);
46 void ApplicationInstance::InitializeApplication() {
47 ShellPtr shell;
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);
68 return;
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())
80 return it->second;
82 // Fall back to looking for a wildcard rule.
83 it = filter_.find("*");
84 if (filter_.size() == 1 && it != filter_.end())
85 return it->second;
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;
100 return;
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,
109 base::Closure());
110 } else {
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("*");
131 if (originator)
132 interfaces = originator->GetAllowedInterfaces(identity_);
133 application_->AcceptConnection(requestor_url.spec(),
134 services.Pass(),
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);
145 //|this| is deleted.
147 // If any queued requests came to shell during time it was shutting down,
148 // start them now.
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(),
158 request->filter,
159 base::Closure());
161 STLDeleteElements(&queued_client_requests);
164 void ApplicationInstance::OnQuitRequestedResult(bool can_quit) {
165 if (can_quit)
166 return;
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_);
179 } // namespace shell
180 } // namespace mojo