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

Side by Side Diff: third_party/WebKit/Source/core/dom/FormElementObserver.cpp

Issue 2865233003: Use an MutationObserver to check when a password form disappears after XHR (Closed)
Patch Set: updates Created 3 years, 7 months 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 2017 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/dom/FormElementObserver.h"
6
7 #include "core/css/CSSComputedStyleDeclaration.h"
8 #include "core/dom/MutationCallback.h"
9 #include "core/dom/MutationObserver.h"
10 #include "core/dom/MutationObserverInit.h"
11 #include "core/dom/MutationRecord.h"
12 #include "core/dom/StaticNodeList.h"
13 #include "core/html/HTMLElement.h"
14 #include "core/html/HTMLFormElement.h"
15 #include "core/html/HTMLInputElement.h"
16 #include "public/web/WebElement.h"
17 #include "public/web/WebFormElementObserverCallback.h"
18
19 namespace blink {
20
21 class FormElementObserver::ObserverCallback : public MutationCallback {
22 public:
23 explicit ObserverCallback(FormElementObserver&);
24 DECLARE_VIRTUAL_TRACE();
25
26 ExecutionContext* GetExecutionContext() const override;
27
28 void Register(HTMLElement&);
29 void Dispose();
30
31 private:
32 void Call(const HeapVector<Member<MutationRecord>>& records,
33 MutationObserver*) override;
34
35 Member<FormElementObserver> element_observer_;
36 Member<MutationObserver> mutation_observer_;
37 };
38
39 FormElementObserver::ObserverCallback::ObserverCallback(
40 FormElementObserver& element_observer)
41 : element_observer_(element_observer) {
42 mutation_observer_ = MutationObserver::Create(this);
43 }
44
45 ExecutionContext* FormElementObserver::ObserverCallback::GetExecutionContext()
46 const {
47 return element_observer_->document_;
48 }
49
50 void FormElementObserver::ObserverCallback::Register(HTMLElement& element) {
51 {
52 Vector<String> filter;
53 filter.ReserveCapacity(3);
54 filter.push_back(String("action"));
55 filter.push_back(String("class"));
56 filter.push_back(String("style"));
57 MutationObserverInit init;
58 init.setAttributes(true);
59 init.setAttributeFilter(filter);
60 mutation_observer_->observe(&element, init, ASSERT_NO_EXCEPTION);
61 }
62 {
63 MutationObserverInit init;
64 init.setChildList(true);
65 mutation_observer_->observe(element.parentElement(), init,
66 ASSERT_NO_EXCEPTION);
67 }
68 }
69
70 void FormElementObserver::ObserverCallback::Dispose() {
71 mutation_observer_->disconnect();
72 }
73
74 void FormElementObserver::ObserverCallback::Call(
75 const HeapVector<Member<MutationRecord>>& records,
76 MutationObserver*) {
77 for (const auto& record : records) {
78 if (record->type() == "childList") {
79 for (unsigned i = 0; i < record->removedNodes()->length(); ++i) {
80 if (!record->removedNodes()->item(i)->IsHTMLElement())
81 continue;
82 element_observer_->NotifyMutation(
83 *ToHTMLElement(record->removedNodes()->item(i)));
84 }
85 } else {
86 HTMLElement& element = *ToHTMLElement(record->target());
87 if (record->attributeName() == "action") {
88 // If the action was modified, we just assume that the form as
89 // submitted.
90 element_observer_->NotifyMutation(element);
91 } else {
92 // Otherwise, either "style" or "class" was modified. Check the
93 // computed style.
94 CSSComputedStyleDeclaration* style =
95 CSSComputedStyleDeclaration::Create(&element);
96 if (style->GetPropertyValue(CSSPropertyDisplay) == "none")
97 element_observer_->NotifyMutation(element);
98 }
99 }
100 }
101 }
102
103 DEFINE_TRACE(FormElementObserver::ObserverCallback) {
104 visitor->Trace(element_observer_);
105 visitor->Trace(mutation_observer_);
106 MutationCallback::Trace(visitor);
107 }
108
109 FormElementObserver::FormElementObserver(Document& document)
110 : document_(&document) {}
111
112 FormElementObserver::~FormElementObserver() {}
113
114 void FormElementObserver::EnsureObserver() {
115 if (!callback_)
116 callback_ = new ObserverCallback(*this);
117 }
118
119 void FormElementObserver::ClearObserver() {
120 if (callback_) {
121 callback_->Dispose();
122 callback_ = nullptr;
123 }
124 }
125
126 void FormElementObserver::Observe(
127 HTMLFormElement& element,
128 std::unique_ptr<WebFormElementObserverCallback> callback) {
129 ObserveInternal(element, std::move(callback));
130 }
131
132 void FormElementObserver::Observe(
133 HTMLInputElement& element,
134 std::unique_ptr<WebFormElementObserverCallback> callback) {
135 ObserveInternal(element, std::move(callback));
136 }
137
138 void FormElementObserver::ObserveInternal(
139 HTMLElement& element,
140 std::unique_ptr<WebFormElementObserverCallback> callback) {
141 DCHECK(element.parentElement());
142 CHECK(callbacks_.Set(&element, std::move(callback)).is_new_entry);
143 EnsureObserver();
144 callback_->Register(element);
145 }
146
147 void FormElementObserver::NotifyMutation(HTMLElement& element) {
148 if (!callbacks_.Contains(&element))
149 return;
150 auto it = callbacks_.find(&element);
151 it->value->ElementWasHiddenOrRemoved();
152 callbacks_.erase(it);
153 if (callbacks_.IsEmpty())
154 ClearObserver();
155 }
156
157 DEFINE_TRACE(FormElementObserver) {
158 visitor->Trace(document_);
159 visitor->Trace(callback_);
160 visitor->Trace(mutation_observer_);
161 visitor->Trace(callbacks_);
162 }
163
164 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698