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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
ash / hud_display / ash_tracing_request.h [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_HUD_DISPLAY_ASH_TRACING_REQUEST_H_
#define ASH_HUD_DISPLAY_ASH_TRACING_REQUEST_H_
#include <sys/stat.h>
#include <memory>
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/platform_file.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "ash/ash_export.h"
namespace ash {
namespace hud_display {
class AshTracingManager;
class AshTracingHandler;
// This is needed for testing to override File IO.
class ASH_EXPORT AshTraceDestinationIO {
public:
virtual ~AshTraceDestinationIO();
// Overrides base::CreateDirectory.
virtual bool CreateDirectory(const base::FilePath& path) = 0;
// Overrides base::File::File(). Returns pair {File file, bool success}.
// Test implementation may return success with invalid file.
virtual std::tuple<base::File, bool> CreateTracingFile(
const base::FilePath& path) = 0;
// Implements memfd_create(2). Returns pair {int fd, bool success}.
// Test implementation may return success with invalid fd.
virtual std::tuple<base::PlatformFile, bool> CreateMemFD(
const char* name,
unsigned int flags) = 0;
// Takes GetPlatformFile() from AshTraceDestination and returns true if
// given fd is valid for storing traces. Checks for -1 in regular case,
// and checks internal status in tests.
virtual bool CanWriteFile(base::PlatformFile fd) = 0;
virtual int fstat(base::PlatformFile fd, struct stat* statbuf) = 0;
virtual ssize_t sendfile(base::PlatformFile out_fd,
base::PlatformFile in_fd,
off_t* offset,
size_t size) = 0;
};
class ASH_EXPORT AshTraceDestination {
public:
AshTraceDestination();
AshTraceDestination(std::unique_ptr<AshTraceDestinationIO> io,
const base::FilePath& path,
base::File&& file,
base::PlatformFile memfd);
AshTraceDestination(const AshTraceDestination&) = delete;
AshTraceDestination& operator=(const AshTraceDestination&) = delete;
~AshTraceDestination();
const base::FilePath& path() const { return path_; }
// Returns PlatformFile for storing trace.
// Can be memfd or file depending on the setup.
base::PlatformFile GetPlatformFile() const;
// Reurns true if GetPlatformFile() will return valid file descriptor.
// In tests when test IO layer is used returns true if test IO layer will
// succeed saving file.
bool CanWriteFile() const;
// Close all files.
void Done();
AshTraceDestinationIO* io() const { return io_.get(); }
private:
std::unique_ptr<AshTraceDestinationIO> io_;
base::FilePath path_;
base::File file_;
base::PlatformFile memfd_ = base::kInvalidPlatformFile;
};
class AshTracingRequest {
public:
enum class Status {
kEmpty, // Object created.
kInitialized, // File data is initialized
kStarted, // Tracing is in progress.
kStopping, // Tracing is being stopped.
kPendingMount, // Tracing is complete, waiting for home directory mount.
kWritingFile, // Writing trace file from memory to file after user login.
kCompleted, // Trace file is written. Object has valid path.
};
// Will start tracing (asynchronously).
explicit AshTracingRequest(AshTracingManager* tracing_manager);
AshTracingRequest(const AshTracingRequest&) = delete;
AshTracingRequest& operator=(const AshTracingRequest&) = delete;
~AshTracingRequest();
void Stop();
// Receive notifications from AshTracingHandler.
void OnTracingStarted();
void OnTracingFinished();
// Will trigger trace file write if needed.
void OnUserLoggedIn();
// Returns file descriptor that will actually be used for tracing.
base::PlatformFile GetPlatformFile() const;
Status status() const { return status_; }
const std::string& error_message() const { return error_message_; }
// Tests generate specific fake IO.
static ASH_EXPORT void SetAshTraceDestinationIOCreatorForTesting(
std::unique_ptr<AshTraceDestinationIO> (*creator)(void));
static ASH_EXPORT void ResetAshTraceDestinationIOCreatorForTesting();
// Tests explicitly check AshTraceDestination behavior and they need to
// be able to generate ThreadPool tasks to crete AshTraceDestination.
// So this function will return a task that can be sent to IO-enabled
// sequence runner to create AshTraceDestination.
using AshTraceDestinationUniquePtr = std::unique_ptr<AshTraceDestination>;
using GenerateTraceDestinationTask =
base::OnceCallback<AshTraceDestinationUniquePtr(void)>;
ASH_EXPORT static GenerateTraceDestinationTask
CreateGenerateTraceDestinationTaskForTesting(
std::unique_ptr<AshTraceDestinationIO> io,
base::Time timestamp);
ASH_EXPORT const AshTraceDestination* GetTraceDestinationForTesting() const;
private:
// Starts tracing after `destination` was initialized on the ThreadPool.
void OnTraceDestinationInitialized(
std::unique_ptr<AshTraceDestination> destination);
// Marks file export operation completed.
void OnPendingFileStored(std::unique_ptr<AshTraceDestination> destination,
bool success,
std::string error_message);
// Stores memory trace file to permanent location.
void StorePendingFile();
// Trace status
Status status_ = Status::kEmpty;
// When trace was started.
const base::Time timestamp_;
bool user_logged_in_ = false;
raw_ptr<AshTracingManager> tracing_manager_;
// This object is deleted once tracing is stopped.
std::unique_ptr<AshTracingHandler> tracing_handler_;
// Non-empty if error has occurred.
std::string error_message_;
std::unique_ptr<AshTraceDestination> trace_destination_;
SEQUENCE_CHECKER(my_sequence_checker_);
base::WeakPtrFactory<AshTracingRequest> weak_factory_{this};
};
} // namespace hud_display
} // namespace ash
#endif // ASH_HUD_DISPLAY_ASH_TRACING_REQUEST_H_