summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/css/remote_font_face_source.h
blob: 5476391da88bbbd074f69f4e265c87c6f270ce19 (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_REMOTE_FONT_FACE_SOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_REMOTE_FONT_FACE_SOURCE_H_

#include "third_party/blink/renderer/core/css/css_font_face_source.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/core/loader/resource/font_resource.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"

namespace blink {

class CSSFontFace;
class Document;
class FontSelector;
class FontCustomPlatformData;

class RemoteFontFaceSource final : public CSSFontFaceSource,
                                   public FontResourceClient {
  USING_PRE_FINALIZER(RemoteFontFaceSource, Dispose);
  USING_GARBAGE_COLLECTED_MIXIN(RemoteFontFaceSource);

 public:
  enum Phase { kNoLimitExceeded, kShortLimitExceeded, kLongLimitExceeded };

  RemoteFontFaceSource(CSSFontFace*, FontSelector*, FontDisplay);
  ~RemoteFontFaceSource() override;
  void Dispose();

  bool IsLoading() const override;
  bool IsLoaded() const override;
  bool IsValid() const override;

  void BeginLoadIfNeeded() override;
  void SetDisplay(FontDisplay) override;

  void NotifyFinished(Resource*) override;
  void FontLoadShortLimitExceeded(FontResource*) override;
  void FontLoadLongLimitExceeded(FontResource*) override;
  String DebugName() const override { return "RemoteFontFaceSource"; }

  bool IsInBlockPeriod() const override { return period_ == kBlockPeriod; }
  bool IsInFailurePeriod() const override { return period_ == kFailurePeriod; }

  // For UMA reporting
  bool HadBlankText() override { return histograms_.HadBlankText(); }
  void PaintRequested() override { histograms_.FallbackFontPainted(period_); }

  void Trace(Visitor*) override;

 protected:
  scoped_refptr<SimpleFontData> CreateFontData(
      const FontDescription&,
      const FontSelectionCapabilities&) override;
  scoped_refptr<SimpleFontData> CreateLoadingFallbackFontData(
      const FontDescription&);

 private:
  // Periods of the Font Display Timeline.
  // https://drafts.csswg.org/css-fonts-4/#font-display-timeline
  // Note that kNotApplicablePeriod is an implementation detail indicating that
  // the font is loaded from memory cache synchronously, and hence, made
  // immediately available. As we never need to use a fallback for it, using
  // other DisplayPeriod values seem artificial. So we use a special value.
  enum DisplayPeriod {
    kBlockPeriod,
    kSwapPeriod,
    kFailurePeriod,
    kNotApplicablePeriod
  };

  class FontLoadHistograms {
    DISALLOW_NEW();

   public:
    // Should not change following order in CacheHitMetrics to be used for
    // metrics values.
    enum class CacheHitMetrics {
      kMiss,
      kDiskHit,
      kDataUrl,
      kMemoryHit,
      kMaxValue = kMemoryHit,
    };
    enum DataSource {
      kFromUnknown,
      kFromDataURL,
      kFromMemoryCache,
      kFromDiskCache,
      kFromNetwork
    };

    FontLoadHistograms()
        : blank_paint_time_recorded_(false),
          is_long_limit_exceeded_(false),
          data_source_(kFromUnknown) {}
    void LoadStarted();
    void FallbackFontPainted(DisplayPeriod);
    void LongLimitExceeded();
    void RecordFallbackTime();
    void RecordRemoteFont(const FontResource*);
    bool HadBlankText() { return !blank_paint_time_.is_null(); }
    DataSource GetDataSource() { return data_source_; }
    void MaySetDataSource(DataSource);

    static DataSource DataSourceForLoadFinish(const FontResource* font) {
      if (font->Url().ProtocolIsData())
        return kFromDataURL;
      return font->GetResponse().WasCached() ? kFromDiskCache : kFromNetwork;
    }

   private:
    void RecordLoadTimeHistogram(const FontResource*, base::TimeDelta duration);
    CacheHitMetrics DataSourceMetricsValue();
    base::TimeTicks load_start_time_;
    base::TimeTicks blank_paint_time_;
    // |blank_paint_time_recorded_| is used to prevent
    // WebFont.BlankTextShownTime to be reported incorrectly when the web font
    // fallbacks immediately. See https://crbug.com/591304
    bool blank_paint_time_recorded_;
    bool is_long_limit_exceeded_;
    DataSource data_source_;
  };

  Document* GetDocument() const;

  DisplayPeriod ComputePeriod() const;
  void UpdatePeriod();
  bool ShouldTriggerWebFontsIntervention();
  bool IsLowPriorityLoadingAllowedForRemoteFont() const override;
  FontDisplay GetFontDisplayWithFeaturePolicyCheck(FontDisplay,
                                                   const FontSelector*,
                                                   ReportOptions) const;

  // Our owning font face.
  Member<CSSFontFace> face_;
  Member<FontSelector> font_selector_;

  // |nullptr| if font is not loaded or failed to decode.
  scoped_refptr<FontCustomPlatformData> custom_font_data_;

  FontDisplay display_;
  Phase phase_;
  DisplayPeriod period_;
  FontLoadHistograms histograms_;
  bool is_intervention_triggered_;
  bool finished_before_document_rendering_begin_;
};

}  // namespace blink

#endif