in_process_dynamic_service_runner.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "mojo/shell/in_process_dynamic_service_runner.h"
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/bind.h"
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/callback_helpers.h"
923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/location.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/logging.h"
1123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "mojo/public/platform/native/gles2_impl_chromium_sync_point_thunks.h"
136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "mojo/public/platform/native/gles2_impl_chromium_texture_mailbox_thunks.h"
146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "mojo/public/platform/native/gles2_impl_thunks.h"
156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "mojo/public/platform/native/gles2_thunks.h"
16a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "mojo/public/platform/native/system_thunks.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace mojo {
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace shell {
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace {
226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)template <typename Thunks>
246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool SetThunks(Thunks (*make_thunks)(),
256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)               const char* function_name,
266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)               base::ScopedNativeLibrary* library) {
276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  typedef size_t (*SetThunksFn)(const Thunks* thunks);
286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SetThunksFn set_thunks =
296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<SetThunksFn>(library->GetFunctionPointer(function_name));
306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!set_thunks)
316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return false;
326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  Thunks thunks = make_thunks();
336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  size_t expected_size = set_thunks(&thunks);
346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (expected_size > sizeof(Thunks)) {
356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    LOG(ERROR) << "Invalid app library: expected " << function_name
366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)               << " to return thunks of size: " << expected_size;
376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return false;
386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return true;
406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)InProcessDynamicServiceRunner::InProcessDynamicServiceRunner(
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Context* context) {
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)InProcessDynamicServiceRunner::~InProcessDynamicServiceRunner() {
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (thread_) {
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK(thread_->HasBeenStarted());
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK(!thread_->HasBeenJoined());
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    thread_->Join();
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // It is important to let the thread exit before unloading the DSO because
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // the library may have registered thread-local data and destructors to run
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // on thread termination.
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  app_library_.Reset(base::NativeLibrary());
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void InProcessDynamicServiceRunner::Start(
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const base::FilePath& app_path,
620de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    ScopedMessagePipeHandle service_handle,
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const base::Closure& app_completed_callback) {
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  app_path_ = app_path;
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!service_handle_.is_valid());
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  service_handle_ = service_handle.Pass();
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(app_completed_callback_runner_.is_null());
7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  app_completed_callback_runner_ = base::Bind(&base::TaskRunner::PostTask,
7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                              base::MessageLoopProxy::current(),
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                              FROM_HERE,
7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                              app_completed_callback);
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(!thread_);
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  thread_.reset(new base::DelegateSimpleThread(this, "app_thread"));
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  thread_->Start();
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void InProcessDynamicServiceRunner::Run() {
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DVLOG(2) << "Loading/running Mojo app in process from library: "
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           << app_path_.value();
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  do {
85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    base::NativeLibraryLoadError error;
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    app_library_.Reset(base::LoadNativeLibrary(app_path_, &error));
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!app_library_.is_valid()) {
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      LOG(ERROR) << "Failed to load app library (error: " << error.ToString()
89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 << ")";
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (!SetThunks(
946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            &MojoMakeSystemThunks, "MojoSetSystemThunks", &app_library_)) {
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // In the component build, Mojo Apps link against mojo_system_impl.
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if !defined(COMPONENT_BUILD)
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // Strictly speaking this is not required, but it's very unusual to have
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // an app that doesn't require the basic system library.
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      LOG(WARNING) << "MojoSetSystemThunks not found in app library";
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
101a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
102a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (SetThunks(&MojoMakeGLES2ControlThunks,
1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  "MojoSetGLES2ControlThunks",
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  &app_library_)) {
1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      // If we have the control thunks, we probably also have the
1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      // GLES2 implementation thunks.
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (!SetThunks(&MojoMakeGLES2ImplThunks,
1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                     "MojoSetGLES2ImplThunks",
1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                     &app_library_)) {
1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        // In the component build, Mojo Apps link against mojo_gles2_impl.
1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#if !defined(COMPONENT_BUILD)
1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        // Warn on this really weird case: The library requires the GLES2
1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        // control functions, but doesn't require the GLES2 implementation.
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        LOG(WARNING) << app_path_.value()
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     << " has MojoSetGLES2ControlThunks, "
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        "but doesn't have MojoSetGLES2ImplThunks.";
1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif
1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      }
1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      // If the application is using GLES2 extension points, register those
1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      // thunks. Applications may use or not use any of these, so don't warn if
1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      // they are missing.
1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      SetThunks(MojoMakeGLES2ImplChromiumTextureMailboxThunks,
1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                "MojoSetGLES2ImplChromiumTextureMailboxThunks",
1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                &app_library_);
1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      SetThunks(MojoMakeGLES2ImplChromiumSyncPointThunks,
1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                "MojoSetGLES2ImplChromiumSyncPointThunks",
1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                &app_library_);
1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Unlike system thunks, we don't warn on a lack of GLES2 thunks because
1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // not everything is a visual app.
1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typedef MojoResult (*MojoMainFunction)(MojoHandle);
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    MojoMainFunction main_function = reinterpret_cast<MojoMainFunction>(
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        app_library_.GetFunctionPointer("MojoMain"));
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!main_function) {
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      LOG(ERROR) << "Entrypoint MojoMain not found: " << app_path_.value();
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // |MojoMain()| takes ownership of the service handle.
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    MojoResult result = main_function(service_handle_.release().value());
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (result < MOJO_RESULT_OK)
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      LOG(ERROR) << "MojoMain returned an error: " << result;
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } while (false);
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  app_completed_callback_runner_.Run();
14923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  app_completed_callback_runner_.Reset();
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace shell
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace mojo
154