Aggregate parameters through mappings.

This will allow to do something like:
- Pass generic parameters to mojo:window_manager
- Pass specific parameters to the final implementation

It will also ensure that when mappings are present, the arguments an
application receive do not depend on the URL used to connect to it the first
time.

This is a reland of https://codereview.chromium.org/1025603004 fixing the
android tests. The arguments were not taken into account because settings
arguments must happen after the context is initialized.

TBR=davemoore@chromium.org

Review URL: https://codereview.chromium.org/1026293002
diff --git a/shell/application_manager/application_manager.cc b/shell/application_manager/application_manager.cc
index 8ffe808..f285962 100644
--- a/shell/application_manager/application_manager.cc
+++ b/shell/application_manager/application_manager.cc
@@ -28,6 +28,17 @@
 // Used by TestAPI.
 bool has_created_instance = false;
 
+std::vector<std::string> Concatenate(const std::vector<std::string>& v1,
+                                     const std::vector<std::string>& v2) {
+  if (!v1.size())
+    return v2;
+  if (!v2.size())
+    return v1;
+  std::vector<std::string> result(v1);
+  result.insert(result.end(), v1.begin(), v1.end());
+  return result;
+}
+
 }  // namespace
 
 ApplicationManager::Delegate::~Delegate() {
@@ -111,6 +122,17 @@
     const GURL& requestor_url,
     InterfaceRequest<ServiceProvider> services,
     ServiceProviderPtr exposed_services) {
+  ConnectToApplicationWithParameters(requested_url, requestor_url,
+                                     services.Pass(), exposed_services.Pass(),
+                                     std::vector<std::string>());
+}
+
+void ApplicationManager::ConnectToApplicationWithParameters(
+    const GURL& requested_url,
+    const GURL& requestor_url,
+    InterfaceRequest<ServiceProvider> services,
+    ServiceProviderPtr exposed_services,
+    const std::vector<std::string>& parameters) {
   DCHECK(requested_url.is_valid());
 
   // We check both the mapped and resolved urls for existing shell_impls because
@@ -129,27 +151,28 @@
   }
 
   if (ConnectToApplicationWithLoader(requested_url, mapped_url, requestor_url,
-                                     &services, &exposed_services,
+                                     &services, &exposed_services, parameters,
                                      GetLoaderForURL(mapped_url))) {
     return;
   }
 
   if (ConnectToApplicationWithLoader(requested_url, resolved_url, requestor_url,
-                                     &services, &exposed_services,
+                                     &services, &exposed_services, parameters,
                                      GetLoaderForURL(resolved_url))) {
     return;
   }
 
   if (ConnectToApplicationWithLoader(requested_url, resolved_url, requestor_url,
-                                     &services, &exposed_services,
+                                     &services, &exposed_services, parameters,
                                      default_loader_.get())) {
     return;
   }
 
-  auto callback = base::Bind(&ApplicationManager::HandleFetchCallback,
-                             weak_ptr_factory_.GetWeakPtr(), requested_url,
-                             requestor_url, base::Passed(services.Pass()),
-                             base::Passed(exposed_services.Pass()));
+  auto callback = base::Bind(
+      &ApplicationManager::HandleFetchCallback, weak_ptr_factory_.GetWeakPtr(),
+      requested_url, requestor_url, base::Passed(services.Pass()),
+      base::Passed(exposed_services.Pass()),
+      Concatenate(parameters, GetArgsForURL(resolved_url)));
 
   if (resolved_url.SchemeIsFile()) {
     new LocalFetcher(resolved_url, GetBaseURLAndQuery(resolved_url, nullptr),
@@ -191,13 +214,15 @@
     const GURL& requestor_url,
     InterfaceRequest<ServiceProvider>* services,
     ServiceProviderPtr* exposed_services,
+    const std::vector<std::string>& parameters,
     ApplicationLoader* loader) {
   if (!loader)
     return false;
 
-  loader->Load(resolved_url,
-               RegisterShell(requested_url, resolved_url, requestor_url,
-                             services->Pass(), exposed_services->Pass()));
+  loader->Load(
+      resolved_url,
+      RegisterShell(requested_url, resolved_url, requestor_url,
+                    services->Pass(), exposed_services->Pass(), parameters));
   return true;
 }
 
@@ -206,7 +231,8 @@
     const GURL& resolved_url,
     const GURL& requestor_url,
     InterfaceRequest<ServiceProvider> services,
-    ServiceProviderPtr exposed_services) {
+    ServiceProviderPtr exposed_services,
+    const std::vector<std::string>& parameters) {
   Identity app_identity(resolved_url);
 
   ApplicationPtr application;
@@ -214,7 +240,8 @@
   ShellImpl* shell =
       new ShellImpl(application.Pass(), this, original_url, app_identity);
   identity_to_shell_impl_[app_identity] = shell;
-  shell->InitializeApplication(GetArgsForURL(original_url));
+  shell->InitializeApplication(Array<String>::From(
+      Concatenate(parameters, GetArgsForURL(app_identity.url))));
   ConnectToClient(shell, resolved_url, requestor_url, services.Pass(),
                   exposed_services.Pass());
   return application_request.Pass();
@@ -242,6 +269,7 @@
     const GURL& requestor_url,
     InterfaceRequest<ServiceProvider> services,
     ServiceProviderPtr exposed_services,
+    const std::vector<std::string>& parameters,
     NativeRunner::CleanupBehavior cleanup_behavior,
     scoped_ptr<Fetcher> fetcher) {
   if (!fetcher) {
@@ -252,8 +280,9 @@
   GURL redirect_url = fetcher->GetRedirectURL();
   if (!redirect_url.is_empty()) {
     // And around we go again... Whee!
-    ConnectToApplication(redirect_url, requestor_url, services.Pass(),
-                         exposed_services.Pass());
+    ConnectToApplicationWithParameters(redirect_url, requestor_url,
+                                       services.Pass(), exposed_services.Pass(),
+                                       parameters);
     return;
   }
 
@@ -270,7 +299,7 @@
 
   InterfaceRequest<Application> request(
       RegisterShell(requested_url, fetcher->GetURL(), requestor_url,
-                    services.Pass(), exposed_services.Pass()));
+                    services.Pass(), exposed_services.Pass(), parameters));
 
   // If the response begins with a #!mojo <content-handler-url>, use it.
   GURL content_handler_url;
@@ -398,7 +427,17 @@
 
 void ApplicationManager::SetArgsForURL(const std::vector<std::string>& args,
                                        const GURL& url) {
-  url_to_args_[url] = args;
+  url_to_args_[url].insert(url_to_args_[url].end(), args.begin(), args.end());
+  GURL mapped_url = delegate_->ResolveMappings(url);
+  if (mapped_url != url) {
+    url_to_args_[mapped_url].insert(url_to_args_[mapped_url].end(),
+                                    args.begin(), args.end());
+  }
+  GURL resolved_url = delegate_->ResolveURL(mapped_url);
+  if (resolved_url != mapped_url) {
+    url_to_args_[resolved_url].insert(url_to_args_[resolved_url].end(),
+                                      args.begin(), args.end());
+  }
 }
 
 void ApplicationManager::SetNativeOptionsForURL(
@@ -457,11 +496,11 @@
   return pipe.handle0.Pass();
 }
 
-Array<String> ApplicationManager::GetArgsForURL(const GURL& url) {
+std::vector<std::string> ApplicationManager::GetArgsForURL(const GURL& url) {
   const auto& args_it = url_to_args_.find(url);
   if (args_it != url_to_args_.end())
-    return Array<String>::From(args_it->second);
-  return Array<String>();
+    return args_it->second;
+  return std::vector<std::string>();
 }
 
 void ApplicationManager::CleanupRunner(NativeRunner* runner) {