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

content / browser / tracing / startup_tracing_controller.h [blame]

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_TRACING_STARTUP_TRACING_CONTROLLER_H_
#define CONTENT_BROWSER_TRACING_STARTUP_TRACING_CONTROLLER_H_

#include "base/files/file_path.h"
#include "base/threading/sequence_bound.h"
#include "content/common/content_export.h"

namespace content {

// Class responsible for starting and stopping startup tracing as configured by
// StartupTracingConfig. All interactions with it are limited to UI thread, but
// the actual logic lives on a background ThreadPool sequence.
class CONTENT_EXPORT StartupTracingController {
 public:
  StartupTracingController();
  ~StartupTracingController();

  static StartupTracingController& GetInstance();

  // Stop the trace recording, write the trace to disk and block until complete.
  // Intended to be used in the situation when the browser process is going to
  // crash (e.g. DCHECK failure) and we want to avoid losing the trace data. Can
  // be called from any thread.
  // May not succeed if called from a sequence that is required to be responsive
  // during trace finalisation.
  static void EmergencyStop();

  void StartIfNeeded();
  void WaitUntilStopped();
  void ShutdownAndWaitForStopIfNeeded();

  // By default, a trace is written into a temporary file which then is renamed,
  // however this can lead to data loss when the browser process crashes.
  // Embedders can disable this (especially if a name provided to
  // SetDefaultBasename makes it clear that the trace is incomplete and final
  // name will be provided via SetDefaultBasename call before calling Stop).
  enum class TempFilePolicy {
    kUseTemporaryFile,
    kWriteDirectly,
  };
  void SetUsingTemporaryFile(TempFilePolicy temp_file_policy);

  // Set default basename for the trace output file to allow //content embedders
  // to customise it using some metadata (like test names).
  //
  // If --enable-trace-output is a directory (default value, empty, designated
  // "current directory"), then the startup trace will be written in a file with
  // the given basename in this directory. Depending on the |extension_type|,
  // an appropriate extension (.json or .proto) will be added.
  //
  // Note that embedders can call it even after tracing has started and Perfetto
  // started streaming the trace into it — in that case,
  // StartupTracingController will rename the file after finishing. However,
  // this is guaranteed to work only when tracing lasts until Stop() (not with
  // duration-based tracing).
  enum class ExtensionType {
    kAppendAppropriate,
    kNone,
  };
  void SetDefaultBasename(std::string basename, ExtensionType extension_type);
  // As the test harness calls SetDefaultBasename, expose ForTest() version for
  // the tests checking the StartupTracingController logic itself.
  void SetDefaultBasenameForTest(std::string basename,
                                 ExtensionType extension_type);

  bool is_finished_for_testing() const { return state_ == State::kStopped; }

  void set_continue_on_shutdown_for_testing() {
    should_continue_on_shutdown_ = true;
  }

 private:
  void Stop(base::OnceClosure on_finished_callback);

  void OnStoppedOnUIThread();

  base::FilePath GetOutputPath();

  enum class State {
    kNotEnabled,
    kRunning,
    kStopped,
  };
  State state_ = State::kNotEnabled;

  // All actual interactions with the tracing service and the process of writing
  // files happens on a background thread.
  class BackgroundTracer;
  base::SequenceBound<BackgroundTracer> background_tracer_;

  base::OnceClosure on_tracing_finished_;
  base::FilePath output_file_;

  std::string default_basename_;
  bool basename_for_test_set_ = false;
  // Used for testing only
  bool should_continue_on_shutdown_ = false;

  TempFilePolicy temp_file_policy_ = TempFilePolicy::kUseTemporaryFile;
};

}  // namespace content

#endif  // CONTENT_BROWSER_TRACING_STARTUP_TRACING_CONTROLLER_H_