#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
-#include "base/scoped_native_library.h"
+#include "mojo/public/platform/native/gles2_impl_chromium_sync_point_thunks.h"
+#include "mojo/public/platform/native/gles2_impl_chromium_texture_mailbox_thunks.h"
+#include "mojo/public/platform/native/gles2_impl_thunks.h"
+#include "mojo/public/platform/native/gles2_thunks.h"
#include "mojo/public/platform/native/system_thunks.h"
namespace mojo {
namespace shell {
+namespace {
+
+template <typename Thunks>
+bool SetThunks(Thunks (*make_thunks)(),
+ const char* function_name,
+ base::ScopedNativeLibrary* library) {
+ typedef size_t (*SetThunksFn)(const Thunks* thunks);
+ SetThunksFn set_thunks =
+ reinterpret_cast<SetThunksFn>(library->GetFunctionPointer(function_name));
+ if (!set_thunks)
+ return false;
+ Thunks thunks = make_thunks();
+ size_t expected_size = set_thunks(&thunks);
+ if (expected_size > sizeof(Thunks)) {
+ LOG(ERROR) << "Invalid app library: expected " << function_name
+ << " to return thunks of size: " << expected_size;
+ return false;
+ }
+ return true;
+}
+}
+
InProcessDynamicServiceRunner::InProcessDynamicServiceRunner(
- Context* context)
- : keep_alive_(context),
- thread_(this, "app_thread") {
+ Context* context) {
}
InProcessDynamicServiceRunner::~InProcessDynamicServiceRunner() {
- if (thread_.HasBeenStarted()) {
- DCHECK(!thread_.HasBeenJoined());
- thread_.Join();
+ if (thread_) {
+ DCHECK(thread_->HasBeenStarted());
+ DCHECK(!thread_->HasBeenJoined());
+ thread_->Join();
}
+
+ // It is important to let the thread exit before unloading the DSO because
+ // the library may have registered thread-local data and destructors to run
+ // on thread termination.
+ app_library_.Reset(base::NativeLibrary());
}
void InProcessDynamicServiceRunner::Start(
FROM_HERE,
app_completed_callback);
- DCHECK(!thread_.HasBeenStarted());
- thread_.Start();
+ DCHECK(!thread_);
+ thread_.reset(new base::DelegateSimpleThread(this, "app_thread"));
+ thread_->Start();
}
void InProcessDynamicServiceRunner::Run() {
do {
base::NativeLibraryLoadError error;
- base::ScopedNativeLibrary app_library(
- base::LoadNativeLibrary(app_path_, &error));
- if (!app_library.is_valid()) {
+ app_library_.Reset(base::LoadNativeLibrary(app_path_, &error));
+ if (!app_library_.is_valid()) {
LOG(ERROR) << "Failed to load app library (error: " << error.ToString()
<< ")";
break;
}
- MojoSetSystemThunksFn mojo_set_system_thunks_fn =
- reinterpret_cast<MojoSetSystemThunksFn>(app_library.GetFunctionPointer(
- "MojoSetSystemThunks"));
- if (mojo_set_system_thunks_fn) {
- MojoSystemThunks system_thunks = MojoMakeSystemThunks();
- size_t expected_size = mojo_set_system_thunks_fn(&system_thunks);
- if (expected_size > sizeof(MojoSystemThunks)) {
- LOG(ERROR)
- << "Invalid app library: expected MojoSystemThunks size: "
- << expected_size;
- break;
- }
- } else {
+ if (!SetThunks(
+ &MojoMakeSystemThunks, "MojoSetSystemThunks", &app_library_)) {
+ // In the component build, Mojo Apps link against mojo_system_impl.
+#if !defined(COMPONENT_BUILD)
// Strictly speaking this is not required, but it's very unusual to have
// an app that doesn't require the basic system library.
LOG(WARNING) << "MojoSetSystemThunks not found in app library";
+#endif
+ }
+
+ if (SetThunks(&MojoMakeGLES2ControlThunks,
+ "MojoSetGLES2ControlThunks",
+ &app_library_)) {
+ // If we have the control thunks, we probably also have the
+ // GLES2 implementation thunks.
+ if (!SetThunks(&MojoMakeGLES2ImplThunks,
+ "MojoSetGLES2ImplThunks",
+ &app_library_)) {
+ // In the component build, Mojo Apps link against mojo_gles2_impl.
+#if !defined(COMPONENT_BUILD)
+ // Warn on this really weird case: The library requires the GLES2
+ // control functions, but doesn't require the GLES2 implementation.
+ LOG(WARNING) << app_path_.value()
+ << " has MojoSetGLES2ControlThunks, "
+ "but doesn't have MojoSetGLES2ImplThunks.";
+#endif
+ }
+
+ // If the application is using GLES2 extension points, register those
+ // thunks. Applications may use or not use any of these, so don't warn if
+ // they are missing.
+ SetThunks(MojoMakeGLES2ImplChromiumTextureMailboxThunks,
+ "MojoSetGLES2ImplChromiumTextureMailboxThunks",
+ &app_library_);
+ SetThunks(MojoMakeGLES2ImplChromiumSyncPointThunks,
+ "MojoSetGLES2ImplChromiumSyncPointThunks",
+ &app_library_);
}
+ // Unlike system thunks, we don't warn on a lack of GLES2 thunks because
+ // not everything is a visual app.
typedef MojoResult (*MojoMainFunction)(MojoHandle);
MojoMainFunction main_function = reinterpret_cast<MojoMainFunction>(
- app_library.GetFunctionPointer("MojoMain"));
+ app_library_.GetFunctionPointer("MojoMain"));
if (!main_function) {
- LOG(ERROR) << "Entrypoint MojoMain not found";
+ LOG(ERROR) << "Entrypoint MojoMain not found: " << app_path_.value();
break;
}
LOG(ERROR) << "MojoMain returned an error: " << result;
} while (false);
- bool success = app_completed_callback_runner_.Run();
+ app_completed_callback_runner_.Run();
app_completed_callback_runner_.Reset();
- LOG_IF(ERROR, !success) << "Failed post run app_completed_callback";
}
} // namespace shell