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
|
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ACTOR_AGGREGATED_JOURNAL_H_
#define CHROME_BROWSER_ACTOR_AGGREGATED_JOURNAL_H_
#include <string>
#include <string_view>
#include <vector>
#include "base/containers/ring_buffer.h"
#include "base/memory/safe_ref.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/supports_user_data.h"
#include "base/types/pass_key.h"
#include "chrome/browser/actor/task_id.h"
#include "chrome/common/actor.mojom.h"
#include "content/public/browser/render_frame_host.h"
#include "url/gurl.h"
namespace actor {
// A class that amalgamates all the journal entries from various RenderFrames.
class AggregatedJournal {
public:
AggregatedJournal();
~AggregatedJournal();
// Journal entry
struct Entry {
std::string url;
std::optional<std::vector<uint8_t>> jpg_screenshot;
mojom::JournalEntryPtr data;
Entry(const std::string& location, mojom::JournalEntryPtr data);
~Entry();
};
// A pending async journal entry.
class PendingAsyncEntry {
public:
// Creation of the event is only from the AggregatedJournal itself. Use
// `AggregatedJournal::CreatePendingAsyncEntry` to create this object.
PendingAsyncEntry(base::PassKey<AggregatedJournal>,
base::SafeRef<AggregatedJournal> journal,
TaskId task_id,
uint64_t trace_id,
std::string_view event_name);
~PendingAsyncEntry();
// End an pending entry with additional details. This can only be called
// once and will be automatically called from the destructor if it hasn't
// been called.
void EndEntry(std::string_view details);
AggregatedJournal& GetJournal();
TaskId GetTaskId();
private:
base::PassKey<AggregatedJournal> pass_key_;
bool terminated_ = false;
base::SafeRef<AggregatedJournal> journal_;
TaskId task_id_;
uint64_t trace_id_;
std::string event_name_;
};
// Observing class for new entries.
class Observer : public base::CheckedObserver {
public:
virtual void WillAddJournalEntry(const Entry& entry) = 0;
};
using EntryBuffer = base::RingBuffer<std::unique_ptr<Entry>, 20>;
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// Create an async entry. This will log a Begin Entry event and when the
// PendingAsyncEntry object is destroyed the End Entry will be logged.
std::unique_ptr<PendingAsyncEntry> CreatePendingAsyncEntry(
const GURL& url,
TaskId task_id,
std::string_view event_name,
std::string_view details);
// Log an instant event.
void Log(const GURL& url,
TaskId task_id,
std::string_view event_name,
std::string_view details);
// Screenshots need to be an instant event with a custom event name to be
// decoded in perfetto.
void LogScreenshot(const GURL& url,
TaskId task_id,
std::string_view mime_type,
const std::vector<uint8_t>& data);
void EnsureJournalBound(content::RenderFrameHost& rfh);
void AppendJournalEntries(content::RenderFrameHost* rfh,
std::vector<mojom::JournalEntryPtr> entries);
EntryBuffer::Iterator Items() { return entries_.Begin(); }
base::SafeRef<AggregatedJournal> GetSafeRef();
void AddEndEvent(base::PassKey<AggregatedJournal>,
TaskId task_id,
uint64_t trace_id,
const std::string& event_name,
std::string_view details);
private:
void AddEntry(std::unique_ptr<Entry>);
uint64_t next_trace_id_;
base::ObserverList<Observer> observers_;
EntryBuffer entries_;
base::WeakPtrFactory<AggregatedJournal> weak_ptr_factory_{this};
};
} // namespace actor
#endif // CHROME_BROWSER_ACTOR_AGGREGATED_JOURNAL_H_
|