| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2014 Google Inc. All rights reserved. | 2 * Copyright (C) 2014 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "web/WebFrameWidgetImpl.h" | 31 #include "web/WebFrameWidgetImpl.h" |
| 32 | 32 |
| 33 #include "core/InputTypeNames.h" | |
| 34 #include "core/editing/EditingUtilities.h" | 33 #include "core/editing/EditingUtilities.h" |
| 35 #include "core/editing/Editor.h" | 34 #include "core/editing/Editor.h" |
| 36 #include "core/editing/FrameSelection.h" | 35 #include "core/editing/FrameSelection.h" |
| 37 #include "core/editing/InputMethodController.h" | 36 #include "core/editing/InputMethodController.h" |
| 38 #include "core/editing/PlainTextRange.h" | 37 #include "core/editing/PlainTextRange.h" |
| 39 #include "core/frame/FrameHost.h" | 38 #include "core/frame/FrameHost.h" |
| 40 #include "core/frame/FrameView.h" | 39 #include "core/frame/FrameView.h" |
| 41 #include "core/frame/RemoteFrame.h" | 40 #include "core/frame/RemoteFrame.h" |
| 42 #include "core/frame/Settings.h" | 41 #include "core/frame/Settings.h" |
| 43 #include "core/frame/VisualViewport.h" | 42 #include "core/frame/VisualViewport.h" |
| 44 #include "core/html/HTMLInputElement.h" | |
| 45 #include "core/html/HTMLTextAreaElement.h" | 43 #include "core/html/HTMLTextAreaElement.h" |
| 46 #include "core/input/EventHandler.h" | 44 #include "core/input/EventHandler.h" |
| 47 #include "core/layout/LayoutView.h" | 45 #include "core/layout/LayoutView.h" |
| 48 #include "core/layout/api/LayoutViewItem.h" | 46 #include "core/layout/api/LayoutViewItem.h" |
| 49 #include "core/layout/compositing/PaintLayerCompositor.h" | 47 #include "core/layout/compositing/PaintLayerCompositor.h" |
| 50 #include "core/page/ContextMenuController.h" | 48 #include "core/page/ContextMenuController.h" |
| 51 #include "core/page/FocusController.h" | 49 #include "core/page/FocusController.h" |
| 52 #include "core/page/Page.h" | 50 #include "core/page/Page.h" |
| 53 #include "core/page/PointerLockController.h" | 51 #include "core/page/PointerLockController.h" |
| 54 #include "platform/KeyboardCodes.h" | 52 #include "platform/KeyboardCodes.h" |
| (...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 focused->selection().rootEditableElementOrDocumentElement(); | 589 focused->selection().rootEditableElementOrDocumentElement(); |
| 592 DCHECK(editable); | 590 DCHECK(editable); |
| 593 | 591 |
| 594 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 592 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 595 // needs to be audited. See http://crbug.com/590369 for more details. | 593 // needs to be audited. See http://crbug.com/590369 for more details. |
| 596 editable->document().updateStyleAndLayoutIgnorePendingStylesheets(); | 594 editable->document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 597 | 595 |
| 598 return PlainTextRange::create(*editable, range); | 596 return PlainTextRange::create(*editable, range); |
| 599 } | 597 } |
| 600 | 598 |
| 601 // TODO(ekaramad):This method is almost duplicated in WebViewImpl as well. This | |
| 602 // code needs to be refactored (http://crbug.com/629721). | |
| 603 WebTextInputInfo WebFrameWidgetImpl::textInputInfo() { | 599 WebTextInputInfo WebFrameWidgetImpl::textInputInfo() { |
| 604 WebTextInputInfo info; | |
| 605 | |
| 606 LocalFrame* focused = focusedLocalFrameInWidget(); | 600 LocalFrame* focused = focusedLocalFrameInWidget(); |
| 607 if (!focused) | 601 if (!focused) |
| 608 return info; | 602 return WebTextInputInfo(); |
| 609 | 603 return focused->inputMethodController().textInputInfo(); |
| 610 FrameSelection& selection = focused->selection(); | |
| 611 if (!selection.isAvailable()) { | |
| 612 // plugins/mouse-capture-inside-shadow.html reaches here. | |
| 613 return info; | |
| 614 } | |
| 615 Element* element = selection.selection().rootEditableElement(); | |
| 616 if (!element) | |
| 617 return info; | |
| 618 | |
| 619 info.inputMode = inputModeOfFocusedElement(); | |
| 620 | |
| 621 info.type = textInputType(); | |
| 622 info.flags = textInputFlags(); | |
| 623 if (info.type == WebTextInputTypeNone) | |
| 624 return info; | |
| 625 | |
| 626 if (!focused->editor().canEdit()) | |
| 627 return info; | |
| 628 | |
| 629 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | |
| 630 // needs to be audited. see http://crbug.com/590369 for more details. | |
| 631 focused->document()->updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 632 | |
| 633 DocumentLifecycle::DisallowTransitionScope disallowTransition( | |
| 634 focused->document()->lifecycle()); | |
| 635 | |
| 636 // Emits an object replacement character for each replaced element so that | |
| 637 // it is exposed to IME and thus could be deleted by IME on android. | |
| 638 info.value = plainText(EphemeralRange::rangeOfContents(*element), | |
| 639 TextIteratorEmitsObjectReplacementCharacter); | |
| 640 | |
| 641 if (info.value.isEmpty()) | |
| 642 return info; | |
| 643 | |
| 644 EphemeralRange firstRange = firstEphemeralRangeOf(selection.selection()); | |
| 645 if (firstRange.isNotNull()) { | |
| 646 PlainTextRange plainTextRange(PlainTextRange::create(*element, firstRange)); | |
| 647 if (plainTextRange.isNotNull()) { | |
| 648 info.selectionStart = plainTextRange.start(); | |
| 649 info.selectionEnd = plainTextRange.end(); | |
| 650 } | |
| 651 } | |
| 652 | |
| 653 EphemeralRange range = | |
| 654 focused->inputMethodController().compositionEphemeralRange(); | |
| 655 if (range.isNotNull()) { | |
| 656 PlainTextRange plainTextRange(PlainTextRange::create(*element, range)); | |
| 657 if (plainTextRange.isNotNull()) { | |
| 658 info.compositionStart = plainTextRange.start(); | |
| 659 info.compositionEnd = plainTextRange.end(); | |
| 660 } | |
| 661 } | |
| 662 | |
| 663 return info; | |
| 664 } | 604 } |
| 665 | 605 |
| 666 // TODO(ekaramad):This method is almost duplicated in WebViewImpl as well. This | |
| 667 // code needs to be refactored (http://crbug.com/629721). | |
| 668 WebTextInputType WebFrameWidgetImpl::textInputType() { | 606 WebTextInputType WebFrameWidgetImpl::textInputType() { |
| 669 LocalFrame* focusedFrame = focusedLocalFrameInWidget(); | 607 LocalFrame* focused = focusedLocalFrameInWidget(); |
| 670 if (!focusedFrame) | 608 if (!focused) |
| 671 return WebTextInputTypeNone; | 609 return WebTextInputTypeNone; |
| 672 | 610 return focused->inputMethodController().textInputType(); |
| 673 if (!focusedFrame->selection().isAvailable()) { | |
| 674 // "mouse-capture-inside-shadow.html" reaches here. | |
| 675 return WebTextInputTypeNone; | |
| 676 } | |
| 677 | |
| 678 // It's important to preserve the equivalence of textInputInfo().type and | |
| 679 // textInputType(), so perform the same rootEditableElement() existence check | |
| 680 // here for consistency. | |
| 681 if (!focusedFrame->selection().selection().rootEditableElement()) | |
| 682 return WebTextInputTypeNone; | |
| 683 | |
| 684 Document* document = focusedFrame->document(); | |
| 685 if (!document) | |
| 686 return WebTextInputTypeNone; | |
| 687 | |
| 688 Element* element = document->focusedElement(); | |
| 689 if (!element) | |
| 690 return WebTextInputTypeNone; | |
| 691 | |
| 692 if (isHTMLInputElement(*element)) { | |
| 693 HTMLInputElement& input = toHTMLInputElement(*element); | |
| 694 const AtomicString& type = input.type(); | |
| 695 | |
| 696 if (input.isDisabledOrReadOnly()) | |
| 697 return WebTextInputTypeNone; | |
| 698 | |
| 699 if (type == InputTypeNames::password) | |
| 700 return WebTextInputTypePassword; | |
| 701 if (type == InputTypeNames::search) | |
| 702 return WebTextInputTypeSearch; | |
| 703 if (type == InputTypeNames::email) | |
| 704 return WebTextInputTypeEmail; | |
| 705 if (type == InputTypeNames::number) | |
| 706 return WebTextInputTypeNumber; | |
| 707 if (type == InputTypeNames::tel) | |
| 708 return WebTextInputTypeTelephone; | |
| 709 if (type == InputTypeNames::url) | |
| 710 return WebTextInputTypeURL; | |
| 711 if (type == InputTypeNames::text) | |
| 712 return WebTextInputTypeText; | |
| 713 | |
| 714 return WebTextInputTypeNone; | |
| 715 } | |
| 716 | |
| 717 if (isHTMLTextAreaElement(*element)) { | |
| 718 if (toHTMLTextAreaElement(*element).isDisabledOrReadOnly()) | |
| 719 return WebTextInputTypeNone; | |
| 720 return WebTextInputTypeTextArea; | |
| 721 } | |
| 722 | |
| 723 if (element->isHTMLElement()) { | |
| 724 if (toHTMLElement(element)->isDateTimeFieldElement()) | |
| 725 return WebTextInputTypeDateTimeField; | |
| 726 } | |
| 727 | |
| 728 document->updateStyleAndLayoutTree(); | |
| 729 if (hasEditableStyle(*element)) | |
| 730 return WebTextInputTypeContentEditable; | |
| 731 | |
| 732 return WebTextInputTypeNone; | |
| 733 } | 611 } |
| 734 | 612 |
| 735 WebColor WebFrameWidgetImpl::backgroundColor() const { | 613 WebColor WebFrameWidgetImpl::backgroundColor() const { |
| 736 if (isTransparent()) | 614 if (isTransparent()) |
| 737 return Color::transparent; | 615 return Color::transparent; |
| 738 if (!m_localRoot->frameView()) | 616 if (!m_localRoot->frameView()) |
| 739 return m_baseBackgroundColor; | 617 return m_baseBackgroundColor; |
| 740 FrameView* view = m_localRoot->frameView(); | 618 FrameView* view = m_localRoot->frameView(); |
| 741 return view->documentBackgroundColor().rgb(); | 619 return view->documentBackgroundColor().rgb(); |
| 742 } | 620 } |
| (...skipping 697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1440 | 1318 |
| 1441 WebPlugin* WebFrameWidgetImpl::focusedPluginIfInputMethodSupported( | 1319 WebPlugin* WebFrameWidgetImpl::focusedPluginIfInputMethodSupported( |
| 1442 LocalFrame* frame) const { | 1320 LocalFrame* frame) const { |
| 1443 WebPluginContainerImpl* container = | 1321 WebPluginContainerImpl* container = |
| 1444 WebLocalFrameImpl::currentPluginContainer(frame); | 1322 WebLocalFrameImpl::currentPluginContainer(frame); |
| 1445 if (container && container->supportsInputMethod()) | 1323 if (container && container->supportsInputMethod()) |
| 1446 return container->plugin(); | 1324 return container->plugin(); |
| 1447 return nullptr; | 1325 return nullptr; |
| 1448 } | 1326 } |
| 1449 | 1327 |
| 1450 WebString WebFrameWidgetImpl::inputModeOfFocusedElement() const { | |
| 1451 if (!RuntimeEnabledFeatures::inputModeAttributeEnabled()) | |
| 1452 return WebString(); | |
| 1453 | |
| 1454 Element* element = focusedElement(); | |
| 1455 if (!element) | |
| 1456 return WebString(); | |
| 1457 | |
| 1458 if (isHTMLInputElement(*element)) { | |
| 1459 const HTMLInputElement& input = toHTMLInputElement(*element); | |
| 1460 if (input.supportsInputModeAttribute()) | |
| 1461 return input.fastGetAttribute(HTMLNames::inputmodeAttr).lower(); | |
| 1462 return WebString(); | |
| 1463 } | |
| 1464 if (isHTMLTextAreaElement(*element)) { | |
| 1465 const HTMLTextAreaElement& textarea = toHTMLTextAreaElement(*element); | |
| 1466 return textarea.fastGetAttribute(HTMLNames::inputmodeAttr).lower(); | |
| 1467 } | |
| 1468 | |
| 1469 return WebString(); | |
| 1470 } | |
| 1471 | |
| 1472 int WebFrameWidgetImpl::textInputFlags() const { | |
| 1473 Element* element = focusedElement(); | |
| 1474 if (!element) | |
| 1475 return WebTextInputFlagNone; | |
| 1476 | |
| 1477 DEFINE_STATIC_LOCAL(AtomicString, autocompleteString, ("autocomplete")); | |
| 1478 DEFINE_STATIC_LOCAL(AtomicString, autocorrectString, ("autocorrect")); | |
| 1479 int flags = 0; | |
| 1480 | |
| 1481 const AtomicString& autocomplete = element->getAttribute(autocompleteString); | |
| 1482 if (autocomplete == "on") | |
| 1483 flags |= WebTextInputFlagAutocompleteOn; | |
| 1484 else if (autocomplete == "off") | |
| 1485 flags |= WebTextInputFlagAutocompleteOff; | |
| 1486 | |
| 1487 const AtomicString& autocorrect = element->getAttribute(autocorrectString); | |
| 1488 if (autocorrect == "on") | |
| 1489 flags |= WebTextInputFlagAutocorrectOn; | |
| 1490 else if (autocorrect == "off") | |
| 1491 flags |= WebTextInputFlagAutocorrectOff; | |
| 1492 | |
| 1493 SpellcheckAttributeState spellcheck = element->spellcheckAttributeState(); | |
| 1494 if (spellcheck == SpellcheckAttributeTrue) | |
| 1495 flags |= WebTextInputFlagSpellcheckOn; | |
| 1496 else if (spellcheck == SpellcheckAttributeFalse) | |
| 1497 flags |= WebTextInputFlagSpellcheckOff; | |
| 1498 | |
| 1499 if (isHTMLTextFormControlElement(element)) { | |
| 1500 HTMLTextFormControlElement* formElement = | |
| 1501 static_cast<HTMLTextFormControlElement*>(element); | |
| 1502 if (formElement->supportsAutocapitalize()) { | |
| 1503 DEFINE_STATIC_LOCAL(const AtomicString, none, ("none")); | |
| 1504 DEFINE_STATIC_LOCAL(const AtomicString, characters, ("characters")); | |
| 1505 DEFINE_STATIC_LOCAL(const AtomicString, words, ("words")); | |
| 1506 DEFINE_STATIC_LOCAL(const AtomicString, sentences, ("sentences")); | |
| 1507 | |
| 1508 const AtomicString& autocapitalize = formElement->autocapitalize(); | |
| 1509 if (autocapitalize == none) | |
| 1510 flags |= WebTextInputFlagAutocapitalizeNone; | |
| 1511 else if (autocapitalize == characters) | |
| 1512 flags |= WebTextInputFlagAutocapitalizeCharacters; | |
| 1513 else if (autocapitalize == words) | |
| 1514 flags |= WebTextInputFlagAutocapitalizeWords; | |
| 1515 else if (autocapitalize == sentences) | |
| 1516 flags |= WebTextInputFlagAutocapitalizeSentences; | |
| 1517 else | |
| 1518 NOTREACHED(); | |
| 1519 } | |
| 1520 } | |
| 1521 | |
| 1522 return flags; | |
| 1523 } | |
| 1524 | |
| 1525 LocalFrame* WebFrameWidgetImpl::focusedLocalFrameAvailableForIme() const { | 1328 LocalFrame* WebFrameWidgetImpl::focusedLocalFrameAvailableForIme() const { |
| 1526 if (!m_imeAcceptEvents) | 1329 if (!m_imeAcceptEvents) |
| 1527 return nullptr; | 1330 return nullptr; |
| 1528 return focusedLocalFrameInWidget(); | 1331 return focusedLocalFrameInWidget(); |
| 1529 } | 1332 } |
| 1530 | 1333 |
| 1531 } // namespace blink | 1334 } // namespace blink |
| OLD | NEW |