1 // Copyright 2013 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. 4 5 #include "mojo/shell/app_container.h" 6 7 #include "base/bind.h" 8 #include "base/callback_forward.h" 9 #include "base/callback_helpers.h" 10 #include "base/file_util.h" 11 #include "base/files/file_path.h" 12 #include "base/native_library.h" 13 #include "base/scoped_native_library.h" 14 #include "base/thread_task_runner_handle.h" 15 #include "base/threading/thread.h" 16 #include "mojo/public/system/core.h" 17 #include "mojo/services/native_viewport/native_viewport_impl.h" 18 #include "mojo/shell/context.h" 19 20 typedef MojoResult (*MojoMainFunction)(MojoHandle pipe); 21 22 namespace mojo { 23 namespace shell { 24 25 AppContainer::AppContainer(Context* context) 26 : context_(context), 27 weak_factory_(this) { 28 } 29 30 AppContainer::~AppContainer() { 31 } 32 33 void AppContainer::Load(const GURL& app_url) { 34 request_ = context_->loader()->Load(app_url, this); 35 } 36 37 void AppContainer::DidCompleteLoad(const GURL& app_url, 38 const base::FilePath& app_path) { 39 CreateMessagePipe(&shell_handle_, &app_handle_); 40 41 native_viewport_.reset( 42 new services::NativeViewportImpl(context_, shell_handle_.Pass())); 43 44 // Launch the app on its own thread. 45 // TODO(beng): Create a unique thread name. 46 app_path_ = app_path; 47 ack_closure_ = 48 base::Bind(&AppContainer::AppCompleted, weak_factory_.GetWeakPtr()); 49 thread_.reset(new base::DelegateSimpleThread(this, "app_thread")); 50 thread_->Start(); 51 } 52 53 void AppContainer::Run() { 54 base::ScopedClosureRunner app_deleter( 55 base::Bind(base::IgnoreResult(&base::DeleteFile), app_path_, false)); 56 base::ScopedNativeLibrary app_library( 57 base::LoadNativeLibrary(app_path_, NULL)); 58 if (!app_library.is_valid()) { 59 LOG(ERROR) << "Failed to load library: " << app_path_.value().c_str(); 60 return; 61 } 62 63 MojoMainFunction main_function = reinterpret_cast<MojoMainFunction>( 64 app_library.GetFunctionPointer("MojoMain")); 65 if (!main_function) { 66 LOG(ERROR) << "Entrypoint MojoMain not found."; 67 return; 68 } 69 70 // |MojoMain()| takes ownership of the app handle. 71 MojoResult result = main_function(app_handle_.release().value()); 72 if (result < MOJO_RESULT_OK) { 73 LOG(ERROR) << "MojoMain returned an error: " << result; 74 return; 75 } 76 context_->task_runners()->ui_runner()->PostTask(FROM_HERE, ack_closure_); 77 } 78 79 void AppContainer::AppCompleted() { 80 native_viewport_.reset(); 81 82 thread_->Join(); 83 thread_.reset(); 84 } 85 86 } // namespace shell 87 } // namespace mojo 88