summaryrefslogtreecommitdiff
path: root/chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc
blob: 90912eaf743691709b5709317215123d85c4f8c4 (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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright 2016 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 "components/arc/crash_collector/arc_crash_collector_bridge.h"

#include <sysexits.h>
#include <unistd.h>

#include <utility>

#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/process/launch.h"
#include "base/task_scheduler/post_task.h"
#include "base/task_scheduler/task_traits.h"
#include "components/arc/arc_bridge_service.h"
#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
#include "mojo/edk/embedder/embedder.h"

namespace {

const char kCrashReporterPath[] = "/sbin/crash_reporter";

// Runs crash_reporter to save the crash info provided via the pipe.
void RunCrashReporter(const std::string& crash_type,
                      const std::string& device,
                      const std::string& board,
                      const std::string& cpu_abi,
                      mojo::edk::ScopedPlatformHandle pipe) {
  base::LaunchOptions options;
  options.fds_to_remap.push_back(
      std::make_pair(pipe.get().handle, STDIN_FILENO));

  auto process =
      base::LaunchProcess({kCrashReporterPath, "--arc_java_crash=" + crash_type,
                           "--arc_device=" + device, "--arc_board=" + board,
                           "--arc_cpu_abi=" + cpu_abi},
                          options);

  int exit_code = 0;
  if (!process.WaitForExit(&exit_code)) {
    LOG(ERROR) << "Failed to wait for " << kCrashReporterPath;
  } else if (exit_code != EX_OK) {
    LOG(ERROR) << kCrashReporterPath << " failed with exit code " << exit_code;
  }
}

}  // namespace

namespace arc {
namespace {

// Singleton factory for ArcCrashCollectorBridge.
class ArcCrashCollectorBridgeFactory
    : public internal::ArcBrowserContextKeyedServiceFactoryBase<
          ArcCrashCollectorBridge,
          ArcCrashCollectorBridgeFactory> {
 public:
  // Factory name used by ArcBrowserContextKeyedServiceFactoryBase.
  static constexpr const char* kName = "ArcCrashCollectorBridgeFactory";

  static ArcCrashCollectorBridgeFactory* GetInstance() {
    return base::Singleton<ArcCrashCollectorBridgeFactory>::get();
  }

 private:
  friend base::DefaultSingletonTraits<ArcCrashCollectorBridgeFactory>;
  ArcCrashCollectorBridgeFactory() = default;
  ~ArcCrashCollectorBridgeFactory() override = default;
};

}  // namespace

// static
ArcCrashCollectorBridge* ArcCrashCollectorBridge::GetForBrowserContext(
    content::BrowserContext* context) {
  return ArcCrashCollectorBridgeFactory::GetForBrowserContext(context);
}

ArcCrashCollectorBridge::ArcCrashCollectorBridge(
    content::BrowserContext* context,
    ArcBridgeService* bridge_service)
    : arc_bridge_service_(bridge_service), binding_(this) {
  arc_bridge_service_->crash_collector()->AddObserver(this);
}

ArcCrashCollectorBridge::~ArcCrashCollectorBridge() {
  arc_bridge_service_->crash_collector()->RemoveObserver(this);
}

void ArcCrashCollectorBridge::OnInstanceReady() {
  mojom::CrashCollectorHostPtr host_ptr;
  binding_.Bind(mojo::MakeRequest(&host_ptr));
  auto* instance =
      ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->crash_collector(), Init);
  DCHECK(instance);
  instance->Init(std::move(host_ptr));
}

void ArcCrashCollectorBridge::DumpCrash(const std::string& type,
                                        mojo::ScopedHandle pipe) {
  mojo::edk::ScopedPlatformHandle pipe_handle;
  mojo::edk::PassWrappedPlatformHandle(pipe.release().value(), &pipe_handle);

  base::PostTaskWithTraits(
      FROM_HERE, {base::WithBaseSyncPrimitives()},
      base::BindOnce(&RunCrashReporter, type, device_, board_, cpu_abi_,
                     base::Passed(std::move(pipe_handle))));
}

void ArcCrashCollectorBridge::SetBuildProperties(const std::string& device,
                                                 const std::string& board,
                                                 const std::string& cpu_abi) {
  device_ = device;
  board_ = board;
  cpu_abi_ = cpu_abi;
}

}  // namespace arc