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
|
// 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_
|