summaryrefslogtreecommitdiffstats
path: root/docshell/base/timeline/TimelineConsumers.h
blob: fb7686553e72b773d27fd8551a9555f2a115fbaa (plain)
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
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_TimelineConsumers_h_
#define mozilla_TimelineConsumers_h_

#include "nsIObserver.h"
#include "nsIDocShell.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/LinkedList.h"
#include "mozilla/StaticMutex.h"
#include "TimelineMarkerEnums.h" // for MarkerTracingType
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
#include "nsTArray.h"

class nsDocShell;
class nsIDocShell;
struct JSContext;

namespace mozilla {
class TimeStamp;
class MarkersStorage;
class AbstractTimelineMarker;

namespace dom {
struct ProfileTimelineMarker;
}

class TimelineConsumers : public nsIObserver
{
public:
  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_NSIOBSERVER

private:
  TimelineConsumers();
  TimelineConsumers(const TimelineConsumers& aOther) = delete;
  void operator=(const TimelineConsumers& aOther) = delete;
  virtual ~TimelineConsumers() = default;

  bool Init();
  bool RemoveObservers();

public:
  static already_AddRefed<TimelineConsumers> Get();

  // Methods for registering interested consumers (i.e. "devtools toolboxes").
  // Each consumer should be directly focused on a particular docshell, but
  // timeline markers don't necessarily have to be tied to that docshell.
  // See the public `AddMarker*` methods below.
  // Main thread only.
  void AddConsumer(nsDocShell* aDocShell);
  void RemoveConsumer(nsDocShell* aDocShell);

  bool HasConsumer(nsIDocShell* aDocShell);

  // Checks if there's any existing interested consumer.
  // May be called from any thread.
  bool IsEmpty();

  // Methods for adding markers relevant for particular docshells, or generic
  // (meaning that they either can't be tied to a particular docshell, or one
  // wasn't accessible in the part of the codebase where they're instantiated).
  // These will only add markers if at least one docshell is currently being
  // observed by a timeline. Markers tied to a particular docshell won't be
  // created unless that docshell is specifically being currently observed.
  // See nsIDocShell::recordProfileTimelineMarkers

  // These methods create a basic TimelineMarker from a name and some metadata,
  // relevant for a specific docshell.
  // Main thread only.
  void AddMarkerForDocShell(nsDocShell* aDocShell,
                            const char* aName,
                            MarkerTracingType aTracingType,
                            MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
  void AddMarkerForDocShell(nsIDocShell* aDocShell,
                            const char* aName,
                            MarkerTracingType aTracingType,
                            MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);

  void AddMarkerForDocShell(nsDocShell* aDocShell,
                            const char* aName,
                            const TimeStamp& aTime,
                            MarkerTracingType aTracingType,
                            MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
  void AddMarkerForDocShell(nsIDocShell* aDocShell,
                            const char* aName,
                            const TimeStamp& aTime,
                            MarkerTracingType aTracingType,
                            MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);

  // These methods register and receive ownership of an already created marker,
  // relevant for a specific docshell.
  // Main thread only.
  void AddMarkerForDocShell(nsDocShell* aDocShell,
                            UniquePtr<AbstractTimelineMarker>&& aMarker);
  void AddMarkerForDocShell(nsIDocShell* aDocShell,
                            UniquePtr<AbstractTimelineMarker>&& aMarker);

  // These methods create a basic marker from a name and some metadata,
  // which doesn't have to be relevant to a specific docshell.
  // May be called from any thread.
  void AddMarkerForAllObservedDocShells(const char* aName,
                                        MarkerTracingType aTracingType,
                                        MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
  void AddMarkerForAllObservedDocShells(const char* aName,
                                        const TimeStamp& aTime,
                                        MarkerTracingType aTracingType,
                                        MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);

  // This method clones and registers an already instantiated marker,
  // which doesn't have to be relevant to a specific docshell.
  // May be called from any thread.
  void AddMarkerForAllObservedDocShells(UniquePtr<AbstractTimelineMarker>& aMarker);

  void PopMarkers(nsDocShell* aDocShell,
                  JSContext* aCx,
                  nsTArray<dom::ProfileTimelineMarker>& aStore);

private:
  static StaticRefPtr<TimelineConsumers> sInstance;
  static bool sInShutdown;

  // Counter for how many timelines are currently interested in markers,
  // and a list of the MarkersStorage interfaces representing them.
  unsigned long mActiveConsumers;
  LinkedList<MarkersStorage> mMarkersStores;

  // Protects this class's data structures.
  static StaticMutex sMutex;
};

} // namespace mozilla

#endif /* mozilla_TimelineConsumers_h_ */