| Index: third_party/WebKit/Source/web/WebFormElementObserverImpl.cpp
|
| diff --git a/third_party/WebKit/Source/web/WebFormElementObserverImpl.cpp b/third_party/WebKit/Source/web/WebFormElementObserverImpl.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..37a12705388c3be713d289dd2dfb8843fc98ad24
|
| --- /dev/null
|
| +++ b/third_party/WebKit/Source/web/WebFormElementObserverImpl.cpp
|
| @@ -0,0 +1,150 @@
|
| +// 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 "web/WebFormElementObserverImpl.h"
|
| +
|
| +#include "core/css/CSSComputedStyleDeclaration.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/WebFormElement.h"
|
| +#include "public/web/WebInputElement.h"
|
| +#include "public/web/modules/password_manager/WebFormElementObserverCallback.h"
|
| +
|
| +namespace blink {
|
| +
|
| +class WebFormElementObserverImpl::ObserverCallback : public MutationCallback {
|
| + public:
|
| + ObserverCallback(HTMLElement&,
|
| + std::unique_ptr<WebFormElementObserverCallback>);
|
| + DECLARE_VIRTUAL_TRACE();
|
| +
|
| + ExecutionContext* GetExecutionContext() const override;
|
| +
|
| + void Disconnect();
|
| +
|
| + private:
|
| + void Call(const HeapVector<Member<MutationRecord>>& records,
|
| + MutationObserver*) override;
|
| +
|
| + Member<HTMLElement> element_;
|
| + Member<MutationObserver> mutation_observer_;
|
| + std::unique_ptr<WebFormElementObserverCallback> callback_;
|
| +};
|
| +
|
| +WebFormElementObserverImpl::ObserverCallback::ObserverCallback(
|
| + HTMLElement& element,
|
| + std::unique_ptr<WebFormElementObserverCallback> callback)
|
| + : element_(&element), callback_(std::move(callback)) {
|
| + DCHECK(element.ownerDocument());
|
| + mutation_observer_ = MutationObserver::Create(this);
|
| +
|
| + {
|
| + 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);
|
| + }
|
| +}
|
| +
|
| +ExecutionContext*
|
| +WebFormElementObserverImpl::ObserverCallback::GetExecutionContext() const {
|
| + return element_->ownerDocument();
|
| +}
|
| +
|
| +void WebFormElementObserverImpl::ObserverCallback::Disconnect() {
|
| + mutation_observer_->disconnect();
|
| + callback_.reset();
|
| +}
|
| +
|
| +void WebFormElementObserverImpl::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) != element_)
|
| + continue;
|
| + callback_->ElementWasHiddenOrRemoved();
|
| + Disconnect();
|
| + return;
|
| + }
|
| + } else {
|
| + HTMLElement& element = *ToHTMLElement(record->target());
|
| + if (record->attributeName() == "action") {
|
| + // If the action was modified, we just assume that the form as
|
| + // submitted.
|
| + callback_->ElementWasHiddenOrRemoved();
|
| + Disconnect();
|
| + return;
|
| + }
|
| + // Otherwise, either "style" or "class" was modified. Check the
|
| + // computed style.
|
| + CSSComputedStyleDeclaration* style =
|
| + CSSComputedStyleDeclaration::Create(&element);
|
| + if (style->GetPropertyValue(CSSPropertyDisplay) == "none") {
|
| + callback_->ElementWasHiddenOrRemoved();
|
| + Disconnect();
|
| + return;
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +DEFINE_TRACE(WebFormElementObserverImpl::ObserverCallback) {
|
| + visitor->Trace(element_);
|
| + visitor->Trace(mutation_observer_);
|
| + MutationCallback::Trace(visitor);
|
| +}
|
| +
|
| +WebFormElementObserver* WebFormElementObserver::Create(
|
| + WebFormElement& element,
|
| + std::unique_ptr<WebFormElementObserverCallback> callback) {
|
| + return new WebFormElementObserverImpl(*element.Unwrap<HTMLFormElement>(),
|
| + std::move(callback));
|
| +}
|
| +
|
| +WebFormElementObserver* WebFormElementObserver::Create(
|
| + WebInputElement& element,
|
| + std::unique_ptr<WebFormElementObserverCallback> callback) {
|
| + return new WebFormElementObserverImpl(*element.Unwrap<HTMLInputElement>(),
|
| + std::move(callback));
|
| +}
|
| +
|
| +WebFormElementObserverImpl::WebFormElementObserverImpl(
|
| + HTMLElement& element,
|
| + std::unique_ptr<WebFormElementObserverCallback> callback)
|
| + : self_keep_alive_(this) {
|
| + mutation_callback_ = new ObserverCallback(element, std::move(callback));
|
| +}
|
| +
|
| +WebFormElementObserverImpl::~WebFormElementObserverImpl() {}
|
| +
|
| +void WebFormElementObserverImpl::Disconnect() {
|
| + mutation_callback_->Disconnect();
|
| + mutation_callback_ = nullptr;
|
| + self_keep_alive_.Clear();
|
| +}
|
| +
|
| +DEFINE_TRACE(WebFormElementObserverImpl) {
|
| + visitor->Trace(mutation_callback_);
|
| +}
|
| +
|
| +} // namespace blink
|
|
|