Fix apptests on Android.
[chromium-blink-merge.git] / mojo / runner / desktop / launcher_process.cc
blob26dbe3af912aef04bd333e4f3e1ed89a12d39e1b
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.
5 #include <stdio.h>
6 #include <string.h>
8 #include <algorithm>
9 #include <iostream>
11 #include "base/base_switches.h"
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/files/file_util.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/trace_event/trace_event.h"
18 #include "components/tracing/startup_tracing.h"
19 #include "mojo/runner/context.h"
20 #include "mojo/runner/switches.h"
22 namespace mojo {
23 namespace runner {
24 namespace {
26 // Whether we're currently tracing.
27 bool g_tracing = false;
29 // Number of tracing blocks written.
30 uint32_t g_blocks = 0;
32 // Trace file, if open.
33 FILE* g_trace_file = nullptr;
35 void WriteTraceDataCollected(
36 base::WaitableEvent* event,
37 const scoped_refptr<base::RefCountedString>& events_str,
38 bool has_more_events) {
39 if (g_blocks) {
40 fwrite(",", 1, 1, g_trace_file);
43 ++g_blocks;
44 fwrite(events_str->data().c_str(), 1, events_str->data().length(),
45 g_trace_file);
46 if (!has_more_events) {
47 static const char kEnd[] = "]}";
48 fwrite(kEnd, 1, strlen(kEnd), g_trace_file);
49 PCHECK(fclose(g_trace_file) == 0);
50 g_trace_file = nullptr;
51 event->Signal();
55 void EndTraceAndFlush(base::WaitableEvent* event) {
56 g_trace_file = fopen("mojo_shell.trace", "w+");
57 PCHECK(g_trace_file);
58 static const char kStart[] = "{\"traceEvents\":[";
59 fwrite(kStart, 1, strlen(kStart), g_trace_file);
60 base::trace_event::TraceLog::GetInstance()->SetDisabled();
61 base::trace_event::TraceLog::GetInstance()->Flush(
62 base::Bind(&WriteTraceDataCollected, base::Unretained(event)));
65 void StopTracingAndFlushToDisk() {
66 g_tracing = false;
67 base::trace_event::TraceLog::GetInstance()->SetDisabled();
68 base::WaitableEvent flush_complete_event(false, false);
69 // TraceLog::Flush requires a message loop but we've already shut ours down.
70 // Spin up a new thread to flush things out.
71 base::Thread flush_thread("mojo_shell_trace_event_flush");
72 flush_thread.Start();
73 flush_thread.message_loop()->PostTask(
74 FROM_HERE,
75 base::Bind(EndTraceAndFlush, base::Unretained(&flush_complete_event)));
76 flush_complete_event.Wait();
79 } // namespace
81 int LauncherProcessMain(int argc, char** argv) {
82 const base::CommandLine& command_line =
83 *base::CommandLine::ForCurrentProcess();
84 if (command_line.HasSwitch(switches::kTraceStartup)) {
85 g_tracing = true;
86 base::trace_event::TraceConfig trace_config(
87 command_line.GetSwitchValueASCII(switches::kTraceStartup),
88 base::trace_event::RECORD_UNTIL_FULL);
89 base::trace_event::TraceLog::GetInstance()->SetEnabled(
90 trace_config, base::trace_event::TraceLog::RECORDING_MODE);
91 } else {
92 // |g_tracing| is not touched in this case and Telemetry will stop tracing
93 // on demand later.
94 tracing::EnableStartupTracingIfConfigFileExists();
97 // We want the shell::Context to outlive the MessageLoop so that pipes are
98 // all gracefully closed / error-out before we try to shut the Context down.
99 Context shell_context;
101 base::MessageLoop message_loop;
102 if (!shell_context.Init()) {
103 return 0;
105 if (g_tracing) {
106 message_loop.PostDelayedTask(FROM_HERE,
107 base::Bind(StopTracingAndFlushToDisk),
108 base::TimeDelta::FromSeconds(5));
111 message_loop.PostTask(
112 FROM_HERE,
113 base::Bind(&Context::RunCommandLineApplication,
114 base::Unretained(&shell_context), base::Closure()));
115 message_loop.Run();
117 // Must be called before |message_loop| is destroyed.
118 shell_context.Shutdown();
121 if (g_tracing)
122 StopTracingAndFlushToDisk();
123 return 0;
126 } // namespace runner
127 } // namespace mojo