Update V8 to version 4.7.19.
[chromium-blink-merge.git] / mojo / shell / application_instance.cc
blob1c2479b1a1a88205307d453e55b928dcd8dc1199
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"
13 #include "mojo/shell/content_handler_connection.h"
15 namespace mojo {
16 namespace shell {
17 namespace {
19 // It's valid to specify mojo: URLs in the filter either as mojo:foo or
20 // mojo://foo/ - but we store the filter in the latter form.
21 CapabilityFilter CanonicalizeFilter(const CapabilityFilter& filter) {
22 CapabilityFilter canonicalized;
23 for (CapabilityFilter::const_iterator it = filter.begin();
24 it != filter.end();
25 ++it) {
26 if (it->first == "*")
27 canonicalized[it->first] = it->second;
28 else
29 canonicalized[GURL(it->first).spec()] = it->second;
31 return canonicalized;
34 } // namespace
36 ApplicationInstance::QueuedClientRequest::QueuedClientRequest()
37 : originator(nullptr) {}
39 ApplicationInstance::QueuedClientRequest::~QueuedClientRequest() {
42 ApplicationInstance::ApplicationInstance(
43 ApplicationPtr application,
44 ApplicationManager* manager,
45 const Identity& originator_identity,
46 const Identity& identity,
47 const CapabilityFilter& filter,
48 uint32_t requesting_content_handler_id,
49 const base::Closure& on_application_end)
50 : manager_(manager),
51 originator_identity_(originator_identity),
52 identity_(identity),
53 filter_(CanonicalizeFilter(filter)),
54 allow_any_application_(filter.size() == 1 && filter.count("*") == 1),
55 requesting_content_handler_id_(requesting_content_handler_id),
56 on_application_end_(on_application_end),
57 application_(application.Pass()),
58 binding_(this),
59 queue_requests_(false) {
60 binding_.set_connection_error_handler([this]() { OnConnectionError(); });
63 ApplicationInstance::~ApplicationInstance() {
64 STLDeleteElements(&queued_client_requests_);
67 void ApplicationInstance::InitializeApplication() {
68 ShellPtr shell;
69 binding_.Bind(GetProxy(&shell));
70 application_->Initialize(shell.Pass(), identity_.url.spec());
73 void ApplicationInstance::ConnectToClient(
74 ApplicationInstance* originator,
75 const GURL& requested_url,
76 const GURL& requestor_url,
77 InterfaceRequest<ServiceProvider> services,
78 ServiceProviderPtr exposed_services,
79 const CapabilityFilter& filter,
80 const ConnectToApplicationCallback& callback) {
81 callback.Run(requesting_content_handler_id_);
82 if (queue_requests_) {
83 QueuedClientRequest* queued_request = new QueuedClientRequest();
84 queued_request->originator = originator;
85 queued_request->requested_url = requested_url;
86 queued_request->requestor_url = requestor_url;
87 queued_request->services = services.Pass();
88 queued_request->exposed_services = exposed_services.Pass();
89 queued_request->filter = filter;
90 queued_client_requests_.push_back(queued_request);
91 return;
94 CallAcceptConnection(originator, requestor_url, services.Pass(),
95 exposed_services.Pass(), requested_url);
98 AllowedInterfaces ApplicationInstance::GetAllowedInterfaces(
99 const Identity& identity) const {
100 // Start by looking for interfaces specific to the supplied identity.
101 auto it = filter_.find(identity.url.spec());
102 if (it != filter_.end())
103 return it->second;
105 // Fall back to looking for a wildcard rule.
106 it = filter_.find("*");
107 if (filter_.size() == 1 && it != filter_.end())
108 return it->second;
110 // Finally, nothing is allowed.
111 return AllowedInterfaces();
114 // Shell implementation:
115 void ApplicationInstance::ConnectToApplication(
116 URLRequestPtr app_request,
117 InterfaceRequest<ServiceProvider> services,
118 ServiceProviderPtr exposed_services,
119 CapabilityFilterPtr filter,
120 const ConnectToApplicationCallback& callback) {
121 std::string url_string = app_request->url.To<std::string>();
122 GURL url(url_string);
123 if (!url.is_valid()) {
124 LOG(ERROR) << "Error: invalid URL: " << url_string;
125 callback.Run(kInvalidContentHandlerID);
126 return;
128 if (allow_any_application_ || filter_.find(url.spec()) != filter_.end()) {
129 CapabilityFilter capability_filter = GetPermissiveCapabilityFilter();
130 if (!filter.is_null())
131 capability_filter = filter->filter.To<CapabilityFilter>();
132 manager_->ConnectToApplication(
133 this, app_request.Pass(), std::string(), identity_.url, services.Pass(),
134 exposed_services.Pass(), capability_filter, base::Closure(), callback);
135 } else {
136 LOG(WARNING) << "CapabilityFilter prevented connection from: " <<
137 identity_.url << " to: " << url.spec();
138 callback.Run(kInvalidContentHandlerID);
142 void ApplicationInstance::QuitApplication() {
143 queue_requests_ = true;
144 application_->OnQuitRequested(
145 base::Bind(&ApplicationInstance::OnQuitRequestedResult,
146 base::Unretained(this)));
149 void ApplicationInstance::CallAcceptConnection(
150 ApplicationInstance* originator,
151 const GURL& requestor_url,
152 InterfaceRequest<ServiceProvider> services,
153 ServiceProviderPtr exposed_services,
154 const GURL& requested_url) {
155 AllowedInterfaces interfaces;
156 interfaces.insert("*");
157 if (originator)
158 interfaces = originator->GetAllowedInterfaces(identity_);
159 application_->AcceptConnection(requestor_url.spec(),
160 services.Pass(),
161 exposed_services.Pass(),
162 Array<String>::From(interfaces).Pass(),
163 requested_url.spec());
166 void ApplicationInstance::OnConnectionError() {
167 std::vector<QueuedClientRequest*> queued_client_requests;
168 queued_client_requests_.swap(queued_client_requests);
169 auto manager = manager_;
170 manager_->OnApplicationInstanceError(this);
171 //|this| is deleted.
173 // If any queued requests came to shell during time it was shutting down,
174 // start them now.
175 for (auto request : queued_client_requests) {
176 mojo::URLRequestPtr url(mojo::URLRequest::New());
177 url->url = mojo::String::From(request->requested_url.spec());
178 ApplicationInstance* originator =
179 manager->GetApplicationInstance(originator_identity_);
180 manager->ConnectToApplication(
181 originator, url.Pass(), std::string(), request->requestor_url,
182 request->services.Pass(), request->exposed_services.Pass(),
183 request->filter, base::Closure(), EmptyConnectCallback());
185 STLDeleteElements(&queued_client_requests);
188 void ApplicationInstance::OnQuitRequestedResult(bool can_quit) {
189 if (can_quit)
190 return;
192 queue_requests_ = false;
193 for (auto request : queued_client_requests_) {
194 CallAcceptConnection(
195 request->originator, request->requestor_url, request->services.Pass(),
196 request->exposed_services.Pass(), request->requested_url);
198 STLDeleteElements(&queued_client_requests_);
201 } // namespace shell
202 } // namespace mojo