1 
2 // Copyright 2017 The Chromium Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 
6 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_FONT_FACE_SET_H_
7 #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_FONT_FACE_SET_H_
8 
9 #include "third_party/blink/public/platform/task_type.h"
10 #include "third_party/blink/renderer/bindings/core/v8/iterable.h"
11 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
12 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
13 #include "third_party/blink/renderer/core/css/font_face.h"
14 #include "third_party/blink/renderer/core/dom/events/event_listener.h"
15 #include "third_party/blink/renderer/core/dom/events/event_target.h"
16 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
17 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
18 #include "third_party/blink/renderer/platform/fonts/font_selector.h"
19 
20 namespace blink {
21 
22 class FontFaceCache;
23 
24 using FontFaceSetIterable = SetlikeIterable<Member<FontFace>>;
25 
26 class CORE_EXPORT FontFaceSet : public EventTargetWithInlineData,
27                                 public ExecutionContextClient,
28                                 public FontFaceSetIterable,
29                                 public FontFace::LoadFontCallback {
30   DEFINE_WRAPPERTYPEINFO();
31 
32  public:
FontFaceSet(ExecutionContext & context)33   FontFaceSet(ExecutionContext& context)
34       : ExecutionContextClient(&context),
35         ready_(MakeGarbageCollected<ReadyProperty>(GetExecutionContext())) {}
36   FontFaceSet(const FontFaceSet&) = delete;
37   FontFaceSet& operator=(const FontFaceSet&) = delete;
38   ~FontFaceSet() override = default;
39 
40   DEFINE_ATTRIBUTE_EVENT_LISTENER(loading, kLoading)
41   DEFINE_ATTRIBUTE_EVENT_LISTENER(loadingdone, kLoadingdone)
42   DEFINE_ATTRIBUTE_EVENT_LISTENER(loadingerror, kLoadingerror)
43 
44   bool check(const String& font, const String& text, ExceptionState&);
45   ScriptPromise load(ScriptState*, const String& font, const String& text);
46   virtual ScriptPromise ready(ScriptState*) = 0;
47 
GetExecutionContext()48   ExecutionContext* GetExecutionContext() const override {
49     return ExecutionContextClient::GetExecutionContext();
50   }
51 
InterfaceName()52   const AtomicString& InterfaceName() const override {
53     return event_target_names::kFontFaceSet;
54   }
55 
56   FontFaceSet* addForBinding(ScriptState*, FontFace*, ExceptionState&);
57   void clearForBinding(ScriptState*, ExceptionState&);
58   bool deleteForBinding(ScriptState*, FontFace*, ExceptionState&);
59   bool hasForBinding(ScriptState*, FontFace*, ExceptionState&) const;
60 
61   void AddFontFacesToFontFaceCache(FontFaceCache*);
62 
63   wtf_size_t size() const;
64   virtual AtomicString status() const = 0;
65 
66   void Trace(Visitor*) const override;
67 
68  protected:
69   static const int kDefaultFontSize;
70   static const char kDefaultFontFamily[];
71 
72   virtual bool ResolveFontStyle(const String&, Font&) = 0;
73   virtual bool InActiveContext() const = 0;
74   virtual FontSelector* GetFontSelector() const = 0;
75   virtual const HeapLinkedHashSet<Member<FontFace>>& CSSConnectedFontFaceList()
76       const = 0;
IsCSSConnectedFontFace(FontFace * font_face)77   bool IsCSSConnectedFontFace(FontFace* font_face) const {
78     return CSSConnectedFontFaceList().Contains(font_face);
79   }
80 
81   virtual void FireDoneEventIfPossible() = 0;
82 
83   void AddToLoadingFonts(FontFace*);
84   void RemoveFromLoadingFonts(FontFace*);
85   void HandlePendingEventsAndPromisesSoon();
86   bool ShouldSignalReady() const;
87   void FireDoneEvent();
88 
89   using ReadyProperty = ScriptPromiseProperty<Member<FontFaceSet>,
90                                               Member<DOMException>>;
91 
92   bool is_loading_ = false;
93   bool should_fire_loading_event_ = false;
94   bool pending_task_queued_ = false;
95   HeapLinkedHashSet<Member<FontFace>> non_css_connected_faces_;
96   HeapHashSet<Member<FontFace>> loading_fonts_;
97   FontFaceArray loaded_fonts_;
98   FontFaceArray failed_fonts_;
99   Member<ReadyProperty> ready_;
100 
101   class IterationSource final : public FontFaceSetIterable::IterationSource {
102    public:
IterationSource(const HeapVector<Member<FontFace>> & font_faces)103     explicit IterationSource(const HeapVector<Member<FontFace>>& font_faces)
104         : index_(0), font_faces_(font_faces) {}
105     bool Next(ScriptState*,
106               Member<FontFace>&,
107               Member<FontFace>&,
108               ExceptionState&) override;
109 
Trace(Visitor * visitor)110     void Trace(Visitor* visitor) const override {
111       visitor->Trace(font_faces_);
112       FontFaceSetIterable::IterationSource::Trace(visitor);
113     }
114 
115    private:
116     wtf_size_t index_;
117     HeapVector<Member<FontFace>> font_faces_;
118   };
119 
120   class LoadFontPromiseResolver final
121       : public GarbageCollected<LoadFontPromiseResolver>,
122         public FontFace::LoadFontCallback {
123    public:
LoadFontPromiseResolver(FontFaceArray * faces,ScriptState * script_state)124     LoadFontPromiseResolver(FontFaceArray* faces, ScriptState* script_state)
125         : num_loading_(faces->size()),
126           error_occured_(false),
127           resolver_(MakeGarbageCollected<ScriptPromiseResolver>(script_state)) {
128       font_faces_.swap(*faces);
129     }
130 
131     void LoadFonts();
Promise()132     ScriptPromise Promise() { return resolver_->Promise(); }
133 
134     void NotifyLoaded(FontFace*) override;
135     void NotifyError(FontFace*) override;
136 
137     void Trace(Visitor*) const override;
138 
139    private:
140     HeapVector<Member<FontFace>> font_faces_;
141     int num_loading_;
142     bool error_occured_;
143     Member<ScriptPromiseResolver> resolver_;
144   };
145 
146  private:
147   FontFaceSetIterable::IterationSource* StartIteration(
148       ScriptState*,
149       ExceptionState&) override;
150 
151   void HandlePendingEventsAndPromises();
152   void FireLoadingEvent();
153 };
154 
155 }  // namespace blink
156 
157 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_FONT_FACE_SET_H_
158