Commit 5c6d9ab4 authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

Move HTMLSelectElement::PopupUpdater to SelectType

This CL also moves:
 - ObserveTreeMutation()
 - UnobserveTreeMutation()
 - DidMutateSubtree()
 - popup_updater_

This CL has no behavior changes.

Bug: 1052232
Change-Id: I381d18022b5b08e04214a9d2e163e1a33b929f52
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2087491Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Commit-Queue: Kent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/master@{#747081}
parent b5018edf
...@@ -35,14 +35,11 @@ ...@@ -35,14 +35,11 @@
#include "third_party/blink/public/strings/grit/blink_strings.h" #include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/bindings/core/v8/html_element_or_long.h" #include "third_party/blink/renderer/bindings/core/v8/html_element_or_long.h"
#include "third_party/blink/renderer/bindings/core/v8/html_option_element_or_html_opt_group_element.h" #include "third_party/blink/renderer/bindings/core/v8/html_option_element_or_html_opt_group_element.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_mutation_observer_init.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h" #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h" #include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/dom/attribute.h" #include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h" #include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
#include "third_party/blink/renderer/core/dom/mutation_observer.h"
#include "third_party/blink/renderer/core/dom/mutation_record.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/node_lists_node_data.h" #include "third_party/blink/renderer/core/dom/node_lists_node_data.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h" #include "third_party/blink/renderer/core/dom/node_traversal.h"
...@@ -1420,7 +1417,6 @@ void HTMLSelectElement::Trace(Visitor* visitor) { ...@@ -1420,7 +1417,6 @@ void HTMLSelectElement::Trace(Visitor* visitor) {
visitor->Trace(suggested_option_); visitor->Trace(suggested_option_);
visitor->Trace(select_type_); visitor->Trace(select_type_);
visitor->Trace(popup_); visitor->Trace(popup_);
visitor->Trace(popup_updater_);
HTMLFormControlElementWithState::Trace(visitor); HTMLFormControlElementWithState::Trace(visitor);
} }
...@@ -1617,79 +1613,6 @@ void HTMLSelectElement::ResetTypeAheadSessionForTesting() { ...@@ -1617,79 +1613,6 @@ void HTMLSelectElement::ResetTypeAheadSessionForTesting() {
type_ahead_.ResetSession(); type_ahead_.ResetSession();
} }
// PopupUpdater notifies updates of the specified SELECT element subtree to
// a PopupMenu object.
class HTMLSelectElement::PopupUpdater : public MutationObserver::Delegate {
public:
explicit PopupUpdater(HTMLSelectElement& select)
: select_(select), observer_(MutationObserver::Create(this)) {
MutationObserverInit* init = MutationObserverInit::Create();
init->setAttributeOldValue(true);
init->setAttributes(true);
// Observe only attributes which affect popup content.
init->setAttributeFilter({"disabled", "label", "selected", "value"});
init->setCharacterData(true);
init->setCharacterDataOldValue(true);
init->setChildList(true);
init->setSubtree(true);
observer_->observe(select_, init, ASSERT_NO_EXCEPTION);
}
ExecutionContext* GetExecutionContext() const override {
return select_->GetDocument().ToExecutionContext();
}
void Deliver(const MutationRecordVector& records,
MutationObserver&) override {
// We disconnect the MutationObserver when a popup is closed. However
// MutationObserver can call back after disconnection.
if (!select_->PopupIsVisible())
return;
for (const auto& record : records) {
if (record->type() == "attributes") {
const auto& element = *To<Element>(record->target());
if (record->oldValue() == element.getAttribute(record->attributeName()))
continue;
} else if (record->type() == "characterData") {
if (record->oldValue() == record->target()->nodeValue())
continue;
}
select_->DidMutateSubtree();
return;
}
}
void Dispose() { observer_->disconnect(); }
void Trace(Visitor* visitor) override {
visitor->Trace(select_);
visitor->Trace(observer_);
MutationObserver::Delegate::Trace(visitor);
}
private:
Member<HTMLSelectElement> select_;
Member<MutationObserver> observer_;
};
void HTMLSelectElement::ObserveTreeMutation() {
DCHECK(!popup_updater_);
popup_updater_ = MakeGarbageCollected<PopupUpdater>(*this);
}
void HTMLSelectElement::UnobserveTreeMutation() {
if (!popup_updater_)
return;
popup_updater_->Dispose();
popup_updater_ = nullptr;
}
void HTMLSelectElement::DidMutateSubtree() {
DCHECK(PopupIsVisible());
DCHECK(popup_);
popup_->UpdateFromElement(PopupMenu::kByDOMChange);
}
void HTMLSelectElement::CloneNonAttributePropertiesFrom( void HTMLSelectElement::CloneNonAttributePropertiesFrom(
const Element& source, const Element& source,
CloneChildrenFlag flag) { CloneChildrenFlag flag) {
......
...@@ -172,7 +172,6 @@ class CORE_EXPORT HTMLSelectElement final ...@@ -172,7 +172,6 @@ class CORE_EXPORT HTMLSelectElement final
void ShowPopup(); void ShowPopup();
void HidePopup(); void HidePopup();
PopupMenu* Popup() const { return popup_.Get(); } PopupMenu* Popup() const { return popup_.Get(); }
void DidMutateSubtree();
void ResetTypeAheadSessionForTesting(); void ResetTypeAheadSessionForTesting();
...@@ -283,9 +282,6 @@ class CORE_EXPORT HTMLSelectElement final ...@@ -283,9 +282,6 @@ class CORE_EXPORT HTMLSelectElement final
int OptionCount() const override; int OptionCount() const override;
String OptionAtIndex(int index) const override; String OptionAtIndex(int index) const override;
void ObserveTreeMutation();
void UnobserveTreeMutation();
void UpdateUsesMenuList(); void UpdateUsesMenuList();
// Apply changes to rendering as a result of attribute changes (multiple, // Apply changes to rendering as a result of attribute changes (multiple,
// size). // size).
...@@ -311,8 +307,6 @@ class CORE_EXPORT HTMLSelectElement final ...@@ -311,8 +307,6 @@ class CORE_EXPORT HTMLSelectElement final
bool is_autofilled_by_preview_; bool is_autofilled_by_preview_;
Member<SelectType> select_type_; Member<SelectType> select_type_;
class PopupUpdater;
Member<PopupUpdater> popup_updater_;
Member<PopupMenu> popup_; Member<PopupMenu> popup_;
int index_to_select_on_cancel_; int index_to_select_on_cancel_;
bool popup_is_visible_; bool popup_is_visible_;
......
...@@ -31,7 +31,10 @@ ...@@ -31,7 +31,10 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "third_party/blink/public/strings/grit/blink_strings.h" #include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_mutation_observer_init.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h" #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/mutation_observer.h"
#include "third_party/blink/renderer/core/dom/mutation_record.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/events/gesture_event.h" #include "third_party/blink/renderer/core/events/gesture_event.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h" #include "third_party/blink/renderer/core/events/keyboard_event.h"
...@@ -53,6 +56,8 @@ ...@@ -53,6 +56,8 @@
namespace blink { namespace blink {
class PopupUpdater;
namespace { namespace {
HTMLOptionElement* EventTargetOption(const Event& event) { HTMLOptionElement* EventTargetOption(const Event& event) {
...@@ -64,6 +69,7 @@ HTMLOptionElement* EventTargetOption(const Event& event) { ...@@ -64,6 +69,7 @@ HTMLOptionElement* EventTargetOption(const Event& event) {
class MenuListSelectType final : public SelectType { class MenuListSelectType final : public SelectType {
public: public:
explicit MenuListSelectType(HTMLSelectElement& select) : SelectType(select) {} explicit MenuListSelectType(HTMLSelectElement& select) : SelectType(select) {}
void Trace(Visitor* visitor) override;
bool DefaultEventHandler(const Event& event) override; bool DefaultEventHandler(const Event& event) override;
void DidSelectOption(HTMLOptionElement* element, void DidSelectOption(HTMLOptionElement* element,
...@@ -84,6 +90,8 @@ class MenuListSelectType final : public SelectType { ...@@ -84,6 +90,8 @@ class MenuListSelectType final : public SelectType {
void HidePopup() override; void HidePopup() override;
void PopupDidHide() override; void PopupDidHide() override;
void DidMutateSubtree();
private: private:
bool ShouldOpenPopupForKeyDownEvent(const KeyboardEvent& event); bool ShouldOpenPopupForKeyDownEvent(const KeyboardEvent& event);
bool ShouldOpenPopupForKeyPressEvent(const KeyboardEvent& event); bool ShouldOpenPopupForKeyPressEvent(const KeyboardEvent& event);
...@@ -92,12 +100,20 @@ class MenuListSelectType final : public SelectType { ...@@ -92,12 +100,20 @@ class MenuListSelectType final : public SelectType {
void DispatchEventsIfSelectedOptionChanged(); void DispatchEventsIfSelectedOptionChanged();
String UpdateTextStyleInternal(); String UpdateTextStyleInternal();
void DidUpdateActiveOption(HTMLOptionElement* option); void DidUpdateActiveOption(HTMLOptionElement* option);
void ObserveTreeMutation();
void UnobserveTreeMutation();
Member<PopupUpdater> popup_updater_;
scoped_refptr<const ComputedStyle> option_style_; scoped_refptr<const ComputedStyle> option_style_;
int ax_menulist_last_active_index_ = -1; int ax_menulist_last_active_index_ = -1;
bool has_updated_menulist_active_option_ = false; bool has_updated_menulist_active_option_ = false;
}; };
void MenuListSelectType::Trace(Visitor* visitor) {
visitor->Trace(popup_updater_);
SelectType::Trace(visitor);
}
bool MenuListSelectType::DefaultEventHandler(const Event& event) { bool MenuListSelectType::DefaultEventHandler(const Event& event) {
// We need to make the layout tree up-to-date to have GetLayoutObject() give // We need to make the layout tree up-to-date to have GetLayoutObject() give
// the correct result below. An author event handler may have set display to // the correct result below. An author event handler may have set display to
...@@ -282,7 +298,7 @@ void MenuListSelectType::ShowPopup() { ...@@ -282,7 +298,7 @@ void MenuListSelectType::ShowPopup() {
return; return;
select_->SetPopupIsVisible(true); select_->SetPopupIsVisible(true);
select_->ObserveTreeMutation(); ObserveTreeMutation();
select_->popup_->Show(); select_->popup_->Show();
if (AXObjectCache* cache = document.ExistingAXObjectCache()) if (AXObjectCache* cache = document.ExistingAXObjectCache())
...@@ -296,7 +312,7 @@ void MenuListSelectType::HidePopup() { ...@@ -296,7 +312,7 @@ void MenuListSelectType::HidePopup() {
void MenuListSelectType::PopupDidHide() { void MenuListSelectType::PopupDidHide() {
select_->SetPopupIsVisible(false); select_->SetPopupIsVisible(false);
select_->UnobserveTreeMutation(); UnobserveTreeMutation();
if (AXObjectCache* cache = select_->GetDocument().ExistingAXObjectCache()) { if (AXObjectCache* cache = select_->GetDocument().ExistingAXObjectCache()) {
if (auto* layout_object = select_->GetLayoutObject()) if (auto* layout_object = select_->GetLayoutObject())
cache->DidHideMenuListPopup(layout_object); cache->DidHideMenuListPopup(layout_object);
...@@ -364,7 +380,7 @@ void MenuListSelectType::DidDetachLayoutTree() { ...@@ -364,7 +380,7 @@ void MenuListSelectType::DidDetachLayoutTree() {
select_->popup_->DisconnectClient(); select_->popup_->DisconnectClient();
select_->SetPopupIsVisible(false); select_->SetPopupIsVisible(false);
select_->popup_ = nullptr; select_->popup_ = nullptr;
select_->UnobserveTreeMutation(); UnobserveTreeMutation();
} }
void MenuListSelectType::DidRecalcStyle(const StyleRecalcChange change) { void MenuListSelectType::DidRecalcStyle(const StyleRecalcChange change) {
...@@ -460,6 +476,84 @@ void MenuListSelectType::DidUpdateActiveOption(HTMLOptionElement* option) { ...@@ -460,6 +476,84 @@ void MenuListSelectType::DidUpdateActiveOption(HTMLOptionElement* option) {
select_->GetLayoutObject(), option_index); select_->GetLayoutObject(), option_index);
} }
// PopupUpdater notifies updates of the specified SELECT element subtree to
// a PopupMenu object.
class PopupUpdater : public MutationObserver::Delegate {
public:
explicit PopupUpdater(MenuListSelectType& select_type,
HTMLSelectElement& select)
: select_type_(select_type),
select_(select),
observer_(MutationObserver::Create(this)) {
MutationObserverInit* init = MutationObserverInit::Create();
init->setAttributeOldValue(true);
init->setAttributes(true);
// Observe only attributes which affect popup content.
init->setAttributeFilter({"disabled", "label", "selected", "value"});
init->setCharacterData(true);
init->setCharacterDataOldValue(true);
init->setChildList(true);
init->setSubtree(true);
observer_->observe(select_, init, ASSERT_NO_EXCEPTION);
}
ExecutionContext* GetExecutionContext() const override {
return select_->GetDocument().ToExecutionContext();
}
void Deliver(const MutationRecordVector& records,
MutationObserver&) override {
// We disconnect the MutationObserver when a popup is closed. However
// MutationObserver can call back after disconnection.
if (!select_->PopupIsVisible())
return;
for (const auto& record : records) {
if (record->type() == "attributes") {
const auto& element = *To<Element>(record->target());
if (record->oldValue() == element.getAttribute(record->attributeName()))
continue;
} else if (record->type() == "characterData") {
if (record->oldValue() == record->target()->nodeValue())
continue;
}
select_type_->DidMutateSubtree();
return;
}
}
void Dispose() { observer_->disconnect(); }
void Trace(Visitor* visitor) override {
visitor->Trace(select_type_);
visitor->Trace(select_);
visitor->Trace(observer_);
MutationObserver::Delegate::Trace(visitor);
}
private:
Member<MenuListSelectType> select_type_;
Member<HTMLSelectElement> select_;
Member<MutationObserver> observer_;
};
void MenuListSelectType::ObserveTreeMutation() {
DCHECK(!popup_updater_);
popup_updater_ = MakeGarbageCollected<PopupUpdater>(*this, *select_);
}
void MenuListSelectType::UnobserveTreeMutation() {
if (!popup_updater_)
return;
popup_updater_->Dispose();
popup_updater_ = nullptr;
}
void MenuListSelectType::DidMutateSubtree() {
DCHECK(select_->PopupIsVisible());
DCHECK(select_->popup_);
select_->popup_->UpdateFromElement(PopupMenu::kByDOMChange);
}
// ============================================================================ // ============================================================================
class ListBoxSelectType final : public SelectType { class ListBoxSelectType final : public SelectType {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment