| Index: mojo/shell/application_instance.cc
|
| diff --git a/mojo/shell/application_instance.cc b/mojo/shell/application_instance.cc
|
| index 1c2479b1a1a88205307d453e55b928dcd8dc1199..a7727d88d768fac1a4dff5087b484b18a446cb33 100644
|
| --- a/mojo/shell/application_instance.cc
|
| +++ b/mojo/shell/application_instance.cc
|
| @@ -33,12 +33,6 @@ CapabilityFilter CanonicalizeFilter(const CapabilityFilter& filter) {
|
|
|
| } // namespace
|
|
|
| -ApplicationInstance::QueuedClientRequest::QueuedClientRequest()
|
| - : originator(nullptr) {}
|
| -
|
| -ApplicationInstance::QueuedClientRequest::~QueuedClientRequest() {
|
| -}
|
| -
|
| ApplicationInstance::ApplicationInstance(
|
| ApplicationPtr application,
|
| ApplicationManager* manager,
|
| @@ -61,6 +55,8 @@ ApplicationInstance::ApplicationInstance(
|
| }
|
|
|
| ApplicationInstance::~ApplicationInstance() {
|
| + for (auto request : queued_client_requests_)
|
| + request->connect_callback().Run(kInvalidContentHandlerID);
|
| STLDeleteElements(&queued_client_requests_);
|
| }
|
|
|
| @@ -71,44 +67,13 @@ void ApplicationInstance::InitializeApplication() {
|
| }
|
|
|
| void ApplicationInstance::ConnectToClient(
|
| - ApplicationInstance* originator,
|
| - const GURL& requested_url,
|
| - const GURL& requestor_url,
|
| - InterfaceRequest<ServiceProvider> services,
|
| - ServiceProviderPtr exposed_services,
|
| - const CapabilityFilter& filter,
|
| - const ConnectToApplicationCallback& callback) {
|
| - callback.Run(requesting_content_handler_id_);
|
| + scoped_ptr<ConnectToApplicationParams> params) {
|
| if (queue_requests_) {
|
| - QueuedClientRequest* queued_request = new QueuedClientRequest();
|
| - queued_request->originator = originator;
|
| - queued_request->requested_url = requested_url;
|
| - queued_request->requestor_url = requestor_url;
|
| - queued_request->services = services.Pass();
|
| - queued_request->exposed_services = exposed_services.Pass();
|
| - queued_request->filter = filter;
|
| - queued_client_requests_.push_back(queued_request);
|
| + queued_client_requests_.push_back(params.release());
|
| return;
|
| }
|
|
|
| - CallAcceptConnection(originator, requestor_url, services.Pass(),
|
| - exposed_services.Pass(), requested_url);
|
| -}
|
| -
|
| -AllowedInterfaces ApplicationInstance::GetAllowedInterfaces(
|
| - const Identity& identity) const {
|
| - // Start by looking for interfaces specific to the supplied identity.
|
| - auto it = filter_.find(identity.url.spec());
|
| - if (it != filter_.end())
|
| - return it->second;
|
| -
|
| - // Fall back to looking for a wildcard rule.
|
| - it = filter_.find("*");
|
| - if (filter_.size() == 1 && it != filter_.end())
|
| - return it->second;
|
| -
|
| - // Finally, nothing is allowed.
|
| - return AllowedInterfaces();
|
| + CallAcceptConnection(params.Pass());
|
| }
|
|
|
| // Shell implementation:
|
| @@ -130,7 +95,7 @@ void ApplicationInstance::ConnectToApplication(
|
| if (!filter.is_null())
|
| capability_filter = filter->filter.To<CapabilityFilter>();
|
| manager_->ConnectToApplication(
|
| - this, app_request.Pass(), std::string(), identity_.url, services.Pass(),
|
| + this, app_request.Pass(), std::string(), GURL(), services.Pass(),
|
| exposed_services.Pass(), capability_filter, base::Closure(), callback);
|
| } else {
|
| LOG(WARNING) << "CapabilityFilter prevented connection from: " <<
|
| @@ -147,24 +112,21 @@ void ApplicationInstance::QuitApplication() {
|
| }
|
|
|
| void ApplicationInstance::CallAcceptConnection(
|
| - ApplicationInstance* originator,
|
| - const GURL& requestor_url,
|
| - InterfaceRequest<ServiceProvider> services,
|
| - ServiceProviderPtr exposed_services,
|
| - const GURL& requested_url) {
|
| + scoped_ptr<ConnectToApplicationParams> params) {
|
| + params->connect_callback().Run(requesting_content_handler_id_);
|
| AllowedInterfaces interfaces;
|
| interfaces.insert("*");
|
| - if (originator)
|
| - interfaces = originator->GetAllowedInterfaces(identity_);
|
| - application_->AcceptConnection(requestor_url.spec(),
|
| - services.Pass(),
|
| - exposed_services.Pass(),
|
| - Array<String>::From(interfaces).Pass(),
|
| - requested_url.spec());
|
| + if (!params->originator_identity().is_null())
|
| + interfaces = GetAllowedInterfaces(params->originator_filter(), identity_);
|
| +
|
| + application_->AcceptConnection(
|
| + params->originator_identity().url.spec(), params->TakeServices(),
|
| + params->TakeExposedServices(), Array<String>::From(interfaces).Pass(),
|
| + params->app_url().spec());
|
| }
|
|
|
| void ApplicationInstance::OnConnectionError() {
|
| - std::vector<QueuedClientRequest*> queued_client_requests;
|
| + std::vector<ConnectToApplicationParams*> queued_client_requests;
|
| queued_client_requests_.swap(queued_client_requests);
|
| auto manager = manager_;
|
| manager_->OnApplicationInstanceError(this);
|
| @@ -173,16 +135,31 @@ void ApplicationInstance::OnConnectionError() {
|
| // If any queued requests came to shell during time it was shutting down,
|
| // start them now.
|
| for (auto request : queued_client_requests) {
|
| - mojo::URLRequestPtr url(mojo::URLRequest::New());
|
| - url->url = mojo::String::From(request->requested_url.spec());
|
| - ApplicationInstance* originator =
|
| - manager->GetApplicationInstance(originator_identity_);
|
| - manager->ConnectToApplication(
|
| - originator, url.Pass(), std::string(), request->requestor_url,
|
| - request->services.Pass(), request->exposed_services.Pass(),
|
| - request->filter, base::Closure(), EmptyConnectCallback());
|
| + // Unfortunately, it is possible that |request->app_url_request()| is null
|
| + // at this point. Consider the following sequence:
|
| + // 1) connect_request_1 arrives at the application manager; the manager
|
| + // decides to fetch the app.
|
| + // 2) connect_request_2 arrives for the same app; because the app is not
|
| + // running yet, the manager decides to fetch the app again.
|
| + // 3) The fetch for step (1) completes and an application instance app_a is
|
| + // registered.
|
| + // 4) app_a goes into two-phase shutdown.
|
| + // 5) The fetch for step (2) completes; the manager finds that there is a
|
| + // running app already, so it connects to app_a.
|
| + // 6) connect_request_2 is queued (and eventually gets here), but its
|
| + // original_request field was already lost to NetworkFetcher at step (2).
|
| + //
|
| + // TODO(yzshen): It seems we should register a pending application instance
|
| + // before starting the fetch. So at step (2) the application manager knows
|
| + // that it can wait for the first fetch to complete instead of doing a
|
| + // second one directly.
|
| + if (!request->app_url_request()) {
|
| + URLRequestPtr url_request = mojo::URLRequest::New();
|
| + url_request->url = request->app_url().spec();
|
| + request->SetURLInfo(url_request.Pass());
|
| + }
|
| + manager->ConnectToApplication(make_scoped_ptr(request));
|
| }
|
| - STLDeleteElements(&queued_client_requests);
|
| }
|
|
|
| void ApplicationInstance::OnQuitRequestedResult(bool can_quit) {
|
| @@ -190,12 +167,10 @@ void ApplicationInstance::OnQuitRequestedResult(bool can_quit) {
|
| return;
|
|
|
| queue_requests_ = false;
|
| - for (auto request : queued_client_requests_) {
|
| - CallAcceptConnection(
|
| - request->originator, request->requestor_url, request->services.Pass(),
|
| - request->exposed_services.Pass(), request->requested_url);
|
| - }
|
| - STLDeleteElements(&queued_client_requests_);
|
| + for (auto request : queued_client_requests_)
|
| + CallAcceptConnection(make_scoped_ptr(request));
|
| +
|
| + queued_client_requests_.clear();
|
| }
|
|
|
| } // namespace shell
|
|
|