in_process_dynamic_service_runner.cc revision 23730a6e56a168d1879203e4b3819bb36e3d8f1f
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"
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/file_util.h"
1023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/location.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/logging.h"
1223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/scoped_native_library.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace mojo {
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace shell {
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)InProcessDynamicServiceRunner::InProcessDynamicServiceRunner(
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    Context* /*context*/)
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : thread_(this, "app_thread") {
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)InProcessDynamicServiceRunner::~InProcessDynamicServiceRunner() {
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (thread_.HasBeenStarted()) {
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK(!thread_.HasBeenJoined());
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    thread_.Join();
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void InProcessDynamicServiceRunner::Start(
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const base::FilePath& app_path,
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ScopedShellHandle service_handle,
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const base::Closure& app_completed_callback) {
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  app_path_ = app_path;
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!service_handle_.is_valid());
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  service_handle_ = service_handle.Pass();
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(app_completed_callback_runner_.is_null());
4023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  app_completed_callback_runner_ = base::Bind(&base::TaskRunner::PostTask,
4123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                              base::MessageLoopProxy::current(),
4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                              FROM_HERE,
4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                              app_completed_callback);
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!thread_.HasBeenStarted());
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  thread_.Start();
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void InProcessDynamicServiceRunner::Run() {
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DVLOG(2) << "Loading/running Mojo app from " << app_path_.value()
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           << " in process";
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ScopedClosureRunner app_deleter(
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(base::IgnoreResult(&base::DeleteFile), app_path_, false));
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  do {
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    std::string load_error;
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::ScopedNativeLibrary app_library(
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::LoadNativeLibrary(app_path_, &load_error));
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!app_library.is_valid()) {
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      LOG(ERROR) << "Failed to load library (error: " << load_error << ")";
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typedef MojoResult (*MojoMainFunction)(MojoHandle);
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    MojoMainFunction main_function = reinterpret_cast<MojoMainFunction>(
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        app_library.GetFunctionPointer("MojoMain"));
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!main_function) {
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      LOG(ERROR) << "Entrypoint MojoMain not found";
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // |MojoMain()| takes ownership of the service handle.
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    MojoResult result = main_function(service_handle_.release().value());
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (result < MOJO_RESULT_OK)
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      LOG(ERROR) << "MojoMain returned an error: " << result;
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } while (false);
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  bool success = app_completed_callback_runner_.Run();
8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  app_completed_callback_runner_.Reset();
8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  LOG_IF(ERROR, !success) << "Failed post run app_completed_callback";
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace shell
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace mojo
86