Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: third_party/WebKit/Source/core/svg/SVGElementProxy.cpp

Issue 2401343002: Tracking filter mutation via SVGElementProxy (Closed)
Patch Set: Fix fullscreen Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 #include "core/svg/SVGElementProxy.h"
6
7 #include "core/dom/IdTargetObserver.h"
8 #include "core/fetch/FetchInitiatorTypeNames.h"
9 #include "core/fetch/FetchRequest.h"
10 #include "core/fetch/ResourceFetcher.h"
11 #include "core/svg/SVGElement.h"
12 #include "core/svg/SVGFilterElement.h"
13 #include "core/svg/SVGResourceClient.h"
14
15 namespace blink {
16
pdr. 2016/11/02 06:35:22 Can you think of any race situations from using Id
fs 2016/11/02 15:49:22 IIRC, Element::updateId is the primary hook (which
17 class SVGElementProxy::IdObserver : public IdTargetObserver {
pdr. 2016/11/02 06:35:22 I didn't know about IdTargetObserver... Would this
fs 2016/11/02 15:49:22 Yes, I did get the same idea. I'll look in to it (
18 public:
19 IdObserver(TreeScope& treeScope, SVGElementProxy& proxy)
20 : IdTargetObserver(treeScope.idTargetObserverRegistry(), proxy.id()),
21 m_treeScope(&treeScope) {}
22
23 void addClient(SVGResourceClient* client) { m_clients.add(client); }
24 bool removeClient(SVGResourceClient* client) {
25 return m_clients.remove(client);
26 }
27
28 TreeScope* treeScope() const { return m_treeScope; }
29 void transferClients(IdObserver& observer) {
30 for (const auto& client : m_clients)
31 observer.m_clients.add(client.key, client.value);
32 m_clients.clear();
33 }
34
35 DEFINE_INLINE_VIRTUAL_TRACE() {
36 visitor->trace(m_clients);
37 visitor->trace(m_treeScope);
38 IdTargetObserver::trace(visitor);
39 }
40
41 void contentChanged() {
42 HeapVector<Member<SVGResourceClient>> clients;
43 copyToVector(m_clients, clients);
44 for (SVGResourceClient* client : clients)
45 client->resourceContentChanged();
46 }
47
48 private:
49 void idTargetChanged() override {
50 HeapVector<Member<SVGResourceClient>> clients;
51 copyToVector(m_clients, clients);
52 for (SVGResourceClient* client : clients)
53 client->resourceElementChanged();
54 }
55 HeapHashCountedSet<Member<SVGResourceClient>> m_clients;
56 Member<TreeScope> m_treeScope;
57 };
58
59 SVGElementProxy::SVGElementProxy(const AtomicString& id)
60 : m_id(id), m_isLocal(true) {}
61
62 SVGElementProxy::SVGElementProxy(const String& url, const AtomicString& id)
63 : m_id(id), m_url(url), m_isLocal(false) {}
64
65 SVGElementProxy::~SVGElementProxy() {}
66
67 void SVGElementProxy::addClient(SVGResourceClient* client) {
68 // An empty id will never be a valid element reference.
69 if (m_id.isEmpty())
70 return;
71 if (m_document)
72 m_document->addClient(client);
73 TreeScope* clientScope = client->treeScope();
74 TreeScope* lookupScope =
75 clientScope ? treeScopeForLookup(*clientScope) : nullptr;
76 if (!lookupScope)
77 return;
78 // Ensure sure we have an observer registered for this tree scope.
79 auto& scopeObserver =
80 m_observers.add(lookupScope, nullptr).storedValue->value;
81 if (!scopeObserver)
82 scopeObserver = new IdObserver(*lookupScope, *this);
83
84 auto& observer = m_clients.add(client, nullptr).storedValue->value;
85 if (!observer)
86 observer = scopeObserver;
87
88 DCHECK(observer && scopeObserver);
89
90 // If the client moved to a different scope, we need to unregister the old
91 // observer and transfer any clients from it before replacing it. Thus any
92 // clients that remain to be removed will be transferred to the new observer,
93 // and hence removed from it instead.
94 if (observer != scopeObserver) {
95 observer->unregister();
96 observer->transferClients(*scopeObserver);
97 observer = scopeObserver;
98 }
99 observer->addClient(client);
100 }
101
102 void SVGElementProxy::removeClient(SVGResourceClient* client) {
103 // An empty id will never be a valid element reference.
104 if (m_id.isEmpty())
105 return;
106 if (m_document)
107 m_document->removeClient(client);
108 auto entry = m_clients.find(client);
109 if (entry == m_clients.end())
110 return;
111 IdObserver* observer = entry->value;
112 DCHECK(observer);
113 // If the client is not the last client in the scope, then no further action
114 // needs to be taken.
115 if (!observer->removeClient(client))
116 return;
117 // Unregister and drop the scope association, then drop the client.
118 observer->unregister();
119 m_observers.remove(observer->treeScope());
120 m_clients.remove(entry);
121 }
122
123 void SVGElementProxy::resolve(Document& document) {
124 if (m_isLocal || m_id.isEmpty() || m_url.isEmpty())
125 return;
126 FetchRequest request(ResourceRequest(m_url), FetchInitiatorTypeNames::css);
127 m_document = DocumentResource::fetchSVGDocument(request, document.fetcher());
128 m_url = String();
129 }
130
131 TreeScope* SVGElementProxy::treeScopeForLookup(TreeScope& treeScope) const {
132 if (m_isLocal)
133 return &treeScope;
134 if (!m_document)
135 return nullptr;
136 return m_document->document();
137 }
138
139 SVGElement* SVGElementProxy::findElement(TreeScope& treeScope) {
140 // An empty id will never be a valid element reference.
141 if (m_id.isEmpty())
142 return nullptr;
143 TreeScope* lookupScope = treeScopeForLookup(treeScope);
144 if (!lookupScope)
145 return nullptr;
146 if (Element* targetElement = lookupScope->getElementById(m_id)) {
147 if (isSVGFilterElement(*targetElement)) {
148 toSVGFilterElement(*targetElement).elementProxySet().add(*this);
149 return toSVGElement(targetElement);
150 }
151 }
152 return nullptr;
153 }
154
155 void SVGElementProxy::contentChanged(TreeScope& treeScope) {
156 if (auto observer = m_observers.get(&treeScope))
157 observer->contentChanged();
158 }
159
160 DEFINE_TRACE(SVGElementProxy) {
161 visitor->trace(m_clients);
162 visitor->trace(m_observers);
163 visitor->trace(m_document);
164 }
165
166 void SVGElementProxySet::add(SVGElementProxy& elementProxy) {
167 m_elementProxies.add(&elementProxy);
168 }
169
170 bool SVGElementProxySet::isEmpty() const {
171 return m_elementProxies.isEmpty();
172 }
173
174 void SVGElementProxySet::notifyContentChanged(TreeScope& treeScope) {
175 for (SVGElementProxy* proxy : m_elementProxies)
176 proxy->contentChanged(treeScope);
177 }
178
179 DEFINE_TRACE(SVGElementProxySet) {
180 visitor->trace(m_elementProxies);
181 }
182
183 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698