15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "mojo/application_manager/background_shell_application_loader.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/bind.h" 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/run_loop.h" 96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "mojo/application_manager/application_manager.h" 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace mojo { 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class BackgroundShellApplicationLoader::BackgroundLoader { 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) explicit BackgroundLoader(ApplicationLoader* loader) : loader_(loader) {} 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ~BackgroundLoader() {} 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void Load(ApplicationManager* manager, 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const GURL& url, 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ScopedMessagePipeHandle shell_handle) { 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<LoadCallbacks> callbacks( 226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) new ApplicationLoader::SimpleLoadCallbacks(shell_handle.Pass())); 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loader_->Load(manager, url, callbacks); 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void OnApplicationError(ApplicationManager* manager, const GURL& url) { 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci loader_->OnApplicationError(manager, url); 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ApplicationLoader* loader_; // Owned by BackgroundShellApplicationLoader 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(BackgroundLoader); 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)BackgroundShellApplicationLoader::BackgroundShellApplicationLoader( 376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_ptr<ApplicationLoader> real_loader, 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& thread_name, 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::MessageLoop::Type message_loop_type) 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : loader_(real_loader.Pass()), 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) message_loop_type_(message_loop_type), 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) thread_name_(thread_name), 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) message_loop_created_(true, false), 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) background_loader_(NULL) { 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)BackgroundShellApplicationLoader::~BackgroundShellApplicationLoader() { 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (thread_) 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) thread_->Join(); 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BackgroundShellApplicationLoader::Load( 536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ApplicationManager* manager, 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const GURL& url, 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<LoadCallbacks> callbacks) { 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication(); 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!shell_handle.is_valid()) 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!thread_) { 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TODO(tim): It'd be nice if we could just have each Load call 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // result in a new thread like DynamicService{Loader, Runner}. But some 636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // loaders are creating multiple ApplicationImpls (NetworkApplicationLoader) 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // sharing a delegate (etc). So we have to keep it single threaded, wait 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // for the thread to initialize, and post to the TaskRunner for subsequent 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Load calls for now. 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) thread_.reset(new base::DelegateSimpleThread(this, thread_name_)); 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) thread_->Start(); 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) message_loop_created_.Wait(); 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(task_runner_.get()); 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) task_runner_->PostTask( 746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FROM_HERE, 756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::Bind( 766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &BackgroundShellApplicationLoader::LoadOnBackgroundThread, 776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::Unretained(this), 786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) manager, 796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) url, 806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::Owned(new ScopedMessagePipeHandle(shell_handle.Pass())))); 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BackgroundShellApplicationLoader::OnApplicationError( 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ApplicationManager* manager, 856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const GURL& url) { 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci task_runner_->PostTask(FROM_HERE, 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&BackgroundShellApplicationLoader:: 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnApplicationErrorOnBackgroundThread, 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(this), 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manager, 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url)); 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BackgroundShellApplicationLoader::Run() { 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::MessageLoop message_loop(message_loop_type_); 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::RunLoop loop; 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) task_runner_ = message_loop.task_runner(); 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) quit_closure_ = loop.QuitClosure(); 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) message_loop_created_.Signal(); 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop.Run(); 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delete background_loader_; 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) background_loader_ = NULL; 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Destroy |loader_| on the thread it's actually used on. 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loader_.reset(); 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BackgroundShellApplicationLoader::LoadOnBackgroundThread( 1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ApplicationManager* manager, 1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const GURL& url, 1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ScopedMessagePipeHandle* shell_handle) { 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(task_runner_->RunsTasksOnCurrentThread()); 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!background_loader_) 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) background_loader_ = new BackgroundLoader(loader_.get()); 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) background_loader_->Load(manager, url, shell_handle->Pass()); 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BackgroundShellApplicationLoader::OnApplicationErrorOnBackgroundThread( 1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ApplicationManager* manager, 1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const GURL& url) { 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(task_runner_->RunsTasksOnCurrentThread()); 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!background_loader_) 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) background_loader_ = new BackgroundLoader(loader_.get()); 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci background_loader_->OnApplicationError(manager, url); 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace mojo 128