tor-browser

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

APZTestData.h (9852B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      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 mozilla_layers_APZTestData_h
      8 #define mozilla_layers_APZTestData_h
      9 
     10 #include <map>
     11 
     12 #include "nsDebug.h"                // for NS_WARNING
     13 #include "nsDOMNavigationTiming.h"  // for DOMHighResTimeStamp
     14 #include "nsTArray.h"
     15 #include "mozilla/Assertions.h"       // for MOZ_ASSERT
     16 #include "mozilla/DebugOnly.h"        // for DebugOnly
     17 #include "mozilla/GfxMessageUtils.h"  // for ParamTraits specializations
     18 #include "mozilla/StaticPrefs_apz.h"
     19 #include "mozilla/ToString.h"  // for ToString
     20 #include "mozilla/gfx/CompositorHitTestInfo.h"
     21 #include "mozilla/layers/LayersMessageUtils.h"  // for ParamTraits specializations
     22 #include "mozilla/layers/ScrollableLayerGuid.h"
     23 #include "ipc/IPCMessageUtils.h"
     24 #include "js/TypeDecls.h"
     25 
     26 namespace mozilla {
     27 namespace layers {
     28 
     29 typedef uint32_t SequenceNumber;
     30 
     31 /**
     32 * This structure is used to store information logged by various gecko
     33 * components for later examination by test code.
     34 * It contains a bucket for every paint (initiated on the client side),
     35 * and every repaint request (initiated on the compositor side by
     36 * AsyncPanZoomController::RequestContentRepait), which are identified by
     37 * sequence numbers, and within that, a set of arbitrary string key/value
     38 * pairs for every scrollable frame, identified by a scroll id.
     39 * There are two instances of this data structure for every content thread:
     40 * one on the client side and one of the compositor side.
     41 * It also contains a list of hit-test results for MozMouseHittest events
     42 * dispatched during testing. This list is only populated on the compositor
     43 * instance of this class.
     44 */
     45 // TODO(botond):
     46 //  - Improve warnings/asserts.
     47 //  - Add ability to associate a repaint request triggered during a layers
     48 //    update with the sequence number of the paint that caused the layers
     49 //    update.
     50 class APZTestData {
     51  typedef ScrollableLayerGuid::ViewID ViewID;
     52  friend struct IPC::ParamTraits<APZTestData>;
     53  friend struct APZTestDataToJSConverter;
     54 
     55 public:
     56  void StartNewPaint(SequenceNumber aSequenceNumber) {
     57    // We should never get more than one paint with the same sequence number.
     58    MOZ_ASSERT(mPaints.find(aSequenceNumber) == mPaints.end());
     59    mPaints.insert(DataStore::value_type(aSequenceNumber, Bucket()));
     60  }
     61  void LogTestDataForPaint(SequenceNumber aSequenceNumber, ViewID aScrollId,
     62                           const std::string& aKey, const std::string& aValue) {
     63    LogTestDataImpl(mPaints, aSequenceNumber, aScrollId, aKey, aValue);
     64  }
     65 
     66  void StartNewRepaintRequest(SequenceNumber aSequenceNumber) {
     67    typedef std::pair<DataStore::iterator, bool> InsertResultT;
     68    DebugOnly<InsertResultT> insertResult = mRepaintRequests.insert(
     69        DataStore::value_type(aSequenceNumber, Bucket()));
     70    MOZ_ASSERT(((InsertResultT&)insertResult).second,
     71               "Already have a repaint request with this sequence number");
     72  }
     73  void LogTestDataForRepaintRequest(SequenceNumber aSequenceNumber,
     74                                    ViewID aScrollId, const std::string& aKey,
     75                                    const std::string& aValue) {
     76    LogTestDataImpl(mRepaintRequests, aSequenceNumber, aScrollId, aKey, aValue);
     77  }
     78  void RecordHitResult(const ScreenPoint& aPoint,
     79                       const mozilla::gfx::CompositorHitTestInfo& aResult,
     80                       const LayersId& aLayersId, const ViewID& aScrollId) {
     81    mHitResults.AppendElement(HitResult{aPoint, aResult, aLayersId, aScrollId});
     82  }
     83  void RecordSampledResult(const CSSPoint& aScrollOffset,
     84                           DOMHighResTimeStamp aSampledTimeStamp,
     85                           const LayersId& aLayersId, const ViewID& aScrollId) {
     86    mSampledResults.AppendElement(
     87        SampledResult{aScrollOffset, aSampledTimeStamp, aLayersId, aScrollId});
     88  }
     89  void RecordAdditionalData(const std::string& aKey,
     90                            const std::string& aValue) {
     91    mAdditionalData[aKey] = aValue;
     92  }
     93 
     94  // Convert this object to a JS representation.
     95  bool ToJS(JS::MutableHandle<JS::Value> aOutValue, JSContext* aContext) const;
     96 
     97  // Use dummy derived structures wrapping the typedefs to work around a type
     98  // name length limit in MSVC.
     99  typedef std::map<std::string, std::string> ScrollFrameDataBase;
    100  struct ScrollFrameData : ScrollFrameDataBase {};
    101  typedef std::map<ViewID, ScrollFrameData> BucketBase;
    102  struct Bucket : BucketBase {};
    103  typedef std::map<SequenceNumber, Bucket> DataStoreBase;
    104  struct DataStore : DataStoreBase {};
    105  struct HitResult {
    106    ScreenPoint point;
    107    mozilla::gfx::CompositorHitTestInfo result;
    108    LayersId layersId;
    109    ViewID scrollId;
    110  };
    111  struct SampledResult {
    112    CSSPoint scrollOffset;
    113    DOMHighResTimeStamp sampledTimeStamp;
    114    LayersId layersId;
    115    ViewID scrollId;
    116  };
    117 
    118 private:
    119  DataStore mPaints;
    120  DataStore mRepaintRequests;
    121  CopyableTArray<HitResult> mHitResults;
    122  CopyableTArray<SampledResult> mSampledResults;
    123  // Additional free-form data that's not grouped paint or scroll frame.
    124  std::map<std::string, std::string> mAdditionalData;
    125 
    126  void LogTestDataImpl(DataStore& aDataStore, SequenceNumber aSequenceNumber,
    127                       ViewID aScrollId, const std::string& aKey,
    128                       const std::string& aValue) {
    129    auto bucketIterator = aDataStore.find(aSequenceNumber);
    130    if (bucketIterator == aDataStore.end()) {
    131      MOZ_ASSERT(false,
    132                 "LogTestDataImpl called with nonexistent sequence number");
    133      return;
    134    }
    135    Bucket& bucket = bucketIterator->second;
    136    ScrollFrameData& scrollFrameData =
    137        bucket[aScrollId];  // create if doesn't exist
    138    MOZ_ASSERT(scrollFrameData.find(aKey) == scrollFrameData.end() ||
    139               scrollFrameData[aKey] == aValue);
    140    scrollFrameData.insert(ScrollFrameData::value_type(aKey, aValue));
    141  }
    142 };
    143 
    144 // A helper class for logging data for a paint.
    145 class APZPaintLogHelper {
    146 public:
    147  APZPaintLogHelper(APZTestData* aTestData, SequenceNumber aPaintSequenceNumber,
    148                    bool aIsTestLoggingEnabled)
    149      : mTestData(aTestData), mPaintSequenceNumber(aPaintSequenceNumber) {
    150    MOZ_ASSERT(!aTestData || aIsTestLoggingEnabled, "don't call me");
    151  }
    152 
    153  template <typename Value>
    154  void LogTestData(ScrollableLayerGuid::ViewID aScrollId,
    155                   const std::string& aKey, const Value& aValue) const {
    156    if (mTestData) {  // avoid stringifying if mTestData == nullptr
    157      LogTestData(aScrollId, aKey, ToString(aValue));
    158    }
    159  }
    160 
    161  void LogTestData(ScrollableLayerGuid::ViewID aScrollId,
    162                   const std::string& aKey, const std::string& aValue) const {
    163    if (mTestData) {
    164      mTestData->LogTestDataForPaint(mPaintSequenceNumber, aScrollId, aKey,
    165                                     aValue);
    166    }
    167  }
    168 
    169 private:
    170  APZTestData* mTestData;
    171  SequenceNumber mPaintSequenceNumber;
    172 };
    173 
    174 }  // namespace layers
    175 }  // namespace mozilla
    176 
    177 namespace IPC {
    178 
    179 template <>
    180 struct ParamTraits<mozilla::layers::APZTestData> {
    181  typedef mozilla::layers::APZTestData paramType;
    182 
    183  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    184    WriteParam(aWriter, aParam.mPaints);
    185    WriteParam(aWriter, aParam.mRepaintRequests);
    186    WriteParam(aWriter, aParam.mHitResults);
    187    WriteParam(aWriter, aParam.mSampledResults);
    188    WriteParam(aWriter, aParam.mAdditionalData);
    189  }
    190 
    191  static bool Read(MessageReader* aReader, paramType* aResult) {
    192    return (ReadParam(aReader, &aResult->mPaints) &&
    193            ReadParam(aReader, &aResult->mRepaintRequests) &&
    194            ReadParam(aReader, &aResult->mHitResults) &&
    195            ReadParam(aReader, &aResult->mSampledResults) &&
    196            ReadParam(aReader, &aResult->mAdditionalData));
    197  }
    198 };
    199 
    200 template <>
    201 struct ParamTraits<mozilla::layers::APZTestData::ScrollFrameData>
    202    : ParamTraits<mozilla::layers::APZTestData::ScrollFrameDataBase> {};
    203 
    204 template <>
    205 struct ParamTraits<mozilla::layers::APZTestData::Bucket>
    206    : ParamTraits<mozilla::layers::APZTestData::BucketBase> {};
    207 
    208 template <>
    209 struct ParamTraits<mozilla::layers::APZTestData::DataStore>
    210    : ParamTraits<mozilla::layers::APZTestData::DataStoreBase> {};
    211 
    212 template <>
    213 struct ParamTraits<mozilla::layers::APZTestData::HitResult> {
    214  typedef mozilla::layers::APZTestData::HitResult paramType;
    215 
    216  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    217    WriteParam(aWriter, aParam.point);
    218    WriteParam(aWriter, aParam.result);
    219    WriteParam(aWriter, aParam.layersId);
    220    WriteParam(aWriter, aParam.scrollId);
    221  }
    222 
    223  static bool Read(MessageReader* aReader, paramType* aResult) {
    224    return (ReadParam(aReader, &aResult->point) &&
    225            ReadParam(aReader, &aResult->result) &&
    226            ReadParam(aReader, &aResult->layersId) &&
    227            ReadParam(aReader, &aResult->scrollId));
    228  }
    229 };
    230 
    231 template <>
    232 struct ParamTraits<mozilla::layers::APZTestData::SampledResult> {
    233  typedef mozilla::layers::APZTestData::SampledResult paramType;
    234 
    235  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    236    WriteParam(aWriter, aParam.scrollOffset);
    237    WriteParam(aWriter, aParam.sampledTimeStamp);
    238    WriteParam(aWriter, aParam.layersId);
    239    WriteParam(aWriter, aParam.scrollId);
    240  }
    241 
    242  static bool Read(MessageReader* aReader, paramType* aResult) {
    243    return (ReadParam(aReader, &aResult->scrollOffset) &&
    244            ReadParam(aReader, &aResult->sampledTimeStamp) &&
    245            ReadParam(aReader, &aResult->layersId) &&
    246            ReadParam(aReader, &aResult->scrollId));
    247  }
    248 };
    249 
    250 }  // namespace IPC
    251 
    252 #endif /* mozilla_layers_APZTestData_h */