| 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" |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 dispatchInvalidationCallbacks(); | 76 dispatchInvalidationCallbacks(); |
| 77 } | 77 } |
| 78 | 78 |
| 79 DEFINE_TRACE(PopupMenuCSSFontSelector) | 79 DEFINE_TRACE(PopupMenuCSSFontSelector) |
| 80 { | 80 { |
| 81 visitor->trace(m_ownerFontSelector); | 81 visitor->trace(m_ownerFontSelector); |
| 82 CSSFontSelector::trace(visitor); | 82 CSSFontSelector::trace(visitor); |
| 83 CSSFontSelectorClient::trace(visitor); | 83 CSSFontSelectorClient::trace(visitor); |
| 84 } | 84 } |
| 85 | 85 |
| 86 class PopupMenuImpl::ItemIterationContext { |
| 87 STACK_ALLOCATED(); |
| 88 public: |
| 89 ItemIterationContext(bool enableExtraStyling, TextDirection dir) |
| 90 : m_enableExtraStyling(enableExtraStyling) |
| 91 , m_direction(dir) |
| 92 { |
| 93 } |
| 94 |
| 95 bool m_enableExtraStyling; |
| 96 TextDirection m_direction; |
| 97 }; |
| 98 |
| 86 PassRefPtrWillBeRawPtr<PopupMenuImpl> PopupMenuImpl::create(ChromeClientImpl* ch
romeClient, PopupMenuClient* client) | 99 PassRefPtrWillBeRawPtr<PopupMenuImpl> PopupMenuImpl::create(ChromeClientImpl* ch
romeClient, PopupMenuClient* client) |
| 87 { | 100 { |
| 88 return adoptRefWillBeNoop(new PopupMenuImpl(chromeClient, client)); | 101 return adoptRefWillBeNoop(new PopupMenuImpl(chromeClient, client)); |
| 89 } | 102 } |
| 90 | 103 |
| 91 PopupMenuImpl::PopupMenuImpl(ChromeClientImpl* chromeClient, PopupMenuClient* cl
ient) | 104 PopupMenuImpl::PopupMenuImpl(ChromeClientImpl* chromeClient, PopupMenuClient* cl
ient) |
| 92 : m_chromeClient(chromeClient) | 105 : m_chromeClient(chromeClient) |
| 93 , m_client(client) | 106 , m_client(client) |
| 94 , m_popup(nullptr) | 107 , m_popup(nullptr) |
| 95 , m_needsUpdate(false) | 108 , m_needsUpdate(false) |
| (...skipping 26 matching lines...) Expand all Loading... |
| 122 void PopupMenuImpl::writeDocument(SharedBuffer* data) | 135 void PopupMenuImpl::writeDocument(SharedBuffer* data) |
| 123 { | 136 { |
| 124 IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(m_client->elem
entRectRelativeToViewport()); | 137 IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(m_client->elem
entRectRelativeToViewport()); |
| 125 | 138 |
| 126 PagePopupClient::addString("<!DOCTYPE html><head><meta charset='UTF-8'><styl
e>\n", data); | 139 PagePopupClient::addString("<!DOCTYPE html><head><meta charset='UTF-8'><styl
e>\n", data); |
| 127 data->append(Platform::current()->loadResource("pickerCommon.css")); | 140 data->append(Platform::current()->loadResource("pickerCommon.css")); |
| 128 data->append(Platform::current()->loadResource("listPicker.css")); | 141 data->append(Platform::current()->loadResource("listPicker.css")); |
| 129 PagePopupClient::addString("</style></head><body><div id=main>Loading...</di
v><script>\n" | 142 PagePopupClient::addString("</style></head><body><div id=main>Loading...</di
v><script>\n" |
| 130 "window.dialogArguments = {\n", data); | 143 "window.dialogArguments = {\n", data); |
| 131 addProperty("selectedIndex", m_client->selectedIndex(), data); | 144 addProperty("selectedIndex", m_client->selectedIndex(), data); |
| 145 const ComputedStyle* ownerStyle = ownerElement().computedStyle(); |
| 132 PagePopupClient::addString("children: [\n", data); | 146 PagePopupClient::addString("children: [\n", data); |
| 133 bool enableExtraStyling = !hasTooManyItemsForStyling(); | 147 ItemIterationContext context(!hasTooManyItemsForStyling(), ownerStyle->direc
tion()); |
| 134 int listIndex = 0; | 148 int listIndex = 0; |
| 135 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())
) { | 149 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())
) { |
| 136 if (isHTMLOptionElement(child)) | 150 if (isHTMLOptionElement(child)) |
| 137 addOption(toHTMLOptionElement(child), listIndex, enableExtraStyling,
data); | 151 addOption(context, toHTMLOptionElement(child), listIndex, data); |
| 138 if (isHTMLOptGroupElement(child)) | 152 if (isHTMLOptGroupElement(child)) |
| 139 addOptGroup(toHTMLOptGroupElement(child), listIndex, enableExtraStyl
ing, data); | 153 addOptGroup(context, toHTMLOptGroupElement(child), listIndex, data); |
| 140 if (isHTMLHRElement(child)) | 154 if (isHTMLHRElement(child)) |
| 141 addSeparator(toHTMLHRElement(child), listIndex, enableExtraStyling,
data); | 155 addSeparator(context, toHTMLHRElement(child), listIndex, data); |
| 142 } | 156 } |
| 143 PagePopupClient::addString("],\n", data); | 157 PagePopupClient::addString("],\n", data); |
| 144 addProperty("anchorRectInScreen", anchorRectInScreen, data); | 158 addProperty("anchorRectInScreen", anchorRectInScreen, data); |
| 145 const ComputedStyle* ownerStyle = ownerElement().computedStyle(); | |
| 146 Color backgroundColor = ownerStyle->visitedDependentColor(CSSPropertyBackgro
undColor); | 159 Color backgroundColor = ownerStyle->visitedDependentColor(CSSPropertyBackgro
undColor); |
| 147 #if OS(LINUX) | 160 #if OS(LINUX) |
| 148 // On other platforms, the <option> background color is the same as the | 161 // On other platforms, the <option> background color is the same as the |
| 149 // <select> background color. On Linux, that makes the <option> | 162 // <select> background color. On Linux, that makes the <option> |
| 150 // background color very dark, so by default, try to use a lighter | 163 // background color very dark, so by default, try to use a lighter |
| 151 // background color for <option>s. | 164 // background color for <option>s. |
| 152 if (LayoutTheme::theme().systemColor(CSSValueButtonface) == backgroundColor) | 165 if (LayoutTheme::theme().systemColor(CSSValueButtonface) == backgroundColor) |
| 153 backgroundColor = LayoutTheme::theme().systemColor(CSSValueMenu); | 166 backgroundColor = LayoutTheme::theme().systemColor(CSSValueMenu); |
| 154 #endif | 167 #endif |
| 155 addProperty("backgroundColor", backgroundColor.serialized(), data); | 168 addProperty("backgroundColor", backgroundColor.serialized(), data); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 return "uppercase"; | 240 return "uppercase"; |
| 228 case LOWERCASE: | 241 case LOWERCASE: |
| 229 return "lowercase"; | 242 return "lowercase"; |
| 230 case TTNONE: | 243 case TTNONE: |
| 231 return "none"; | 244 return "none"; |
| 232 } | 245 } |
| 233 ASSERT_NOT_REACHED(); | 246 ASSERT_NOT_REACHED(); |
| 234 return ""; | 247 return ""; |
| 235 } | 248 } |
| 236 | 249 |
| 237 void PopupMenuImpl::addElementStyle(HTMLElement& element, bool enableExtraStylin
g, SharedBuffer* data) | 250 void PopupMenuImpl::addElementStyle(ItemIterationContext& context, HTMLElement&
element, SharedBuffer* data) |
| 238 { | 251 { |
| 239 const ComputedStyle* style = m_client->computedStyleForItem(element); | 252 const ComputedStyle* style = m_client->computedStyleForItem(element); |
| 240 ASSERT(style); | 253 ASSERT(style); |
| 241 PagePopupClient::addString("style: {\n", data); | 254 PagePopupClient::addString("style: {\n", data); |
| 242 addProperty("visibility", String(style->visibility() == HIDDEN ? "hidden" :
""), data); | 255 if (style->visibility() == HIDDEN) |
| 243 addProperty("display", String(style->display() == NONE ? "none" : ""), data)
; | 256 addProperty("visibility", String("hidden"), data); |
| 244 addProperty("direction", String(style->direction() == RTL ? "rtl" : "ltr"),
data); | 257 if (style->display() == NONE) |
| 245 addProperty("unicodeBidi", String(isOverride(style->unicodeBidi()) ? "bidi-o
verride" : "normal"), data); | 258 addProperty("display", String("none"), data); |
| 246 if (enableExtraStyling) { | 259 if (context.m_direction != style->direction()) |
| 260 addProperty("direction", String(style->direction() == RTL ? "rtl" : "ltr
"), data); |
| 261 if (isOverride(style->unicodeBidi())) |
| 262 addProperty("unicodeBidi", String("bidi-override"), data); |
| 263 if (context.m_enableExtraStyling) { |
| 247 addProperty("color", style->visitedDependentColor(CSSPropertyColor).seri
alized(), data); | 264 addProperty("color", style->visitedDependentColor(CSSPropertyColor).seri
alized(), data); |
| 248 addProperty("backgroundColor", style->visitedDependentColor(CSSPropertyB
ackgroundColor).serialized(), data); | 265 addProperty("backgroundColor", style->visitedDependentColor(CSSPropertyB
ackgroundColor).serialized(), data); |
| 249 const FontDescription& fontDescription = style->font().fontDescription()
; | 266 const FontDescription& fontDescription = style->font().fontDescription()
; |
| 250 addProperty("fontSize", fontDescription.computedPixelSize(), data); | 267 addProperty("fontSize", fontDescription.computedPixelSize(), data); |
| 251 addProperty("fontWeight", String(fontWeightToString(fontDescription.weig
ht())), data); | 268 addProperty("fontWeight", String(fontWeightToString(fontDescription.weig
ht())), data); |
| 252 PagePopupClient::addString("fontFamily: [\n", data); | 269 PagePopupClient::addString("fontFamily: [\n", data); |
| 253 for (const FontFamily* f = &fontDescription.family(); f; f = f->next())
{ | 270 for (const FontFamily* f = &fontDescription.family(); f; f = f->next())
{ |
| 254 addJavaScriptString(f->family().string(), data); | 271 addJavaScriptString(f->family().string(), data); |
| 255 if (f->next()) | 272 if (f->next()) |
| 256 PagePopupClient::addString(",\n", data); | 273 PagePopupClient::addString(",\n", data); |
| 257 } | 274 } |
| 258 PagePopupClient::addString("],\n", data); | 275 PagePopupClient::addString("],\n", data); |
| 259 addProperty("fontStyle", String(fontStyleToString(fontDescription.style(
))), data); | 276 addProperty("fontStyle", String(fontStyleToString(fontDescription.style(
))), data); |
| 260 addProperty("fontVariant", String(fontVariantToString(fontDescription.va
riant())), data); | 277 addProperty("fontVariant", String(fontVariantToString(fontDescription.va
riant())), data); |
| 261 addProperty("textTransform", String(textTransformToString(style->textTra
nsform())), data); | 278 addProperty("textTransform", String(textTransformToString(style->textTra
nsform())), data); |
| 262 } | 279 } |
| 263 PagePopupClient::addString("},\n", data); | 280 PagePopupClient::addString("},\n", data); |
| 264 } | 281 } |
| 265 | 282 |
| 266 void PopupMenuImpl::addOption(HTMLOptionElement& element, int& listIndex, bool e
nableExtraStyling, SharedBuffer* data) | 283 void PopupMenuImpl::addOption(ItemIterationContext& context, HTMLOptionElement&
element, int& listIndex, SharedBuffer* data) |
| 267 { | 284 { |
| 268 PagePopupClient::addString("{\n", data); | 285 PagePopupClient::addString("{\n", data); |
| 269 PagePopupClient::addString("type: \"option\",\n", data); | 286 PagePopupClient::addString("type: \"option\",\n", data); |
| 270 addProperty("label", element.text(), data); | 287 addProperty("label", element.text(), data); |
| 271 addProperty("title", element.title(), data); | |
| 272 ASSERT(listIndex == element.listIndex()); | 288 ASSERT(listIndex == element.listIndex()); |
| 273 addProperty("value", listIndex++, data); | 289 addProperty("value", listIndex++, data); |
| 274 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); | 290 if (!element.title().isEmpty()) |
| 275 addProperty("disabled", element.isDisabledFormControl(), data); | 291 addProperty("title", element.title(), data); |
| 276 addElementStyle(element, enableExtraStyling, data); | 292 const AtomicString& ariaLabel = element.fastGetAttribute(HTMLNames::aria_lab
elAttr); |
| 293 if (!ariaLabel.isEmpty()) |
| 294 addProperty("ariaLabel", ariaLabel, data); |
| 295 if (element.isDisabledFormControl()) |
| 296 addProperty("disabled", true, data); |
| 297 addElementStyle(context, element, data); |
| 277 PagePopupClient::addString("},\n", data); | 298 PagePopupClient::addString("},\n", data); |
| 278 } | 299 } |
| 279 | 300 |
| 280 void PopupMenuImpl::addOptGroup(HTMLOptGroupElement& element, int& listIndex, bo
ol enableExtraStyling, SharedBuffer* data) | 301 void PopupMenuImpl::addOptGroup(ItemIterationContext& context, HTMLOptGroupEleme
nt& element, int& listIndex, SharedBuffer* data) |
| 281 { | 302 { |
| 282 ++listIndex; | 303 ++listIndex; |
| 283 PagePopupClient::addString("{\n", data); | 304 PagePopupClient::addString("{\n", data); |
| 284 PagePopupClient::addString("type: \"optgroup\",\n", data); | 305 PagePopupClient::addString("type: \"optgroup\",\n", data); |
| 285 addProperty("label", element.groupLabelText(), data); | 306 addProperty("label", element.groupLabelText(), data); |
| 286 addProperty("title", element.title(), data); | 307 addProperty("title", element.title(), data); |
| 287 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); | 308 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); |
| 288 addProperty("disabled", element.isDisabledFormControl(), data); | 309 addProperty("disabled", element.isDisabledFormControl(), data); |
| 289 addElementStyle(element, enableExtraStyling, data); | 310 addElementStyle(context, element, data); |
| 290 PagePopupClient::addString("children: [", data); | 311 PagePopupClient::addString("children: [", data); |
| 291 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(element)) { | 312 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(element)) { |
| 292 if (isHTMLOptionElement(child)) | 313 if (isHTMLOptionElement(child)) |
| 293 addOption(toHTMLOptionElement(child), listIndex, enableExtraStyling,
data); | 314 addOption(context, toHTMLOptionElement(child), listIndex, data); |
| 294 // TODO(tkent): Ignore nested OPTGROUP. crbug.com/502101. | 315 // TODO(tkent): Ignore nested OPTGROUP. crbug.com/502101. |
| 295 if (isHTMLOptGroupElement(child)) | 316 if (isHTMLOptGroupElement(child)) |
| 296 addOptGroup(toHTMLOptGroupElement(child), listIndex, enableExtraStyl
ing, data); | 317 addOptGroup(context, toHTMLOptGroupElement(child), listIndex, data); |
| 297 if (isHTMLHRElement(child)) | 318 if (isHTMLHRElement(child)) |
| 298 addSeparator(toHTMLHRElement(child), listIndex, enableExtraStyling,
data); | 319 addSeparator(context, toHTMLHRElement(child), listIndex, data); |
| 299 } | 320 } |
| 300 PagePopupClient::addString("],\n", data); | 321 PagePopupClient::addString("],\n", data); |
| 301 PagePopupClient::addString("},\n", data); | 322 PagePopupClient::addString("},\n", data); |
| 302 } | 323 } |
| 303 | 324 |
| 304 void PopupMenuImpl::addSeparator(HTMLHRElement& element, int& listIndex, bool en
ableExtraStyling, SharedBuffer* data) | 325 void PopupMenuImpl::addSeparator(ItemIterationContext& context, HTMLHRElement& e
lement, int& listIndex, SharedBuffer* data) |
| 305 { | 326 { |
| 306 ++listIndex; | 327 ++listIndex; |
| 307 PagePopupClient::addString("{\n", data); | 328 PagePopupClient::addString("{\n", data); |
| 308 PagePopupClient::addString("type: \"separator\",\n", data); | 329 PagePopupClient::addString("type: \"separator\",\n", data); |
| 309 addProperty("title", element.title(), data); | 330 addProperty("title", element.title(), data); |
| 310 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); | 331 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); |
| 311 addProperty("disabled", element.isDisabledFormControl(), data); | 332 addProperty("disabled", element.isDisabledFormControl(), data); |
| 312 addElementStyle(element, enableExtraStyling, data); | 333 addElementStyle(context, element, data); |
| 313 PagePopupClient::addString("},\n", data); | 334 PagePopupClient::addString("},\n", data); |
| 314 } | 335 } |
| 315 | 336 |
| 316 void PopupMenuImpl::selectFontsFromOwnerDocument(Document& document) | 337 void PopupMenuImpl::selectFontsFromOwnerDocument(Document& document) |
| 317 { | 338 { |
| 318 Document& ownerDocument = ownerElement().document(); | 339 Document& ownerDocument = ownerElement().document(); |
| 319 document.styleEngine().setFontSelector(PopupMenuCSSFontSelector::create(&doc
ument, ownerDocument.styleEngine().fontSelector())); | 340 document.styleEngine().setFontSelector(PopupMenuCSSFontSelector::create(&doc
ument, ownerDocument.styleEngine().fontSelector())); |
| 320 } | 341 } |
| 321 | 342 |
| 322 void PopupMenuImpl::setValueAndClosePopup(int numValue, const String& stringValu
e) | 343 void PopupMenuImpl::setValueAndClosePopup(int numValue, const String& stringValu
e) |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 if (!m_popup || !m_client) | 429 if (!m_popup || !m_client) |
| 409 return; | 430 return; |
| 410 ownerElement().document().updateLayoutTreeIfNeeded(); | 431 ownerElement().document().updateLayoutTreeIfNeeded(); |
| 411 if (!m_client) | 432 if (!m_client) |
| 412 return; | 433 return; |
| 413 m_needsUpdate = false; | 434 m_needsUpdate = false; |
| 414 RefPtr<SharedBuffer> data = SharedBuffer::create(); | 435 RefPtr<SharedBuffer> data = SharedBuffer::create(); |
| 415 PagePopupClient::addString("window.updateData = {\n", data.get()); | 436 PagePopupClient::addString("window.updateData = {\n", data.get()); |
| 416 PagePopupClient::addString("type: \"update\",\n", data.get()); | 437 PagePopupClient::addString("type: \"update\",\n", data.get()); |
| 417 PagePopupClient::addString("children: [", data.get()); | 438 PagePopupClient::addString("children: [", data.get()); |
| 418 bool enableExtraStyling = !hasTooManyItemsForStyling(); | 439 ItemIterationContext context(!hasTooManyItemsForStyling(), ownerElement().co
mputedStyle()->direction()); |
| 419 int listIndex = 0; | 440 int listIndex = 0; |
| 420 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())
) { | 441 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())
) { |
| 421 if (isHTMLOptionElement(child)) | 442 if (isHTMLOptionElement(child)) |
| 422 addOption(toHTMLOptionElement(child), listIndex, enableExtraStyling,
data.get()); | 443 addOption(context, toHTMLOptionElement(child), listIndex, data.get()
); |
| 423 if (isHTMLOptGroupElement(child)) | 444 if (isHTMLOptGroupElement(child)) |
| 424 addOptGroup(toHTMLOptGroupElement(child), listIndex, enableExtraStyl
ing, data.get()); | 445 addOptGroup(context, toHTMLOptGroupElement(child), listIndex, data.g
et()); |
| 425 if (isHTMLHRElement(child)) | 446 if (isHTMLHRElement(child)) |
| 426 addSeparator(toHTMLHRElement(child), listIndex, enableExtraStyling,
data.get()); | 447 addSeparator(context, toHTMLHRElement(child), listIndex, data.get())
; |
| 427 } | 448 } |
| 428 PagePopupClient::addString("],\n", data.get()); | 449 PagePopupClient::addString("],\n", data.get()); |
| 429 PagePopupClient::addString("}\n", data.get()); | 450 PagePopupClient::addString("}\n", data.get()); |
| 430 m_popup->postMessage(String::fromUTF8(data->data(), data->size())); | 451 m_popup->postMessage(String::fromUTF8(data->data(), data->size())); |
| 431 } | 452 } |
| 432 | 453 |
| 433 | 454 |
| 434 void PopupMenuImpl::disconnectClient() | 455 void PopupMenuImpl::disconnectClient() |
| 435 { | 456 { |
| 436 m_client = nullptr; | 457 m_client = nullptr; |
| 437 // Cannot be done during finalization, so instead done when the | 458 // Cannot be done during finalization, so instead done when the |
| 438 // layout object is destroyed and disconnected. | 459 // layout object is destroyed and disconnected. |
| 439 dispose(); | 460 dispose(); |
| 440 } | 461 } |
| 441 | 462 |
| 442 } // namespace blink | 463 } // namespace blink |
| OLD | NEW |