tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

DDMediaLogs.h (7458B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef DDMediaLogs_h_
      8 #define DDMediaLogs_h_
      9 
     10 #include "DDLifetimes.h"
     11 #include "DDMediaLog.h"
     12 #include "MultiWriterQueue.h"
     13 #include "mozilla/MozPromise.h"
     14 
     15 namespace mozilla {
     16 
     17 // Main object managing all processed logs, and yet-unprocessed messages.
     18 struct DDMediaLogs {
     19 public:
     20  // Construct a DDMediaLogs object if possible.
     21  struct ConstructionResult {
     22    nsresult mRv;
     23    DDMediaLogs* mMediaLogs;
     24  };
     25  static ConstructionResult New();
     26 
     27  // If not already shutdown, performs normal end-of-life processing, and shuts
     28  // down the processing thread (blocking).
     29  ~DDMediaLogs();
     30 
     31  // Shutdown the processing thread (blocking), and free as much memory as
     32  // possible.
     33  void Panic();
     34 
     35  inline void Log(const char* aSubjectTypeName, const void* aSubjectPointer,
     36                  DDLogCategory aCategory, const char* aLabel,
     37                  DDLogValue&& aValue) {
     38    if (mMessagesQueue.PushF(
     39            [&](DDLogMessage& aMessage, MessagesQueue::Index i) {
     40              aMessage.mIndex = i;
     41              aMessage.mTimeStamp = DDNow();
     42              aMessage.mObject.Set(aSubjectTypeName, aSubjectPointer);
     43              aMessage.mCategory = aCategory;
     44              aMessage.mLabel = aLabel;
     45              aMessage.mValue = std::move(aValue);
     46            })) {
     47      // Filled a buffer-full of messages, process it in another thread.
     48      DispatchProcessLog();
     49    }
     50  }
     51 
     52  // Process the log right now; should only be used on the processing thread,
     53  // or after shutdown for end-of-life log retrieval. Work includes:
     54  // - Processing incoming buffers, to update object lifetimes and links;
     55  // - Resolve pending promises that requested logs;
     56  // - Clean-up old logs from memory.
     57  void ProcessLog();
     58 
     59  using LogMessagesPromise =
     60      MozPromise<nsCString, nsresult, /* IsExclusive = */ true>;
     61 
     62  // Retrieve all messages associated with an HTMLMediaElement.
     63  // This will trigger an async processing run (to ensure most recent messages
     64  // get retrieved too), and the returned promise will be resolved with all
     65  // found log messages.
     66  RefPtr<LogMessagesPromise> RetrieveMessages(
     67      const dom::HTMLMediaElement* aMediaElement);
     68 
     69  size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
     70 
     71 private:
     72  // Constructor, takes the given thread to use for log processing.
     73  explicit DDMediaLogs(nsCOMPtr<nsIThread>&& aThread);
     74 
     75  // Shutdown the processing thread, blocks until that thread exits.
     76  // If aPanic is true, just free as much memory as possible.
     77  // Otherwise, perform a final processing run, output end-logs (if enabled).
     78  void Shutdown(bool aPanic);
     79 
     80  // Get the log of yet-unassociated messages.
     81  DDMediaLog& LogForUnassociatedMessages();
     82  const DDMediaLog& LogForUnassociatedMessages() const;
     83 
     84  // Get the log for the given HTMLMediaElement. Returns nullptr if there is no
     85  // such log yet.
     86  DDMediaLog* GetLogFor(const dom::HTMLMediaElement* aMediaElement);
     87 
     88  // Get the log for the given HTMLMediaElement.
     89  // A new log is created if that element didn't already have one.
     90  DDMediaLog& LogFor(const dom::HTMLMediaElement* aMediaElement);
     91 
     92  // Associate a lifetime, and all its already-linked lifetimes, with an
     93  // HTMLMediaElement.
     94  // All messages involving the modified lifetime(s) are moved to the
     95  // corresponding log.
     96  void SetMediaElement(DDLifetime& aLifetime,
     97                       const dom::HTMLMediaElement* aMediaElement);
     98 
     99  // Find the lifetime corresponding to an object (known type and pointer) that
    100  // was known to be alive at aIndex.
    101  // If there is no such lifetime yet, create it with aTimeStamp as implicit
    102  // construction timestamp.
    103  // If the object is of type HTMLMediaElement, run SetMediaElement() on it.
    104  DDLifetime& FindOrCreateLifetime(const DDLogObject& aObject,
    105                                   DDMessageIndex aIndex,
    106                                   const DDTimeStamp& aTimeStamp);
    107 
    108  // Link two lifetimes together (at a given time corresponding to aIndex).
    109  // If only one is associated with an HTMLMediaElement, run SetMediaElement on
    110  // the other one.
    111  void LinkLifetimes(DDLifetime& aParentLifetime, const char* aLinkName,
    112                     DDLifetime& aChildLifetime, DDMessageIndex aIndex);
    113 
    114  // Unlink all lifetimes linked to aLifetime; only used to know when links
    115  // expire, so that they won't be used after this time.
    116  void UnlinkLifetime(DDLifetime& aLifetime, DDMessageIndex aIndex);
    117 
    118  // Unlink two lifetimes; only used to know when a link expires, so that it
    119  // won't be used after this time.
    120  void UnlinkLifetimes(DDLifetime& aParentLifetime, DDLifetime& aChildLifetime,
    121                       DDMessageIndex aIndex);
    122 
    123  // Remove all links involving aLifetime from the database.
    124  void DestroyLifetimeLinks(const DDLifetime& aLifetime);
    125 
    126  // Process all incoming log messages.
    127  // This will create the appropriate DDLifetime and links objects, and then
    128  // move processed messages to logs associated with different
    129  // HTMLMediaElements.
    130  void ProcessBuffer();
    131 
    132  // Pending promises (added by RetrieveMessages) are resolved with all new
    133  // log messages corresponding to requested HTMLMediaElements -- These
    134  // messages are removed from our logs.
    135  void FulfillPromises();
    136 
    137  // Remove processed messages that have a low chance of being requested,
    138  // based on the assumption that users/scripts will regularly call
    139  // RetrieveMessages for HTMLMediaElements they are interested in.
    140  void CleanUpLogs();
    141 
    142  // Request log-processing on the processing thread. Thread-safe.
    143  nsresult DispatchProcessLog();
    144 
    145  // Request log-processing on the processing thread.
    146  nsresult DispatchProcessLog(const MutexAutoLock& aProofOfLock);
    147 
    148  using MessagesQueue =
    149      MultiWriterQueue<DDLogMessage, MultiWriterQueueDefaultBufferSize,
    150                       MultiWriterQueueReaderLocking_None>;
    151  MessagesQueue mMessagesQueue;
    152 
    153  DDLifetimes mLifetimes;
    154 
    155  // mMediaLogs[0] contains unsorted message (with mMediaElement=nullptr).
    156  // mMediaLogs[1+] contains sorted messages for each media element.
    157  nsTArray<DDMediaLog> mMediaLogs;
    158 
    159  struct DDObjectLink {
    160    const DDLogObject mParent;
    161    const DDLogObject mChild;
    162    const char* const mLinkName;
    163    const DDMessageIndex mLinkingIndex;
    164    Maybe<DDMessageIndex> mUnlinkingIndex;
    165 
    166    DDObjectLink(DDLogObject aParent, DDLogObject aChild, const char* aLinkName,
    167                 DDMessageIndex aLinkingIndex)
    168        : mParent(aParent),
    169          mChild(aChild),
    170          mLinkName(aLinkName),
    171          mLinkingIndex(aLinkingIndex),
    172          mUnlinkingIndex(Nothing{}) {}
    173  };
    174  // Links between live objects, updated while messages are processed.
    175  nsTArray<DDObjectLink> mObjectLinks;
    176 
    177  // Protects members below.
    178  Mutex mMutex MOZ_UNANNOTATED;
    179 
    180  // Processing thread.
    181  nsCOMPtr<nsIThread> mThread;
    182 
    183  struct PendingPromise {
    184    MozPromiseHolder<LogMessagesPromise> mPromiseHolder;
    185    const dom::HTMLMediaElement* mMediaElement;
    186  };
    187  // Most cases should have 1 media panel requesting 1 promise at a time.
    188  AutoTArray<PendingPromise, 2> mPendingPromises;
    189 };
    190 
    191 }  // namespace mozilla
    192 
    193 #endif  // DDMediaLogs_h_