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

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

Powered by Google App Engine
This is Rietveld 408576698