Avi Drissman | 4e1b7bc3 | 2022-09-15 14:03:50 | [diff] [blame] | 1 | // Copyright 2020 The Chromium Authors |
Alexander Timin | fc975678 | 2020-12-23 22:05:52 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef CONTENT_BROWSER_TRACING_STARTUP_TRACING_CONTROLLER_H_ |
| 6 | #define CONTENT_BROWSER_TRACING_STARTUP_TRACING_CONTROLLER_H_ |
| 7 | |
Lei Zhang | 0d85a9d3 | 2021-05-06 19:21:47 | [diff] [blame] | 8 | #include "base/files/file_path.h" |
Alexander Timin | fc975678 | 2020-12-23 22:05:52 | [diff] [blame] | 9 | #include "base/threading/sequence_bound.h" |
Alexander Timin | 2149a931 | 2021-01-08 10:03:57 | [diff] [blame] | 10 | #include "content/common/content_export.h" |
Alexander Timin | fc975678 | 2020-12-23 22:05:52 | [diff] [blame] | 11 | |
| 12 | namespace content { |
| 13 | |
| 14 | // Class responsible for starting and stopping startup tracing as configured by |
| 15 | // StartupTracingConfig. All interactions with it are limited to UI thread, but |
| 16 | // the actual logic lives on a background ThreadPool sequence. |
Alexander Timin | 2149a931 | 2021-01-08 10:03:57 | [diff] [blame] | 17 | class CONTENT_EXPORT StartupTracingController { |
Alexander Timin | fc975678 | 2020-12-23 22:05:52 | [diff] [blame] | 18 | public: |
| 19 | StartupTracingController(); |
| 20 | ~StartupTracingController(); |
| 21 | |
| 22 | static StartupTracingController& GetInstance(); |
| 23 | |
Alexander Timin | a3a8668 | 2021-01-08 12:26:06 | [diff] [blame] | 24 | // Stop the trace recording, write the trace to disk and block until complete. |
| 25 | // Intended to be used in the situation when the browser process is going to |
| 26 | // crash (e.g. DCHECK failure) and we want to avoid losing the trace data. Can |
| 27 | // be called from any thread. |
| 28 | // May not succeed if called from a sequence that is required to be responsive |
| 29 | // during trace finalisation. |
| 30 | static void EmergencyStop(); |
| 31 | |
Alexander Timin | fc975678 | 2020-12-23 22:05:52 | [diff] [blame] | 32 | void StartIfNeeded(); |
| 33 | void WaitUntilStopped(); |
ssid | 6bedaa9 | 2021-06-16 10:25:24 | [diff] [blame] | 34 | void ShutdownAndWaitForStopIfNeeded(); |
Alexander Timin | fc975678 | 2020-12-23 22:05:52 | [diff] [blame] | 35 | |
Alexander Timin | 2149a931 | 2021-01-08 10:03:57 | [diff] [blame] | 36 | // By default, a trace is written into a temporary file which then is renamed, |
| 37 | // however this can lead to data loss when the browser process crashes. |
| 38 | // Embedders can disable this (especially if a name provided to |
| 39 | // SetDefaultBasename makes it clear that the trace is incomplete and final |
| 40 | // name will be provided via SetDefaultBasename call before calling Stop). |
| 41 | enum class TempFilePolicy { |
| 42 | kUseTemporaryFile, |
| 43 | kWriteDirectly, |
| 44 | }; |
| 45 | void SetUsingTemporaryFile(TempFilePolicy temp_file_policy); |
| 46 | |
| 47 | // Set default basename for the trace output file to allow //content embedders |
| 48 | // to customise it using some metadata (like test names). |
| 49 | // |
| 50 | // If --enable-trace-output is a directory (default value, empty, designated |
| 51 | // "current directory"), then the startup trace will be written in a file with |
| 52 | // the given basename in this directory. Depending on the |extension_type|, |
| 53 | // an appropriate extension (.json or .proto) will be added. |
| 54 | // |
| 55 | // Note that embedders can call it even after tracing has started and Perfetto |
| 56 | // started streaming the trace into it — in that case, |
| 57 | // StartupTracingController will rename the file after finishing. However, |
| 58 | // this is guaranteed to work only when tracing lasts until Stop() (not with |
| 59 | // duration-based tracing). |
| 60 | enum class ExtensionType { |
| 61 | kAppendAppropriate, |
| 62 | kNone, |
| 63 | }; |
| 64 | void SetDefaultBasename(std::string basename, ExtensionType extension_type); |
| 65 | // As the test harness calls SetDefaultBasename, expose ForTest() version for |
| 66 | // the tests checking the StartupTracingController logic itself. |
| 67 | void SetDefaultBasenameForTest(std::string basename, |
| 68 | ExtensionType extension_type); |
| 69 | |
| 70 | bool is_finished_for_testing() const { return state_ == State::kStopped; } |
| 71 | |
ssid | 6bedaa9 | 2021-06-16 10:25:24 | [diff] [blame] | 72 | void set_continue_on_shutdown_for_testing() { |
| 73 | should_continue_on_shutdown_ = true; |
| 74 | } |
| 75 | |
Alexander Timin | fc975678 | 2020-12-23 22:05:52 | [diff] [blame] | 76 | private: |
| 77 | void Stop(base::OnceClosure on_finished_callback); |
| 78 | |
| 79 | void OnStoppedOnUIThread(); |
| 80 | |
Alexander Timin | 2149a931 | 2021-01-08 10:03:57 | [diff] [blame] | 81 | base::FilePath GetOutputPath(); |
| 82 | |
Alexander Timin | fc975678 | 2020-12-23 22:05:52 | [diff] [blame] | 83 | enum class State { |
Alexander Timin | 2149a931 | 2021-01-08 10:03:57 | [diff] [blame] | 84 | kNotEnabled, |
Alexander Timin | fc975678 | 2020-12-23 22:05:52 | [diff] [blame] | 85 | kRunning, |
Alexander Timin | 2149a931 | 2021-01-08 10:03:57 | [diff] [blame] | 86 | kStopped, |
Alexander Timin | fc975678 | 2020-12-23 22:05:52 | [diff] [blame] | 87 | }; |
Alexander Timin | 2149a931 | 2021-01-08 10:03:57 | [diff] [blame] | 88 | State state_ = State::kNotEnabled; |
Alexander Timin | fc975678 | 2020-12-23 22:05:52 | [diff] [blame] | 89 | |
| 90 | // All actual interactions with the tracing service and the process of writing |
| 91 | // files happens on a background thread. |
| 92 | class BackgroundTracer; |
| 93 | base::SequenceBound<BackgroundTracer> background_tracer_; |
| 94 | |
| 95 | base::OnceClosure on_tracing_finished_; |
| 96 | base::FilePath output_file_; |
Alexander Timin | 2149a931 | 2021-01-08 10:03:57 | [diff] [blame] | 97 | |
| 98 | std::string default_basename_; |
| 99 | bool basename_for_test_set_ = false; |
ssid | 6bedaa9 | 2021-06-16 10:25:24 | [diff] [blame] | 100 | // Used for testing only |
| 101 | bool should_continue_on_shutdown_ = false; |
Alexander Timin | 2149a931 | 2021-01-08 10:03:57 | [diff] [blame] | 102 | |
Sunny Sachanandani | bfd462f5 | 2025-08-08 21:31:34 | [diff] [blame] | 103 | // Write directly to trace file on iOS since there might not be a graceful |
| 104 | // shutdown for tracing to stop with continuous background tracing. |
| 105 | TempFilePolicy temp_file_policy_ = |
| 106 | #if BUILDFLAG(IS_IOS) |
| 107 | TempFilePolicy::kWriteDirectly; |
| 108 | #else |
| 109 | TempFilePolicy::kUseTemporaryFile; |
| 110 | #endif |
Alexander Timin | fc975678 | 2020-12-23 22:05:52 | [diff] [blame] | 111 | }; |
| 112 | |
| 113 | } // namespace content |
| 114 | |
| 115 | #endif // CONTENT_BROWSER_TRACING_STARTUP_TRACING_CONTROLLER_H_ |