OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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 SVGElementProxy_h | |
6 #define SVGElementProxy_h | |
7 | |
8 #include "core/fetch/DocumentResource.h" | |
9 #include "platform/heap/Handle.h" | |
10 #include "wtf/text/AtomicString.h" | |
11 #include "wtf/text/WTFString.h" | |
12 | |
13 namespace blink { | |
14 | |
15 class Document; | |
16 class SVGElement; | |
17 class SVGResourceClient; | |
18 class TreeScope; | |
19 | |
20 // A proxy to an SVGElement. Allows access to an element with a certain 'id', | |
21 // and provides its clients with notifications when the proxied element | |
22 // changes. | |
23 // | |
24 // SVGElements can be referenced using CSS, for example like: | |
25 // | |
26 // filter: url(#baz); | |
27 // | |
28 // or | |
29 // | |
30 // filter: url(foo.com/bar.svg#baz); | |
31 // | |
32 // SVGElementProxy provide a mechanism to persistently reference an SVGElement | |
33 // in such cases - regardless of if the proxied element reside in the same | |
34 // document (read: tree scope) or in an external (resource) document. In the | |
35 // latter case, SVGElementProxy will transparently take care of the loading of | |
36 // the document (if requested, see SVGElementProxy::resolve.) | |
37 // | |
38 // The proxy uses an 'id' (c.f getElementById) to determine which element to | |
39 // proxy. The id is looked up in the TreeScope of the element for a | |
40 // same-document reference and in the TreeScope of the Document for a external | |
41 // document reference. | |
42 // | |
43 // For same document references, the proxy will track changes that could affect | |
44 // the 'id' lookup, to handle elements being added, removed or having their | |
45 // 'id' mutated. (This does not apply for the external document case because | |
46 // it's assumed they will not mutate after load, due to scripts not being run | |
47 // et.c.) | |
48 // | |
49 // SVGElementProxys are created by CSSURIValue, and have SVGResourceClients as | |
50 // a means to deliver change notifications. Clients that are interested in | |
51 // change notifications hence need to register a SVGResourceClient with the | |
52 // proxy. Most commonly this registration would take place when the | |
53 // ComputedStyle changes. | |
54 // | |
55 // Registration of a client does not establish a link to the proxied element | |
56 // right away. That is instead deferred until element(...) is called on the | |
57 // SVGElementProxy. At this point, the proxy will be registered with either the | |
58 // element (on success) or a set of "pending proxies" managed by | |
59 // SVGDocumentExtensions. (For external references lookups will not be | |
60 // registered, per the same assumption as mentioned above.) | |
61 // | |
62 // As content is mutated, clients will get notified via the proxied element | |
63 // which in turn will notify all registered proxies, which will notify all | |
64 // registered clients. | |
65 // | |
66 // <event> -> SVG...Element -> SVGElementProxy(0..N) -> SVGResourceClient(0..N) | |
67 // | |
68 class SVGElementProxy : public GarbageCollectedFinalized<SVGElementProxy>, | |
69 private DocumentResourceClient { | |
70 USING_GARBAGE_COLLECTED_MIXIN(SVGElementProxy); | |
71 USING_PRE_FINALIZER(SVGElementProxy, detachDocumentClient); | |
72 | |
73 public: | |
74 // Create a proxy to an element in the same document. (See also | |
75 // SVGURLReferenceResolver and the definition of 'local url'.) | |
76 static SVGElementProxy* create(const AtomicString& id) { | |
77 return new SVGElementProxy(id); | |
78 } | |
79 | |
80 // Create a proxy to an element in a different document (indicated by |url|.) | |
81 static SVGElementProxy* create(const String& url, const AtomicString& id) { | |
82 return new SVGElementProxy(url, id); | |
83 } | |
84 virtual ~SVGElementProxy(); | |
85 | |
86 void addClient(SVGResourceClient*); | |
87 void removeClient(SVGResourceClient*); | |
88 | |
89 // Resolve a potentially external document reference. | |
90 void resolve(Document&); | |
91 | |
92 // Returns the proxied element, or null if the proxy is invalid. | |
93 SVGElement* element(TreeScope&); | |
esprehn
2016/10/25 01:18:42
getElement or findElement?
fs
2016/10/25 15:00:53
Done.
| |
94 | |
95 // Notify the proxy that the structure of the subtree rooted at the proxied | |
96 // element has mutated. This should generally only be called via a proxy | |
97 // tracker. | |
98 void contentChanged(); | |
99 | |
100 // Notify the proxy that the reference to the proxied element may now be | |
101 // pointing somewhere else (the id of an element changed, the resource | |
102 // document of the proxy finished loading, the element was removed from the | |
103 // document tree etc.) This should generally only be called via a proxy | |
104 // tracker. | |
105 void proxiedElementChanged(); | |
106 | |
107 const AtomicString& id() const { return m_id; } | |
108 | |
109 // The current "generation" of this proxy. This is essentially a sequence | |
110 // number (or counter) incremented with each change to the proxied element | |
111 // (or its descendants, although that depends on the type of element being | |
112 // proxied.) | |
113 unsigned generation() const { return m_generation; } | |
esprehn
2016/10/25 01:18:42
I'd prefer a dirty bit specific to the subtree or
fs
2016/10/25 15:00:53
This mechanism is only here for the case of the ta
| |
114 | |
115 DECLARE_VIRTUAL_TRACE(); | |
116 | |
117 private: | |
118 explicit SVGElementProxy(const AtomicString&); | |
119 SVGElementProxy(const String&, const AtomicString&); | |
120 | |
121 void detachDocumentClient(); | |
122 // ResourceClient implementation. Used when referencing an external resource | |
123 // document. | |
124 void notifyFinished(Resource*) override; | |
125 String debugName() const override { return "SVGElementProxy"; } | |
126 | |
127 void incrementGeneration() { m_generation++; } | |
128 TreeScope* treeScopeForLookup(TreeScope&) const; | |
129 | |
130 HeapHashSet<Member<SVGResourceClient>> m_clients; | |
131 Member<DocumentResource> m_document; | |
132 AtomicString m_id; | |
133 // URL for resolving references to external resource documents. Contains an | |
134 // absolute URL to the resource to load. Cleared when a load has been | |
135 // initiated. Ignored if m_isLocal is true. | |
136 String m_url; | |
137 unsigned m_generation; | |
138 bool m_isLocal; | |
139 }; | |
140 | |
141 // Collection of SVGElementProxys. This is hosted by elements that can be | |
142 // subject to proxies (currently only SVGFilterElement), and is mainly a helper | |
143 // for dealing with the many-to-one structure of SVGElementProxy. | |
144 class SVGElementProxySet : public GarbageCollected<SVGElementProxySet> { | |
145 public: | |
146 void add(SVGElementProxy&); | |
147 bool isEmpty() const; | |
148 | |
149 // Notify proxy clients that the (content of the) proxied element has | |
150 // changed. | |
151 void notifyContentChanged(); | |
152 | |
153 // Notify proxy clients that the reference to the proxied element is no | |
154 // longer valid. This also clears references to the proxied element. | |
155 void invalidateProxies(); | |
156 | |
157 DECLARE_TRACE(); | |
158 | |
159 private: | |
160 using ProxySet = HeapHashSet<WeakMember<SVGElementProxy>>; | |
161 ProxySet m_elementProxies; | |
162 }; | |
163 | |
164 } // namespace blink | |
165 | |
166 #endif // SVGElementProxy_h | |
OLD | NEW |