summaryrefslogtreecommitdiffstats
path: root/mojo/shell/public/cpp/lib/application_runner.cc
blob: 5253053d43f55ebe113404b038976858ab1abffc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "mojo/shell/public/cpp/application_runner.h"

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/process/launch.h"
#include "mojo/shell/public/cpp/shell_client.h"
#include "mojo/shell/public/cpp/shell_connection.h"

namespace mojo {

int g_application_runner_argc;
const char* const* g_application_runner_argv;

ApplicationRunner::ApplicationRunner(ShellClient* client)
    : client_(scoped_ptr<ShellClient>(client)),
      message_loop_type_(base::MessageLoop::TYPE_DEFAULT),
      has_run_(false) {}

ApplicationRunner::~ApplicationRunner() {}

void ApplicationRunner::InitBaseCommandLine() {
  base::CommandLine::Init(g_application_runner_argc, g_application_runner_argv);
}

void ApplicationRunner::set_message_loop_type(base::MessageLoop::Type type) {
  DCHECK_NE(base::MessageLoop::TYPE_CUSTOM, type);
  DCHECK(!has_run_);

  message_loop_type_ = type;
}

MojoResult ApplicationRunner::Run(MojoHandle shell_client_request_handle,
                                  bool init_base) {
  DCHECK(!has_run_);
  has_run_ = true;

  scoped_ptr<base::AtExitManager> at_exit;
  if (init_base) {
    InitBaseCommandLine();
    at_exit.reset(new base::AtExitManager);
  }

  {
    scoped_ptr<base::MessageLoop> loop;
    loop.reset(new base::MessageLoop(message_loop_type_));

    connection_.reset(new ShellConnection(
        client_.get(),
        MakeRequest<shell::mojom::ShellClient>(MakeScopedHandle(
            MessagePipeHandle(shell_client_request_handle)))));
    loop->Run();
    // It's very common for the client to cache the app and terminate on errors.
    // If we don't delete the client before the app we run the risk of the
    // client having a stale reference to the app and trying to use it.
    // Note that we destruct the message loop first because that might trigger
    // connection error handlers and they might access objects created by the
    // client.
    loop.reset();
    client_.reset();
    connection_.reset();
  }
  return MOJO_RESULT_OK;
}

MojoResult ApplicationRunner::Run(MojoHandle shell_client_request_handle) {
  bool init_base = true;
  if (base::CommandLine::InitializedForCurrentProcess()) {
    init_base =
        !base::CommandLine::ForCurrentProcess()->HasSwitch("single-process");
  }
  return Run(shell_client_request_handle, init_base);
}

void ApplicationRunner::DestroyShellConnection() {
  connection_.reset();
}

void ApplicationRunner::Quit() {
  base::MessageLoop::current()->QuitWhenIdle();
}

}  // namespace mojo