- add sources.
[platform/framework/web/crosswalk.git] / src / mojo / shell / app_container.cc
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/public/utility/scoped_handle.h"
18 #include "mojo/services/native_viewport/native_viewport_controller.h"
19 #include "mojo/shell/context.h"
20
21 typedef MojoResult (*MojoMainFunction)(mojo::Handle pipe);
22
23 namespace mojo {
24 namespace shell {
25
26 void LaunchAppOnThread(
27     const base::FilePath& app_path,
28     Handle app_handle_raw) {
29   base::ScopedClosureRunner app_deleter(
30       base::Bind(base::IgnoreResult(&base::DeleteFile), app_path, false));
31   ScopedHandle app_handle(app_handle_raw);
32
33   base::ScopedNativeLibrary app_library(
34       base::LoadNativeLibrary(app_path, NULL));
35   if (!app_library.is_valid()) {
36     LOG(ERROR) << "Failed to load library: " << app_path.value().c_str();
37     return;
38   }
39
40   MojoMainFunction main_function = reinterpret_cast<MojoMainFunction>(
41       app_library.GetFunctionPointer("MojoMain"));
42   if (!main_function) {
43     LOG(ERROR) << "Entrypoint MojoMain not found.";
44     return;
45   }
46
47   MojoResult result = main_function(app_handle.get());
48   if (result < MOJO_RESULT_OK) {
49     LOG(ERROR) << "MojoMain returned an error: " << result;
50     return;
51   }
52
53   LOG(INFO) << "MojoMain succeeded: " << result;
54 }
55
56 AppContainer::AppContainer(Context* context)
57     : context_(context),
58       weak_factory_(this) {
59 }
60
61 AppContainer::~AppContainer() {
62 }
63
64 void AppContainer::Load(const GURL& app_url) {
65   request_ = context_->loader()->Load(app_url, this);
66 }
67
68 void AppContainer::DidCompleteLoad(const GURL& app_url,
69                                    const base::FilePath& app_path) {
70   Handle app_handle;
71   MojoResult result = CreateMessagePipe(&shell_handle_, &app_handle);
72   if (result < MOJO_RESULT_OK) {
73     // Failure..
74   }
75
76   // Launch the app on its own thread.
77   // TODO(beng): Create a unique thread name.
78   thread_.reset(new base::Thread("app_thread"));
79   thread_->Start();
80   thread_->message_loop_proxy()->PostTaskAndReply(
81       FROM_HERE,
82       base::Bind(&LaunchAppOnThread, app_path, app_handle),
83       base::Bind(&AppContainer::AppCompleted, weak_factory_.GetWeakPtr()));
84
85   const char* hello_msg = "Hello";
86   result = WriteMessage(shell_handle_, hello_msg,
87                         static_cast<uint32_t>(strlen(hello_msg)+1),
88                         NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
89   if (result < MOJO_RESULT_OK) {
90     // Failure..
91   }
92
93   // TODO(beng): This should be created on demand by the NativeViewportService
94   //             when it is retrieved by the app.
95   native_viewport_controller_.reset(
96       new services::NativeViewportController(context_, shell_handle_));
97 }
98
99 void AppContainer::AppCompleted() {
100   native_viewport_controller_->Close();
101
102   thread_.reset();
103   Close(shell_handle_);
104 }
105
106 }  // namespace shell
107 }  // namespace mojo