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.
4
5#include "chrome/browser/diagnostics/diagnostics_controller.h"
6
7#include <string>
8
9#include "base/command_line.h"
10#include "base/logging.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/metrics/histogram.h"
13#include "base/time/time.h"
14#include "chrome/browser/diagnostics/diagnostics_model.h"
15#include "chrome/browser/diagnostics/diagnostics_test.h"
16#include "chrome/browser/diagnostics/diagnostics_writer.h"
17#include "chrome/common/chrome_switches.h"
18
19#if defined(OS_CHROMEOS)
20#include "chromeos/chromeos_switches.h"
21#endif
22
23namespace diagnostics {
24
25DiagnosticsController* DiagnosticsController::GetInstance() {
26  return Singleton<DiagnosticsController>::get();
27}
28
29DiagnosticsController::DiagnosticsController() : writer_(NULL) {}
30
31DiagnosticsController::~DiagnosticsController() {}
32
33const DiagnosticsModel& DiagnosticsController::GetResults() const {
34  return *model_;
35}
36
37bool DiagnosticsController::HasResults() {
38  return (model_.get() && model_->GetTestRunCount() > 0);
39}
40
41void DiagnosticsController::ClearResults() { model_.reset(); }
42
43void DiagnosticsController::RecordRegularStartup() {
44#if defined(OS_CHROMEOS)  // Only collecting UMA stats on ChromeOS
45  // Count the number of normal starts, so we can compare that with the number
46  // of recovery runs to get a percentage.
47  UMA_HISTOGRAM_ENUMERATION(
48      "Diagnostics.RecoveryRun", RECOVERY_NOT_RUN, RECOVERY_RUN_METRICS_COUNT);
49
50  // For each of the test types, record a normal start (no diagnostics run), so
51  // we have a common denominator.
52  for (int i = 0; i < DIAGNOSTICS_TEST_ID_COUNT; ++i) {
53    RecordUMARecoveryResult(static_cast<DiagnosticsTestId>(i), RESULT_NOT_RUN);
54    RecordUMATestResult(static_cast<DiagnosticsTestId>(i), RESULT_NOT_RUN);
55  }
56#endif
57}
58
59// This entry point is called from early in startup when very few things have
60// been initialized, so be careful what you use.
61int DiagnosticsController::Run(const CommandLine& command_line,
62                               DiagnosticsWriter* writer) {
63  writer_ = writer;
64
65  model_.reset(MakeDiagnosticsModel(command_line));
66  model_->RunAll(writer_);
67
68  return 0;
69}
70
71// This entry point is called from early in startup when very few things have
72// been initialized, so be careful what you use.
73int DiagnosticsController::RunRecovery(const CommandLine& command_line,
74                                       DiagnosticsWriter* writer) {
75// Separate out recoveries that we execute automatically as a result of a
76// crash from user-run recoveries.
77#if defined(OS_CHROMEOS)  // Only collecting UMA stats on ChromeOS
78  if (command_line.HasSwitch(chromeos::switches::kLoginUser)) {
79    UMA_HISTOGRAM_ENUMERATION("Diagnostics.RecoveryRun",
80                              diagnostics::RECOVERY_CRASH_RUN,
81                              diagnostics::RECOVERY_RUN_METRICS_COUNT);
82  } else {
83    UMA_HISTOGRAM_ENUMERATION("Diagnostics.RecoveryRun",
84                              diagnostics::RECOVERY_USER_RUN,
85                              diagnostics::RECOVERY_RUN_METRICS_COUNT);
86  }
87#endif
88
89  if (!HasResults()) {
90    if (writer) {
91      writer->WriteInfoLine("No diagnostics have been run.");
92      writer->OnAllRecoveryDone(model_.get());
93    }
94    return -1;
95  }
96
97  writer_ = writer;
98
99  model_->RecoverAll(writer_);
100  return 0;
101}
102
103}  // namespace diagnostics
104