1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_IMAGE_ELEMENT_TIMING_H_
6 #define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_IMAGE_ELEMENT_TIMING_H_
7 
8 #include <utility>
9 
10 #include "third_party/blink/public/web/web_swap_result.h"
11 #include "third_party/blink/renderer/core/dom/element.h"
12 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
13 #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
14 #include "third_party/blink/renderer/platform/supplementable.h"
15 #include "third_party/blink/renderer/platform/wtf/functional.h"
16 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
17 
18 #include "third_party/blink/renderer/platform/wtf/vector.h"
19 
20 namespace blink {
21 
22 class ImageResourceContent;
23 class PropertyTreeStateOrAlias;
24 class StyleFetchedImage;
25 
26 // ImageElementTiming is responsible for tracking the paint timings for <img>
27 // elements for a given window.
28 class CORE_EXPORT ImageElementTiming final
29     : public GarbageCollected<ImageElementTiming>,
30       public Supplement<LocalDOMWindow> {
31  public:
32   static const char kSupplementName[];
33 
34   // The maximum amount of characters included in Element Timing and Largest
35   // Contentful Paint for inline images.
36   static constexpr const unsigned kInlineImageMaxChars = 100;
37 
38   explicit ImageElementTiming(LocalDOMWindow&);
39   ImageElementTiming(const ImageElementTiming&) = delete;
40   ImageElementTiming& operator=(const ImageElementTiming&) = delete;
41   virtual ~ImageElementTiming() = default;
42 
43   static ImageElementTiming& From(LocalDOMWindow&);
44 
45   void NotifyImageFinished(const LayoutObject&, const ImageResourceContent*);
46 
47   void NotifyBackgroundImageFinished(const StyleFetchedImage*);
48   base::TimeTicks GetBackgroundImageLoadTime(const StyleFetchedImage*);
49 
50   // Called when the LayoutObject has been painted. This method might queue a
51   // swap promise to compute and report paint timestamps.
52   void NotifyImagePainted(
53       const LayoutObject*,
54       const ImageResourceContent* cached_image,
55       const PropertyTreeStateOrAlias& current_paint_chunk_properties,
56       const IntRect& image_border);
57 
58   void NotifyBackgroundImagePainted(
59       Node*,
60       const StyleFetchedImage* background_image,
61       const PropertyTreeStateOrAlias& current_paint_chunk_properties,
62       const IntRect& image_border);
63 
64   void NotifyImageRemoved(const LayoutObject*,
65                           const ImageResourceContent* image);
66 
67   void Trace(Visitor*) const override;
68 
69  private:
70   friend class ImageElementTimingTest;
71 
72   void NotifyImagePaintedInternal(
73       Node*,
74       const LayoutObject&,
75       const ImageResourceContent& cached_image,
76       const PropertyTreeStateOrAlias& current_paint_chunk_properties,
77       base::TimeTicks load_time,
78       const IntRect& image_border);
79 
80   // Callback for the swap promise. Reports paint timestamps.
81   void ReportImagePaintSwapTime(WebSwapResult, base::TimeTicks timestamp);
82 
83   // Class containing information about image element timing.
84   class ElementTimingInfo final : public GarbageCollected<ElementTimingInfo> {
85    public:
ElementTimingInfo(const String & url,const FloatRect & rect,const base::TimeTicks & response_end,const AtomicString & identifier,const IntSize & intrinsic_size,const AtomicString & id,Element * element)86     ElementTimingInfo(const String& url,
87                       const FloatRect& rect,
88                       const base::TimeTicks& response_end,
89                       const AtomicString& identifier,
90                       const IntSize& intrinsic_size,
91                       const AtomicString& id,
92                       Element* element)
93         : url(url),
94           rect(rect),
95           response_end(response_end),
96           identifier(identifier),
97           intrinsic_size(intrinsic_size),
98           id(id),
99           element(element) {}
100     ElementTimingInfo(const ElementTimingInfo&) = delete;
101     ElementTimingInfo& operator=(const ElementTimingInfo&) = delete;
102     ~ElementTimingInfo() = default;
103 
Trace(Visitor * visitor)104     void Trace(Visitor* visitor) const { visitor->Trace(element); }
105 
106     String url;
107     FloatRect rect;
108     base::TimeTicks response_end;
109     AtomicString identifier;
110     IntSize intrinsic_size;
111     AtomicString id;
112     Member<Element> element;
113   };
114 
115   // Vector containing the element timing infos that will be reported during the
116   // next swap promise callback.
117   HeapVector<Member<ElementTimingInfo>> element_timings_;
118   struct ImageInfo {
ImageInfoImageInfo119     ImageInfo() {}
120 
121     base::TimeTicks load_time_;
122     bool is_painted_ = false;
123   };
124   typedef std::pair<const LayoutObject*, const ImageResourceContent*> RecordId;
125   // Hashmap of pairs of elements, LayoutObjects (for the elements) and
126   // ImageResourceContent (for the src) which correspond to either images or
127   // background images whose paint has been observed. For background images,
128   // only the |is_painted_| bit is used, as the timestamp needs to be tracked by
129   // |background_image_timestamps_|.
130   WTF::HashMap<RecordId, ImageInfo> images_notified_;
131 
132   // Hashmap of background images which contain information about the load time
133   // of the background image.
134   HeapHashMap<WeakMember<const StyleFetchedImage>, base::TimeTicks>
135       background_image_timestamps_;
136 };
137 
138 }  // namespace blink
139 
140 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_IMAGE_ELEMENT_TIMING_H_
141