// Copyright (c) 2014 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/PopupMenuImpl.h" #include "core/HTMLNames.h" #include "core/css/CSSFontSelector.h" #include "core/dom/ElementTraversal.h" #include "core/dom/ExecutionContextTask.h" #include "core/dom/NodeComputedStyle.h" #include "core/dom/StyleEngine.h" #include "core/events/ScopedEventQueue.h" #include "core/frame/FrameView.h" #include "core/html/HTMLHRElement.h" #include "core/html/HTMLOptGroupElement.h" #include "core/html/HTMLOptionElement.h" #include "core/html/HTMLSelectElement.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/layout/LayoutTheme.h" #include "core/page/PagePopup.h" #include "platform/geometry/IntRect.h" #include "platform/text/PlatformLocale.h" #include "public/platform/Platform.h" #include "public/web/WebColorChooser.h" #include "web/ChromeClientImpl.h" #include "web/WebViewImpl.h" namespace blink { namespace { const char* fontWeightToString(FontWeight weight) { switch (weight) { case FontWeight100: return "100"; case FontWeight200: return "200"; case FontWeight300: return "300"; case FontWeight400: return "400"; case FontWeight500: return "500"; case FontWeight600: return "600"; case FontWeight700: return "700"; case FontWeight800: return "800"; case FontWeight900: return "900"; } ASSERT_NOT_REACHED(); return nullptr; } const char* fontVariantToString(FontVariant variant) { switch (variant) { case FontVariantNormal: return "normal"; case FontVariantSmallCaps: return "small-caps"; } ASSERT_NOT_REACHED(); return nullptr; } // TODO crbug.com/516675 Add stretch to serialization const char* fontStyleToString(FontStyle style) { switch (style) { case FontStyleNormal: return "normal"; case FontStyleOblique: return "oblique"; case FontStyleItalic: return "italic"; } ASSERT_NOT_REACHED(); return nullptr; } const char* textTransformToString(ETextTransform transform) { switch (transform) { case CAPITALIZE: return "capitalize"; case UPPERCASE: return "uppercase"; case LOWERCASE: return "lowercase"; case TTNONE: return "none"; } ASSERT_NOT_REACHED(); return ""; } } // anonymous namespace class PopupMenuCSSFontSelector : public CSSFontSelector, private CSSFontSelectorClient { USING_GARBAGE_COLLECTED_MIXIN(PopupMenuCSSFontSelector); public: static PopupMenuCSSFontSelector* create(Document* document, CSSFontSelector* ownerFontSelector) { return new PopupMenuCSSFontSelector(document, ownerFontSelector); } ~PopupMenuCSSFontSelector(); // We don't override willUseFontData() for now because the old PopupListBox // only worked with fonts loaded when opening the popup. PassRefPtr getFontData(const FontDescription&, const AtomicString&) override; DECLARE_VIRTUAL_TRACE(); private: PopupMenuCSSFontSelector(Document*, CSSFontSelector*); void fontsNeedUpdate(CSSFontSelector*) override; Member m_ownerFontSelector; }; PopupMenuCSSFontSelector::PopupMenuCSSFontSelector(Document* document, CSSFontSelector* ownerFontSelector) : CSSFontSelector(document) , m_ownerFontSelector(ownerFontSelector) { m_ownerFontSelector->registerForInvalidationCallbacks(this); } PopupMenuCSSFontSelector::~PopupMenuCSSFontSelector() { #if !ENABLE(OILPAN) m_ownerFontSelector->unregisterForInvalidationCallbacks(this); #endif } PassRefPtr PopupMenuCSSFontSelector::getFontData(const FontDescription& description, const AtomicString& name) { return m_ownerFontSelector->getFontData(description, name); } void PopupMenuCSSFontSelector::fontsNeedUpdate(CSSFontSelector* fontSelector) { dispatchInvalidationCallbacks(); } DEFINE_TRACE(PopupMenuCSSFontSelector) { visitor->trace(m_ownerFontSelector); CSSFontSelector::trace(visitor); CSSFontSelectorClient::trace(visitor); } // ---------------------------------------------------------------- class PopupMenuImpl::ItemIterationContext { STACK_ALLOCATED(); public: ItemIterationContext(const ComputedStyle& style, SharedBuffer* buffer) : m_baseStyle(style) , m_backgroundColor(style.visitedDependentColor(CSSPropertyBackgroundColor)) , m_listIndex(0) , m_isInGroup(false) , m_buffer(buffer) { DCHECK(m_buffer); #if OS(LINUX) // On other platforms, the