Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "core/dom/AccessibleNode.h" | 5 #include "core/dom/AccessibleNode.h" |
| 6 | 6 |
| 7 #include "core/dom/AXObjectCache.h" | 7 #include "core/dom/AXObjectCache.h" |
| 8 #include "core/dom/Element.h" | 8 #include "core/dom/Element.h" |
| 9 #include "core/dom/QualifiedName.h" | 9 #include "core/dom/QualifiedName.h" |
| 10 #include "core/frame/Settings.h" | 10 #include "core/frame/Settings.h" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 if (AccessibleNode* accessibleNode = element->existingAccessibleNode()) { | 28 if (AccessibleNode* accessibleNode = element->existingAccessibleNode()) { |
| 29 for (const auto& item : accessibleNode->m_stringProperties) { | 29 for (const auto& item : accessibleNode->m_stringProperties) { |
| 30 if (item.first == property) | 30 if (item.first == property) |
| 31 return item.second; | 31 return item.second; |
| 32 } | 32 } |
| 33 } | 33 } |
| 34 | 34 |
| 35 // Fall back on the equivalent ARIA attribute. | 35 // Fall back on the equivalent ARIA attribute. |
| 36 switch (property) { | 36 switch (property) { |
| 37 case AOMStringProperty::kAutocomplete: | 37 case AOMStringProperty::kAutocomplete: |
| 38 return element->getAttribute(aria_autocompleteAttr); | 38 return element->fastGetAttribute(aria_autocompleteAttr); |
| 39 case AOMStringProperty::kChecked: | 39 case AOMStringProperty::kChecked: |
| 40 return element->getAttribute(aria_checkedAttr); | 40 return element->fastGetAttribute(aria_checkedAttr); |
| 41 case AOMStringProperty::kCurrent: | 41 case AOMStringProperty::kCurrent: |
| 42 return element->getAttribute(aria_currentAttr); | 42 return element->fastGetAttribute(aria_currentAttr); |
| 43 case AOMStringProperty::kInvalid: | 43 case AOMStringProperty::kInvalid: |
| 44 return element->getAttribute(aria_invalidAttr); | 44 return element->fastGetAttribute(aria_invalidAttr); |
| 45 case AOMStringProperty::kKeyShortcuts: | 45 case AOMStringProperty::kKeyShortcuts: |
| 46 return element->getAttribute(aria_keyshortcutsAttr); | 46 return element->fastGetAttribute(aria_keyshortcutsAttr); |
| 47 case AOMStringProperty::kLabel: | 47 case AOMStringProperty::kLabel: |
| 48 return element->getAttribute(aria_labelAttr); | 48 return element->fastGetAttribute(aria_labelAttr); |
| 49 case AOMStringProperty::kLive: | 49 case AOMStringProperty::kLive: |
| 50 return element->getAttribute(aria_liveAttr); | 50 return element->fastGetAttribute(aria_liveAttr); |
| 51 case AOMStringProperty::kOrientation: | 51 case AOMStringProperty::kOrientation: |
| 52 return element->getAttribute(aria_orientationAttr); | 52 return element->fastGetAttribute(aria_orientationAttr); |
| 53 case AOMStringProperty::kPlaceholder: | 53 case AOMStringProperty::kPlaceholder: |
| 54 return element->getAttribute(aria_placeholderAttr); | 54 return element->fastGetAttribute(aria_placeholderAttr); |
| 55 case AOMStringProperty::kRelevant: | 55 case AOMStringProperty::kRelevant: |
| 56 return element->getAttribute(aria_relevantAttr); | 56 return element->fastGetAttribute(aria_relevantAttr); |
| 57 case AOMStringProperty::kRole: | 57 case AOMStringProperty::kRole: |
| 58 return element->getAttribute(roleAttr); | 58 return element->fastGetAttribute(roleAttr); |
| 59 case AOMStringProperty::kRoleDescription: | 59 case AOMStringProperty::kRoleDescription: |
| 60 return element->getAttribute(aria_roledescriptionAttr); | 60 return element->fastGetAttribute(aria_roledescriptionAttr); |
| 61 case AOMStringProperty::kSort: | 61 case AOMStringProperty::kSort: |
| 62 return element->getAttribute(aria_sortAttr); | 62 return element->fastGetAttribute(aria_sortAttr); |
| 63 case AOMStringProperty::kValueText: | 63 case AOMStringProperty::kValueText: |
| 64 return element->getAttribute(aria_valuetextAttr); | 64 return element->fastGetAttribute(aria_valuetextAttr); |
| 65 } | 65 } |
| 66 | 66 |
| 67 NOTREACHED(); | 67 NOTREACHED(); |
| 68 return nullAtom; | 68 return nullAtom; |
| 69 } | 69 } |
| 70 | 70 |
| 71 // static | |
| 72 bool AccessibleNode::getProperty(Element* element, | |
| 73 AOMBooleanProperty property, | |
| 74 bool& isNull) { | |
| 75 isNull = true; | |
| 76 if (!element) | |
| 77 return false; | |
| 78 | |
| 79 if (AccessibleNode* accessibleNode = element->existingAccessibleNode()) { | |
| 80 for (const auto& item : accessibleNode->m_booleanProperties) { | |
| 81 if (item.first == property) { | |
| 82 isNull = false; | |
| 83 return item.second; | |
| 84 } | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 // Fall back on the equivalent ARIA attribute. | |
| 89 AtomicString attrValue; | |
| 90 switch (property) { | |
| 91 case AOMBooleanProperty::kAtomic: | |
| 92 attrValue = element->fastGetAttribute(aria_atomicAttr); | |
| 93 break; | |
| 94 case AOMBooleanProperty::kBusy: | |
| 95 attrValue = element->fastGetAttribute(aria_busyAttr); | |
| 96 break; | |
| 97 case AOMBooleanProperty::kDisabled: | |
| 98 attrValue = element->fastGetAttribute(aria_disabledAttr); | |
| 99 break; | |
| 100 case AOMBooleanProperty::kExpanded: | |
| 101 attrValue = element->fastGetAttribute(aria_expandedAttr); | |
| 102 break; | |
| 103 case AOMBooleanProperty::kHidden: | |
| 104 attrValue = element->fastGetAttribute(aria_hiddenAttr); | |
| 105 break; | |
| 106 case AOMBooleanProperty::kModal: | |
| 107 attrValue = element->fastGetAttribute(aria_modalAttr); | |
| 108 break; | |
| 109 case AOMBooleanProperty::kMultiline: | |
| 110 attrValue = element->fastGetAttribute(aria_multilineAttr); | |
| 111 break; | |
| 112 case AOMBooleanProperty::kMultiselectable: | |
| 113 attrValue = element->fastGetAttribute(aria_multiselectableAttr); | |
| 114 break; | |
| 115 case AOMBooleanProperty::kReadOnly: | |
| 116 attrValue = element->fastGetAttribute(aria_readonlyAttr); | |
| 117 break; | |
| 118 case AOMBooleanProperty::kRequired: | |
| 119 attrValue = element->fastGetAttribute(aria_requiredAttr); | |
| 120 break; | |
| 121 case AOMBooleanProperty::kSelected: | |
| 122 attrValue = element->fastGetAttribute(aria_selectedAttr); | |
| 123 break; | |
| 124 } | |
| 125 | |
| 126 if (attrValue.isNull()) | |
|
esprehn
2017/04/07 00:11:24
equalIgnoringASCIICase handles nulls, so you can d
dmazzoni
2017/04/21 07:11:37
Done.
| |
| 127 return false; | |
| 128 | |
| 129 isNull = false; | |
| 130 return equalIgnoringASCIICase(attrValue, "true"); | |
| 131 } | |
| 132 | |
| 133 bool AccessibleNode::atomic(bool& isNull) const { | |
| 134 return getProperty(m_element, AOMBooleanProperty::kAtomic, isNull); | |
| 135 } | |
| 136 | |
| 137 void AccessibleNode::setAtomic(bool atomic) { | |
| 138 setBooleanProperty(AOMBooleanProperty::kAtomic, atomic); | |
| 139 notifyAttributeChanged(aria_atomicAttr); | |
| 140 } | |
| 141 | |
| 71 AtomicString AccessibleNode::autocomplete() const { | 142 AtomicString AccessibleNode::autocomplete() const { |
| 72 return getProperty(m_element, AOMStringProperty::kAutocomplete); | 143 return getProperty(m_element, AOMStringProperty::kAutocomplete); |
| 73 } | 144 } |
| 74 | 145 |
| 75 void AccessibleNode::setAutocomplete(const AtomicString& autocomplete) { | 146 void AccessibleNode::setAutocomplete(const AtomicString& autocomplete) { |
| 76 setStringProperty(AOMStringProperty::kAutocomplete, autocomplete); | 147 setStringProperty(AOMStringProperty::kAutocomplete, autocomplete); |
| 77 notifyAttributeChanged(aria_autocompleteAttr); | 148 notifyAttributeChanged(aria_autocompleteAttr); |
| 78 } | 149 } |
| 79 | 150 |
| 151 bool AccessibleNode::busy(bool& isNull) const { | |
| 152 return getProperty(m_element, AOMBooleanProperty::kBusy, isNull); | |
| 153 } | |
| 154 | |
| 155 void AccessibleNode::setBusy(bool busy) { | |
| 156 setBooleanProperty(AOMBooleanProperty::kBusy, busy); | |
| 157 notifyAttributeChanged(aria_busyAttr); | |
| 158 } | |
| 159 | |
| 80 AtomicString AccessibleNode::checked() const { | 160 AtomicString AccessibleNode::checked() const { |
| 81 return getProperty(m_element, AOMStringProperty::kChecked); | 161 return getProperty(m_element, AOMStringProperty::kChecked); |
| 82 } | 162 } |
| 83 | 163 |
| 84 void AccessibleNode::setChecked(const AtomicString& checked) { | 164 void AccessibleNode::setChecked(const AtomicString& checked) { |
| 85 setStringProperty(AOMStringProperty::kChecked, checked); | 165 setStringProperty(AOMStringProperty::kChecked, checked); |
| 86 notifyAttributeChanged(aria_checkedAttr); | 166 notifyAttributeChanged(aria_checkedAttr); |
| 87 } | 167 } |
| 88 | 168 |
| 89 AtomicString AccessibleNode::current() const { | 169 AtomicString AccessibleNode::current() const { |
| 90 return getProperty(m_element, AOMStringProperty::kCurrent); | 170 return getProperty(m_element, AOMStringProperty::kCurrent); |
| 91 } | 171 } |
| 92 | 172 |
| 93 void AccessibleNode::setCurrent(const AtomicString& current) { | 173 void AccessibleNode::setCurrent(const AtomicString& current) { |
| 94 setStringProperty(AOMStringProperty::kCurrent, current); | 174 setStringProperty(AOMStringProperty::kCurrent, current); |
| 95 | 175 |
| 96 if (AXObjectCache* cache = m_element->document().existingAXObjectCache()) | 176 if (AXObjectCache* cache = m_element->document().existingAXObjectCache()) |
| 97 cache->handleAttributeChanged(aria_currentAttr, m_element); | 177 cache->handleAttributeChanged(aria_currentAttr, m_element); |
| 98 } | 178 } |
| 99 | 179 |
| 180 bool AccessibleNode::disabled(bool& isNull) const { | |
| 181 return getProperty(m_element, AOMBooleanProperty::kDisabled, isNull); | |
| 182 } | |
| 183 | |
| 184 void AccessibleNode::setDisabled(bool disabled) { | |
| 185 setBooleanProperty(AOMBooleanProperty::kDisabled, disabled); | |
| 186 notifyAttributeChanged(aria_disabledAttr); | |
| 187 } | |
| 188 | |
| 189 bool AccessibleNode::expanded(bool& isNull) const { | |
| 190 return getProperty(m_element, AOMBooleanProperty::kExpanded, isNull); | |
| 191 } | |
| 192 | |
| 193 void AccessibleNode::setExpanded(bool expanded) { | |
| 194 setBooleanProperty(AOMBooleanProperty::kExpanded, expanded); | |
| 195 notifyAttributeChanged(aria_expandedAttr); | |
| 196 } | |
| 197 | |
| 198 bool AccessibleNode::hidden(bool& isNull) const { | |
| 199 return getProperty(m_element, AOMBooleanProperty::kHidden, isNull); | |
| 200 } | |
| 201 | |
| 202 void AccessibleNode::setHidden(bool hidden) { | |
| 203 setBooleanProperty(AOMBooleanProperty::kHidden, hidden); | |
| 204 notifyAttributeChanged(aria_hiddenAttr); | |
| 205 } | |
| 206 | |
| 100 AtomicString AccessibleNode::invalid() const { | 207 AtomicString AccessibleNode::invalid() const { |
| 101 return getProperty(m_element, AOMStringProperty::kInvalid); | 208 return getProperty(m_element, AOMStringProperty::kInvalid); |
| 102 } | 209 } |
| 103 | 210 |
| 104 void AccessibleNode::setInvalid(const AtomicString& invalid) { | 211 void AccessibleNode::setInvalid(const AtomicString& invalid) { |
| 105 setStringProperty(AOMStringProperty::kInvalid, invalid); | 212 setStringProperty(AOMStringProperty::kInvalid, invalid); |
| 106 notifyAttributeChanged(aria_invalidAttr); | 213 notifyAttributeChanged(aria_invalidAttr); |
| 107 } | 214 } |
| 108 | 215 |
| 109 AtomicString AccessibleNode::keyShortcuts() const { | 216 AtomicString AccessibleNode::keyShortcuts() const { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 126 | 233 |
| 127 AtomicString AccessibleNode::live() const { | 234 AtomicString AccessibleNode::live() const { |
| 128 return getProperty(m_element, AOMStringProperty::kLive); | 235 return getProperty(m_element, AOMStringProperty::kLive); |
| 129 } | 236 } |
| 130 | 237 |
| 131 void AccessibleNode::setLive(const AtomicString& live) { | 238 void AccessibleNode::setLive(const AtomicString& live) { |
| 132 setStringProperty(AOMStringProperty::kLive, live); | 239 setStringProperty(AOMStringProperty::kLive, live); |
| 133 notifyAttributeChanged(aria_liveAttr); | 240 notifyAttributeChanged(aria_liveAttr); |
| 134 } | 241 } |
| 135 | 242 |
| 243 bool AccessibleNode::modal(bool& isNull) const { | |
| 244 return getProperty(m_element, AOMBooleanProperty::kModal, isNull); | |
| 245 } | |
| 246 | |
| 247 void AccessibleNode::setModal(bool modal) { | |
| 248 setBooleanProperty(AOMBooleanProperty::kModal, modal); | |
| 249 notifyAttributeChanged(aria_modalAttr); | |
| 250 } | |
| 251 | |
| 252 bool AccessibleNode::multiline(bool& isNull) const { | |
| 253 return getProperty(m_element, AOMBooleanProperty::kMultiline, isNull); | |
| 254 } | |
| 255 | |
| 256 void AccessibleNode::setMultiline(bool multiline) { | |
| 257 setBooleanProperty(AOMBooleanProperty::kMultiline, multiline); | |
| 258 notifyAttributeChanged(aria_multilineAttr); | |
| 259 } | |
| 260 | |
| 261 bool AccessibleNode::multiselectable(bool& isNull) const { | |
| 262 return getProperty(m_element, AOMBooleanProperty::kMultiselectable, isNull); | |
| 263 } | |
| 264 | |
| 265 void AccessibleNode::setMultiselectable(bool multiselectable) { | |
| 266 setBooleanProperty(AOMBooleanProperty::kMultiselectable, multiselectable); | |
| 267 notifyAttributeChanged(aria_multiselectableAttr); | |
| 268 } | |
| 269 | |
| 136 AtomicString AccessibleNode::orientation() const { | 270 AtomicString AccessibleNode::orientation() const { |
| 137 return getProperty(m_element, AOMStringProperty::kOrientation); | 271 return getProperty(m_element, AOMStringProperty::kOrientation); |
| 138 } | 272 } |
| 139 | 273 |
| 140 void AccessibleNode::setOrientation(const AtomicString& orientation) { | 274 void AccessibleNode::setOrientation(const AtomicString& orientation) { |
| 141 setStringProperty(AOMStringProperty::kOrientation, orientation); | 275 setStringProperty(AOMStringProperty::kOrientation, orientation); |
| 142 notifyAttributeChanged(aria_orientationAttr); | 276 notifyAttributeChanged(aria_orientationAttr); |
| 143 } | 277 } |
| 144 | 278 |
| 145 AtomicString AccessibleNode::placeholder() const { | 279 AtomicString AccessibleNode::placeholder() const { |
| 146 return getProperty(m_element, AOMStringProperty::kPlaceholder); | 280 return getProperty(m_element, AOMStringProperty::kPlaceholder); |
| 147 } | 281 } |
| 148 | 282 |
| 149 void AccessibleNode::setPlaceholder(const AtomicString& placeholder) { | 283 void AccessibleNode::setPlaceholder(const AtomicString& placeholder) { |
| 150 setStringProperty(AOMStringProperty::kPlaceholder, placeholder); | 284 setStringProperty(AOMStringProperty::kPlaceholder, placeholder); |
| 151 notifyAttributeChanged(aria_placeholderAttr); | 285 notifyAttributeChanged(aria_placeholderAttr); |
| 152 } | 286 } |
| 153 | 287 |
| 288 bool AccessibleNode::readOnly(bool& isNull) const { | |
| 289 return getProperty(m_element, AOMBooleanProperty::kReadOnly, isNull); | |
| 290 } | |
| 291 | |
| 292 void AccessibleNode::setReadOnly(bool readOnly) { | |
| 293 setBooleanProperty(AOMBooleanProperty::kReadOnly, readOnly); | |
| 294 notifyAttributeChanged(aria_readonlyAttr); | |
| 295 } | |
| 296 | |
| 154 AtomicString AccessibleNode::relevant() const { | 297 AtomicString AccessibleNode::relevant() const { |
| 155 return getProperty(m_element, AOMStringProperty::kRelevant); | 298 return getProperty(m_element, AOMStringProperty::kRelevant); |
| 156 } | 299 } |
| 157 | 300 |
| 158 void AccessibleNode::setRelevant(const AtomicString& relevant) { | 301 void AccessibleNode::setRelevant(const AtomicString& relevant) { |
| 159 setStringProperty(AOMStringProperty::kRelevant, relevant); | 302 setStringProperty(AOMStringProperty::kRelevant, relevant); |
| 160 notifyAttributeChanged(aria_relevantAttr); | 303 notifyAttributeChanged(aria_relevantAttr); |
| 161 } | 304 } |
| 162 | 305 |
| 306 bool AccessibleNode::required(bool& isNull) const { | |
| 307 return getProperty(m_element, AOMBooleanProperty::kRequired, isNull); | |
| 308 } | |
| 309 | |
| 310 void AccessibleNode::setRequired(bool required) { | |
| 311 setBooleanProperty(AOMBooleanProperty::kRequired, required); | |
| 312 notifyAttributeChanged(aria_requiredAttr); | |
| 313 } | |
| 314 | |
| 163 AtomicString AccessibleNode::role() const { | 315 AtomicString AccessibleNode::role() const { |
| 164 return getProperty(m_element, AOMStringProperty::kRole); | 316 return getProperty(m_element, AOMStringProperty::kRole); |
| 165 } | 317 } |
| 166 | 318 |
| 167 void AccessibleNode::setRole(const AtomicString& role) { | 319 void AccessibleNode::setRole(const AtomicString& role) { |
| 168 setStringProperty(AOMStringProperty::kRole, role); | 320 setStringProperty(AOMStringProperty::kRole, role); |
| 169 notifyAttributeChanged(roleAttr); | 321 notifyAttributeChanged(roleAttr); |
| 170 } | 322 } |
| 171 | 323 |
| 172 AtomicString AccessibleNode::roleDescription() const { | 324 AtomicString AccessibleNode::roleDescription() const { |
| 173 return getProperty(m_element, AOMStringProperty::kRoleDescription); | 325 return getProperty(m_element, AOMStringProperty::kRoleDescription); |
| 174 } | 326 } |
| 175 | 327 |
| 176 void AccessibleNode::setRoleDescription(const AtomicString& roleDescription) { | 328 void AccessibleNode::setRoleDescription(const AtomicString& roleDescription) { |
| 177 setStringProperty(AOMStringProperty::kRoleDescription, roleDescription); | 329 setStringProperty(AOMStringProperty::kRoleDescription, roleDescription); |
| 178 notifyAttributeChanged(aria_roledescriptionAttr); | 330 notifyAttributeChanged(aria_roledescriptionAttr); |
| 179 } | 331 } |
| 180 | 332 |
| 333 bool AccessibleNode::selected(bool& isNull) const { | |
| 334 return getProperty(m_element, AOMBooleanProperty::kSelected, isNull); | |
| 335 } | |
| 336 | |
| 337 void AccessibleNode::setSelected(bool selected) { | |
| 338 setBooleanProperty(AOMBooleanProperty::kSelected, selected); | |
| 339 notifyAttributeChanged(aria_selectedAttr); | |
| 340 } | |
| 341 | |
| 181 AtomicString AccessibleNode::sort() const { | 342 AtomicString AccessibleNode::sort() const { |
| 182 return getProperty(m_element, AOMStringProperty::kSort); | 343 return getProperty(m_element, AOMStringProperty::kSort); |
| 183 } | 344 } |
| 184 | 345 |
| 185 void AccessibleNode::setSort(const AtomicString& sort) { | 346 void AccessibleNode::setSort(const AtomicString& sort) { |
| 186 setStringProperty(AOMStringProperty::kSort, sort); | 347 setStringProperty(AOMStringProperty::kSort, sort); |
| 187 notifyAttributeChanged(aria_sortAttr); | 348 notifyAttributeChanged(aria_sortAttr); |
| 188 } | 349 } |
| 189 | 350 |
| 190 AtomicString AccessibleNode::valueText() const { | 351 AtomicString AccessibleNode::valueText() const { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 201 for (auto& item : m_stringProperties) { | 362 for (auto& item : m_stringProperties) { |
| 202 if (item.first == property) { | 363 if (item.first == property) { |
| 203 item.second = value; | 364 item.second = value; |
| 204 return; | 365 return; |
| 205 } | 366 } |
| 206 } | 367 } |
| 207 | 368 |
| 208 m_stringProperties.push_back(std::make_pair(property, value)); | 369 m_stringProperties.push_back(std::make_pair(property, value)); |
| 209 } | 370 } |
| 210 | 371 |
| 372 void AccessibleNode::setBooleanProperty(AOMBooleanProperty property, | |
| 373 bool value) { | |
| 374 for (auto& item : m_booleanProperties) { | |
| 375 if (item.first == property) { | |
| 376 item.second = value; | |
| 377 return; | |
| 378 } | |
| 379 } | |
| 380 | |
| 381 m_booleanProperties.push_back(std::make_pair(property, value)); | |
| 382 } | |
| 383 | |
| 211 void AccessibleNode::notifyAttributeChanged( | 384 void AccessibleNode::notifyAttributeChanged( |
| 212 const blink::QualifiedName& attribute) { | 385 const blink::QualifiedName& attribute) { |
| 213 // TODO(dmazzoni): Make a cleaner API for this rather than pretending | 386 // TODO(dmazzoni): Make a cleaner API for this rather than pretending |
| 214 // the DOM attribute changed. | 387 // the DOM attribute changed. |
| 215 if (AXObjectCache* cache = getAXObjectCache()) | 388 if (AXObjectCache* cache = getAXObjectCache()) |
| 216 cache->handleAttributeChanged(attribute, m_element); | 389 cache->handleAttributeChanged(attribute, m_element); |
| 217 } | 390 } |
| 218 | 391 |
| 219 AXObjectCache* AccessibleNode::getAXObjectCache() { | 392 AXObjectCache* AccessibleNode::getAXObjectCache() { |
| 220 return m_element->document().existingAXObjectCache(); | 393 return m_element->document().existingAXObjectCache(); |
| 221 } | 394 } |
| 222 | 395 |
| 223 DEFINE_TRACE(AccessibleNode) { | 396 DEFINE_TRACE(AccessibleNode) { |
| 224 visitor->trace(m_element); | 397 visitor->trace(m_element); |
| 225 } | 398 } |
| 226 | 399 |
| 227 } // namespace blink | 400 } // namespace blink |
| OLD | NEW |