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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/dom/FormElementObserver.cpp
diff --git a/third_party/WebKit/Source/core/dom/FormElementObserver.cpp b/third_party/WebKit/Source/core/dom/FormElementObserver.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ad69cfeba178dd9c8d5166c9f3a8db4f680d6253
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/FormElementObserver.cpp
@@ -0,0 +1,153 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/dom/FormElementObserver.h"
+
+#include "core/dom/MutationCallback.h"
+#include "core/dom/MutationObserver.h"
+#include "core/dom/MutationObserverInit.h"
+#include "core/dom/MutationRecord.h"
+#include "core/dom/StaticNodeList.h"
+#include "core/html/HTMLElement.h"
+#include "core/html/HTMLFormElement.h"
+#include "core/html/HTMLInputElement.h"
+#include "public/web/WebElement.h"
+#include "public/web/WebFormElementObserverCallback.h"
+
+namespace blink {
+
+class FormElementObserver::ObserverCallback : public MutationCallback {
+ public:
+ explicit ObserverCallback(FormElementObserver&);
+ DECLARE_VIRTUAL_TRACE();
+
+ ExecutionContext* GetExecutionContext() const override;
+
+ void Register(HTMLElement&);
+ void Dispose();
+
+ private:
+ void Call(const HeapVector<Member<MutationRecord>>& records,
+ MutationObserver*) override;
+
+ Member<FormElementObserver> element_observer_;
+ Member<MutationObserver> mutation_observer_;
+};
+
+FormElementObserver::ObserverCallback::ObserverCallback(
+ FormElementObserver& element_observer)
+ : element_observer_(element_observer) {
+ mutation_observer_ = MutationObserver::Create(this);
+}
+
+ExecutionContext* FormElementObserver::ObserverCallback::GetExecutionContext()
+ const {
+ return element_observer_->document_;
+}
+
+void FormElementObserver::ObserverCallback::Register(HTMLElement& element) {
+ {
+ Vector<String> filter;
+ filter.ReserveCapacity(3);
+ filter.push_back(String("action"));
+ filter.push_back(String("class"));
+ filter.push_back(String("style"));
+ MutationObserverInit init;
+ init.setAttributes(true);
+ init.setAttributeFilter(filter);
+ mutation_observer_->observe(&element, init, ASSERT_NO_EXCEPTION);
+ }
+ {
+ MutationObserverInit init;
+ init.setChildList(true);
+ mutation_observer_->observe(element.parentElement(), init,
+ ASSERT_NO_EXCEPTION);
+ }
+}
+
+void FormElementObserver::ObserverCallback::Dispose() {
+ mutation_observer_->disconnect();
+}
+
+void FormElementObserver::ObserverCallback::Call(
+ const HeapVector<Member<MutationRecord>>& records,
+ MutationObserver*) {
+ for (const auto& record : records) {
+ if (record->type() == "childList") {
+ for (unsigned i = 0; i < record->removedNodes()->length(); ++i) {
+ if (!record->removedNodes()->item(i)->IsHTMLElement())
+ continue;
+ element_observer_->NotifyMutation(
+ *ToHTMLElement(record->removedNodes()->item(i)));
+ }
+ } else {
+ HTMLElement& element = *ToHTMLElement(record->target());
+ element_observer_->NotifyMutation(element);
+ }
+ }
+}
+
+DEFINE_TRACE(FormElementObserver::ObserverCallback) {
+ visitor->Trace(element_observer_);
+ visitor->Trace(mutation_observer_);
+ MutationCallback::Trace(visitor);
+}
+
+FormElementObserver::FormElementObserver(Document& document)
+ : document_(&document) {}
+
+FormElementObserver::~FormElementObserver() {}
+
+void FormElementObserver::EnsureObserver() {
+ if (!callback_)
+ callback_ = new ObserverCallback(*this);
+}
+
+void FormElementObserver::ClearObserver() {
+ if (callback_) {
+ callback_->Dispose();
+ callback_ = nullptr;
+ }
+}
+
+void FormElementObserver::Observe(
+ HTMLFormElement& element,
+ std::unique_ptr<WebFormElementObserverCallback> callback) {
+ ObserveInternal(element, std::move(callback));
+}
+
+void FormElementObserver::Observe(
+ HTMLInputElement& element,
+ std::unique_ptr<WebFormElementObserverCallback> callback) {
+ ObserveInternal(element, std::move(callback));
+}
+
+void FormElementObserver::ObserveInternal(
+ HTMLElement& element,
+ std::unique_ptr<WebFormElementObserverCallback> callback) {
+ DCHECK(element.parentElement());
+ CHECK(callbacks_.Set(&element, std::move(callback)).is_new_entry);
+ EnsureObserver();
+ callback_->Register(element);
+}
+
+void FormElementObserver::NotifyMutation(HTMLElement& element) {
+ if (!callbacks_.Contains(&element))
+ return;
+ auto it = callbacks_.find(&element);
+ if (!it->value->ShouldStopObserving())
jochen (gone - plz use gerrit) 2017/05/10 11:45:41 To avoid duplicating the logic to check whether we
+ return;
+ callbacks_.erase(it);
+ if (callbacks_.IsEmpty())
+ ClearObserver();
+}
+
+DEFINE_TRACE(FormElementObserver) {
+ visitor->Trace(document_);
+ visitor->Trace(callback_);
+ visitor->Trace(mutation_observer_);
+ visitor->Trace(callbacks_);
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698