OLD | NEW |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "web/PopupMenuImpl.h" | 6 #include "web/PopupMenuImpl.h" |
7 | 7 |
8 #include "core/HTMLNames.h" | 8 #include "core/HTMLNames.h" |
9 #include "core/css/CSSFontSelector.h" | 9 #include "core/css/CSSFontSelector.h" |
10 #include "core/dom/ElementTraversal.h" | 10 #include "core/dom/ElementTraversal.h" |
11 #include "core/dom/ExecutionContextTask.h" | 11 #include "core/dom/ExecutionContextTask.h" |
12 #include "core/dom/NodeComputedStyle.h" | 12 #include "core/dom/NodeComputedStyle.h" |
13 #include "core/dom/StyleEngine.h" | 13 #include "core/dom/StyleEngine.h" |
14 #include "core/frame/FrameView.h" | 14 #include "core/frame/FrameView.h" |
15 #include "core/html/HTMLHRElement.h" | 15 #include "core/html/HTMLHRElement.h" |
16 #include "core/html/HTMLOptGroupElement.h" | 16 #include "core/html/HTMLOptGroupElement.h" |
17 #include "core/html/HTMLOptionElement.h" | 17 #include "core/html/HTMLOptionElement.h" |
18 #include "core/html/parser/HTMLParserIdioms.h" | 18 #include "core/html/parser/HTMLParserIdioms.h" |
19 #include "core/layout/LayoutTheme.h" | 19 #include "core/layout/LayoutTheme.h" |
20 #include "core/page/PagePopup.h" | 20 #include "core/page/PagePopup.h" |
21 #include "platform/geometry/IntRect.h" | 21 #include "platform/geometry/IntRect.h" |
22 #include "platform/text/PlatformLocale.h" | 22 #include "platform/text/PlatformLocale.h" |
23 #include "public/platform/Platform.h" | 23 #include "public/platform/Platform.h" |
24 #include "public/web/WebColorChooser.h" | 24 #include "public/web/WebColorChooser.h" |
25 #include "web/ChromeClientImpl.h" | 25 #include "web/ChromeClientImpl.h" |
26 #include "web/WebViewImpl.h" | 26 #include "web/WebViewImpl.h" |
27 | 27 |
28 namespace blink { | 28 namespace blink { |
29 | 29 |
| 30 // We don't make child style information if the popup will have a lot of items |
| 31 // because of a performance problem. |
| 32 // TODO(tkent): This is a workaround. We should do a performance optimization. |
| 33 static const unsigned styledChildrenLimit = 100; |
| 34 |
30 class PopupMenuCSSFontSelector : public CSSFontSelector { | 35 class PopupMenuCSSFontSelector : public CSSFontSelector { |
31 public: | 36 public: |
32 static PassRefPtrWillBeRawPtr<PopupMenuCSSFontSelector> create(Document* doc
ument, CSSFontSelector* ownerFontSelector) | 37 static PassRefPtrWillBeRawPtr<PopupMenuCSSFontSelector> create(Document* doc
ument, CSSFontSelector* ownerFontSelector) |
33 { | 38 { |
34 return adoptRefWillBeNoop(new PopupMenuCSSFontSelector(document, ownerFo
ntSelector)); | 39 return adoptRefWillBeNoop(new PopupMenuCSSFontSelector(document, ownerFo
ntSelector)); |
35 } | 40 } |
36 | 41 |
37 // We don't override willUseFontData() for now because the old PopupListBox | 42 // We don't override willUseFontData() for now because the old PopupListBox |
38 // only worked with fonts loaded when opening the popup. | 43 // only worked with fonts loaded when opening the popup. |
39 virtual PassRefPtr<FontData> getFontData(const FontDescription&, const Atomi
cString&) override; | 44 virtual PassRefPtr<FontData> getFontData(const FontDescription&, const Atomi
cString&) override; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 { | 92 { |
88 IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(m_client->elem
entRectRelativeToViewport()); | 93 IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(m_client->elem
entRectRelativeToViewport()); |
89 | 94 |
90 PagePopupClient::addString("<!DOCTYPE html><head><meta charset='UTF-8'><styl
e>\n", data); | 95 PagePopupClient::addString("<!DOCTYPE html><head><meta charset='UTF-8'><styl
e>\n", data); |
91 data->append(Platform::current()->loadResource("pickerCommon.css")); | 96 data->append(Platform::current()->loadResource("pickerCommon.css")); |
92 data->append(Platform::current()->loadResource("listPicker.css")); | 97 data->append(Platform::current()->loadResource("listPicker.css")); |
93 PagePopupClient::addString("</style></head><body><div id=main>Loading...</di
v><script>\n" | 98 PagePopupClient::addString("</style></head><body><div id=main>Loading...</di
v><script>\n" |
94 "window.dialogArguments = {\n", data); | 99 "window.dialogArguments = {\n", data); |
95 addProperty("selectedIndex", m_client->selectedIndex(), data); | 100 addProperty("selectedIndex", m_client->selectedIndex(), data); |
96 PagePopupClient::addString("children: [\n", data); | 101 PagePopupClient::addString("children: [\n", data); |
| 102 bool enableExtraStyling = ownerElement().countChildren() < styledChildrenLim
it; |
97 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())
) { | 103 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())
) { |
98 if (isHTMLOptionElement(child)) | 104 if (isHTMLOptionElement(child)) |
99 addOption(toHTMLOptionElement(child), data); | 105 addOption(toHTMLOptionElement(child), enableExtraStyling, data); |
100 if (isHTMLOptGroupElement(child)) | 106 if (isHTMLOptGroupElement(child)) |
101 addOptGroup(toHTMLOptGroupElement(child), data); | 107 addOptGroup(toHTMLOptGroupElement(child), enableExtraStyling, data); |
102 if (isHTMLHRElement(child)) | 108 if (isHTMLHRElement(child)) |
103 addSeparator(toHTMLHRElement(child), data); | 109 addSeparator(toHTMLHRElement(child), enableExtraStyling, data); |
104 } | 110 } |
105 PagePopupClient::addString("],\n", data); | 111 PagePopupClient::addString("],\n", data); |
106 addProperty("anchorRectInScreen", anchorRectInScreen, data); | 112 addProperty("anchorRectInScreen", anchorRectInScreen, data); |
107 const ComputedStyle* ownerStyle = ownerElement().computedStyle(); | 113 const ComputedStyle* ownerStyle = ownerElement().computedStyle(); |
108 Color backgroundColor = ownerStyle->visitedDependentColor(CSSPropertyBackgro
undColor); | 114 Color backgroundColor = ownerStyle->visitedDependentColor(CSSPropertyBackgro
undColor); |
109 #if OS(LINUX) | 115 #if OS(LINUX) |
110 // On other platforms, the <option> background color is the same as the | 116 // On other platforms, the <option> background color is the same as the |
111 // <select> background color. On Linux, that makes the <option> | 117 // <select> background color. On Linux, that makes the <option> |
112 // background color very dark, so by default, try to use a lighter | 118 // background color very dark, so by default, try to use a lighter |
113 // background color for <option>s. | 119 // background color for <option>s. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 return "normal"; | 179 return "normal"; |
174 case FontStyleItalic: | 180 case FontStyleItalic: |
175 return "italic"; | 181 return "italic"; |
176 default: | 182 default: |
177 ASSERT_NOT_REACHED(); | 183 ASSERT_NOT_REACHED(); |
178 break; | 184 break; |
179 } | 185 } |
180 return 0; | 186 return 0; |
181 } | 187 } |
182 | 188 |
183 void PopupMenuImpl::addElementStyle(HTMLElement& element, SharedBuffer* data) | 189 void PopupMenuImpl::addElementStyle(HTMLElement& element, bool enableExtraStylin
g, SharedBuffer* data) |
184 { | 190 { |
185 const ComputedStyle* style = m_client->computedStyleForItem(element); | 191 const ComputedStyle* style = m_client->computedStyleForItem(element); |
186 ASSERT(style); | 192 ASSERT(style); |
187 PagePopupClient::addString("style: {\n", data); | 193 PagePopupClient::addString("style: {\n", data); |
188 addProperty("color", style->visitedDependentColor(CSSPropertyColor).serializ
ed(), data); | 194 addProperty("visibility", String(style->visibility() == HIDDEN ? "hidden" :
""), data); |
189 addProperty("backgroundColor", style->visitedDependentColor(CSSPropertyBackg
roundColor).serialized(), data); | 195 addProperty("display", String(style->display() == NONE ? "none" : ""), data)
; |
190 const FontDescription& fontDescription = style->font().fontDescription(); | |
191 addProperty("fontSize", fontDescription.computedPixelSize(), data); | |
192 addProperty("fontWeight", String(fontWeightToString(fontDescription.weight()
)), data); | |
193 PagePopupClient::addString("fontFamily: [\n", data); | |
194 for (const FontFamily* f = &fontDescription.family(); f; f = f->next()) { | |
195 addJavaScriptString(f->family().string(), data); | |
196 if (f->next()) | |
197 PagePopupClient::addString(",\n", data); | |
198 } | |
199 PagePopupClient::addString("],\n", data); | |
200 addProperty("fontStyle", String(fontStyleToString(fontDescription.style())),
data); | |
201 addProperty("fontVariant", String(fontVariantToString(fontDescription.varian
t())), data); | |
202 addProperty("visibility", String(style->visibility() == HIDDEN ? "hidden" :
"visible"), data); | |
203 addProperty("display", String(style->display() == NONE ? "none" : "block"),
data); | |
204 addProperty("direction", String(style->direction() == RTL ? "rtl" : "ltr"),
data); | 196 addProperty("direction", String(style->direction() == RTL ? "rtl" : "ltr"),
data); |
205 addProperty("unicodeBidi", String(isOverride(style->unicodeBidi()) ? "bidi-o
verride" : "normal"), data); | 197 addProperty("unicodeBidi", String(isOverride(style->unicodeBidi()) ? "bidi-o
verride" : "normal"), data); |
| 198 if (enableExtraStyling) { |
| 199 addProperty("color", style->visitedDependentColor(CSSPropertyColor).seri
alized(), data); |
| 200 addProperty("backgroundColor", style->visitedDependentColor(CSSPropertyB
ackgroundColor).serialized(), data); |
| 201 const FontDescription& fontDescription = style->font().fontDescription()
; |
| 202 addProperty("fontSize", fontDescription.computedPixelSize(), data); |
| 203 addProperty("fontWeight", String(fontWeightToString(fontDescription.weig
ht())), data); |
| 204 PagePopupClient::addString("fontFamily: [\n", data); |
| 205 for (const FontFamily* f = &fontDescription.family(); f; f = f->next())
{ |
| 206 addJavaScriptString(f->family().string(), data); |
| 207 if (f->next()) |
| 208 PagePopupClient::addString(",\n", data); |
| 209 } |
| 210 PagePopupClient::addString("],\n", data); |
| 211 addProperty("fontStyle", String(fontStyleToString(fontDescription.style(
))), data); |
| 212 addProperty("fontVariant", String(fontVariantToString(fontDescription.va
riant())), data); |
| 213 } |
206 PagePopupClient::addString("},\n", data); | 214 PagePopupClient::addString("},\n", data); |
207 } | 215 } |
208 | 216 |
209 void PopupMenuImpl::addOption(HTMLOptionElement& element, SharedBuffer* data) | 217 void PopupMenuImpl::addOption(HTMLOptionElement& element, bool enableExtraStylin
g, SharedBuffer* data) |
210 { | 218 { |
211 PagePopupClient::addString("{\n", data); | 219 PagePopupClient::addString("{\n", data); |
212 PagePopupClient::addString("type: \"option\",\n", data); | 220 PagePopupClient::addString("type: \"option\",\n", data); |
213 addProperty("label", element.text(), data); | 221 addProperty("label", element.text(), data); |
214 addProperty("title", element.title(), data); | 222 addProperty("title", element.title(), data); |
215 addProperty("value", element.listIndex(), data); | 223 addProperty("value", element.listIndex(), data); |
216 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); | 224 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); |
217 addProperty("disabled", element.isDisabledFormControl(), data); | 225 addProperty("disabled", element.isDisabledFormControl(), data); |
218 addElementStyle(element, data); | 226 addElementStyle(element, enableExtraStyling, data); |
219 PagePopupClient::addString("},\n", data); | 227 PagePopupClient::addString("},\n", data); |
220 } | 228 } |
221 | 229 |
222 void PopupMenuImpl::addOptGroup(HTMLOptGroupElement& element, SharedBuffer* data
) | 230 void PopupMenuImpl::addOptGroup(HTMLOptGroupElement& element, bool enableExtraSt
yling, SharedBuffer* data) |
223 { | 231 { |
224 PagePopupClient::addString("{\n", data); | 232 PagePopupClient::addString("{\n", data); |
225 PagePopupClient::addString("type: \"optgroup\",\n", data); | 233 PagePopupClient::addString("type: \"optgroup\",\n", data); |
226 addProperty("label", element.groupLabelText(), data); | 234 addProperty("label", element.groupLabelText(), data); |
227 addProperty("title", element.title(), data); | 235 addProperty("title", element.title(), data); |
228 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); | 236 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); |
229 addProperty("disabled", element.isDisabledFormControl(), data); | 237 addProperty("disabled", element.isDisabledFormControl(), data); |
230 addElementStyle(element, data); | 238 addElementStyle(element, enableExtraStyling, data); |
231 PagePopupClient::addString("children: [", data); | 239 PagePopupClient::addString("children: [", data); |
232 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(element)) { | 240 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(element)) { |
233 if (isHTMLOptionElement(child)) | 241 if (isHTMLOptionElement(child)) |
234 addOption(toHTMLOptionElement(child), data); | 242 addOption(toHTMLOptionElement(child), enableExtraStyling, data); |
235 if (isHTMLOptGroupElement(child)) | 243 if (isHTMLOptGroupElement(child)) |
236 addOptGroup(toHTMLOptGroupElement(child), data); | 244 addOptGroup(toHTMLOptGroupElement(child), enableExtraStyling, data); |
237 if (isHTMLHRElement(child)) | 245 if (isHTMLHRElement(child)) |
238 addSeparator(toHTMLHRElement(child), data); | 246 addSeparator(toHTMLHRElement(child), enableExtraStyling, data); |
239 } | 247 } |
240 PagePopupClient::addString("],\n", data); | 248 PagePopupClient::addString("],\n", data); |
241 PagePopupClient::addString("},\n", data); | 249 PagePopupClient::addString("},\n", data); |
242 } | 250 } |
243 | 251 |
244 void PopupMenuImpl::addSeparator(HTMLHRElement& element, SharedBuffer* data) | 252 void PopupMenuImpl::addSeparator(HTMLHRElement& element, bool enableExtraStyling
, SharedBuffer* data) |
245 { | 253 { |
246 PagePopupClient::addString("{\n", data); | 254 PagePopupClient::addString("{\n", data); |
247 PagePopupClient::addString("type: \"separator\",\n", data); | 255 PagePopupClient::addString("type: \"separator\",\n", data); |
248 addProperty("title", element.title(), data); | 256 addProperty("title", element.title(), data); |
249 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); | 257 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); |
250 addProperty("disabled", element.isDisabledFormControl(), data); | 258 addProperty("disabled", element.isDisabledFormControl(), data); |
251 addElementStyle(element, data); | 259 addElementStyle(element, enableExtraStyling, data); |
252 PagePopupClient::addString("},\n", data); | 260 PagePopupClient::addString("},\n", data); |
253 } | 261 } |
254 | 262 |
255 void PopupMenuImpl::selectFontsFromOwnerDocument(Document& document) | 263 void PopupMenuImpl::selectFontsFromOwnerDocument(Document& document) |
256 { | 264 { |
257 Document& ownerDocument = ownerElement().document(); | 265 Document& ownerDocument = ownerElement().document(); |
258 document.styleEngine().setFontSelector(PopupMenuCSSFontSelector::create(&doc
ument, ownerDocument.styleEngine().fontSelector())); | 266 document.styleEngine().setFontSelector(PopupMenuCSSFontSelector::create(&doc
ument, ownerDocument.styleEngine().fontSelector())); |
259 } | 267 } |
260 | 268 |
261 void PopupMenuImpl::setValueAndClosePopup(int numValue, const String& stringValu
e) | 269 void PopupMenuImpl::setValueAndClosePopup(int numValue, const String& stringValu
e) |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 if (!m_popup || !m_client) | 355 if (!m_popup || !m_client) |
348 return; | 356 return; |
349 ownerElement().document().updateLayoutTreeIfNeeded(); | 357 ownerElement().document().updateLayoutTreeIfNeeded(); |
350 if (!m_client) | 358 if (!m_client) |
351 return; | 359 return; |
352 m_needsUpdate = false; | 360 m_needsUpdate = false; |
353 RefPtr<SharedBuffer> data = SharedBuffer::create(); | 361 RefPtr<SharedBuffer> data = SharedBuffer::create(); |
354 PagePopupClient::addString("window.updateData = {\n", data.get()); | 362 PagePopupClient::addString("window.updateData = {\n", data.get()); |
355 PagePopupClient::addString("type: \"update\",\n", data.get()); | 363 PagePopupClient::addString("type: \"update\",\n", data.get()); |
356 PagePopupClient::addString("children: [", data.get()); | 364 PagePopupClient::addString("children: [", data.get()); |
| 365 bool enableExtraStyling = ownerElement().countChildren() < styledChildrenLim
it; |
357 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())
) { | 366 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())
) { |
358 if (isHTMLOptionElement(child)) | 367 if (isHTMLOptionElement(child)) |
359 addOption(toHTMLOptionElement(child), data.get()); | 368 addOption(toHTMLOptionElement(child), enableExtraStyling, data.get()
); |
360 if (isHTMLOptGroupElement(child)) | 369 if (isHTMLOptGroupElement(child)) |
361 addOptGroup(toHTMLOptGroupElement(child), data.get()); | 370 addOptGroup(toHTMLOptGroupElement(child), enableExtraStyling, data.g
et()); |
362 if (isHTMLHRElement(child)) | 371 if (isHTMLHRElement(child)) |
363 addSeparator(toHTMLHRElement(child), data.get()); | 372 addSeparator(toHTMLHRElement(child), enableExtraStyling, data.get())
; |
364 } | 373 } |
365 PagePopupClient::addString("],\n", data.get()); | 374 PagePopupClient::addString("],\n", data.get()); |
366 PagePopupClient::addString("}\n", data.get()); | 375 PagePopupClient::addString("}\n", data.get()); |
367 m_popup->postMessage(String::fromUTF8(data->data(), data->size())); | 376 m_popup->postMessage(String::fromUTF8(data->data(), data->size())); |
368 } | 377 } |
369 | 378 |
370 | 379 |
371 void PopupMenuImpl::disconnectClient() | 380 void PopupMenuImpl::disconnectClient() |
372 { | 381 { |
373 m_client = nullptr; | 382 m_client = nullptr; |
374 // Cannot be done during finalization, so instead done when the | 383 // Cannot be done during finalization, so instead done when the |
375 // layout object is destroyed and disconnected. | 384 // layout object is destroyed and disconnected. |
376 dispose(); | 385 dispose(); |
377 } | 386 } |
378 | 387 |
379 } // namespace blink | 388 } // namespace blink |
OLD | NEW |