[iOS] Upstream WebCore/html changes
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 18 Dec 2013 00:15:02 +0000 (00:15 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 18 Dec 2013 00:15:02 +0000 (00:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=125765

Reviewed by Darin Adler.

Source/WebCore:

* WebCore.xcodeproj/project.pbxproj:
* html/Autocapitalize.cpp: Added.
* html/Autocapitalize.h: Added. Also, added FIXME comment to forward declare AtomicString once we upstream
more of the iOS port.
* html/BaseChooserOnlyDateAndTimeInputType.cpp:
(WebCore::BaseChooserOnlyDateAndTimeInputType::handleDOMActivateEvent): Opt out of code when building for iOS.
* html/BaseDateAndTimeInputType.cpp:
(WebCore::BaseDateAndTimeInputType::isKeyboardFocusable): Added; iOS-specific.
* html/BaseDateAndTimeInputType.h:
* html/FileInputType.cpp:
(WebCore::FileInputType::FileInputType): Added iOS-specific code.
(WebCore::FileInputType::~FileInputType): Opt out of code when building for iOS. Also, added FIXME comment.
(WebCore::FileInputType::requestIcon): Ditto.
(WebCore::FileInputType::filesChosen): Added; iOS-specific.
(WebCore::FileInputType::displayString): Added; iOS-specific.
(WebCore::FileInputType::receiveDroppedFiles): Guarded code with ENABLE(DRAG_SUPPORT).
* html/FileInputType.h:
* html/FormController.cpp:
(WebCore::FormController::formElementsCharacterCount): Added.
* html/FormController.h:
* html/HTMLAppletElement.cpp:
(WebCore::HTMLAppletElement::updateWidget): Opt out of code when building for iOS.
* html/HTMLAreaElement.cpp:
(WebCore::HTMLAreaElement::computePath): Changed argument datatype from RenderElement* to RenderObject*.
Also, added FIXME comment to fix this up once we upstream iOS's DOMUIKitExtensions.{h, mm}.
(WebCore::HTMLAreaElement::computeRect): Ditto.
* html/HTMLAreaElement.h:
* html/HTMLAttributeNames.in: Added attributes ongesture{start, change, end}, autocorrect, autocapitalize,
data-youtube-id, onwebkit{currentplaybacktargetiswirelesschanged, playbacktargetavailabilitychanged}, webkit-playsinline,
x-webkit-airplay, and x-webkit-wirelessvideoplaybackdisabled.
* html/HTMLBodyElement.cpp:
(WebCore::HTMLBodyElement::scrollLeft): Added iOS-specific code.
(WebCore::HTMLBodyElement::scrollTop): Ditto.
* html/HTMLCanvasElement.cpp:
(WebCore::HTMLCanvasElement::HTMLCanvasElement): Added iOS-specific code and FIXME comment.
(WebCore::HTMLCanvasElement::createImageBuffer): Added iOS-specific code.
* html/HTMLCanvasElement.h: Added iOS-specific code and FIXME comment.
* html/HTMLDocument.cpp:
(WebCore::HTMLDocument::HTMLDocument): Added argument isSynthesized (default to false), which is
passed through to Document::Document(), to create a synthesized document.
* html/HTMLDocument.h:
(WebCore::HTMLDocument::createSynthesizedDocument): Added.
* html/HTMLElement.cpp:
(WebCore::HTMLElement::collectStyleForPresentationAttribute): Added iOS-specific code.
(WebCore::populateEventNameForAttributeLocalNameMap): Ditto.
(WebCore::HTMLElement::willRespondToMouseMoveEvents): Added; iOS-specific.
(WebCore::HTMLElement::willRespondToMouseWheelEvents): Added; iOS-specific.
(WebCore::HTMLElement::willRespondToMouseClickEvents): Added; iOS-specific.
* html/HTMLElement.h:
* html/HTMLFormControlElement.cpp: Added FIXME comment to share more code with class HTMLFormElement.
(WebCore::HTMLFormControlElement::autocorrect): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
(WebCore::HTMLFormControlElement::setAutocorrect): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
(WebCore::HTMLFormControlElement::autocapitalizeType): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
(WebCore::HTMLFormControlElement::autocapitalize): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
(WebCore::HTMLFormControlElement::setAutocapitalize): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
* html/HTMLFormControlElement.h:
* html/HTMLFormElement.cpp: Added FIXME comment to share more code with class HTMLFormControlElement.
(WebCore::HTMLFormElement::submitImplicitly): Modified to code to allow implicit submission of multi-input
forms only if Settings::allowMultiElementImplicitSubmission() returns true. Such behavior is expected by older
iOS apps. Also, changed datatype of variable submissionTriggerCount from int to unsigned because it represents
a non-negative value.
(WebCore::HTMLFormElement::autocorrect): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
(WebCore::HTMLFormElement::setAutocorrect): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
(WebCore::HTMLFormElement::autocapitalizeType): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
(WebCore::HTMLFormElement::autocapitalize): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
(WebCore::HTMLFormElement::setAutocapitalize): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
* html/HTMLFormElement.h:
* html/HTMLFormElement.idl: Added iOS-specific attributes: autocorrect and autocapitalize.
* html/HTMLIFrameElement.h:
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::displayString): Added; guarded by PLATFORM(IOS).
(WebCore::HTMLInputElement::dateType): Added; guarded by PLATFORM(IOS).
* html/HTMLInputElement.h:
* html/HTMLInputElement.idl: Added iOS-specific attributes: autocorrect and autocapitalize.
* html/HTMLLabelElement.cpp:
(WebCore::HTMLLabelElement::willRespondToMouseClickEvents): Added iOS-specific code.
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::HTMLMediaElement): Added iOS-specific code and FIXME comment.
(WebCore::HTMLMediaElement::~HTMLMediaElement): Added iOS-specific code.
(WebCore::HTMLMediaElement::parseMediaPlayerAttribute): Added; iOS-specific.
(WebCore::HTMLMediaElement::parseAttribute): Added iOS-specific code.
(WebCore::HTMLMediaElement::insertedInto): Ditto.
(WebCore::HTMLMediaElement::load): Ditto.
(WebCore::HTMLMediaElement::prepareForLoad): Ditto.
(WebCore::HTMLMediaElement::autoplay): Ditto.
(WebCore::HTMLMediaElement::play): Ditto.
(WebCore::HTMLMediaElement::playInternal): Ditto.
(WebCore::HTMLMediaElement::pauseInternal): Ditto.
(WebCore::HTMLMediaElement::setVolumne): Opt out of code when building for iOS.
(WebCore::HTMLMediaElement::setMuted): Ditto.
(WebCore::HTMLMediaElement::mediaPlayerTimeChanged): Added iOS-specific code.
(WebCore::HTMLMediaElement::updateVolume): Ditto.
(WebCore::HTMLMediaElement::updatePlayState): Ditto.
(WebCore::HTMLMediaElement::userCancelledLoad): Added iOS-specific code and FIXME comment.
(WebCore::HTMLMediaElement::resume): Added iOS-specific comment. See <rdar://problem/9751303>.
(WebCore::HTMLMediaElement::deliverNotification): Added iOS-specific code.
(WebCore::HTMLMediaElement::getPluginProxyParams): Added iOS-specific code. Also, changed src() to getNonEmptyURLAttribute()
in the non-iOS code as their doesn't exist a method called src in this class or its superclasses.
(WebCore::HTMLMediaElement::webkitShowPlaybackTargetPicker): Added; guarded by ENABLE(IOS_AIRPLAY).
(WebCore::HTMLMediaElement::webkitCurrentPlaybackTargetIsWireless): Added; guarded by ENABLE(IOS_AIRPLAY).
(WebCore::HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged): Added; guarded by ENABLE(IOS_AIRPLAY).
(WebCore::HTMLMediaElement::mediaPlayerPlaybackTargetAvailabilityChanged): Added; guarded by ENABLE(IOS_AIRPLAY).
(WebCore::HTMLMediaElement::addEventListener): Added; guarded by ENABLE(IOS_AIRPLAY).
(WebCore::HTMLMediaElement::removeEventListener): Added; guarded by ENABLE(IOS_AIRPLAY).
(WebCore::HTMLMediaElement::enqueuePlaybackTargetAvailabilityChangedEvent): Added; guarded by ENABLE(IOS_AIRPLAY).
(WebCore::HTMLMediaElement::enterFullscreen): Added iOS-specific code.
(WebCore::HTMLMediaElement::exitFullscreen): Ditto.
(WebCore::HTMLMediaElement::createMediaPlayer): Added ENABLE(IOS_AIRPLAY)-guarded code.
(WebCore::HTMLMediaElement::userRequestsMediaLoading): Added; guarded by PLATFORM(IOS).
(WebCore::HTMLMediaElement::shouldUseVideoPluginProxy): Use dot operator instead of dereference operator (->)
when accessing Document::settings().
(WebCore::HTMLMediaElement::didAddUserAgentShadowRoot): Added ENABLE(PLUGIN_PROXY_FOR_VIDEO)-guarded code.
* html/HTMLMediaElement.h:
(WebCore::HTMLMediaElement::userGestureRequiredToShowPlaybackTargetPicker): Added; guarded by ENABLE(IOS_AIRPLAY).
* html/HTMLMediaElement.idl: Added ENABLE_IOS_AIRPLAY-guarded attributes and functions:webkitCurrentPlaybackTargetIsWireless,
onwebkit{currentplaybacktargetiswirelesschanged, playbacktargetavailabilitychanged}, and webkitShowPlaybackTargetPicker().
* html/HTMLMetaElement.cpp:
(WebCore::HTMLMetaElement::process): Added iOS-specific code.
* html/HTMLObjectElement.cpp:
(WebCore::shouldNotPerformURLAdjustment): Added; iOS-specific.
(WebCore::HTMLObjectElement::parametersForPlugin): Modified to call shouldNotPerformURLAdjustment() when
building for iOS.
* html/HTMLPlugInElement.h:
* html/HTMLPlugInImageElement.cpp:
(WebCore::HTMLPlugInImageElement::createRenderer): Added iOS-specific code.
(WebCore::HTMLPlugInImageElement::createShadowIFrameSubtree): Added; iOS-specific.
* html/HTMLPlugInImageElement.h:
* html/HTMLSelectElement.cpp:
(WebCore::HTMLSelectElement::usesMenuList): Added iOS-specific code.
(WebCore::HTMLSelectElement::createRenderer): Ditto.
(WebCore::HTMLSelectElement::childShouldCreateRenderer): Ditto.
(WebCore::HTMLSelectElement::willRespondToMouseClickEvents): Added; iOS-specific.
(WebCore::HTMLSelectElement::updateListBoxSelection): Added iOS-specific code.
(WebCore::HTMLSelectElement::scrollToSelection): Ditto.
(WebCore::HTMLSelectElement::setOptionsChangedOnRenderer): Ditto.
(WebCore::HTMLSelectElement::menuListDefaultEventHandler): Opt out of code when building for iOS.
(WebCore::HTMLSelectElement::defaultEventHandler): Added iOS-specific code.
* html/HTMLSelectElement.h:
* html/HTMLTextAreaElement.cpp:
(WebCore::HTMLTextAreaElement::willRespondToMouseClickEvents): Added; iOS-specific.
* html/HTMLTextAreaElement.h:
* html/HTMLTextAreaElement.idl: Added iOS-specific attributes: autocorrect and autocapitalize.
* html/HTMLTextFormControlElement.cpp:
(WebCore::HTMLTextFormControlElement::select): Added iOS-specific code and FIXME comment.
(WebCore::HTMLTextFormControlElement::setSelectionRange): Opt out of code when building for iOS.
(WebCore::HTMLTextFormControlElement::hidePlaceholder): Added; guarded by PLATFORM(IOS).
(WebCore::HTMLTextFormControlElement::showPlaceholderIfNecessary): Added; guarded by PLATFORM(IOS).
* html/HTMLTextFormControlElement.h:
* html/HTMLVideoElement.cpp:
(WebCore::HTMLVideoElement::createRenderer): Fix up call to HTMLMediaElement::createRenderer().
(WebCore::HTMLVideoElement::parseAttribute): Added iOS-specific code.
(WebCore::HTMLVideoElement::supportsFullscreen): Ditto.
(WebCore::HTMLVideoElement::webkitWirelessVideoPlaybackDisabled): Added; guarded by ENABLE(IOS_AIRPLAY).
(WebCore::HTMLVideoElement::setWebkitWirelessVideoPlaybackDisabled): Added; guarded by ENABLE(IOS_AIRPLAY).
* html/HTMLVideoElement.h:
* html/HTMLVideoElement.idl: Added ENABLE_IOS_AIRPLAY-guarded attribute: webkitWirelessVideoPlaybackDisabled.
* html/ImageDocument.cpp:
(WebCore::ImageDocument::createDocumentStructure): Added iOS-specific code.
(WebCore::ImageDocument::scale): Ditto.
(WebCore::ImageDocument::resizeImageToFit): Ditto.
(WebCore::ImageDocument::imageClicked): Ditto.
(WebCore::ImageDocument::imageFitsInWindow): Ditto.
(WebCore::ImageDocument::windowSizeChanged): Ditto.
* html/InputType.cpp:
(WebCore::InputType::dateType): Added; guarded by PLATFORM(IOS).
(WebCore::InputType::isKeyboardFocusable): Added iOS-specific code.
(WebCore::InputType::displayString): Added; guarded by PLATFORM(IOS).
* html/InputType.h:
* html/PluginDocument.cpp:
(WebCore::PluginDocumentParser::createDocumentStructure): Added iOS-specific code.
* html/RangeInputType.cpp:
(WebCore::RangeInputType::handleTouchEvent): Ditto.
(WebCore::RangeInputType::disabledAttributeChanged): Added; iOS-specific.
* html/RangeInputType.h:
* html/SearchInputType.cpp:
(WebCore::SearchInputType::addSearchResult): Opt out of code when building for iOS.
* html/TextFieldInputType.cpp:
(WebCore::TextFieldInputType::isKeyboardFocusable): Added iOS-specific code.
* html/TextFieldInputType.h:
* html/WebAutocapitalize.h: Added.
* html/canvas/CanvasRenderingContext2D.cpp:
(WebCore::CanvasRenderingContext2D::createImageData): Added iOS-specific code.
(WebCore::CanvasRenderingContext2D::getImageData): Ditto.
* html/parser/HTMLConstructionSite.h:
(WebCore::HTMLConstructionSite::isTelephoneNumberParsingEnabled): Added; guarded by PLATFORM(IOS).
* html/parser/HTMLParserScheduler.h:
(WebCore::HTMLParserScheduler::checkForYieldBeforeToken): Added iOS-specific code.
* html/parser/HTMLTreeBuilder.cpp:
(WebCore::HTMLTreeBuilder::insertPhoneNumberLink): Added; guarded by PLATFORM(IOS).
(WebCore::HTMLTreeBuilder::linkifyPhoneNumbers): Added; guarded by PLATFORM(IOS).
(WebCore::disallowTelephoneNumberParsing): Added; guarded by PLATFORM(IOS).
(WebCore::shouldParseTelephoneNumbersInNode): Added; guarded by PLATFORM(IOS).
(WebCore::HTMLTreeBuilder::processCharacterBufferForInBody): Added iOS-specific code.
* html/parser/HTMLTreeBuilder.h:
* html/shadow/MediaControlElements.cpp:
(WebCore::MediaControlClosedCaptionsTrackListElement::MediaControlClosedCaptionsTrackListElement): Guarded member initialization of m_controls with ENABLE(VIDEO_TRACK). Also added UNUSED_PARAM(event) when building with
VIDEO_TRACK disabled.
(WebCore::MediaControlClosedCaptionsTrackListElement::defaultEventHandler): Added UNUSED_PARAM(event) when
building with VIDEO_TRACK disabled.
* html/shadow/MediaControls.h:
* html/shadow/SliderThumbElement.cpp:
(WebCore::SliderThumbElement::SliderThumbElement): Added iOS-specific code.
(WebCore::SliderThumbElement::dragFrom): Opt out of code when building for iOS.
(WebCore::SliderThumbElement::willDetachRenderers):  Added iOS-specific code.
(WebCore::SliderThumbElement::exclusiveTouchIdentifier): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
(WebCore::SliderThumbElement::setExclusiveTouchIdentifier): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
(WebCore::SliderThumbElement::clearExclusiveTouchIdentifier): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
(WebCore::findTouchWithIdentifier): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
(WebCore::SliderThumbElement::handleTouchStart): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
(WebCore::SliderThumbElement::handleTouchMove): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
(WebCore::SliderThumbElement::handleTouchEndAndCancel): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
(WebCore::SliderThumbElement::didAttachRenderers): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
(WebCore::SliderThumbElement::handleTouchEvent): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
(WebCore::SliderThumbElement::shouldAcceptTouchEvents): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
(WebCore::SliderThumbElement::registerForTouchEvents): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
(WebCore::SliderThumbElement::unregisterForTouchEvents): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
(WebCore::SliderThumbElement::disabledAttributeChanged): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
* html/shadow/SliderThumbElement.h:
* html/shadow/TextControlInnerElements.cpp:
(WebCore::SearchFieldResultsButtonElement::defaultEventHandler): Opt out of code when building for iOS.
* html/shadow/TextControlInnerElements.h:
* page/Settings.in: Added setting allowMultiElementImplicitSubmission to enable/disable multi-input implicit form
submission (disabled by default). Also added FIXME comment to rename this setting to allowMultiElementImplicitFormSubmission
once we upstream the iOS changes to WebView.mm.

Source/WTF:

Defined ENABLE_IOS_AUTOCORRECT_AND_AUTOCAPITALIZE, enabled by default on iOS.

* wtf/FeatureDefines.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@160733 268f45cc-cd09-0410-ab3c-d52691b4dbfc

75 files changed:
Source/WTF/ChangeLog
Source/WTF/wtf/FeatureDefines.h
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/html/Autocapitalize.cpp [new file with mode: 0644]
Source/WebCore/html/Autocapitalize.h [new file with mode: 0644]
Source/WebCore/html/BaseChooserOnlyDateAndTimeInputType.cpp
Source/WebCore/html/BaseDateAndTimeInputType.cpp
Source/WebCore/html/BaseDateAndTimeInputType.h
Source/WebCore/html/FileInputType.cpp
Source/WebCore/html/FileInputType.h
Source/WebCore/html/FormController.cpp
Source/WebCore/html/FormController.h
Source/WebCore/html/HTMLAppletElement.cpp
Source/WebCore/html/HTMLAreaElement.cpp
Source/WebCore/html/HTMLAreaElement.h
Source/WebCore/html/HTMLAttributeNames.in
Source/WebCore/html/HTMLBodyElement.cpp
Source/WebCore/html/HTMLCanvasElement.cpp
Source/WebCore/html/HTMLCanvasElement.h
Source/WebCore/html/HTMLDocument.cpp
Source/WebCore/html/HTMLDocument.h
Source/WebCore/html/HTMLElement.cpp
Source/WebCore/html/HTMLElement.h
Source/WebCore/html/HTMLFormControlElement.cpp
Source/WebCore/html/HTMLFormControlElement.h
Source/WebCore/html/HTMLFormElement.cpp
Source/WebCore/html/HTMLFormElement.h
Source/WebCore/html/HTMLFormElement.idl
Source/WebCore/html/HTMLIFrameElement.h
Source/WebCore/html/HTMLInputElement.cpp
Source/WebCore/html/HTMLInputElement.h
Source/WebCore/html/HTMLInputElement.idl
Source/WebCore/html/HTMLLabelElement.cpp
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLMediaElement.h
Source/WebCore/html/HTMLMediaElement.idl
Source/WebCore/html/HTMLMetaElement.cpp
Source/WebCore/html/HTMLObjectElement.cpp
Source/WebCore/html/HTMLPlugInElement.h
Source/WebCore/html/HTMLPlugInImageElement.cpp
Source/WebCore/html/HTMLPlugInImageElement.h
Source/WebCore/html/HTMLSelectElement.cpp
Source/WebCore/html/HTMLSelectElement.h
Source/WebCore/html/HTMLTextAreaElement.cpp
Source/WebCore/html/HTMLTextAreaElement.h
Source/WebCore/html/HTMLTextAreaElement.idl
Source/WebCore/html/HTMLTextFormControlElement.cpp
Source/WebCore/html/HTMLTextFormControlElement.h
Source/WebCore/html/HTMLVideoElement.cpp
Source/WebCore/html/HTMLVideoElement.h
Source/WebCore/html/HTMLVideoElement.idl
Source/WebCore/html/ImageDocument.cpp
Source/WebCore/html/InputType.cpp
Source/WebCore/html/InputType.h
Source/WebCore/html/PluginDocument.cpp
Source/WebCore/html/RangeInputType.cpp
Source/WebCore/html/RangeInputType.h
Source/WebCore/html/SearchInputType.cpp
Source/WebCore/html/TextFieldInputType.cpp
Source/WebCore/html/TextFieldInputType.h
Source/WebCore/html/WebAutocapitalize.h [new file with mode: 0644]
Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
Source/WebCore/html/parser/HTMLConstructionSite.h
Source/WebCore/html/parser/HTMLParserScheduler.h
Source/WebCore/html/parser/HTMLTreeBuilder.cpp
Source/WebCore/html/parser/HTMLTreeBuilder.h
Source/WebCore/html/shadow/MediaControlElements.cpp
Source/WebCore/html/shadow/MediaControlElements.h
Source/WebCore/html/shadow/MediaControls.h
Source/WebCore/html/shadow/SliderThumbElement.cpp
Source/WebCore/html/shadow/SliderThumbElement.h
Source/WebCore/html/shadow/TextControlInnerElements.cpp
Source/WebCore/html/shadow/TextControlInnerElements.h
Source/WebCore/page/Settings.in

index 78ba2223a15a6da1989cb6be0186705ee284f748..3a54351035c9f07e5a71cc5f8ad6b6d54dc0c7de 100644 (file)
@@ -1,3 +1,14 @@
+2013-12-16  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Upstream WebCore/html changes
+        https://bugs.webkit.org/show_bug.cgi?id=125765
+
+        Reviewed by Darin Adler.
+
+        Defined ENABLE_IOS_AUTOCORRECT_AND_AUTOCAPITALIZE, enabled by default on iOS.
+
+        * wtf/FeatureDefines.h:
+
 2013-12-17  Alex Christensen  <achristensen@webkit.org>
 
         Compile fix for WebGL on Windows without GRAPHICS_SURFACE.
index 421668a3e8efbf4f56be70d1d4badf0802fbeee8..e9874728a2a2e6030e93e8d1ff038bd3c037fea4 100644 (file)
 #define ENABLE_ICONDATABASE 0
 #endif
 
+#if !defined(ENABLE_IOS_AUTOCORRECT_AND_AUTOCAPITALIZE)
+#define ENABLE_IOS_AUTOCORRECT_AND_AUTOCAPITALIZE 1
+#endif
+
 #if !defined(ENABLE_IOS_GESTURE_EVENTS)
 #define ENABLE_IOS_GESTURE_EVENTS 1
 #endif
index 76f1190b9b12920a42667c0b032f2b94742a9837..4ff6dc09bfe89c5621a02c7ed83388407491f043 100644 (file)
@@ -1,3 +1,235 @@
+2013-12-16  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Upstream WebCore/html changes
+        https://bugs.webkit.org/show_bug.cgi?id=125765
+
+        Reviewed by Darin Adler.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * html/Autocapitalize.cpp: Added.
+        * html/Autocapitalize.h: Added. Also, added FIXME comment to forward declare AtomicString once we upstream
+        more of the iOS port.
+        * html/BaseChooserOnlyDateAndTimeInputType.cpp:
+        (WebCore::BaseChooserOnlyDateAndTimeInputType::handleDOMActivateEvent): Opt out of code when building for iOS.
+        * html/BaseDateAndTimeInputType.cpp:
+        (WebCore::BaseDateAndTimeInputType::isKeyboardFocusable): Added; iOS-specific.
+        * html/BaseDateAndTimeInputType.h:
+        * html/FileInputType.cpp:
+        (WebCore::FileInputType::FileInputType): Added iOS-specific code.
+        (WebCore::FileInputType::~FileInputType): Opt out of code when building for iOS. Also, added FIXME comment.
+        (WebCore::FileInputType::requestIcon): Ditto.
+        (WebCore::FileInputType::filesChosen): Added; iOS-specific.
+        (WebCore::FileInputType::displayString): Added; iOS-specific.
+        (WebCore::FileInputType::receiveDroppedFiles): Guarded code with ENABLE(DRAG_SUPPORT).
+        * html/FileInputType.h:
+        * html/FormController.cpp:
+        (WebCore::FormController::formElementsCharacterCount): Added.
+        * html/FormController.h:
+        * html/HTMLAppletElement.cpp:
+        (WebCore::HTMLAppletElement::updateWidget): Opt out of code when building for iOS.
+        * html/HTMLAreaElement.cpp:
+        (WebCore::HTMLAreaElement::computePath): Changed argument datatype from RenderElement* to RenderObject*.
+        Also, added FIXME comment to fix this up once we upstream iOS's DOMUIKitExtensions.{h, mm}.
+        (WebCore::HTMLAreaElement::computeRect): Ditto.
+        * html/HTMLAreaElement.h:
+        * html/HTMLAttributeNames.in: Added attributes ongesture{start, change, end}, autocorrect, autocapitalize,
+        data-youtube-id, onwebkit{currentplaybacktargetiswirelesschanged, playbacktargetavailabilitychanged}, webkit-playsinline,
+        x-webkit-airplay, and x-webkit-wirelessvideoplaybackdisabled.
+        * html/HTMLBodyElement.cpp:
+        (WebCore::HTMLBodyElement::scrollLeft): Added iOS-specific code.
+        (WebCore::HTMLBodyElement::scrollTop): Ditto.
+        * html/HTMLCanvasElement.cpp:
+        (WebCore::HTMLCanvasElement::HTMLCanvasElement): Added iOS-specific code and FIXME comment.
+        (WebCore::HTMLCanvasElement::createImageBuffer): Added iOS-specific code.
+        * html/HTMLCanvasElement.h: Added iOS-specific code and FIXME comment.
+        * html/HTMLDocument.cpp:
+        (WebCore::HTMLDocument::HTMLDocument): Added argument isSynthesized (default to false), which is
+        passed through to Document::Document(), to create a synthesized document.
+        * html/HTMLDocument.h:
+        (WebCore::HTMLDocument::createSynthesizedDocument): Added.
+        * html/HTMLElement.cpp:
+        (WebCore::HTMLElement::collectStyleForPresentationAttribute): Added iOS-specific code.
+        (WebCore::populateEventNameForAttributeLocalNameMap): Ditto.
+        (WebCore::HTMLElement::willRespondToMouseMoveEvents): Added; iOS-specific.
+        (WebCore::HTMLElement::willRespondToMouseWheelEvents): Added; iOS-specific.
+        (WebCore::HTMLElement::willRespondToMouseClickEvents): Added; iOS-specific.
+        * html/HTMLElement.h:
+        * html/HTMLFormControlElement.cpp: Added FIXME comment to share more code with class HTMLFormElement.
+        (WebCore::HTMLFormControlElement::autocorrect): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
+        (WebCore::HTMLFormControlElement::setAutocorrect): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
+        (WebCore::HTMLFormControlElement::autocapitalizeType): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
+        (WebCore::HTMLFormControlElement::autocapitalize): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
+        (WebCore::HTMLFormControlElement::setAutocapitalize): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
+        * html/HTMLFormControlElement.h:
+        * html/HTMLFormElement.cpp: Added FIXME comment to share more code with class HTMLFormControlElement.
+        (WebCore::HTMLFormElement::submitImplicitly): Modified to code to allow implicit submission of multi-input
+        forms only if Settings::allowMultiElementImplicitSubmission() returns true. Such behavior is expected by older
+        iOS apps. Also, changed datatype of variable submissionTriggerCount from int to unsigned because it represents
+        a non-negative value.
+        (WebCore::HTMLFormElement::autocorrect): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
+        (WebCore::HTMLFormElement::setAutocorrect): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
+        (WebCore::HTMLFormElement::autocapitalizeType): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
+        (WebCore::HTMLFormElement::autocapitalize): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
+        (WebCore::HTMLFormElement::setAutocapitalize): Added; guarded by PLATFORM(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE).
+        * html/HTMLFormElement.h:
+        * html/HTMLFormElement.idl: Added iOS-specific attributes: autocorrect and autocapitalize.
+        * html/HTMLIFrameElement.h:
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::displayString): Added; guarded by PLATFORM(IOS).
+        (WebCore::HTMLInputElement::dateType): Added; guarded by PLATFORM(IOS).
+        * html/HTMLInputElement.h:
+        * html/HTMLInputElement.idl: Added iOS-specific attributes: autocorrect and autocapitalize.
+        * html/HTMLLabelElement.cpp:
+        (WebCore::HTMLLabelElement::willRespondToMouseClickEvents): Added iOS-specific code.
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::HTMLMediaElement): Added iOS-specific code and FIXME comment.
+        (WebCore::HTMLMediaElement::~HTMLMediaElement): Added iOS-specific code.
+        (WebCore::HTMLMediaElement::parseMediaPlayerAttribute): Added; iOS-specific.
+        (WebCore::HTMLMediaElement::parseAttribute): Added iOS-specific code.
+        (WebCore::HTMLMediaElement::insertedInto): Ditto.
+        (WebCore::HTMLMediaElement::load): Ditto.
+        (WebCore::HTMLMediaElement::prepareForLoad): Ditto.
+        (WebCore::HTMLMediaElement::autoplay): Ditto.
+        (WebCore::HTMLMediaElement::play): Ditto.
+        (WebCore::HTMLMediaElement::playInternal): Ditto.
+        (WebCore::HTMLMediaElement::pauseInternal): Ditto.
+        (WebCore::HTMLMediaElement::setVolumne): Opt out of code when building for iOS.
+        (WebCore::HTMLMediaElement::setMuted): Ditto.
+        (WebCore::HTMLMediaElement::mediaPlayerTimeChanged): Added iOS-specific code.
+        (WebCore::HTMLMediaElement::updateVolume): Ditto.
+        (WebCore::HTMLMediaElement::updatePlayState): Ditto.
+        (WebCore::HTMLMediaElement::userCancelledLoad): Added iOS-specific code and FIXME comment.
+        (WebCore::HTMLMediaElement::resume): Added iOS-specific comment. See <rdar://problem/9751303>.
+        (WebCore::HTMLMediaElement::deliverNotification): Added iOS-specific code.
+        (WebCore::HTMLMediaElement::getPluginProxyParams): Added iOS-specific code. Also, changed src() to getNonEmptyURLAttribute()
+        in the non-iOS code as their doesn't exist a method called src in this class or its superclasses.
+        (WebCore::HTMLMediaElement::webkitShowPlaybackTargetPicker): Added; guarded by ENABLE(IOS_AIRPLAY).
+        (WebCore::HTMLMediaElement::webkitCurrentPlaybackTargetIsWireless): Added; guarded by ENABLE(IOS_AIRPLAY).
+        (WebCore::HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged): Added; guarded by ENABLE(IOS_AIRPLAY).
+        (WebCore::HTMLMediaElement::mediaPlayerPlaybackTargetAvailabilityChanged): Added; guarded by ENABLE(IOS_AIRPLAY).
+        (WebCore::HTMLMediaElement::addEventListener): Added; guarded by ENABLE(IOS_AIRPLAY).
+        (WebCore::HTMLMediaElement::removeEventListener): Added; guarded by ENABLE(IOS_AIRPLAY).
+        (WebCore::HTMLMediaElement::enqueuePlaybackTargetAvailabilityChangedEvent): Added; guarded by ENABLE(IOS_AIRPLAY).
+        (WebCore::HTMLMediaElement::enterFullscreen): Added iOS-specific code.
+        (WebCore::HTMLMediaElement::exitFullscreen): Ditto.
+        (WebCore::HTMLMediaElement::createMediaPlayer): Added ENABLE(IOS_AIRPLAY)-guarded code.
+        (WebCore::HTMLMediaElement::userRequestsMediaLoading): Added; guarded by PLATFORM(IOS).
+        (WebCore::HTMLMediaElement::shouldUseVideoPluginProxy): Use dot operator instead of dereference operator (->)
+        when accessing Document::settings().
+        (WebCore::HTMLMediaElement::didAddUserAgentShadowRoot): Added ENABLE(PLUGIN_PROXY_FOR_VIDEO)-guarded code.
+        * html/HTMLMediaElement.h:
+        (WebCore::HTMLMediaElement::userGestureRequiredToShowPlaybackTargetPicker): Added; guarded by ENABLE(IOS_AIRPLAY).
+        * html/HTMLMediaElement.idl: Added ENABLE_IOS_AIRPLAY-guarded attributes and functions:webkitCurrentPlaybackTargetIsWireless,
+        onwebkit{currentplaybacktargetiswirelesschanged, playbacktargetavailabilitychanged}, and webkitShowPlaybackTargetPicker().
+        * html/HTMLMetaElement.cpp:
+        (WebCore::HTMLMetaElement::process): Added iOS-specific code.
+        * html/HTMLObjectElement.cpp:
+        (WebCore::shouldNotPerformURLAdjustment): Added; iOS-specific.
+        (WebCore::HTMLObjectElement::parametersForPlugin): Modified to call shouldNotPerformURLAdjustment() when
+        building for iOS.
+        * html/HTMLPlugInElement.h:
+        * html/HTMLPlugInImageElement.cpp:
+        (WebCore::HTMLPlugInImageElement::createRenderer): Added iOS-specific code.
+        (WebCore::HTMLPlugInImageElement::createShadowIFrameSubtree): Added; iOS-specific.
+        * html/HTMLPlugInImageElement.h:
+        * html/HTMLSelectElement.cpp:
+        (WebCore::HTMLSelectElement::usesMenuList): Added iOS-specific code.
+        (WebCore::HTMLSelectElement::createRenderer): Ditto.
+        (WebCore::HTMLSelectElement::childShouldCreateRenderer): Ditto.
+        (WebCore::HTMLSelectElement::willRespondToMouseClickEvents): Added; iOS-specific.
+        (WebCore::HTMLSelectElement::updateListBoxSelection): Added iOS-specific code.
+        (WebCore::HTMLSelectElement::scrollToSelection): Ditto.
+        (WebCore::HTMLSelectElement::setOptionsChangedOnRenderer): Ditto.
+        (WebCore::HTMLSelectElement::menuListDefaultEventHandler): Opt out of code when building for iOS.
+        (WebCore::HTMLSelectElement::defaultEventHandler): Added iOS-specific code.
+        * html/HTMLSelectElement.h:
+        * html/HTMLTextAreaElement.cpp:
+        (WebCore::HTMLTextAreaElement::willRespondToMouseClickEvents): Added; iOS-specific.
+        * html/HTMLTextAreaElement.h:
+        * html/HTMLTextAreaElement.idl: Added iOS-specific attributes: autocorrect and autocapitalize.
+        * html/HTMLTextFormControlElement.cpp:
+        (WebCore::HTMLTextFormControlElement::select): Added iOS-specific code and FIXME comment.
+        (WebCore::HTMLTextFormControlElement::setSelectionRange): Opt out of code when building for iOS.
+        (WebCore::HTMLTextFormControlElement::hidePlaceholder): Added; guarded by PLATFORM(IOS).
+        (WebCore::HTMLTextFormControlElement::showPlaceholderIfNecessary): Added; guarded by PLATFORM(IOS).
+        * html/HTMLTextFormControlElement.h:
+        * html/HTMLVideoElement.cpp:
+        (WebCore::HTMLVideoElement::createRenderer): Fix up call to HTMLMediaElement::createRenderer().
+        (WebCore::HTMLVideoElement::parseAttribute): Added iOS-specific code.
+        (WebCore::HTMLVideoElement::supportsFullscreen): Ditto.
+        (WebCore::HTMLVideoElement::webkitWirelessVideoPlaybackDisabled): Added; guarded by ENABLE(IOS_AIRPLAY).
+        (WebCore::HTMLVideoElement::setWebkitWirelessVideoPlaybackDisabled): Added; guarded by ENABLE(IOS_AIRPLAY).
+        * html/HTMLVideoElement.h:
+        * html/HTMLVideoElement.idl: Added ENABLE_IOS_AIRPLAY-guarded attribute: webkitWirelessVideoPlaybackDisabled.
+        * html/ImageDocument.cpp:
+        (WebCore::ImageDocument::createDocumentStructure): Added iOS-specific code.
+        (WebCore::ImageDocument::scale): Ditto.
+        (WebCore::ImageDocument::resizeImageToFit): Ditto.
+        (WebCore::ImageDocument::imageClicked): Ditto.
+        (WebCore::ImageDocument::imageFitsInWindow): Ditto.
+        (WebCore::ImageDocument::windowSizeChanged): Ditto.
+        * html/InputType.cpp:
+        (WebCore::InputType::dateType): Added; guarded by PLATFORM(IOS).
+        (WebCore::InputType::isKeyboardFocusable): Added iOS-specific code.
+        (WebCore::InputType::displayString): Added; guarded by PLATFORM(IOS).
+        * html/InputType.h:
+        * html/PluginDocument.cpp:
+        (WebCore::PluginDocumentParser::createDocumentStructure): Added iOS-specific code.
+        * html/RangeInputType.cpp:
+        (WebCore::RangeInputType::handleTouchEvent): Ditto.
+        (WebCore::RangeInputType::disabledAttributeChanged): Added; iOS-specific.
+        * html/RangeInputType.h:
+        * html/SearchInputType.cpp:
+        (WebCore::SearchInputType::addSearchResult): Opt out of code when building for iOS.
+        * html/TextFieldInputType.cpp:
+        (WebCore::TextFieldInputType::isKeyboardFocusable): Added iOS-specific code.
+        * html/TextFieldInputType.h:
+        * html/WebAutocapitalize.h: Added.
+        * html/canvas/CanvasRenderingContext2D.cpp:
+        (WebCore::CanvasRenderingContext2D::createImageData): Added iOS-specific code.
+        (WebCore::CanvasRenderingContext2D::getImageData): Ditto.
+        * html/parser/HTMLConstructionSite.h:
+        (WebCore::HTMLConstructionSite::isTelephoneNumberParsingEnabled): Added; guarded by PLATFORM(IOS).
+        * html/parser/HTMLParserScheduler.h:
+        (WebCore::HTMLParserScheduler::checkForYieldBeforeToken): Added iOS-specific code.
+        * html/parser/HTMLTreeBuilder.cpp:
+        (WebCore::HTMLTreeBuilder::insertPhoneNumberLink): Added; guarded by PLATFORM(IOS).
+        (WebCore::HTMLTreeBuilder::linkifyPhoneNumbers): Added; guarded by PLATFORM(IOS).
+        (WebCore::disallowTelephoneNumberParsing): Added; guarded by PLATFORM(IOS).
+        (WebCore::shouldParseTelephoneNumbersInNode): Added; guarded by PLATFORM(IOS).
+        (WebCore::HTMLTreeBuilder::processCharacterBufferForInBody): Added iOS-specific code.
+        * html/parser/HTMLTreeBuilder.h:
+        * html/shadow/MediaControlElements.cpp:
+        (WebCore::MediaControlClosedCaptionsTrackListElement::MediaControlClosedCaptionsTrackListElement): Guarded member initialization of m_controls with ENABLE(VIDEO_TRACK). Also added UNUSED_PARAM(event) when building with
+        VIDEO_TRACK disabled.
+        (WebCore::MediaControlClosedCaptionsTrackListElement::defaultEventHandler): Added UNUSED_PARAM(event) when
+        building with VIDEO_TRACK disabled.
+        * html/shadow/MediaControls.h:
+        * html/shadow/SliderThumbElement.cpp:
+        (WebCore::SliderThumbElement::SliderThumbElement): Added iOS-specific code.
+        (WebCore::SliderThumbElement::dragFrom): Opt out of code when building for iOS.
+        (WebCore::SliderThumbElement::willDetachRenderers):  Added iOS-specific code.
+        (WebCore::SliderThumbElement::exclusiveTouchIdentifier): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
+        (WebCore::SliderThumbElement::setExclusiveTouchIdentifier): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
+        (WebCore::SliderThumbElement::clearExclusiveTouchIdentifier): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
+        (WebCore::findTouchWithIdentifier): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
+        (WebCore::SliderThumbElement::handleTouchStart): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
+        (WebCore::SliderThumbElement::handleTouchMove): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
+        (WebCore::SliderThumbElement::handleTouchEndAndCancel): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
+        (WebCore::SliderThumbElement::didAttachRenderers): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
+        (WebCore::SliderThumbElement::handleTouchEvent): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
+        (WebCore::SliderThumbElement::shouldAcceptTouchEvents): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
+        (WebCore::SliderThumbElement::registerForTouchEvents): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
+        (WebCore::SliderThumbElement::unregisterForTouchEvents): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
+        (WebCore::SliderThumbElement::disabledAttributeChanged): Added; guarded by ENABLE(TOUCH_EVENTS) && PLATFORM(IOS).
+        * html/shadow/SliderThumbElement.h:
+        * html/shadow/TextControlInnerElements.cpp:
+        (WebCore::SearchFieldResultsButtonElement::defaultEventHandler): Opt out of code when building for iOS.
+        * html/shadow/TextControlInnerElements.h:
+        * page/Settings.in: Added setting allowMultiElementImplicitSubmission to enable/disable multi-input implicit form
+        submission (disabled by default). Also added FIXME comment to rename this setting to allowMultiElementImplicitFormSubmission
+        once we upstream the iOS changes to WebView.mm.
+
 2013-12-17  Brady Eidson  <beidson@apple.com>
 
         DatabaseProcess: Pipe through object store IDs and transaction mode for "openTransaction"
index c2e05aa653cafb3a2ebdceb3d94eb1c880f7df99..9ce03865deaa97e0a77bcfd7c20b3a03acf99ea1 100644 (file)
                A454424F119B3687009BE912 /* RenderMeter.h in Headers */ = {isa = PBXBuildFile; fileRef = A454424D119B3687009BE912 /* RenderMeter.h */; };
                A456FA2611AD4A830020B420 /* LabelsNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A456FA2411AD4A830020B420 /* LabelsNodeList.cpp */; };
                A456FA2711AD4A830020B420 /* LabelsNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = A456FA2511AD4A830020B420 /* LabelsNodeList.h */; };
+               A501920E132EBF2E008BFE55 /* Autocapitalize.h in Headers */ = {isa = PBXBuildFile; fileRef = A501920C132EBF2E008BFE55 /* Autocapitalize.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A502C5DF13049B3500FC7D53 /* WebSafeGCActivityCallbackIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = A502C5DD13049B3500FC7D53 /* WebSafeGCActivityCallbackIOS.h */; };
                A513B3D7114B1666001C429B /* KeyEventCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = A5C974CF11485FF10066F2AB /* KeyEventCocoa.h */; };
                A513B3D8114B166A001C429B /* KeyEventCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = A5C974D011485FF10066F2AB /* KeyEventCocoa.mm */; };
                A593CF8B1840535200BFCE27 /* InspectorWebAgentBase.h in Headers */ = {isa = PBXBuildFile; fileRef = A593CF8A1840535200BFCE27 /* InspectorWebAgentBase.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A5A2AF0B1829734300DE1729 /* PageDebuggable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5A2AF091829734300DE1729 /* PageDebuggable.cpp */; };
                A5A2AF0C1829734300DE1729 /* PageDebuggable.h in Headers */ = {isa = PBXBuildFile; fileRef = A5A2AF0A1829734300DE1729 /* PageDebuggable.h */; };
+               A5A7AA43132F0ECC00D3A3C2 /* WebAutocapitalize.h in Headers */ = {isa = PBXBuildFile; fileRef = A5A7AA42132F0ECC00D3A3C2 /* WebAutocapitalize.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A5ABB78713B904BC00F197E3 /* LineBreakIteratorPoolICU.h in Headers */ = {isa = PBXBuildFile; fileRef = A5ABB78613B904BC00F197E3 /* LineBreakIteratorPoolICU.h */; };
                A5AFB34F115151A700B045CB /* StepRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5AFB34D115151A700B045CB /* StepRange.cpp */; };
                A5AFB350115151A700B045CB /* StepRange.h in Headers */ = {isa = PBXBuildFile; fileRef = A5AFB34E115151A700B045CB /* StepRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A5C566AB127A3AAD00E8A3FF /* DiskImageCacheClientIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = A5C566AA127A3AAD00E8A3FF /* DiskImageCacheClientIOS.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               A5F6E16B132ED46E008EDAE3 /* Autocapitalize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5F6E16C132ED46E008EDAE3 /* Autocapitalize.cpp */; };
                A5F9EF701266750D00FCCF52 /* DiskImageCacheIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = A5F9EF6E1266750D00FCCF52 /* DiskImageCacheIOS.mm */; };
                A5F9EF711266750D00FCCF52 /* DiskImageCacheIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = A5F9EF6F1266750D00FCCF52 /* DiskImageCacheIOS.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A6148A6212E41D3A0044A784 /* DOMHTMLKeygenElementInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = A6148A6112E41D3A0044A784 /* DOMHTMLKeygenElementInternal.h */; };
                A454424D119B3687009BE912 /* RenderMeter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderMeter.h; sourceTree = "<group>"; };
                A456FA2411AD4A830020B420 /* LabelsNodeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LabelsNodeList.cpp; sourceTree = "<group>"; };
                A456FA2511AD4A830020B420 /* LabelsNodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelsNodeList.h; sourceTree = "<group>"; };
+               A501920C132EBF2E008BFE55 /* Autocapitalize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Autocapitalize.h; sourceTree = "<group>"; };
                A502C5DD13049B3500FC7D53 /* WebSafeGCActivityCallbackIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebSafeGCActivityCallbackIOS.h; path = ios/WebSafeGCActivityCallbackIOS.h; sourceTree = "<group>"; };
                A518225317E28CF100A9BA1D /* Scripts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Scripts; sourceTree = "<group>"; };
                A518225417E2A0D400A9BA1D /* InspectorOverlayPage.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = InspectorOverlayPage.css; sourceTree = "<group>"; };
                A593CF8A1840535200BFCE27 /* InspectorWebAgentBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorWebAgentBase.h; sourceTree = "<group>"; };
                A5A2AF091829734300DE1729 /* PageDebuggable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageDebuggable.cpp; sourceTree = "<group>"; };
                A5A2AF0A1829734300DE1729 /* PageDebuggable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageDebuggable.h; sourceTree = "<group>"; };
+               A5A7AA42132F0ECC00D3A3C2 /* WebAutocapitalize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebAutocapitalize.h; sourceTree = "<group>"; };
                A5ABB78613B904BC00F197E3 /* LineBreakIteratorPoolICU.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LineBreakIteratorPoolICU.h; sourceTree = "<group>"; };
                A5AFB34D115151A700B045CB /* StepRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StepRange.cpp; sourceTree = "<group>"; };
                A5AFB34E115151A700B045CB /* StepRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StepRange.h; sourceTree = "<group>"; };
                A5C566AA127A3AAD00E8A3FF /* DiskImageCacheClientIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiskImageCacheClientIOS.h; sourceTree = "<group>"; };
                A5C974CF11485FF10066F2AB /* KeyEventCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KeyEventCocoa.h; path = cocoa/KeyEventCocoa.h; sourceTree = "<group>"; };
                A5C974D011485FF10066F2AB /* KeyEventCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = KeyEventCocoa.mm; path = cocoa/KeyEventCocoa.mm; sourceTree = "<group>"; };
+               A5F6E16C132ED46E008EDAE3 /* Autocapitalize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Autocapitalize.cpp; sourceTree = "<group>"; };
                A5F9EF6E1266750D00FCCF52 /* DiskImageCacheIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DiskImageCacheIOS.mm; sourceTree = "<group>"; };
                A5F9EF6F1266750D00FCCF52 /* DiskImageCacheIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiskImageCacheIOS.h; sourceTree = "<group>"; };
                A6148A6112E41D3A0044A784 /* DOMHTMLKeygenElementInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMHTMLKeygenElementInternal.h; sourceTree = "<group>"; };
                                97C1F5511228558800EDE616 /* parser */,
                                4150F9ED12B6E0990008C860 /* shadow */,
                                B1AD4E7713A12A7200846B27 /* track */,
+                               A5F6E16C132ED46E008EDAE3 /* Autocapitalize.cpp */,
+                               A501920C132EBF2E008BFE55 /* Autocapitalize.h */,
                                379E61C5126CA5C300B63E8D /* BaseButtonInputType.cpp */,
                                379E61C6126CA5C300B63E8D /* BaseButtonInputType.h */,
                                379E61C7126CA5C300B63E8D /* BaseCheckableInputType.cpp */,
                                15C77089100D3C6A005BA267 /* ValidityState.idl */,
                                E44613B40CD6344E00FADA75 /* VoidCallback.h */,
                                E44613A00CD6331000FADA75 /* VoidCallback.idl */,
+                               A5A7AA42132F0ECC00D3A3C2 /* WebAutocapitalize.h */,
                                F55B3DAB1251F12D003EF269 /* WeekInputType.cpp */,
                                F55B3DAC1251F12D003EF269 /* WeekInputType.h */,
                        );
                                26E98A10130A9FCA008EB7B2 /* TextCodecASCIIFastPath.h in Headers */,
                                B2C3DA3C0D006C1D00EF6F26 /* TextCodecICU.h in Headers */,
                                B2C3DA3E0D006C1D00EF6F26 /* TextCodecLatin1.h in Headers */,
+                               A5A7AA43132F0ECC00D3A3C2 /* WebAutocapitalize.h in Headers */,
                                B2AFFC9A0D00A5DF0030074D /* TextCodecMac.h in Headers */,
                                B2C3DA400D006C1D00EF6F26 /* TextCodecUserDefined.h in Headers */,
                                B2C3DA420D006C1D00EF6F26 /* TextCodecUTF16.h in Headers */,
                                E4D58EB917B4ED8900CBDCA8 /* StyleFontSizeFunctions.h in Headers */,
                                1FAFBF1915A5FA7400083A20 /* UTIUtilities.h in Headers */,
                                2E3BBF081162DA1100B9409A /* UUID.h in Headers */,
+                               A501920E132EBF2E008BFE55 /* Autocapitalize.h in Headers */,
                                50D32858163B313F0016111E /* ValidatedCustomFilterOperation.h in Headers */,
                                F5A154281279534D00D0B0C0 /* ValidationMessage.h in Headers */,
                                F513A3EA15FF4841001526DB /* ValidationMessageClient.h in Headers */,
                                931CBD0C161A44E900E4C874 /* ScrollingStateNode.cpp in Sources */,
                                931CBD13161A44F800E4C874 /* ScrollingStateNodeMac.mm in Sources */,
                                931CBD0E161A44E900E4C874 /* ScrollingStateScrollingNode.cpp in Sources */,
+                               A5F6E16B132ED46E008EDAE3 /* Autocapitalize.cpp in Sources */,
                                0FA88EBD16A8D1BD00F99984 /* ScrollingStateScrollingNodeMac.mm in Sources */,
                                0FB8890E167D30160010CDA5 /* ScrollingStateStickyNode.cpp in Sources */,
                                931CBD10161A44E900E4C874 /* ScrollingStateTree.cpp in Sources */,
diff --git a/Source/WebCore/html/Autocapitalize.cpp b/Source/WebCore/html/Autocapitalize.cpp
new file mode 100644 (file)
index 0000000..5d2cf99
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Autocapitalize.h"
+
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+static const AtomicString& valueOn()
+{
+    static NeverDestroyed<const AtomicString> valueOn("on", AtomicString::ConstructFromLiteral);
+    return valueOn;
+}
+
+static const AtomicString& valueOff()
+{
+    static NeverDestroyed<const AtomicString> valueOff("off", AtomicString::ConstructFromLiteral);
+    return valueOff;
+}
+
+static const AtomicString& valueNone()
+{
+    static NeverDestroyed<const AtomicString> valueNone("none", AtomicString::ConstructFromLiteral);
+    return valueNone;
+}
+
+static const AtomicString& valueWords()
+{
+    static NeverDestroyed<const AtomicString> valueWords("words", AtomicString::ConstructFromLiteral);
+    return valueWords;
+}
+
+static const AtomicString& valueSentences()
+{
+    static NeverDestroyed<const AtomicString> valueSentences("sentences", AtomicString::ConstructFromLiteral);
+    return valueSentences;
+}
+
+static const AtomicString& valueAllCharacters()
+{
+    static NeverDestroyed<const AtomicString> valueAllCharacters("characters", AtomicString::ConstructFromLiteral);
+    return valueAllCharacters;
+}
+
+WebAutocapitalizeType autocapitalizeTypeForAttributeValue(const AtomicString& attributeValue)
+{
+    // Omitted / missing values are the Default state.
+    if (attributeValue.isNull() || attributeValue.isEmpty())
+        return WebAutocapitalizeTypeDefault;
+
+    if (equalIgnoringCase(attributeValue, valueOn()) || equalIgnoringCase(attributeValue, valueSentences()))
+        return WebAutocapitalizeTypeSentences;
+    if (equalIgnoringCase(attributeValue, valueOff()) || equalIgnoringCase(attributeValue, valueNone()))
+        return WebAutocapitalizeTypeNone;
+    if (equalIgnoringCase(attributeValue, valueWords()))
+        return WebAutocapitalizeTypeWords;
+    if (equalIgnoringCase(attributeValue, valueAllCharacters()))
+        return WebAutocapitalizeTypeAllCharacters;
+
+    // Unrecognized values fall back to "on".
+    return WebAutocapitalizeTypeSentences;
+}
+
+const AtomicString& stringForAutocapitalizeType(WebAutocapitalizeType type)
+{
+    switch (type) {
+    case WebAutocapitalizeTypeDefault:
+        return nullAtom;
+    case WebAutocapitalizeTypeNone:
+        return valueNone();
+    case WebAutocapitalizeTypeSentences:
+        return valueSentences();
+    case WebAutocapitalizeTypeWords:
+        return valueWords();
+    case WebAutocapitalizeTypeAllCharacters:
+        return valueAllCharacters();
+    }
+
+    ASSERT_NOT_REACHED();
+    return nullAtom;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/html/Autocapitalize.h b/Source/WebCore/html/Autocapitalize.h
new file mode 100644 (file)
index 0000000..809ff10
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Autocapitalize_h
+#define Autocapitalize_h
+
+#include "WebAutocapitalize.h"
+
+// FIXME: Forward declare AtomicString instead of including AtomicString.h once we upstream the iOS port.
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+WebAutocapitalizeType autocapitalizeTypeForAttributeValue(const AtomicString&);
+const AtomicString& stringForAutocapitalizeType(WebAutocapitalizeType);
+
+}
+
+#endif // Autocapitalize_h
index 02d4e651b3c8d1eda7a375bceaedc988acbf1ccc..7b7d2c817f0a97c9fbbea6e4360a3cca0b82db5d 100644 (file)
@@ -53,7 +53,10 @@ void BaseChooserOnlyDateAndTimeInputType::handleDOMActivateEvent(Event*)
     DateTimeChooserParameters parameters;
     if (!element().setupDateTimeChooserParameters(parameters))
         return;
+#if !PLATFORM(IOS)
+    // FIXME: Is this correct? Why don't we do this on iOS?
     m_dateTimeChooser = element().document().page()->chrome().openDateTimeChooser(this, parameters);
+#endif
 }
 
 void BaseChooserOnlyDateAndTimeInputType::createShadowSubtree()
index 213c9fffc71485f5c9894e52d9ee750501f21a3b..16f5df7e091483aeb3e1fd712b7d3b000cfb78e3 100644 (file)
@@ -173,5 +173,12 @@ bool BaseDateAndTimeInputType::valueMissing(const String& value) const
     return element().isRequired() && value.isEmpty();
 }
 
+#if PLATFORM(IOS)
+bool BaseDateAndTimeInputType::isKeyboardFocusable(KeyboardEvent*) const
+{
+    return !element().isReadOnly() && element().isTextFormControlFocusable();
+}
+#endif
+
 } // namespace WebCore
 #endif
index 68d20a8c751c7d3376166bd022babc48bad8b30d..e91905e44a7bf7b5fc208460516d8017059deb43 100644 (file)
@@ -49,10 +49,15 @@ protected:
     String serializeWithComponents(const DateComponents&) const;
     virtual bool setMillisecondToDateComponents(double, DateComponents*) const = 0;
     virtual String visibleValue() const OVERRIDE;
+#if PLATFORM(IOS)
+    virtual bool isKeyboardFocusable(KeyboardEvent*) const OVERRIDE;
+#endif
 
 private:
     virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const = 0;
+#if !PLATFORM(IOS)
     virtual DateComponents::Type dateType() const = 0;
+#endif
     virtual double valueAsDate() const OVERRIDE;
     virtual void setValueAsDate(double, ExceptionCode&) const OVERRIDE;
     virtual double valueAsDouble() const OVERRIDE;
index 4db43815f9b3f0b88907e8da43fe6e56b1f9a647..c07afb89e5a9655b061dd67eb3e322ca16656a1c 100644 (file)
@@ -94,8 +94,11 @@ FileInputType::~FileInputType()
     if (m_fileChooser)
         m_fileChooser->invalidate();
 
+#if !PLATFORM(IOS)
+    // FIXME: Is this correct? Why don't we do this on iOS?
     if (m_fileIconLoader)
         m_fileIconLoader->invalidate();
+#endif
 }
 
 Vector<FileChooserFileInfo> FileInputType::filesFromFormControlState(const FormControlState& state)
@@ -327,6 +330,9 @@ void FileInputType::multipleAttributeChanged()
 
 void FileInputType::requestIcon(const Vector<String>& paths)
 {
+#if PLATFORM(IOS)
+    UNUSED_PARAM(paths);
+#else
     if (!paths.size())
         return;
 
@@ -340,6 +346,7 @@ void FileInputType::requestIcon(const Vector<String>& paths)
     m_fileIconLoader = std::make_unique<FileIconLoader>(static_cast<FileIconLoaderClient&>(*this));
 
     chrome->loadIconForFiles(paths, m_fileIconLoader.get());
+#endif
 }
 
 void FileInputType::applyFileChooserSettings(const FileChooserSettings& settings)
@@ -391,6 +398,20 @@ void FileInputType::setFiles(PassRefPtr<FileList> files)
     input->setChangedSinceLastFormControlChangeEvent(false);
 }
 
+#if PLATFORM(IOS)
+void FileInputType::filesChosen(const Vector<FileChooserFileInfo>& paths, const String& displayString, Icon* icon)
+{
+    m_displayString = displayString;
+    filesChosen(paths);
+    updateRendering(icon);
+}
+
+String FileInputType::displayString() const
+{
+    return m_displayString;
+}
+#endif
+
 void FileInputType::filesChosen(const Vector<FileChooserFileInfo>& files)
 {
     setFiles(createFileList(files));
@@ -426,6 +447,7 @@ void FileInputType::updateRendering(PassRefPtr<Icon> icon)
         element().renderer()->repaint();
 }
 
+#if ENABLE(DRAG_SUPPORT)
 bool FileInputType::receiveDroppedFiles(const DragData& dragData)
 {
     Vector<String> paths;
@@ -454,6 +476,7 @@ bool FileInputType::receiveDroppedFiles(const DragData& dragData)
     }
     return true;
 }
+#endif // ENABLE(DRAG_SUPPORT)
 
 Icon* FileInputType::icon() const
 {
index 9cfaccf1295a93ac0da3306c0d2dc4b6785ef1d0..de9712eda8ad33fee85ddac1e3bab1677056f106 100644 (file)
@@ -41,6 +41,7 @@ namespace WebCore {
 
 class DragData;
 class FileList;
+class Icon;
 
 class FileInputType : public BaseClickableWithKeyInputType, private FileChooserClient, private FileIconLoaderClient {
 public:
@@ -62,10 +63,17 @@ private:
     virtual bool canChangeFromAnotherType() const OVERRIDE;
     virtual FileList* files() OVERRIDE;
     virtual void setFiles(PassRefPtr<FileList>) OVERRIDE;
+#if PLATFORM(IOS)
+    virtual String displayString() const OVERRIDE;
+#endif
     virtual bool canSetValue(const String&) OVERRIDE;
     virtual bool getTypeSpecificValue(String&) OVERRIDE; // Checked first, before internal storage or the value attribute.
     virtual void setValue(const String&, bool valueChanged, TextFieldEventBehavior) OVERRIDE;
+
+#if ENABLE(DRAG_SUPPORT)
     virtual bool receiveDroppedFiles(const DragData&) OVERRIDE;
+#endif
+
     virtual Icon* icon() const OVERRIDE;
     virtual bool isFileUpload() const OVERRIDE;
     virtual void createShadowSubtree() OVERRIDE;
@@ -75,6 +83,9 @@ private:
 
     // FileChooserClient implementation.
     virtual void filesChosen(const Vector<FileChooserFileInfo>&) OVERRIDE;
+#if PLATFORM(IOS)
+    virtual void filesChosen(const Vector<FileChooserFileInfo>&, const String& displayString, Icon*) OVERRIDE;
+#endif
 
     // FileIconLoaderClient implementation.
     virtual void updateRendering(PassRefPtr<Icon>) OVERRIDE;
@@ -88,10 +99,15 @@ private:
     void applyFileChooserSettings(const FileChooserSettings&);
 
     RefPtr<FileChooser> m_fileChooser;
+#if !PLATFORM(IOS)
     std::unique_ptr<FileIconLoader> m_fileIconLoader;
+#endif
 
     RefPtr<FileList> m_fileList;
     RefPtr<Icon> m_icon;
+#if PLATFORM(IOS)
+    String m_displayString;
+#endif
 };
 
 } // namespace WebCore
index 47e2312b924bdfb0c8d4978fc546ebd142b1d3e6..9752d3475e60f8209255326033f5ad4abbaed7b6 100644 (file)
@@ -379,6 +379,17 @@ FormController::~FormController()
 {
 }
 
+unsigned FormController::formElementsCharacterCount() const
+{
+    unsigned count = 0;
+    for (auto& element : m_formElementsWithState) {
+        FormControlState state = element->saveFormControlState();
+        if (state.valueSize() && element->isTextFormControl())
+            count += state[0].length();
+    }
+    return count;
+}
+
 static String formStateSignature()
 {
     // In the legacy version of serialized state, the first item was a name
index 9dbca625269e4b27d63cd64d18462d23c1dbf21e..e146b64f60cbeda784c109bd91401ee7e2a1ffef 100644 (file)
@@ -84,6 +84,9 @@ public:
 
     void registerFormElementWithState(HTMLFormControlElementWithState*);
     void unregisterFormElementWithState(HTMLFormControlElementWithState*);
+
+    unsigned formElementsCharacterCount() const;
+
     // This should be callled only by Document::formElementsState().
     Vector<String> formElementsState() const;
     // This should be callled only by Document::setStateForNewFormElements().
index 732d8e78954f0826e06b1ccd864771c8fe582aed..bf21352225ac49233fd5493638ba839ced00b40d 100644 (file)
@@ -99,6 +99,9 @@ void HTMLAppletElement::updateWidget(PluginCreationOption pluginCreationOption)
     if (!isFinishedParsingChildren())
         return;
 
+#if PLATFORM(IOS)
+    UNUSED_PARAM(pluginCreationOption);
+#else
     // FIXME: It's sadness that we have this special case here.
     //        See http://trac.webkit.org/changeset/25128 and
     //        plugins/netscape-plugin-setwindow-size.html
@@ -160,6 +163,7 @@ void HTMLAppletElement::updateWidget(PluginCreationOption pluginCreationOption)
     ASSERT(frame);
 
     renderer->setWidget(frame->loader().subframeLoader().createJavaAppletWidget(roundedIntSize(LayoutSize(contentWidth, contentHeight)), *this, paramNames, paramValues));
+#endif // !PLATFORM(IOS)
 }
 
 bool HTMLAppletElement::canEmbedJava() const
index 7196207dcfe4f775d300e45f769c761ff1a90f33..e0931e68709fa70165b7d998fe9428a9f6b9cdde 100644 (file)
@@ -91,7 +91,8 @@ bool HTMLAreaElement::mapMouseEvent(LayoutPoint location, const LayoutSize& size
     return true;
 }
 
-Path HTMLAreaElement::computePath(RenderElement* obj) const
+// FIXME: We should use RenderElement* instead of RenderObject* once we upstream iOS's DOMUIKitExtensions.{h, mm}.
+Path HTMLAreaElement::computePath(RenderObject* obj) const
 {
     if (!obj)
         return Path();
@@ -115,8 +116,9 @@ Path HTMLAreaElement::computePath(RenderElement* obj) const
     p.translate(toFloatSize(absPos));
     return p;
 }
-    
-LayoutRect HTMLAreaElement::computeRect(RenderElement* obj) const
+
+// FIXME: Use RenderElement* instead of RenderObject* once we upstream iOS's DOMUIKitExtensions.{h, mm}.
+LayoutRect HTMLAreaElement::computeRect(RenderObject* obj) const
 {
     return enclosingLayoutRect(computePath(obj).fastBoundingRect());
 }
index 1c2c8e3b444a387f8f4ebdd193710b812210e98b..2d61168f29daabc2572389c89d786d14668ae539 100644 (file)
@@ -41,8 +41,9 @@ public:
 
     bool mapMouseEvent(LayoutPoint location, const LayoutSize&, HitTestResult&);
 
-    LayoutRect computeRect(RenderElement*) const;
-    Path computePath(RenderElement*) const;
+    // FIXME: Use RenderElement* instead of RenderObject* once we upstream iOS's DOMUIKitExtensions.{h, mm}.
+    LayoutRect computeRect(RenderObject*) const;
+    Path computePath(RenderObject*) const;
 
     // The parent map's image.
     HTMLImageElement* imageElement() const;
index 644b24fdc43a76dd1d4e53bd5513c91d9daf228f..949d04fdf649ca66c1726e72b2a8df6229e29226 100644 (file)
@@ -203,6 +203,9 @@ oninvalid
 onkeydown
 onkeypress
 onkeyup
+ongesturestart
+ongesturechange
+ongestureend
 onload
 onloadeddata
 onloadedmetadata
@@ -342,3 +345,12 @@ webkitallowfullscreen
 webkitdirectory
 width
 wrap
+
+autocorrect
+autocapitalize
+data-youtube-id
+onwebkitcurrentplaybacktargetiswirelesschanged
+onwebkitplaybacktargetavailabilitychanged
+webkit-playsinline
+x-webkit-airplay
+x-webkit-wirelessvideoplaybackdisabled
index f1c65e5085a33cc7d890c8404d7ce9c443ebd6a6..8e3e299bf621a3a2f1ec8ffb2eb281ac1322a9da 100644 (file)
@@ -208,7 +208,11 @@ int HTMLBodyElement::scrollLeft()
     FrameView* view = frame->view();
     if (!view)
         return 0;
+#if PLATFORM(IOS)
+    return adjustForZoom(view->actualVisibleContentRect().x(), *frame);
+#else
     return adjustForZoom(view->scrollX(), *frame);
+#endif
 }
 
 void HTMLBodyElement::setScrollLeft(int scrollLeft)
@@ -232,7 +236,11 @@ int HTMLBodyElement::scrollTop()
     FrameView* view = frame->view();
     if (!view)
         return 0;
+#if PLATFORM(IOS)
+    return adjustForZoom(view->actualVisibleContentRect().y(), *frame);
+#else
     return adjustForZoom(view->scrollY(), *frame);
+#endif
 }
 
 void HTMLBodyElement::setScrollTop(int scrollTop)
index 9f8acec953c4df6cb252b0778c8200e737aa5430..2dd845a53102312e282d08c0c6319d63a0ab4b25 100644 (file)
@@ -65,7 +65,9 @@ static const int DefaultHeight = 150;
 // Firefox limits width/height to 32767 pixels, but slows down dramatically before it
 // reaches that limit. We limit by area instead, giving us larger maximum dimensions,
 // in exchange for a smaller maximum canvas size.
+#if !PLATFORM(IOS)
 static const float MaxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pixels
+#endif
 
 HTMLCanvasElement::HTMLCanvasElement(const QualifiedName& tagName, Document& document)
     : HTMLElement(tagName, document)
@@ -74,6 +76,10 @@ HTMLCanvasElement::HTMLCanvasElement(const QualifiedName& tagName, Document& doc
     , m_ignoreReset(false)
     , m_deviceScaleFactor(targetDeviceScaleFactor())
     , m_originClean(true)
+#if PLATFORM(IOS)
+    // FIXME: We should look to reconcile usage of MaxCanvasArea and m_maximumDecodedImageSize.
+    , m_maximumDecodedImageSize(document.settings() ? document.settings()->maximumDecodedImageSize() : 0)
+#endif
     , m_hasCreatedImageBuffer(false)
     , m_didClearImageBuffer(false)
 {
@@ -573,8 +579,13 @@ void HTMLCanvasElement::createImageBuffer() const
     if (!deviceSize.isExpressibleAsIntSize())
         return;
 
+#if PLATFORM(IOS)
+    if (deviceSize.width() * deviceSize.height() * 4 > m_maximumDecodedImageSize)
+        return;
+#else
     if (deviceSize.width() * deviceSize.height() > MaxCanvasArea)
         return;
+#endif
 
     IntSize bufferSize(deviceSize.width(), deviceSize.height());
     if (!bufferSize.width() || !bufferSize.height())
index 6b503192f2aa5e4c2fb069cc8d5a418d2fd3cac0..f3772cc4eea612ded2343aa6d1ba9f046ce29d8d 100644 (file)
@@ -127,6 +127,12 @@ public:
     void setOriginTainted() { m_originClean = false; }
     bool originClean() const { return m_originClean; }
 
+#if PLATFORM(IOS)
+    // FIXME: Can we use unsigned data types, unsigned or size_t?
+    void setMaximumDecodedImageSize(float maximumDecodedImageSize) { m_maximumDecodedImageSize = maximumDecodedImageSize; }
+    float maximumDecodedImageSize() { return m_maximumDecodedImageSize; }
+#endif
+
     AffineTransform baseTransform() const;
 
 #if ENABLE(WEBGL)    
@@ -176,6 +182,11 @@ private:
     float m_deviceScaleFactor;
     bool m_originClean;
 
+#if PLATFORM(IOS)
+    // FIXME: Can we use a unsigned data type, unsigned or size_t?
+    float m_maximumDecodedImageSize;
+#endif
+
     // m_createdImageBuffer means we tried to malloc the buffer.  We didn't necessarily get it.
     mutable bool m_hasCreatedImageBuffer;
     mutable bool m_didClearImageBuffer;
index 135d7d04796debf7c78fcb9e23336531144273f2..1cee83dcd92b06b59ddfa585b0431be4b3653e1d 100644 (file)
@@ -82,8 +82,8 @@ namespace WebCore {
 
 using namespace HTMLNames;
 
-HTMLDocument::HTMLDocument(Frame* frame, const URL& url, DocumentClassFlags documentClasses)
-    : Document(frame, url, documentClasses | HTMLDocumentClass)
+HTMLDocument::HTMLDocument(Frame* frame, const URL& url, DocumentClassFlags documentClasses, bool isSynthesized)
+    : Document(frame, url, documentClasses | HTMLDocumentClass, isSynthesized)
 {
     clearXMLVersion();
 }
index 15340de11111526db5128461f64cfe698a22ef1e..e9062c85b045685288f6c7d3f5abf8273997d220 100644 (file)
@@ -35,6 +35,12 @@ public:
     {
         return adoptRef(new HTMLDocument(frame, url));
     }
+
+    static PassRefPtr<HTMLDocument> createSynthesizedDocument(Frame* frame, const URL& url)
+    {
+        return adoptRef(new HTMLDocument(frame, url, true));
+    }
+
     virtual ~HTMLDocument();
 
     int width();
@@ -80,7 +86,7 @@ public:
     static bool isCaseSensitiveAttribute(const QualifiedName&);
 
 protected:
-    HTMLDocument(Frame*, const URL&, DocumentClassFlags = 0);
+    HTMLDocument(Frame*, const URL&, DocumentClassFlags = 0, bool isSynthesized = false);
 
 private:
     virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&);
index d50bb5055e1d661b51bb25c4d03747c5d3aecd68..cee9babf478d03789221aa97d55729fcb70a978b 100644 (file)
@@ -180,11 +180,17 @@ void HTMLElement::collectStyleForPresentationAttribute(const QualifiedName& name
             addPropertyToPresentationAttributeStyle(style, CSSPropertyWordWrap, CSSValueBreakWord);
             addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitNbspMode, CSSValueSpace);
             addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace);
+#if PLATFORM(IOS)
+            addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitTextSizeAdjust, CSSValueNone);
+#endif
         } else if (equalIgnoringCase(value, "plaintext-only")) {
             addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitUserModify, CSSValueReadWritePlaintextOnly);
             addPropertyToPresentationAttributeStyle(style, CSSPropertyWordWrap, CSSValueBreakWord);
             addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitNbspMode, CSSValueSpace);
             addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace);
+#if PLATFORM(IOS)
+            addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitTextSizeAdjust, CSSValueNone);
+#endif
         } else if (equalIgnoringCase(value, "false"))
             addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitUserModify, CSSValueReadOnly);
     } else if (name == hiddenAttr) {
@@ -284,6 +290,11 @@ static NEVER_INLINE void populateEventNameForAttributeLocalNameMap(HashMap<Atomi
         &onvolumechangeAttr,
         &onwaitingAttr,
         &onwheelAttr,
+#if ENABLE(IOS_GESTURE_EVENTS)
+        &ongesturechangeAttr,
+        &ongestureendAttr,
+        &ongesturestartAttr,
+#endif
 #if ENABLE(FULLSCREEN_API)
         &onwebkitfullscreenchangeAttr,
         &onwebkitfullscreenerrorAttr,
@@ -1077,6 +1088,21 @@ void HTMLElement::addHTMLColorToStyle(MutableStyleProperties& style, CSSProperty
     style.setProperty(propertyID, cssValuePool().createColorValue(parsedColor.rgb()));
 }
 
+bool HTMLElement::willRespondToMouseMoveEvents()
+{
+    return !isDisabledFormControl() && Element::willRespondToMouseMoveEvents();
+}
+
+bool HTMLElement::willRespondToMouseWheelEvents()
+{
+    return !isDisabledFormControl() && Element::willRespondToMouseWheelEvents();
+}
+
+bool HTMLElement::willRespondToMouseClickEvents()
+{
+    return !isDisabledFormControl() && Element::willRespondToMouseClickEvents();
+}
+
 } // namespace WebCore
 
 #ifndef NDEBUG
index 374abe5df08598d059625c7635887c040b23bc12..5caf475a7a5aaf4fb0e8b3953796c1724276c487 100644 (file)
@@ -92,6 +92,10 @@ public:
     virtual bool isHTMLUnknownElement() const { return false; }
     virtual bool isTextControlInnerTextElement() const { return false; }
 
+    virtual bool willRespondToMouseMoveEvents() OVERRIDE;
+    virtual bool willRespondToMouseWheelEvents() OVERRIDE;
+    virtual bool willRespondToMouseClickEvents() OVERRIDE;
+
     virtual bool isLabelable() const { return false; }
     virtual FormNamedItem* asFormNamedItem() { return 0; }
 
index 329663fa372ba50eedffbce8605ea3f621f3b68a..79ab37ee2e3c50f073a71ca6d71f65a537a3ac73 100644 (file)
@@ -469,6 +469,45 @@ bool HTMLFormControlElement::isDefaultButtonForForm() const
     return isSuccessfulSubmitButton() && form() && form()->defaultButton() == this;
 }
 
+#if ENABLE(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE)
+// FIXME: We should look to share these methods with class HTMLFormElement instead of duplicating them.
+
+bool HTMLFormControlElement::autocorrect() const
+{
+    const AtomicString& autocorrectValue = fastGetAttribute(autocorrectAttr);
+    if (!autocorrectValue.isEmpty())
+        return !equalIgnoringCase(autocorrectValue, "off");
+    if (HTMLFormElement* form = this->form())
+        return form->autocorrect();
+    return true;
+}
+
+void HTMLFormControlElement::setAutocorrect(bool autocorrect)
+{
+    setAttribute(autocorrectAttr, autocorrect ? AtomicString("on", AtomicString::ConstructFromLiteral) : AtomicString("off", AtomicString::ConstructFromLiteral));
+}
+
+WebAutocapitalizeType HTMLFormControlElement::autocapitalizeType() const
+{
+    WebAutocapitalizeType type = autocapitalizeTypeForAttributeValue(fastGetAttribute(autocapitalizeAttr));
+    if (type == WebAutocapitalizeTypeDefault) {
+        if (HTMLFormElement* form = this->form())
+            return form->autocapitalizeType();
+    }
+    return type;
+}
+
+const AtomicString& HTMLFormControlElement::autocapitalize() const
+{
+    return stringForAutocapitalizeType(autocapitalizeType());
+}
+
+void HTMLFormControlElement::setAutocapitalize(const AtomicString& value)
+{
+    setAttribute(autocapitalizeAttr, value);
+}
+#endif
+
 HTMLFormControlElement* HTMLFormControlElement::enclosingFormControlElement(Node* node)
 {
     for (; node; node = node->parentNode()) {
index 28e6790782b3b9f7ebeff56cbae100e04894bc40..efbbb58ec810703749eb0eb7a4110ded7fd96f49 100644 (file)
 #include "FormAssociatedElement.h"
 #include "LabelableElement.h"
 
+#if ENABLE(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE)
+#include "Autocapitalize.h"
+#endif
+
 namespace WebCore {
 
 class FormDataList;
@@ -85,6 +89,15 @@ public:
     virtual bool isActivatedSubmit() const { return false; }
     virtual void setActivatedSubmit(bool) { }
 
+#if ENABLE(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE)
+    bool autocorrect() const;
+    void setAutocorrect(bool);
+
+    WebAutocapitalizeType autocapitalizeType() const;
+    const AtomicString& autocapitalize() const;
+    void setAutocapitalize(const AtomicString&);
+#endif
+
     virtual bool willValidate() const OVERRIDE;
     void updateVisibleValidationMessage();
     void hideVisibleValidationMessage();
index 6ce185c9bcec4a3cba9ae6a0144aa8dc23d35d1f..0e82ec319e270d6f21dfc44ca243cf1a43bdd74b 100644 (file)
@@ -172,7 +172,7 @@ Node* HTMLFormElement::item(unsigned index)
 
 void HTMLFormElement::submitImplicitly(Event* event, bool fromImplicitSubmissionTrigger)
 {
-    int submissionTriggerCount = 0;
+    unsigned submissionTriggerCount = 0;
     for (unsigned i = 0; i < m_associatedElements.size(); ++i) {
         FormAssociatedElement* formAssociatedElement = m_associatedElements[i];
         if (!formAssociatedElement->isFormControlElement())
@@ -186,7 +186,13 @@ void HTMLFormElement::submitImplicitly(Event* event, bool fromImplicitSubmission
         } else if (formElement->canTriggerImplicitSubmission())
             ++submissionTriggerCount;
     }
-    if (fromImplicitSubmissionTrigger && submissionTriggerCount == 1)
+
+    if (!submissionTriggerCount)
+        return;
+
+    // Older iOS apps using WebViews expect the behavior of auto submitting multi-input forms.
+    Settings* settings = document().settings();
+    if (fromImplicitSubmissionTrigger && (submissionTriggerCount == 1 || (settings && settings->allowMultiElementImplicitSubmission())))
         prepareForSubmission(event);
 }
 
@@ -377,6 +383,40 @@ void HTMLFormElement::reset()
     m_isInResetFunction = false;
 }
 
+#if ENABLE(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE)
+// FIXME: We should look to share these methods with class HTMLFormControlElement instead of duplicating them.
+
+bool HTMLFormElement::autocorrect() const
+{
+    const AtomicString& autocorrectValue = fastGetAttribute(autocorrectAttr);
+    if (!autocorrectValue.isEmpty())
+        return !equalIgnoringCase(autocorrectValue, "off");
+    if (HTMLFormElement* form = this->form())
+        return form->autocorrect();
+    return true;
+}
+
+void HTMLFormElement::setAutocorrect(bool autocorrect)
+{
+    setAttribute(autocorrectAttr, autocorrect ? AtomicString("on", AtomicString::ConstructFromLiteral) : AtomicString("off", AtomicString::ConstructFromLiteral));
+}
+
+WebAutocapitalizeType HTMLFormElement::autocapitalizeType() const
+{
+    return autocapitalizeTypeForAttributeValue(fastGetAttribute(autocapitalizeAttr));
+}
+
+const AtomicString& HTMLFormElement::autocapitalize() const
+{
+    return stringForAutocapitalizeType(autocapitalizeType());
+}
+
+void HTMLFormElement::setAutocapitalize(const AtomicString& value)
+{
+    setAttribute(autocapitalizeAttr, value);
+}
+#endif
+
 void HTMLFormElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
 {
     if (name == actionAttr)
index 7603d8098484c4fb3e85b844958470b550fd7851..22fe9e1c1c28166219b3684fcbb33911631b15c9 100644 (file)
 #include "HTMLElement.h"
 #include <wtf/OwnPtr.h>
 
+#if ENABLE(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE)
+#include "Autocapitalize.h"
+#endif
+
 namespace WebCore {
 
 class Event;
@@ -61,6 +65,15 @@ public:
 
     bool shouldAutocomplete() const;
 
+#if ENABLE(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE)
+    bool autocorrect() const;
+    void setAutocorrect(bool);
+
+    WebAutocapitalizeType autocapitalizeType() const;
+    const AtomicString& autocapitalize() const;
+    void setAutocapitalize(const AtomicString&);
+#endif
+
     // FIXME: Should rename these two functions to say "form control" or "form-associated element" instead of "form element".
     void registerFormElement(FormAssociatedElement*);
     void removeFormElement(FormAssociatedElement*);
index fa4c157e4689b027613852de8e775e0175926399..8493f7ad8aa3efcdcd1b7fa11145c978abffda55 100644 (file)
@@ -36,6 +36,9 @@
 
     getter Element (unsigned long index);
 
+    [Conditional=IOS_AUTOCORRECT_AND_AUTOCAPITALIZE] attribute boolean autocorrect;
+    [Conditional=IOS_AUTOCORRECT_AND_AUTOCAPITALIZE, TreatNullAs=NullString] attribute DOMString autocapitalize;
+
 #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
     [ImplementedAs=submitFromJavaScript] void submit();
 #else
index 54bff65830d98d031c9b254319cc90a46688cf74..470dd61e34a059ca296d3b695fc00c1b75978041 100644 (file)
@@ -37,6 +37,10 @@ public:
 private:
     HTMLIFrameElement(const QualifiedName&, Document&);
 
+#if PLATFORM(IOS)
+    virtual bool isKeyboardFocusable(KeyboardEvent*) const OVERRIDE { return false; }
+#endif
+
     virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
     virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE;
     virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStyleProperties&) OVERRIDE;
index 3a4d9901c464f120ffbd6f12b73b9fd2e0467bae..37e88b4adf9c44b3f18439ac267cf9bd3244d10d 100644 (file)
@@ -1210,7 +1210,6 @@ void HTMLInputElement::defaultEventHandler(Event* evt)
 
 bool HTMLInputElement::willRespondToMouseClickEvents()
 {
-    // FIXME: Consider implementing willRespondToMouseClickEvents() in InputType if more accurate results are necessary.
     if (!isDisabledFormControl())
         return true;
 
@@ -1351,16 +1350,25 @@ void HTMLInputElement::setFiles(PassRefPtr<FileList> files)
     m_inputType->setFiles(files);
 }
 
+#if ENABLE(DRAG_SUPPORT)
 bool HTMLInputElement::receiveDroppedFiles(const DragData& dragData)
 {
     return m_inputType->receiveDroppedFiles(dragData);
 }
+#endif
 
 Icon* HTMLInputElement::icon() const
 {
     return m_inputType->icon();
 }
 
+#if PLATFORM(IOS)
+String HTMLInputElement::displayString() const
+{
+    return m_inputType->displayString();
+}
+#endif
+
 bool HTMLInputElement::canReceiveDroppedFiles() const
 {
     return m_canReceiveDroppedFiles;
@@ -1631,6 +1639,13 @@ bool HTMLInputElement::isSpeechEnabled() const
 
 #endif
 
+#if PLATFORM(IOS)
+DateComponents::Type HTMLInputElement::dateType() const
+{
+    return m_inputType->dateType();
+}
+#endif
+
 bool HTMLInputElement::isTextButton() const
 {
     return m_inputType->isTextButton();
index 02b2c4f7dec194660510cc1447bccee0a9373b04..af452528e63c3637642976dd5a0b683bf260c4ba 100644 (file)
 #include "HTMLTextFormControlElement.h"
 #include "StepRange.h"
 
+#if PLATFORM(IOS)
+#include "DateComponents.h"
+#endif
+
 namespace WebCore {
 
 class CheckedRadioButtons;
@@ -138,6 +142,10 @@ public:
     bool isSpeechEnabled() const;
 #endif
 
+#if PLATFORM(IOS)
+    DateComponents::Type dateType() const;
+#endif
+
     HTMLElement* containerElement() const;
     virtual TextControlInnerTextElement* innerTextElement() const OVERRIDE;
     HTMLElement* innerBlockElement() const;
@@ -243,10 +251,15 @@ public:
     FileList* files();
     void setFiles(PassRefPtr<FileList>);
 
+#if ENABLE(DRAG_SUPPORT)
     // Returns true if the given DragData has more than one dropped files.
     bool receiveDroppedFiles(const DragData&);
+#endif
 
     Icon* icon() const;
+#if PLATFORM(IOS)
+    String displayString() const;
+#endif
     // These functions are used for rendering the input active during a
     // drag-and-drop operation.
     bool canReceiveDroppedFiles() const;
index 727bf693a894581871cc7b293162b68c66e7c119..434202c4e190d90662b4c066eb3187fd118a9d9b 100644 (file)
@@ -125,6 +125,9 @@ interface HTMLInputElement : HTMLElement {
     readonly attribute URL absoluteImageURL;
 #endif
 
+    [Conditional=IOS_AUTOCORRECT_AND_AUTOCAPITALIZE] attribute boolean autocorrect;
+    [Conditional=IOS_AUTOCORRECT_AND_AUTOCAPITALIZE, TreatNullAs=NullString] attribute DOMString autocapitalize;
+
     // See http://www.w3.org/TR/html-media-capture/
     [Conditional=MEDIA_CAPTURE] attribute DOMString capture;
 };
index 2ad9a3874c2bec62f62d2972ea19550c273f22e1..1cbed01e6c6fe9b48750f81de535c580bc046266 100644 (file)
@@ -141,10 +141,7 @@ void HTMLLabelElement::defaultEventHandler(Event* evt)
 
 bool HTMLLabelElement::willRespondToMouseClickEvents()
 {
-    if (control() && control()->willRespondToMouseClickEvents())
-        return true;
-
-    return HTMLElement::willRespondToMouseClickEvents();
+    return (control() && control()->willRespondToMouseClickEvents()) || HTMLElement::willRespondToMouseClickEvents();
 }
 
 void HTMLLabelElement::focus(bool, FocusDirection direction)
index f6bf82fe4f20a8221fa3bf8f4dc4822caf466baf..253df8f74eab518a2dac84b1189f49a4583d6783 100644 (file)
@@ -83,6 +83,7 @@
 
 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
 #include "RenderEmbeddedObject.h"
+#include "SubframeLoader.h"
 #include "Widget.h"
 #endif
 
 #include "MediaElementAudioSourceNode.h"
 #endif
 
+#if PLATFORM(IOS)
+#include "RuntimeApplicationChecksIOS.h"
+#endif
+
+#if ENABLE(IOS_AIRPLAY)
+#include "WebKitPlaybackTargetAvailabilityEvent.h"
+#endif
+
 #if PLATFORM(MAC)
 #include "DisplaySleepDisabler.h"
 #endif
@@ -248,7 +257,11 @@ private:
 #endif
 
 HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& document, bool createdByParser)
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+    : HTMLFrameOwnerElement(tagName, document)
+#else
     : HTMLElement(tagName, document)
+#endif
     , ActiveDOMObject(&document)
     , m_loadTimer(this, &HTMLMediaElement::loadTimerFired)
     , m_progressEventTimer(this, &HTMLMediaElement::progressEventTimerFired)
@@ -310,6 +323,10 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum
 #if ENABLE(PAGE_VISIBILITY_API)
     , m_isDisplaySleepDisablingSuspended(document.hidden())
 #endif
+#if PLATFORM(IOS)
+    , m_requestingPlay(false)
+    , m_userStartedPlayback(false)
+#endif
 #if ENABLE(VIDEO_TRACK)
     , m_tracksAreReady(true)
     , m_haveVisibleTextTrack(false)
@@ -335,6 +352,9 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum
     LOG(Media, "HTMLMediaElement::HTMLMediaElement");
     setHasCustomStyleResolveCallbacks();
 
+    // FIXME: We should clean up and look to better merge the iOS and non-iOS code below.
+    Settings* settings = document.settings();
+#if !PLATFORM(IOS)
     document.registerForMediaVolumeCallbacks(this);
     document.registerForPrivateBrowsingStateChangedCallbacks(this);
 
@@ -342,10 +362,20 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum
     document.registerForVisibilityStateChangedCallbacks(this);
 #endif
 
-    if (document.settings() && document.settings()->mediaPlaybackRequiresUserGesture()) {
+    if (settings && settings->mediaPlaybackRequiresUserGesture()) {
         addBehaviorRestriction(RequireUserGestureForRateChangeRestriction);
         addBehaviorRestriction(RequireUserGestureForLoadRestriction);
     }
+#else
+    m_sendProgressEvents = false;
+    if (!settings || settings->mediaPlaybackRequiresUserGesture()) {
+        addBehaviorRestriction(RequireUserGestureForRateChangeRestriction);
+#if ENABLE(IOS_AIRPLAY)
+        addBehaviorRestriction(RequireUserGestureToShowPlaybackTargetPicker);
+#endif
+    } else
+        m_restrictions = NoRestrictions;
+#endif // !PLATFORM(IOS)
 
     addElementToDocumentMap(*this, document);
 
@@ -392,6 +422,11 @@ HTMLMediaElement::~HTMLMediaElement()
     }
 #endif
 
+#if ENABLE(IOS_AIRPLAY)
+    if (m_player && !hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent))
+        m_player->setHasPlaybackTargetAvailabilityListeners(false);
+#endif
+
     if (m_mediaController) {
         m_mediaController->removeMediaElement(this);
         m_mediaController = 0;
@@ -456,11 +491,46 @@ bool HTMLMediaElement::isMouseFocusable() const
     return false;
 }
 
+#if PLATFORM(IOS)
+bool HTMLMediaElement::parseMediaPlayerAttribute(const QualifiedName& name, const AtomicString& value)
+{
+    ASSERT(m_player);
+    if (name == data_youtube_idAttr) {
+        m_player->attributeChanged(name.toString(), value);
+        return true;
+    }
+    if (name == titleAttr) {
+        m_player->attributeChanged(name.toString(), value);
+        return true;
+    }
+
+    if (Settings* settings = document().settings()) {
+#if ENABLE(IOS_AIRPLAY)
+        if (name == webkitairplayAttr && settings->mediaPlaybackAllowsAirPlay()) {
+            m_player->attributeChanged(name.toString(), value);
+            return true;
+        }
+#endif
+        if (name == webkit_playsinlineAttr && settings->mediaPlaybackAllowsInline()) {
+            m_player->attributeChanged(name.toString(), ASCIILiteral(value.isNull() ? "false" : "true"));
+            return true;
+        }
+    }
+    return false;
+}
+#endif
+
 void HTMLMediaElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
 {
     if (name == srcAttr) {
+#if PLATFORM(IOS)
+        // Note, unless the restriction on requiring user action has been removed,
+        // do not begin downloading data on iOS.
+        if (!userGestureRequiredForLoad() && !value.isNull()) {
+#else
         // Trigger a reload, as long as the 'src' attribute is present.
         if (!value.isNull()) {
+#endif
             clearMediaPlayer(LoadMediaResource);
             scheduleDelayedAction(LoadMediaResource);
         }
@@ -535,6 +605,16 @@ void HTMLMediaElement::parseAttribute(const QualifiedName& name, const AtomicStr
         setAttributeEventListener(eventNames().webkitbeginfullscreenEvent, name, value);
     else if (name == onwebkitendfullscreenAttr)
         setAttributeEventListener(eventNames().webkitendfullscreenEvent, name, value);
+#if ENABLE(IOS_AIRPLAY)
+    else if (name == onwebkitcurrentplaybacktargetiswirelesschangedAttr)
+        setAttributeEventListener(eventNames().webkitcurrentplaybacktargetiswirelesschangedEvent, name, value);
+    else if (name == onwebkitplaybacktargetavailabilitychangedAttr)
+        setAttributeEventListener(eventNames().webkitplaybacktargetavailabilitychangedEvent, name, value);
+#endif
+#if PLATFORM(IOS)
+    else if (m_player && parseMediaPlayerAttribute(name, value))
+        return;
+#endif
     else
         HTMLElement::parseAttribute(name, value);
 }
@@ -612,7 +692,11 @@ Node::InsertionNotificationRequest HTMLMediaElement::insertedInto(ContainerNode&
     if (insertionPoint.inDocument()) {
         m_inActiveDocument = true;
 
-        if (m_networkState == NETWORK_EMPTY && !getAttribute(srcAttr).isEmpty())
+#if PLATFORM(IOS)
+        if (!userGestureRequiredForLoad() && m_networkState == NETWORK_EMPTY && !fastGetAttribute(srcAttr).isEmpty())
+#else
+        if (m_networkState == NETWORK_EMPTY && !fastGetAttribute(srcAttr).isEmpty())
+#endif
             scheduleDelayedAction(LoadMediaResource);
     }
 
@@ -824,6 +908,15 @@ void HTMLMediaElement::load()
         removeBehaviorsRestrictionsAfterFirstUserGesture();
     prepareForLoad();
     loadInternal();
+
+#if PLATFORM(IOS)
+    // Unless this method was called directly by the user or the application allows any script to trigger playback,
+    // return now because prepareToPlay() tells the media engine to start loading data as soon as the movie validates.
+    Settings* settings = document().settings();
+    if (!m_loadInitiatedByUserGesture && (!settings || settings->mediaPlaybackRequiresUserGesture()))
+        return;
+#endif
+
     prepareToPlay();
 }
 
@@ -860,7 +953,7 @@ void HTMLMediaElement::prepareForLoad()
 #endif
 
 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
-    if (shouldUseVideoPluginProxy())
+    if (shouldUseVideoPluginProxy()) {
         if (m_player)
             m_player->cancelLoad();
         else
@@ -912,6 +1005,12 @@ void HTMLMediaElement::prepareForLoad()
     if (m_preload != MediaPlayer::None)
         setShouldDelayLoadEvent(true);
 
+#if PLATFORM(IOS)
+    Settings* settings = document().settings();
+    if (m_preload != MediaPlayer::None && settings && settings->mediaDataLoadsAutomatically())
+        prepareToPlay();
+#endif
+
     configureMediaControls();
 }
 
@@ -2511,6 +2610,16 @@ bool HTMLMediaElement::ended() const
 
 bool HTMLMediaElement::autoplay() const
 {
+#if PLATFORM(IOS)
+    // Unless the restriction on requiring user actions has been lifted, we do not
+    // allow playback to start just because the page has "autoplay". They are either
+    // lifted through Settings, or once the user explictly calls load() or play()
+    // because they have OK'ed us loading data. This allows playback to continue if
+    // the URL is changed while the movie is playing.
+    if (userGestureRequiredForRateChange() || userGestureRequiredForLoad())
+        return false;
+#endif
+
     return fastHasAttribute(autoplayAttr);
 }
 
@@ -2553,6 +2662,10 @@ void HTMLMediaElement::play()
     if (ScriptController::processingUserGesture())
         removeBehaviorsRestrictionsAfterFirstUserGesture();
 
+#if PLATFORM(IOS)
+    userRequestsMediaLoading();
+#endif
+
     playInternal();
 }
 
@@ -2581,6 +2694,9 @@ void HTMLMediaElement::playInternal()
             scheduleEvent(eventNames().playingEvent);
     }
     m_autoplaying = false;
+#if PLATFORM(IOS)
+    m_requestingPlay = true;
+#endif
     updatePlayState();
     updateMediaController();
 }
@@ -2601,8 +2717,15 @@ void HTMLMediaElement::pauseInternal()
     LOG(Media, "HTMLMediaElement::pauseInternal");
 
     // 4.8.10.9. Playing the media resource
-    if (!m_player || m_networkState == NETWORK_EMPTY)
+    if (!m_player || m_networkState == NETWORK_EMPTY) {
+#if PLATFORM(IOS)
+        // Unless the restriction on media requiring user action has been lifted
+        // don't trigger loading if a script calls pause().
+        if (userGestureRequiredForRateChange())
+            return;
+#endif
         scheduleDelayedAction(LoadMediaResource);
+    }
 
     m_autoplaying = false;
 
@@ -2777,12 +2900,14 @@ void HTMLMediaElement::setVolume(double vol, ExceptionCode& ec)
         return;
     }
     
+#if !PLATFORM(IOS)
     if (m_volume != vol) {
         m_volume = vol;
         m_volumeInitialized = true;
         updateVolume();
         scheduleEvent(eventNames().volumechangeEvent);
     }
+#endif
 }
 
 bool HTMLMediaElement::muted() const
@@ -2794,6 +2919,9 @@ void HTMLMediaElement::setMuted(bool muted)
 {
     LOG(Media, "HTMLMediaElement::setMuted(%s)", boolString(muted));
 
+#if PLATFORM(IOS)
+    UNUSED_PARAM(muted);
+#else
     if (m_muted != muted) {
         m_muted = muted;
         // Avoid recursion when the player reports volume changes.
@@ -2806,6 +2934,7 @@ void HTMLMediaElement::setMuted(bool muted)
         }
         scheduleEvent(eventNames().volumechangeEvent);
     }
+#endif
 }
 
 void HTMLMediaElement::togglePlayState()
@@ -3757,9 +3886,14 @@ void HTMLMediaElement::mediaPlayerTimeChanged(MediaPlayer*)
             updateMediaController();
         } else
             m_sentEndEvent = false;
-    }
-    else
+    } else {
+#if PLATFORM(IOS)
+        // The controller changes movie time directly instead of calling through here so we need
+        // to post timeupdate events in response to time changes.
+        scheduleTimeupdateEvent(false);
+#endif
         m_sentEndEvent = false;
+    }
 
     updatePlayState();
     endProcessingMediaPlayerCallback();
@@ -4053,6 +4187,14 @@ double HTMLMediaElement::maxTimeSeekable() const
     
 void HTMLMediaElement::updateVolume()
 {
+#if PLATFORM(IOS)
+    // Only the user can change audio volume so update the cached volume and post the changed event.
+    float volume = m_player->volume();
+    if (m_volume != volume) {
+        m_volume = volume;
+        scheduleEvent(eventNames().volumechangeEvent);
+    }
+#else
     if (!m_player)
         return;
 
@@ -4074,6 +4216,7 @@ void HTMLMediaElement::updateVolume()
 
     if (hasMediaControls())
         mediaControls()->changedVolume();
+#endif
 }
 
 void HTMLMediaElement::updatePlayState()
@@ -4095,6 +4238,13 @@ void HTMLMediaElement::updatePlayState()
     bool shouldBePlaying = potentiallyPlaying();
     bool playerPaused = m_player->paused();
 
+#if PLATFORM(IOS)
+    if (shouldBePlaying && !m_requestingPlay && !m_player->readyForPlayback())
+        shouldBePlaying = false;
+    else if (!shouldBePlaying && m_requestingPlay && m_player->readyForPlayback())
+        shouldBePlaying = true;
+#endif
+
     LOG(Media, "HTMLMediaElement::updatePlayState - shouldBePlaying = %s, playerPaused = %s", 
         boolString(shouldBePlaying), boolString(playerPaused));
 
@@ -4140,6 +4290,10 @@ void HTMLMediaElement::updatePlayState()
             mediaControls()->playbackStopped();
         m_activityToken = nullptr;
     }
+    
+#if PLATFORM(IOS)
+    m_requestingPlay = false;
+#endif
 
     updateMediaController();
 
@@ -4163,8 +4317,14 @@ void HTMLMediaElement::userCancelledLoad()
 {
     LOG(Media, "HTMLMediaElement::userCancelledLoad");
 
+    // FIXME: We should look to reconcile the iOS and non-iOS code (below).
+#if PLATFORM(IOS)
+    if (m_networkState == NETWORK_EMPTY || m_readyState >= HAVE_METADATA)
+        return;
+#else
     if (m_networkState == NETWORK_EMPTY || m_completelyLoaded)
         return;
+#endif
 
     // If the media data fetching process is aborted by the user:
 
@@ -4315,6 +4475,9 @@ void HTMLMediaElement::resume()
         // m_error is only left at MEDIA_ERR_ABORTED when the document becomes inactive (it is set to
         //  MEDIA_ERR_ABORTED while the abortEvent is being sent, but cleared immediately afterwards).
         // This behavior is not specified but it seems like a sensible thing to do.
+#if PLATFORM(IOS)
+        // FIXME: <rdar://problem/9751303> Merge: Does r1033092 need to be refixed in ToT?
+#endif
         // As it is not safe to immedately start loading now, let's schedule a load.
         scheduleDelayedAction(LoadMediaResource);
     }
@@ -4359,6 +4522,7 @@ void HTMLMediaElement::defaultEventHandler(Event* event)
     HTMLElement::defaultEventHandler(event);
 }
 
+#if !PLATFORM(IOS)
 bool HTMLMediaElement::willRespondToMouseClickEvents()
 {
 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
@@ -4367,6 +4531,7 @@ bool HTMLMediaElement::willRespondToMouseClickEvents()
 #endif
     return HTMLElement::willRespondToMouseClickEvents();
 }
+#endif // !PLATFORM(IOS)
 
 #if ENABLE(VIDEO_TRACK)
 bool HTMLMediaElement::requiresTextTrackRepresentation() const
@@ -4392,12 +4557,53 @@ void HTMLMediaElement::ensureMediaPlayer()
 void HTMLMediaElement::deliverNotification(MediaPlayerProxyNotificationType notification)
 {
     if (notification == MediaPlayerNotificationPlayPauseButtonPressed) {
+#if PLATFORM(IOS)
+        userRequestsMediaLoading();
+#endif
         togglePlayState();
         return;
     }
+#if PLATFORM(IOS)
+    else if (notification == MediaPlayerRequestBeginPlayback) {
+        if (m_paused)
+            playInternal();
+    } else if (notification == MediaPlayerRequestPausePlayback) {
+        if (!m_paused)
+            pauseInternal();
+    } else if (notification == MediaPlayerNotificationLoseFocus) {
+        if (!m_paused)
+            pauseInternal();
+    } else if (notification == MediaPlayerNotificationDidPlayToTheEnd) {
+        if (!m_paused && !loop())
+            pauseInternal();
+    } else if (notification == MediaPlayerNotificationMediaValidated || notification == MediaPlayerNotificationReadyForInspection) {
+        // The media player sometimes reports an apparently spurious error just as we request playback, and then follows almost
+        // immediately with ReadyForInspection and/or MediaValidated. The spec doesn't deal with a "fatal" error followed
+        // by ressurection, so if we have set an error clear it now.
+        m_error = 0;
+    } else if (notification == MediaPlayerNotificationEnteredFullscreen) {
+        scheduleEvent(eventNames().webkitbeginfullscreenEvent);
+        m_isFullscreen = true;
+    } else if (notification == MediaPlayerNotificationExitedFullscreen) {
+        scheduleEvent(eventNames().webkitendfullscreenEvent);
+        m_isFullscreen = false;
+    }
+#endif
 
     if (m_player)
         m_player->deliverNotification(notification);
+
+#if PLATFORM(IOS)
+    if (notification == MediaPlayerNotificationMediaValidated) {
+        // If the element is supposed to autoplay and we allow it, tell the media engine to begin loading
+        // data now. Playback will begin automatically when enough data has loaded.
+        if (m_autoplaying && m_paused && autoplay())
+            prepareToPlay();
+    } else if (notification == MediaPlayerNotificationEnteredFullscreen)
+        didBecomeFullscreenElement();
+    else if (notification == MediaPlayerNotificationExitedFullscreen)
+        willStopBeingFullscreenElement();
+#endif
 }
 
 void HTMLMediaElement::setMediaPlayerProxy(WebMediaPlayerProxy* proxy)
@@ -4426,7 +4632,13 @@ void HTMLMediaElement::getPluginProxyParams(URL& url, Vector<String>& names, Vec
         values.append(ASCIILiteral("true"));
     }
 
-    url = src();
+#if PLATFORM(IOS)
+    // Don't pass the URL to the plug-in as part of the initialization arguments, we always pass the URL
+    // in loadResource and calling selectNextSourceChild here can mess up the processing of <source>
+    // elements later.
+    UNUSED_PARAM(url);
+#else
+    url = getNonEmptyURLAttribute(srcAttr);
     if (!isSafeToLoadURL(url, Complain))
         url = selectNextSourceChild(0, 0, DoNothing);
 
@@ -4435,6 +4647,44 @@ void HTMLMediaElement::getPluginProxyParams(URL& url, Vector<String>& names, Vec
         names.append(ASCIILiteral("_media_element_src_"));
         values.append(m_currentSrc.string());
     }
+#endif
+
+#if PLATFORM(IOS)
+    Settings* settings = document().settings();
+    if (settings && settings->mediaPlaybackAllowsInline() && (applicationIsDumpRenderTree() || fastHasAttribute(webkit_playsinlineAttr))) {
+        names.append(ASCIILiteral("_media_element_allow_inline_"));
+        values.append(ASCIILiteral("true"));
+    }
+
+    String airplay = fastGetAttribute(webkitairplayAttr);
+    if (equalIgnoringCase(airplay, "allow") || equalIgnoringCase(airplay, "deny")) {
+        names.append(ASCIILiteral("_media_element_airplay_"));
+        values.append(airplay.lower());
+    }
+
+    if (fastHasAttribute(data_youtube_idAttr)) {
+        names.append(ASCIILiteral("_media_element_youtube_video_id_"));
+        values.append(fastGetAttribute(data_youtube_idAttr));
+    }
+
+    String interfaceName = settings ? settings->networkInterfaceName() : String();
+    if (!interfaceName.isEmpty()) {
+        names.append(ASCIILiteral("_media_element_network_interface_name"));
+        values.append(interfaceName);
+    }
+
+    if (fastHasAttribute(titleAttr)) {
+        names.append(titleAttr.toString());
+        values.append(fastGetAttribute(titleAttr));
+    }
+#endif
+
+#if ENABLE(IOS_AIRPLAY)
+    if (isVideo() && fastHasAttribute(webkitwirelessvideoplaybackdisabledAttr)) {
+        names.append(ASCIILiteral("_media_element_wireless_video_playback_disabled"));
+        values.append(ASCIILiteral("true"));
+    }
+#endif
 }
 
 void HTMLMediaElement::createMediaPlayerProxy()
@@ -4480,6 +4730,79 @@ void HTMLMediaElement::updateWidget(PluginCreationOption)
 
 #endif // ENABLE(PLUGIN_PROXY_FOR_VIDEO)
 
+#if ENABLE(IOS_AIRPLAY)
+void HTMLMediaElement::webkitShowPlaybackTargetPicker()
+{
+    if (!document().page())
+        return;
+
+    if (!m_player)
+        return;
+
+    if (userGestureRequiredToShowPlaybackTargetPicker() && !ScriptController::processingUserGesture())
+        return;
+
+    if (document().settings()->mediaPlaybackAllowsAirPlay())
+        return;
+
+    m_player->showPlaybackTargetPicker();
+}
+
+bool HTMLMediaElement::webkitCurrentPlaybackTargetIsWireless() const
+{
+    return m_player && m_player->isCurrentPlaybackTargetWireless();
+}
+
+void HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged(MediaPlayer*)
+{
+    scheduleEvent(eventNames().webkitcurrentplaybacktargetiswirelesschangedEvent);
+}
+
+void HTMLMediaElement::mediaPlayerPlaybackTargetAvailabilityChanged(MediaPlayer*)
+{
+    enqueuePlaybackTargetAvailabilityChangedEvent();
+}
+
+bool HTMLMediaElement::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
+{
+    if (eventType != eventNames().webkitplaybacktargetavailabilitychangedEvent)
+        return Node::addEventListener(eventType, listener, useCapture);
+
+    bool isFirstAvailabilityChangedListener = !hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent);
+    if (!Node::addEventListener(eventType, listener, useCapture))
+        return false;
+    if (m_player && isFirstAvailabilityChangedListener)
+        m_player->setHasPlaybackTargetAvailabilityListeners(true);
+
+    enqueuePlaybackTargetAvailabilityChangedEvent(); // Ensure the event listener gets at least one event.
+    return true;
+}
+
+bool HTMLMediaElement::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
+{
+    if (eventType != eventNames().webkitplaybacktargetavailabilitychangedEvent)
+        return Node::removeEventListener(eventType, listener, useCapture);
+
+    if (!Node::removeEventListener(eventType, listener, useCapture))
+        return false;
+
+    bool didRemoveLastAvailabilityChangedListener = !hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent);
+    if (m_player && didRemoveLastAvailabilityChangedListener)
+        m_player->setHasPlaybackTargetAvailabilityListeners(false);
+    return true;
+}
+
+void HTMLMediaElement::enqueuePlaybackTargetAvailabilityChangedEvent()
+{
+    if (!m_player)
+        return;
+    bool isAirPlayAvailable = m_player->hasWirelessPlaybackTargets();
+    RefPtr<Event> event = WebKitPlaybackTargetAvailabilityEvent::create(eventNames().webkitplaybacktargetavailabilitychangedEvent, isAirPlayAvailable);
+    event->setTarget(this);
+    m_asyncEventQueue.enqueueEvent(event.release());
+}
+#endif
+
 bool HTMLMediaElement::isFullscreen() const
 {
     if (m_isFullscreen)
@@ -4518,8 +4841,13 @@ void HTMLMediaElement::enterFullscreen()
     if (hasMediaControls())
         mediaControls()->enteredFullscreen();
     if (document().page()) {
+#if !PLATFORM(IOS)
         document().page()->chrome().client().enterFullscreenForNode(this);
         scheduleEvent(eventNames().webkitbeginfullscreenEvent);
+#else
+        if (m_player)
+            m_player->enterFullscreen();
+#endif
     }
 }
 
@@ -4541,8 +4869,13 @@ void HTMLMediaElement::exitFullscreen()
     if (document().page()) {
         if (document().page()->chrome().requiresFullscreenForVideoPlayback())
             pauseInternal();
+#if !PLATFORM(IOS)
         document().page()->chrome().client().exitFullscreenForNode(this);
         scheduleEvent(eventNames().webkitendfullscreenEvent);
+#else
+        if (m_player)
+            m_player->exitFullscreen();
+#endif
     }
 }
 
@@ -4939,6 +5272,13 @@ void HTMLMediaElement::createMediaPlayer()
         m_audioSourceNode->unlock();
     }
 #endif
+
+#if ENABLE(IOS_AIRPLAY)
+    if (hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent)) {
+        m_player->setHasPlaybackTargetAvailabilityListeners(true);
+        enqueuePlaybackTargetAvailabilityChangedEvent(); // Ensure the event listener gets at least one event.
+    }
+#endif
 }
 
 #if ENABLE(WEB_AUDIO)
@@ -4959,6 +5299,16 @@ AudioSourceProvider* HTMLMediaElement::audioSourceProvider()
 }
 #endif
 
+#if PLATFORM(IOS)
+void HTMLMediaElement::userRequestsMediaLoading()
+{
+    // The user is requesting data loading and/or playback, so remove the "only change playback in response
+    // to a user gesture" restriction on this movie.
+    m_userStartedPlayback = true;
+    m_restrictions = NoRestrictions;
+}
+#endif
+
 const String& HTMLMediaElement::mediaGroup() const
 {
     return m_mediaGroup;
@@ -5236,7 +5586,7 @@ void HTMLMediaElement::removeBehaviorsRestrictionsAfterFirstUserGesture()
 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
 bool HTMLMediaElement::shouldUseVideoPluginProxy() const
 {
-    return document()->settings() && document()->settings()->isVideoPluginProxyEnabled();
+    return document().settings() && document().settings()->isVideoPluginProxyEnabled();
 }
 #endif
 
@@ -5301,6 +5651,11 @@ bool HTMLMediaElement::ensureMediaControlsInjectedScript()
 
 void HTMLMediaElement::didAddUserAgentShadowRoot(ShadowRoot* root)
 {
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+    // JavaScript controls are not enabled with the video plugin proxy.
+    UNUSED_PARAM(root);
+    return;
+#else
     Page* page = document().page();
     if (!page)
         return;
@@ -5337,8 +5692,9 @@ void HTMLMediaElement::didAddUserAgentShadowRoot(ShadowRoot* root)
     JSC::call(exec, overlay, callType, callData, globalObject, argList);
     if (exec->hadException())
         exec->clearException();
-}
 #endif
+}
+#endif // ENABLE(MEDIA_CONTROLS_SCRIPT)
 
 unsigned long long HTMLMediaElement::fileSize() const
 {
index c3d1bf173d8a1f93e61dbe80e062df2cf6465c99..1cf109bb12b3186a812e42af0f28008b5ca86f5e 100644 (file)
@@ -35,6 +35,7 @@
 #include "MediaPlayer.h"
 
 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+#include "HTMLFrameOwnerElement.h"
 #include "HTMLPlugInImageElement.h"
 #include "MediaPlayerProxy.h"
 #endif
@@ -97,7 +98,13 @@ typedef CueIntervalTree::IntervalType CueInterval;
 typedef Vector<CueInterval> CueList;
 #endif
 
-class HTMLMediaElement : public HTMLElement, private MediaPlayerClient, public MediaPlayerSupportsTypeClient, private MediaCanStartListener, public ActiveDOMObject, public MediaControllerInterface
+class HTMLMediaElement
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+    : public HTMLFrameOwnerElement
+#else
+    : public HTMLElement
+#endif
+    , private MediaPlayerClient, public MediaPlayerSupportsTypeClient, private MediaCanStartListener, public ActiveDOMObject, public MediaControllerInterface
 #if ENABLE(VIDEO_TRACK)
     , private AudioTrackClient
     , private TextTrackClient
@@ -329,7 +336,7 @@ public:
 #endif
 
 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
-    void allocateMediaPlayerIfNecessary();
+    void ensureMediaPlayer();
     void setNeedWidgetUpdate(bool needWidgetUpdate) { m_needWidgetUpdate = needWidgetUpdate; }
     void deliverNotification(MediaPlayerProxyNotificationType notification);
     void setMediaPlayerProxy(WebMediaPlayerProxy* proxy);
@@ -338,6 +345,17 @@ public:
     void updateWidget(PluginCreationOption);
 #endif
 
+#if ENABLE(IOS_AIRPLAY)
+    void webkitShowPlaybackTargetPicker();
+    bool webkitCurrentPlaybackTargetIsWireless() const;
+
+    virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture) OVERRIDE;
+    virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture) OVERRIDE;
+
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitcurrentplaybacktargetiswirelesschanged);
+    DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitplaybacktargetavailabilitychanged);
+#endif
+
     // EventTarget function.
     // Both Node (via HTMLElement) and ActiveDOMObject define this method, which
     // causes an ambiguity error at compile time. This class's constructor
@@ -389,7 +407,9 @@ public:
     MediaController* controller() const;
     void setController(PassRefPtr<MediaController>);
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseClickEvents() OVERRIDE;
+#endif
 
     void enteredOrExitedFullscreen() { configureMediaControls(); }
 
@@ -432,6 +452,9 @@ protected:
         RequireUserGestureForFullscreenRestriction = 1 << 2,
         RequirePageConsentToLoadMediaRestriction = 1 << 3,
         RequirePageConsentToResumeMediaRestriction = 1 << 4,
+#if ENABLE(IOS_AIRPLAY)
+        RequireUserGestureToShowPlaybackTargetPicker = 1 << 5,
+#endif
     };
     typedef unsigned BehaviorRestrictions;
     
@@ -440,6 +463,9 @@ protected:
     bool userGestureRequiredForFullscreen() const { return m_restrictions & RequireUserGestureForFullscreenRestriction; }
     bool pageConsentRequiredForLoad() const { return m_restrictions & RequirePageConsentToLoadMediaRestriction; }
     bool pageConsentRequiredForResume() const { return m_restrictions & RequirePageConsentToResumeMediaRestriction; }
+#if ENABLE(IOS_AIRPLAY)
+    bool userGestureRequiredToShowPlaybackTargetPicker() const { return m_restrictions & RequireUserGestureToShowPlaybackTargetPicker; }
+#endif
     
     void addBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions |= restriction; }
     void removeBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions &= ~restriction; }
@@ -522,6 +548,12 @@ private:
     virtual bool mediaPlayerKeyNeeded(MediaPlayer*, Uint8Array*) OVERRIDE;
 #endif
 
+#if ENABLE(IOS_AIRPLAY)
+    virtual void mediaPlayerCurrentPlaybackTargetIsWirelessChanged(MediaPlayer*) OVERRIDE;
+    virtual void mediaPlayerPlaybackTargetAvailabilityChanged(MediaPlayer*) OVERRIDE;
+    void enqueuePlaybackTargetAvailabilityChangedEvent();
+#endif
+
     virtual String mediaPlayerReferrer() const OVERRIDE;
     virtual String mediaPlayerUserAgent() const OVERRIDE;
     virtual CORSMode mediaPlayerCORSMode() const OVERRIDE;
@@ -615,6 +647,11 @@ private:
     double minTimeSeekable() const;
     double maxTimeSeekable() const;
 
+#if PLATFORM(IOS)
+    bool parseMediaPlayerAttribute(const QualifiedName&, const AtomicString&);
+    void userRequestsMediaLoading();
+#endif
+
     // Pauses playback without changing any states or generating events
     void setPausedInternal(bool);
 
@@ -758,6 +795,11 @@ private:
     bool m_isDisplaySleepDisablingSuspended : 1;
 #endif
 
+#if PLATFORM(IOS)
+    bool m_requestingPlay : 1;
+    bool m_userStartedPlayback : 1;
+#endif
+
 #if ENABLE(VIDEO_TRACK)
     bool m_tracksAreReady : 1;
     bool m_haveVisibleTextTrack : 1;
index 43b65804f59278b1d1eb97a7a6e90ad90e2179e5..b233dde816c4d24d61c12992e5d5b64fc10cae82 100644 (file)
 #if !defined(LANGUAGE_GOBJECT) || !LANGUAGE_GOBJECT
     [Conditional=MEDIA_SOURCE] VideoPlaybackQuality getVideoPlaybackQuality();
 #endif
+
+    [Conditional=IOS_AIRPLAY] void webkitShowPlaybackTargetPicker();
+    [Conditional=IOS_AIRPLAY] readonly attribute boolean webkitCurrentPlaybackTargetIsWireless;
+    [Conditional=IOS_AIRPLAY] attribute EventListener onwebkitcurrentplaybacktargetiswirelesschanged;
+    [Conditional=IOS_AIRPLAY] attribute EventListener onwebkitplaybacktargetavailabilitychanged;
 };
index a8fecd9fd460c16b727aec2c03d408c98d7c169b..6f360fe2becd90956e7c9203e5295629070ed5b3 100644 (file)
@@ -73,6 +73,12 @@ void HTMLMetaElement::process()
 
     if (equalIgnoringCase(name(), "viewport"))
         document().processViewport(contentValue, ViewportArguments::ViewportMeta);
+#if PLATFORM(IOS)
+    else if (equalIgnoringCase(name(), "format-detection"))
+        document().processFormatDetection(contentValue);
+    else if (equalIgnoringCase(name(), "apple-mobile-web-app-orientations"))
+        document().processWebAppOrientations();
+#endif
     else if (equalIgnoringCase(name(), "referrer"))
         document().processReferrerPolicy(contentValue);
 #if ENABLE(LEGACY_VIEWPORT_ADAPTION)
index 533dfe100a0202a5ea3b8abb19c76d42d602d4e6..4812f1bf622791fcb3ec4f1efbd465f84f141a97 100644 (file)
 #include "Widget.h"
 #include <wtf/Ref.h>
 
+#if PLATFORM(IOS)
+#include "RuntimeApplicationChecksIOS.h"
+#include "WebCoreSystemInterface.h"
+#endif
+
 namespace WebCore {
 
 using namespace HTMLNames;
@@ -146,6 +151,14 @@ static void mapDataParamToSrc(Vector<String>* paramNames, Vector<String>* paramV
     }
 }
 
+#if PLATFORM(IOS)
+static bool shouldNotPerformURLAdjustment()
+{
+    static bool shouldNotPerformURLAdjustment = applicationIsNASAHD() && !iosExecutableWasLinkedOnOrAfterVersion(wkIOSSystemVersion_5_0);
+    return shouldNotPerformURLAdjustment;
+}
+#endif
+
 // FIXME: This function should not deal with url or serviceType!
 void HTMLObjectElement::parametersForPlugin(Vector<String>& paramNames, Vector<String>& paramValues, String& url, String& serviceType)
 {
@@ -204,6 +217,11 @@ void HTMLObjectElement::parametersForPlugin(Vector<String>& paramNames, Vector<S
     // attribute, not by a param element. However, for compatibility, allow the
     // resource's URL to be given by a param named "src", "movie", "code" or "url"
     // if we know that resource points to a plug-in.
+#if PLATFORM(IOS)
+    if (shouldNotPerformURLAdjustment())
+        return;
+#endif
+
     if (url.isEmpty() && !urlParameter.isEmpty()) {
         SubframeLoader& loader = document().frame()->loader().subframeLoader();
         if (loader.resourceWillUsePlugin(urlParameter, serviceType, shouldPreferPlugInsForImages()))
index 4441ae4914be54f2208d7af766cb3ab4a9f2af48..833e9eea5d4b0e9d5063fd1d8e32edb458b4e932 100644 (file)
@@ -81,6 +81,9 @@ public:
 
     bool canProcessDrag() const;
 
+#if PLATFORM(IOS)
+    virtual bool willRespondToMouseMoveEvents() OVERRIDE { return false; }
+#endif
     virtual bool willRespondToMouseClickEvents() OVERRIDE;
 
     virtual bool isPlugInImageElement() const { return false; }
index be244279e4dcfb333aff18598ec424a3dd4b3b56..3e29b9cf8758cc99602de8a0ba834bf24eb6274e 100644 (file)
 #include <wtf/HashMap.h>
 #include <wtf/text/StringHash.h>
 
+#if PLATFORM(IOS)
+#include "HTMLIFrameElement.h"
+#include "RenderBlockFlow.h"
+#include "YouTubeEmbedShadowElement.h"
+#endif
+
 namespace WebCore {
 
 using namespace HTMLNames;
@@ -220,6 +226,13 @@ RenderElement* HTMLPlugInImageElement::createRenderer(PassRef<RenderStyle> style
         return image;
     }
 
+#if PLATFORM(IOS)
+    if (ShadowRoot* shadowRoot = this->shadowRoot()) {
+        Element* shadowElement = toElement(shadowRoot->firstChild());
+        if (shadowElement && shadowElement->shadowPseudoId() == "-apple-youtube-shadow-iframe")
+            return new RenderBlockFlow(*this, std::move(style));
+    }
+#endif
     return HTMLPlugInElement::createRenderer(std::move(style));
 }
 
@@ -412,6 +425,38 @@ bool HTMLPlugInImageElement::partOfSnapshotOverlay(Node* node)
     return node && snapshotLabel && (node == snapshotLabel.get() || node->isDescendantOf(snapshotLabel.get()));
 }
 
+#if PLATFORM(IOS)
+void HTMLPlugInImageElement::createShadowIFrameSubtree(const String& src)
+{
+    if (this->shadowRoot())
+        return;
+
+    if (src.isEmpty())
+        return;
+
+    RefPtr<YouTubeEmbedShadowElement> shadowElement = YouTubeEmbedShadowElement::create(document());
+    ShadowRoot& root = this->ensureUserAgentShadowRoot();
+    root.appendChild(shadowElement, ASSERT_NO_EXCEPTION);
+
+    RefPtr<HTMLIFrameElement> iframeElement = HTMLIFrameElement::create(HTMLNames::iframeTag, document());
+    if (hasAttribute(HTMLNames::widthAttr))
+        iframeElement->setAttribute(HTMLNames::widthAttr, AtomicString("100%", AtomicString::ConstructFromLiteral));
+    if (hasAttribute(HTMLNames::heightAttr)) {
+        iframeElement->setAttribute(HTMLNames::styleAttr, AtomicString("max-height: 100%", AtomicString::ConstructFromLiteral));
+        iframeElement->setAttribute(HTMLNames::heightAttr, getAttribute(HTMLNames::heightAttr));
+    }
+    iframeElement->setAttribute(HTMLNames::srcAttr, src);
+    iframeElement->setAttribute(HTMLNames::frameborderAttr, AtomicString("0", AtomicString::ConstructFromLiteral));
+
+    // Disable frame flattening for this iframe.
+    iframeElement->setAttribute(HTMLNames::scrollingAttr, AtomicString("no", AtomicString::ConstructFromLiteral));
+    shadowElement->appendChild(iframeElement, ASSERT_NO_EXCEPTION);
+
+    if (renderer())
+        Style::reattachRenderTree(*this);
+}
+#endif
+
 void HTMLPlugInImageElement::removeSnapshotTimerFired(Timer<HTMLPlugInImageElement>*)
 {
     m_snapshotImage = nullptr;
index e4f582bdbecf10e4cf1c42ec63b19e8fd295bdbe..41027c4fa654bde1ea8698280d25ad6acbdf92c5 100644 (file)
@@ -73,6 +73,10 @@ public:
     // Public for FrameView::addWidgetToUpdate()
     bool needsWidgetUpdate() const { return m_needsWidgetUpdate; }
     void setNeedsWidgetUpdate(bool needsWidgetUpdate) { m_needsWidgetUpdate = needsWidgetUpdate; }
+    
+#if PLATFORM(IOS)
+    void createShadowIFrameSubtree(const String& src);
+#endif
 
     void userDidClickSnapshot(PassRefPtr<MouseEvent>, bool forwardEvent);
     void checkSnapshotStatus();
index b00702dc9657211dc8cf7e523045f133bb55f44c..55068affc5c8c1c29e165d70fe3786cbd83d15d9 100644 (file)
@@ -191,12 +191,16 @@ void HTMLSelectElement::listBoxSelectItem(int listIndex, bool allowMultiplySelec
 
 bool HTMLSelectElement::usesMenuList() const
 {
+#if !PLATFORM(IOS)
     const Page* page = document().page();
     RefPtr<RenderTheme> renderTheme = page ? &page->theme() : RenderTheme::defaultTheme();
     if (renderTheme->delegatesMenuListRendering())
         return true;
 
     return !m_multiple && m_size <= 1;
+#else
+    return !m_multiple;
+#endif
 }
 
 int HTMLSelectElement::activeSelectionStartListIndex() const
@@ -345,17 +349,23 @@ bool HTMLSelectElement::canSelectAll() const
 
 RenderElement* HTMLSelectElement::createRenderer(PassRef<RenderStyle> style)
 {
+#if !PLATFORM(IOS)
     if (usesMenuList())
         return new RenderMenuList(*this, std::move(style));
     return new RenderListBox(*this, std::move(style));
+#else
+    return new RenderMenuList(*this, std::move(style));
+#endif
 }
 
 bool HTMLSelectElement::childShouldCreateRenderer(const Node& child) const
 {
     if (!HTMLFormControlElementWithState::childShouldCreateRenderer(child))
         return false;
+#if !PLATFORM(IOS)
     if (!usesMenuList())
         return isHTMLOptionElement(child) || isHTMLOptGroupElement(child) || validationMessageShadowTreeContains(child);
+#endif
     return validationMessageShadowTreeContains(child);
 }
 
@@ -495,6 +505,13 @@ bool HTMLSelectElement::isRequiredFormControl() const
     return isRequired();
 }
 
+#if PLATFORM(IOS)
+bool HTMLSelectElement::willRespondToMouseClickEvents()
+{
+    return !isDisabledFormControl();
+}
+#endif
+
 // Returns the 1st valid item |skip| items from |listIndex| in direction |direction| if there is one.
 // Otherwise, it returns the valid item closest to that boundary which is past |listIndex| if there is one.
 // Otherwise, it returns |listIndex|.
@@ -617,7 +634,11 @@ void HTMLSelectElement::setActiveSelectionEndIndex(int index)
 
 void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions)
 {
+#if !PLATFORM(IOS)
     ASSERT(renderer() && (renderer()->isListBox() || m_multiple));
+#else
+    ASSERT(renderer() && (renderer()->isMenuList() || m_multiple));
+#endif
     ASSERT(!listItems().size() || m_activeSelectionAnchorIndex >= 0);
 
     unsigned start = std::min(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex);
@@ -683,20 +704,29 @@ void HTMLSelectElement::dispatchChangeEventForMenuList()
 
 void HTMLSelectElement::scrollToSelection()
 {
+#if !PLATFORM(IOS)
     if (usesMenuList())
         return;
 
     if (auto renderer = this->renderer())
         toRenderListBox(renderer)->selectionChanged();
+#else
+    if (auto renderer = this->renderer())
+        renderer->repaint();
+#endif
 }
 
 void HTMLSelectElement::setOptionsChangedOnRenderer()
 {
     if (auto renderer = this->renderer()) {
+#if !PLATFORM(IOS)
         if (usesMenuList())
             toRenderMenuList(renderer)->setOptionsChanged(true);
         else
             toRenderListBox(renderer)->setOptionsChanged(true);
+#else
+        toRenderMenuList(renderer)->setOptionsChanged(true);
+#endif
     }
 }
 
@@ -1228,6 +1258,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event)
 
     if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) {
         focus();
+#if !PLATFORM(IOS)
         if (renderer() && renderer()->isMenuList()) {
             if (RenderMenuList* menuList = toRenderMenuList(renderer())) {
                 if (menuList->popupIsVisible())
@@ -1243,15 +1274,18 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event)
                 }
             }
         }
+#endif
         event->setDefaultHandled();
     }
 
+#if !PLATFORM(IOS)
     if (event->type() == eventNames().blurEvent && !focused()) {
         if (RenderMenuList* menuList = toRenderMenuList(renderer())) {
             if (menuList->popupIsVisible())
                 menuList->hidePopup();
         }
     }
+#endif
 }
 
 void HTMLSelectElement::updateSelectedState(int listIndex, bool multi, bool shift)
@@ -1472,6 +1506,7 @@ void HTMLSelectElement::defaultEventHandler(Event* event)
     if (!renderer())
         return;
 
+#if !PLATFORM(IOS)
     if (isDisabledFormControl()) {
         HTMLFormControlElementWithState::defaultEventHandler(event);
         return;
@@ -1481,6 +1516,9 @@ void HTMLSelectElement::defaultEventHandler(Event* event)
         menuListDefaultEventHandler(event);
     else 
         listBoxDefaultEventHandler(event);
+#else
+    menuListDefaultEventHandler(event);
+#endif
     if (event->defaultHandled())
         return;
 
index dd18c16b2bb3c94059fe39ef47e61e4ecca95cee..c4e4af55085e6175b04a8d9ea6a6f104376d679b 100644 (file)
@@ -94,6 +94,10 @@ public:
 
     void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true);
 
+#if PLATFORM(IOS)
+    virtual bool willRespondToMouseClickEvents() OVERRIDE;
+#endif
+
     bool canSelectAll() const;
     void selectAll();
     int listToOptionIndex(int listIndex) const;
index b7aa4bb904e0c04991b670a745894fb5367019a8..f70de7117db2e20610c2632b2b103960cf5bb812 100644 (file)
@@ -545,4 +545,9 @@ void HTMLTextAreaElement::updatePlaceholderText()
     m_placeholder->setInnerText(placeholderText, ASSERT_NO_EXCEPTION);
 }
 
+bool HTMLTextAreaElement::willRespondToMouseClickEvents()
+{
+    return !isDisabledFormControl();
 }
+
+} // namespace WebCore
index e89330858c1eabbe8d9cf2ec670e78967476157e..7c1657003fbb595a09f4aa9f776239c663abb84b 100644 (file)
@@ -60,6 +60,8 @@ public:
     void setCols(int);
     void setRows(int);
 
+    virtual bool willRespondToMouseClickEvents() OVERRIDE;
+
 private:
     HTMLTextAreaElement(const QualifiedName&, Document&, HTMLFormElement*);
 
index bd5b7a5c4c3bf59d95d9e002a3c48ac287e6197d..9533d602cc0533818d6ea69dc5281aa820a7f9b5 100644 (file)
@@ -65,6 +65,9 @@ interface HTMLTextAreaElement : HTMLElement {
                            optional DOMString direction);
 #endif
 
+    [Conditional=IOS_AUTOCORRECT_AND_AUTOCAPITALIZE] attribute boolean autocorrect;
+    [Conditional=IOS_AUTOCORRECT_AND_AUTOCAPITALIZE, TreatNullAs=NullString] attribute DOMString autocapitalize;
+
 #if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C
     [Reflect] attribute DOMString accessKey;
 #endif
index 070b75704c8044fc4f7f43c81eae04df450060d3..27cb31278db1fcd22561584d49978487a86caf5f 100644 (file)
@@ -185,7 +185,14 @@ void HTMLTextFormControlElement::setSelectionDirection(const String& direction)
 
 void HTMLTextFormControlElement::select()
 {
+    // FIXME: We should abstract the selection behavior into an EditingBehavior function instead
+    // of hardcoding the behavior using a macro define.
+#if PLATFORM(IOS)
+    // We don't want to select all the text on iOS. Instead use the standard textfield behavior of going to the end of the line.
+    setSelectionRange(std::numeric_limits<int>::max(), std::numeric_limits<int>::max(), SelectionHasForwardDirection);
+#else
     setSelectionRange(0, std::numeric_limits<int>::max(), SelectionHasNoDirection);
+#endif
 }
 
 String HTMLTextFormControlElement::selectedText() const
@@ -300,12 +307,14 @@ void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextField
     else
         endPosition = visiblePositionForIndex(end);
 
+#if !PLATFORM(IOS)
     // startPosition and endPosition can be null position for example when
     // "-webkit-user-select: none" style attribute is specified.
     if (startPosition.isNotNull() && endPosition.isNotNull()) {
         ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowHost() == this
             && endPosition.deepEquivalent().deprecatedNode()->shadowHost() == this);
     }
+#endif
     VisibleSelection newSelection;
     if (direction == SelectionHasBackwardDirection)
         newSelection = VisibleSelection(endPosition, startPosition);
@@ -544,6 +553,25 @@ String HTMLTextFormControlElement::innerTextValue() const
     return finishText(result);
 }
 
+#if PLATFORM(IOS)
+void HTMLTextFormControlElement::hidePlaceholder()
+{
+    if (!supportsPlaceholder())
+        return;
+    HTMLElement* placeholder = placeholderElement();
+    if (!placeholder) {
+        updatePlaceholderText();
+        return;
+    }
+    placeholder->setInlineStyleProperty(CSSPropertyVisibility, ASCIILiteral("hidden"));
+}
+
+void HTMLTextFormControlElement::showPlaceholderIfNecessary()
+{
+    updatePlaceholderVisibility(false);
+}
+#endif
+
 static void getNextSoftBreak(RootInlineBox*& line, Node*& breakNode, unsigned& breakOffset)
 {
     RootInlineBox* next;
index 3dbb4ddb2ab626328da1069dae2b5cc0b3fa4870..fbd75a165ed6dcebca36f6d7df570f9ae6b2f075 100644 (file)
@@ -86,6 +86,10 @@ public:
     String directionForFormData() const;
 
     void setTextAsOfLastFormControlChangeEvent(const String& text) { m_textAsOfLastFormControlChangeEvent = text; }
+#if PLATFORM(IOS)
+    void hidePlaceholder();
+    void showPlaceholderIfNecessary();
+#endif
 
 protected:
     HTMLTextFormControlElement(const QualifiedName&, Document&, HTMLFormElement*);
index b6912912961f14c5fa4f25ae233f971f1fd40354..0bd937c07d3d2fa6abd21875a3d7945f06fd8708 100644 (file)
@@ -71,7 +71,7 @@ RenderElement* HTMLVideoElement::createRenderer(PassRef<RenderStyle> style)
 {
 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
     if (shouldUseVideoPluginProxy())
-        return HTMLMediaElement::createRenderer(arena, style);
+        return HTMLMediaElement::createRenderer(std::move(style));
 #endif
     return new RenderVideo(*this, std::move(style));
 }
@@ -131,8 +131,23 @@ void HTMLVideoElement::parseAttribute(const QualifiedName& name, const AtomicStr
             if (renderer())
                 toRenderImage(renderer())->imageResource()->setCachedImage(0); 
         }
-    } else
+    }
+#if ENABLE(IOS_AIRPLAY)
+    else if (name == webkitwirelessvideoplaybackdisabledAttr) {
+        if (player())
+            player()->setWirelessVideoPlaybackDisabled(webkitWirelessVideoPlaybackDisabled());
+    } else {
         HTMLMediaElement::parseAttribute(name, value);
+
+        if (name == webkitairplayAttr) {
+            if (player())
+                player()->setWirelessVideoPlaybackDisabled(webkitWirelessVideoPlaybackDisabled());
+        }
+    }
+#else
+    else
+        HTMLMediaElement::parseAttribute(name, value);    
+#endif
 }
 
 bool HTMLVideoElement::supportsFullscreen() const
@@ -144,6 +159,10 @@ bool HTMLVideoElement::supportsFullscreen() const
     if (!player() || !player()->supportsFullscreen())
         return false;
 
+#if PLATFORM(IOS)
+    // Fullscreen implemented by player.
+    return true;
+#else
 #if ENABLE(FULLSCREEN_API)
     // If the full screen API is enabled and is supported for the current element
     // do not require that the player has a video track to enter full screen.
@@ -155,6 +174,7 @@ bool HTMLVideoElement::supportsFullscreen() const
         return false;
 
     return page->chrome().client().supportsFullscreenForNode(this);
+#endif // PLATFORM(IOS)
 }
 
 unsigned HTMLVideoElement::videoWidth() const
@@ -307,6 +327,25 @@ bool HTMLVideoElement::webkitDisplayingFullscreen()
     return isFullscreen();
 }
 
+#if ENABLE(IOS_AIRPLAY)
+bool HTMLVideoElement::webkitWirelessVideoPlaybackDisabled() const
+{
+    Settings* settings = document().settings();
+    if (!settings || !settings->mediaPlaybackAllowsAirPlay())
+        return true;
+
+    String legacyAirplayAttributeValue = fastGetAttribute(webkitairplayAttr);
+    if (equalIgnoringCase(legacyAirplayAttributeValue, "deny"))
+        return true;
+    return fastHasAttribute(webkitwirelessvideoplaybackdisabledAttr);
+}
+
+void HTMLVideoElement::setWebkitWirelessVideoPlaybackDisabled(bool disabled)
+{
+    setBooleanAttribute(webkitwirelessvideoplaybackdisabledAttr, disabled);
+}
+#endif
+
 void HTMLVideoElement::didMoveToNewDocument(Document* oldDocument)
 {
     if (m_imageLoader)
index 080f57c4b91d6a71a68ed436d5749591a4a0414e..31390de6c3cc6323756b4085feb5d32a66c98eb0 100644 (file)
@@ -54,6 +54,11 @@ public:
     void webkitEnterFullScreen(ExceptionCode& ec) { webkitEnterFullscreen(ec); }
     void webkitExitFullScreen() { webkitExitFullscreen(); }
 
+#if ENABLE(IOS_AIRPLAY)
+    bool webkitWirelessVideoPlaybackDisabled() const;
+    void setWebkitWirelessVideoPlaybackDisabled(bool);
+#endif
+
 #if ENABLE(MEDIA_STATISTICS)
     // Statistics
     unsigned webkitDecodedFrameCount() const;
index c615c89d0924cb3eccf70c08f2fef7d5754530d0..51dcccfb7b8b8209b2f91589c1f9159b168a2ec8 100644 (file)
@@ -43,6 +43,8 @@
     [RaisesException] void webkitEnterFullScreen();
     void webkitExitFullScreen();
 
+    [Conditional=IOS_AIRPLAY] attribute boolean webkitWirelessVideoPlaybackDisabled;
+
     // The number of frames that have been decoded and made available for
     // playback.
     [Conditional=MEDIA_STATISTICS] readonly attribute unsigned long webkitDecodedFrameCount;
index 9abc0391fbb8b2d13fbbab8fe8ea8528c9f11548..8fb40362b47b6e55df31fd9d75927ef1516555c3 100644 (file)
@@ -219,6 +219,10 @@ void ImageDocument::createDocumentStructure()
         if (DOMWindow* domWindow = this->domWindow())
             domWindow->addEventListener("resize", listener, false);
         imageElement->addEventListener("click", listener.release(), false);
+#if PLATFORM(IOS)
+        // Set the viewport to be in device pixels (rather than the default of 980).
+        processViewport(ASCIILiteral("width=device-width"), ViewportArguments::ImageDocument);
+#endif
     }
 
     m_imageElement = imageElement.get();
@@ -226,8 +230,12 @@ void ImageDocument::createDocumentStructure()
 
 float ImageDocument::scale() const
 {
+#if PLATFORM(IOS)
+    // On iOS big images are subsampled to make them smaller. So, don't resize them.
+    return 1;
+#else
     if (!m_imageElement)
-        return 1.0f;
+        return 1;
 
     FrameView* view = frame()->view();
     if (!view)
@@ -235,15 +243,19 @@ float ImageDocument::scale() const
 
     LayoutSize imageSize = m_imageElement->cachedImage()->imageSizeForRenderer(m_imageElement->renderer(), pageZoomFactor(this));
     LayoutSize windowSize = LayoutSize(view->width(), view->height());
-    
-    float widthScale = (float)windowSize.width() / imageSize.width();
-    float heightScale = (float)windowSize.height() / imageSize.height();
+
+    float widthScale = static_cast<float>(windowSize.width()) / imageSize.width();
+    float heightScale = static_cast<float>(windowSize.height()) / imageSize.height();
 
     return std::min(widthScale, heightScale);
+#endif
 }
 
 void ImageDocument::resizeImageToFit()
 {
+#if PLATFORM(IOS)
+    // On iOS big images are subsampled to make them smaller. So, don't resize them.
+#else
     if (!m_imageElement)
         return;
 
@@ -252,31 +264,38 @@ void ImageDocument::resizeImageToFit()
     float scale = this->scale();
     m_imageElement->setWidth(static_cast<int>(imageSize.width() * scale));
     m_imageElement->setHeight(static_cast<int>(imageSize.height() * scale));
-    
+
     m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueWebkitZoomIn);
+#endif
 }
 
 void ImageDocument::imageClicked(int x, int y)
 {
+#if PLATFORM(IOS)
+    // On iOS big images are subsampled to make them smaller. So, don't resize them.
+    UNUSED_PARAM(x);
+    UNUSED_PARAM(y);
+#else
     if (!m_imageSizeIsKnown || imageFitsInWindow())
         return;
 
     m_shouldShrinkImage = !m_shouldShrinkImage;
-    
+
     if (m_shouldShrinkImage)
         windowSizeChanged();
     else {
         restoreImageSize();
-        
+
         updateLayout();
-        
+
         float scale = this->scale();
-        
+
         int scrollX = static_cast<int>(x / scale - (float)frame()->view()->width() / 2);
         int scrollY = static_cast<int>(y / scale - (float)frame()->view()->height() / 2);
-        
+
         frame()->view()->setScrollPosition(IntPoint(scrollX, scrollY));
     }
+#endif
 }
 
 void ImageDocument::imageUpdated()
@@ -324,9 +343,12 @@ bool ImageDocument::imageFitsInWindow() const
         return true;
 
     LayoutSize imageSize = m_imageElement->cachedImage()->imageSizeForRenderer(m_imageElement->renderer(), pageZoomFactor(this));
+#if PLATFORM(IOS)
+    LayoutSize windowSize = view->contentsToScreen(view->actualVisibleContentRect()).size();
+#else
     LayoutSize windowSize = LayoutSize(view->width(), view->height());
-    
-    return imageSize.width() <= windowSize.width() && imageSize.height() <= windowSize.height();    
+#endif
+    return imageSize.width() <= windowSize.width() && imageSize.height() <= windowSize.height();
 }
 
 void ImageDocument::windowSizeChanged()
@@ -335,7 +357,21 @@ void ImageDocument::windowSizeChanged()
         return;
 
     bool fitsInWindow = imageFitsInWindow();
-    
+
+#if PLATFORM(IOS)
+    if (fitsInWindow)
+        return;
+
+    LayoutSize imageSize = m_imageElement->cachedImage()->imageSizeForRenderer(m_imageElement->renderer(), pageZoomFactor(this));
+    LayoutRect visibleScreenSize = frame()->view()->contentsToScreen(frame()->view()->actualVisibleContentRect());
+
+    float widthScale = static_cast<float>(visibleScreenSize.width()) / imageSize.width();
+    float heightScale = static_cast<float>(visibleScreenSize.height()) / imageSize.height();
+    if (widthScale < heightScale)
+        processViewport(String::format("width=%d", imageSize.width().toInt()), ViewportArguments::ImageDocument);
+    else
+        processViewport(String::format("width=%d", static_cast<int>(1.0f + (1.0f - heightScale)) * imageSize.width().toInt()), ViewportArguments::ImageDocument);
+#else
     // If the image has been explicitly zoomed in, restore the cursor if the image fits
     // and set it to a zoom out cursor if the image doesn't fit
     if (!m_shouldShrinkImage) {
@@ -345,7 +381,7 @@ void ImageDocument::windowSizeChanged()
             m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueWebkitZoomOut);
         return;
     }
-    
+
     if (m_didShrinkImage) {
         // If the window has been resized so that the image fits, restore the image size
         // otherwise update the restored image size.
@@ -360,6 +396,7 @@ void ImageDocument::windowSizeChanged()
             m_didShrinkImage = true;
         }
     }
+#endif
 }
 
 CachedImage* ImageDocument::cachedImage()
index 9bd3649a663dad7680fc385854683cc2909e4c41..cfbd1e32be2c45a16465261e7993d9e2146fe81d 100644 (file)
@@ -525,6 +525,13 @@ String InputType::serialize(const Decimal&) const
     return String();
 }
 
+#if PLATFORM(IOS)
+DateComponents::Type InputType::dateType() const
+{
+    return DateComponents::Invalid;
+}
+#endif
+
 void InputType::dispatchSimulatedClickIfActive(KeyboardEvent* event) const
 {
     if (element().active())
@@ -551,7 +558,7 @@ bool InputType::hasCustomFocusLogic() const
 
 bool InputType::isKeyboardFocusable(KeyboardEvent* event) const
 {
-    return element().isTextFormControlKeyboardFocusable(event);
+    return !element().isReadOnly() && element().isTextFormControlKeyboardFocusable(event);
 }
 
 bool InputType::isMouseFocusable() const
@@ -716,11 +723,13 @@ String InputType::sanitizeValue(const String& proposedValue) const
     return proposedValue;
 }
 
+#if ENABLE(DRAG_SUPPORT)
 bool InputType::receiveDroppedFiles(const DragData&)
 {
     ASSERT_NOT_REACHED();
     return false;
 }
+#endif
 
 Icon* InputType::icon() const
 {
@@ -728,6 +737,14 @@ Icon* InputType::icon() const
     return 0;
 }
 
+#if PLATFORM(IOS)
+String InputType::displayString() const
+{
+    ASSERT_NOT_REACHED();
+    return String();
+}
+#endif
+
 bool InputType::shouldResetOnDocumentActivation()
 {
     return false;
index e4c8a496433ae11edec1def143163665117d33ab..d0dc504fbb58526fec502f656ce3b6490fce1161 100644 (file)
 #include <wtf/Noncopyable.h>
 #include <wtf/RefPtr.h>
 
+#if PLATFORM(IOS)
+#include "DateComponents.h"
+#endif
+
 namespace WebCore {
 
 class BeforeTextInsertedEvent;
@@ -243,9 +247,15 @@ public:
     virtual bool shouldRespectAlignAttribute();
     virtual FileList* files();
     virtual void setFiles(PassRefPtr<FileList>);
+#if ENABLE(DRAG_SUPPORT)
     // Should return true if the given DragData has more than one dropped files.
     virtual bool receiveDroppedFiles(const DragData&);
+#endif
     virtual Icon* icon() const;
+#if PLATFORM(IOS)
+    virtual String displayString() const;
+#endif
+
     // Should return true if the corresponding renderer for a type can display a suggested value.
     virtual bool canSetSuggestedValue();
     virtual bool shouldSendChangeEventAfterCheckedChanged();
@@ -294,6 +304,10 @@ public:
     // string. This should not be called for types without valueAsNumber.
     virtual String serialize(const Decimal&) const;
 
+#if PLATFORM(IOS)
+    virtual DateComponents::Type dateType() const;
+#endif
+
     virtual bool supportsIndeterminateAppearance() const;
 
     virtual bool supportsSelectionAPI() const;
index 113a56bd8c15854c2cc4e9f32ee8f89cafa5cefc..0d4a9f2e4a0fe5214e5f88213aa0889b3adc0da5 100644 (file)
@@ -74,10 +74,19 @@ void PluginDocumentParser::createDocumentStructure()
     if (document()->frame())
         document()->frame()->loader().dispatchDocumentElementAvailable();
 
+#if PLATFORM(IOS)
+    // Should not be able to zoom into standalone plug-in documents.
+    document()->processViewport(ASCIILiteral("user-scalable=no"), ViewportArguments::PluginDocument);
+#endif
+
     RefPtr<Element> body = document()->createElement(bodyTag, false);
-    body->setAttribute(marginwidthAttr, "0");
-    body->setAttribute(marginheightAttr, "0");
-    body->setAttribute(styleAttr, "background-color: rgb(38,38,38)");
+    body->setAttribute(marginwidthAttr, AtomicString("0", AtomicString::ConstructFromLiteral));
+    body->setAttribute(marginheightAttr, AtomicString("0", AtomicString::ConstructFromLiteral));
+#if PLATFORM(IOS)
+    body->setAttribute(styleAttr, AtomicString("background-color: rgb(217,224,233)", AtomicString::ConstructFromLiteral));
+#else
+    body->setAttribute(styleAttr, AtomicString("background-color: rgb(38,38,38)", AtomicString::ConstructFromLiteral));
+#endif
 
     rootElement->appendChild(body, IGNORE_EXCEPTION);
         
index 9f6114406a068e72b3df432b3c3eb97b3d9a0368..4b16a005d3393d61ecfc37959e0cbb3e1c5c2392 100644 (file)
@@ -138,6 +138,7 @@ bool RangeInputType::isSteppable() const
     return true;
 }
 
+#if !PLATFORM(IOS)
 void RangeInputType::handleMouseDownEvent(MouseEvent* event)
 {
     if (element().isDisabledOrReadOnly())
@@ -154,11 +155,14 @@ void RangeInputType::handleMouseDownEvent(MouseEvent* event)
         return;
     thumb.dragFrom(event->absoluteLocation());
 }
+#endif
 
 #if ENABLE(TOUCH_EVENTS)
-#if ENABLE(TOUCH_SLIDER)
 void RangeInputType::handleTouchEvent(TouchEvent* event)
 {
+#if PLATFORM(IOS)
+    typedSliderThumbElement().handleTouchEvent(event);
+#elif ENABLE(TOUCH_SLIDER)
     if (element().isDisabledOrReadOnly())
         return;
 
@@ -172,14 +176,23 @@ void RangeInputType::handleTouchEvent(TouchEvent* event)
         typedSliderThumbElement().setPositionFromPoint(touches->item(0)->absoluteLocation());
         event->setDefaultHandled();
     }
+#endif
 }
 
+#if ENABLE(TOUCH_SLIDER)
 bool RangeInputType::hasTouchEventHandler() const
 {
     return true;
 }
 #endif
+
+#if PLATFORM(IOS)
+void RangeInputType::disabledAttributeChanged()
+{
+    typedSliderThumbElement().disabledAttributeChanged();
+}
 #endif
+#endif // ENABLE(TOUCH_EVENTS)
 
 void RangeInputType::handleKeydownEvent(KeyboardEvent* event)
 {
index d112f1b18cfbe0789c5e37e85b12f3f20b47d7c0..ac01e24edb4efd70baf514919484b76f87ce6394 100644 (file)
@@ -51,7 +51,9 @@ private:
     virtual bool supportsRequired() const OVERRIDE;
     virtual StepRange createStepRange(AnyStepHandling) const OVERRIDE;
     virtual bool isSteppable() const OVERRIDE;
+#if !PLATFORM(IOS)
     virtual void handleMouseDownEvent(MouseEvent*) OVERRIDE;
+#endif
     virtual void handleKeydownEvent(KeyboardEvent*) OVERRIDE;
     virtual RenderElement* createRenderer(PassRef<RenderStyle>) const OVERRIDE;
     virtual void createShadowSubtree() OVERRIDE;
@@ -77,10 +79,18 @@ private:
     Vector<Decimal> m_tickMarkValues;
 #endif
 
-#if ENABLE(TOUCH_EVENTS) && ENABLE(TOUCH_SLIDER)
+#if ENABLE(TOUCH_EVENTS)
     virtual void handleTouchEvent(TouchEvent*) OVERRIDE;
+
+#if PLATFORM(IOS)
+    virtual void disabledAttributeChanged() OVERRIDE;
+#else
+#if ENABLE(TOUCH_SLIDER)
     virtual bool hasTouchEventHandler() const OVERRIDE;
 #endif
+#endif // PLATFORM(IOS)
+#endif // ENABLE(TOUCH_EVENTS)
+
 };
 
 } // namespace WebCore
index a54751dc373c90f4664e42c043b2dbaa9c90e0d7..3ddae972d32bbc256b0a9eae7bcd09554d6b5263 100644 (file)
@@ -59,8 +59,10 @@ void SearchInputType::attach()
 
 void SearchInputType::addSearchResult()
 {
+#if !PLATFORM(IOS)
     if (RenderObject* renderer = element().renderer())
         toRenderSearchField(renderer)->addSearchResult();
+#endif
 }
 
 RenderElement* SearchInputType::createRenderer(PassRef<RenderStyle> style) const
index 3891f69fd608f1bd2e64d46af98331def5e97f47..1948f8fdd3983cb7b690903188991086544cfdc7 100644 (file)
@@ -70,6 +70,10 @@ TextFieldInputType::~TextFieldInputType()
 
 bool TextFieldInputType::isKeyboardFocusable(KeyboardEvent*) const
 {
+#if PLATFORM(IOS)
+    if (element().isReadOnly())
+        return false;
+#endif
     return element().isTextFormControlFocusable();
 }
 
index 522dd7ffe2d555ce836ee321fe73618c4d9aabe7..dcfde9086f7469862411e7653470b917d84d1a0f 100644 (file)
@@ -69,6 +69,9 @@ protected:
     virtual void handleBlurEvent() OVERRIDE;
     virtual void setValue(const String&, bool valueChanged, TextFieldEventBehavior) OVERRIDE;
     virtual void updateInnerTextValue() OVERRIDE;
+#if PLATFORM(IOS)
+    virtual String sanitizeValue(const String&) const OVERRIDE;
+#endif
 
     virtual String convertFromVisibleValue(const String&) const;
     enum ValueChangeState {
@@ -87,7 +90,9 @@ private:
     virtual bool shouldSubmitImplicitly(Event*) OVERRIDE;
     virtual RenderElement* createRenderer(PassRef<RenderStyle>) const OVERRIDE;
     virtual bool shouldUseInputMethod() const OVERRIDE;
+#if !PLATFORM(IOS)
     virtual String sanitizeValue(const String&) const OVERRIDE;
+#endif
     virtual bool shouldRespectListAttribute() OVERRIDE;
     virtual HTMLElement* placeholderElement() const OVERRIDE;
     virtual void updatePlaceholderText() OVERRIDE;
diff --git a/Source/WebCore/html/WebAutocapitalize.h b/Source/WebCore/html/WebAutocapitalize.h
new file mode 100644 (file)
index 0000000..b76dda5
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebAutocapitalize_h
+#define WebAutocapitalize_h
+
+typedef enum {
+    WebAutocapitalizeTypeDefault,
+    WebAutocapitalizeTypeNone,
+    WebAutocapitalizeTypeWords,
+    WebAutocapitalizeTypeSentences,
+    WebAutocapitalizeTypeAllCharacters
+} WebAutocapitalizeType;
+
+#endif // WebAutocapitalize_h
index 0909c2ad396a215507b2afbd4ca152d365e88171..7a8d729bc074222ec2444227cdd18aa9912ab9a8 100755 (executable)
 #include <wtf/text/StringBuilder.h>
 
 #if USE(CG)
+#if !PLATFORM(IOS)
 #include <ApplicationServices/ApplicationServices.h>
+#endif // !PLATFORM(IOS)
+#endif
+
+#if PLATFORM(IOS)
+#include "Settings.h"
 #endif
 
 namespace WebCore {
@@ -1809,6 +1815,15 @@ PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float
         return 0;
     }
 
+#if PLATFORM(IOS)
+    // If the canvas element was created before Document had a Frame,
+    // then no maximumDecodedImageSize was set.
+    if (!canvas()->maximumDecodedImageSize()) {
+        if (Settings* settings = canvas()->document().settings())
+            canvas()->setMaximumDecodedImageSize(settings->maximumDecodedImageSize());
+    }
+#endif
+
     FloatSize logicalSize(fabs(sw), fabs(sh));
     if (!logicalSize.isExpressibleAsIntSize())
         return 0;
@@ -1859,6 +1874,15 @@ PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(ImageBuffer::Coordi
         sh = -sh;
     }
 
+#if PLATFORM(IOS)
+    // If the canvas element was created before Document had a Frame,
+    // then no maximumDecodedImageSize was set.
+    if (!canvas()->maximumDecodedImageSize()) {
+        if (Settings* settings = canvas()->document().settings())
+            canvas()->setMaximumDecodedImageSize(settings->maximumDecodedImageSize());
+    }
+#endif
+
     FloatRect logicalRect(sx, sy, sw, sh);
     if (logicalRect.width() < 1)
         logicalRect.setWidth(1);
index 561a1e8f9990b7599627c1406f3a031af45df20d..727da0750892ca678660a389e1f9c99e8406d4b8 100644 (file)
@@ -133,6 +133,10 @@ public:
 
     ParserContentPolicy parserContentPolicy() { return m_parserContentPolicy; }
 
+#if PLATFORM(IOS)
+    bool isTelephoneNumberParsingEnabled() { return m_document->isTelephoneNumberParsingEnabled(); }
+#endif
+
     class RedirectToFosterParentGuard {
         WTF_MAKE_NONCOPYABLE(RedirectToFosterParentGuard);
     public:
index dab8627fa6d99e68d4f4ec9d8f1e7cc8b39b7e9e..82c97c34d37b1feb3504b3bd2aa8ad4d621fda3d 100644 (file)
 #include <wtf/PassOwnPtr.h>
 #include <wtf/RefPtr.h>
 
+#if PLATFORM(IOS)
+#include "WebCoreThread.h"
+#endif
+
 namespace WebCore {
 
 class Document;
@@ -69,6 +73,10 @@ public:
     // Inline as this is called after every token in the parser.
     void checkForYieldBeforeToken(PumpSession& session)
     {
+#if PLATFORM(IOS)
+        if (WebThreadShouldYield())
+            session.needsYield = true;
+#endif
         if (session.processedTokens > m_parserChunkSize || session.didSeeScript) {
             // monotonicallyIncreasingTime() can be expensive. By delaying, we avoided calling
             // monotonicallyIncreasingTime() when constructing non-yielding PumpSessions.
index 20ba1e10d8168e3dbfed3506e6a62203f74315f8..cd57566148b3ec21c1ee9a0ead5dd384d717f25b 100644 (file)
 #include <wtf/MainThread.h>
 #include <wtf/unicode/CharacterNames.h>
 
+// FIXME: Extract the following iOS-specific code into a separate file.
+#if PLATFORM(IOS)
+#include "SoftLinking.h"
+
+#ifdef __has_include
+#if __has_include(<DataDetectorsCore/DDDFACache.h>)
+#include <DataDetectorsCore/DDDFACache.h>
+#else
+typedef void* DDDFACacheRef;
+#endif
+
+#if __has_include(<DataDetectorsCore/DDDFAScanner.h>)
+#include <DataDetectorsCore/DDDFAScanner.h>
+#else
+typedef void* DDDFAScannerRef;
+#endif
+#endif
+
+SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(DataDetectorsCore)
+SOFT_LINK(DataDetectorsCore, DDDFACacheCreateFromFramework, DDDFACacheRef, (), ())
+SOFT_LINK(DataDetectorsCore, DDDFAScannerCreateFromCache, DDDFAScannerRef, (DDDFACacheRef cache), (cache))
+SOFT_LINK(DataDetectorsCore, DDDFAScannerFirstResultInUnicharArray, Boolean, (DDDFAScannerRef scanner, const UniChar* str, unsigned length, int* startPos, int* endPos), (scanner, str, length, startPos, endPos))
+#endif
+
 namespace WebCore {
 
 using namespace HTMLNames;
@@ -2342,6 +2366,97 @@ void HTMLTreeBuilder::processCharacter(AtomicHTMLToken* token)
     processCharacterBuffer(buffer);
 }
 
+// FIXME: Extract the following iOS-specific code into a separate file.
+#if PLATFORM(IOS)
+// From the string 4089961010, creates a link of the form <a href="tel:4089961010">4089961010</a> and inserts it.
+void HTMLTreeBuilder::insertPhoneNumberLink(const String& string)
+{
+    Vector<Attribute> attributes;
+    attributes.append(Attribute(HTMLNames::hrefAttr, ASCIILiteral("tel:") + string));
+
+    const AtomicString& aTagLocalName = aTag.localName();
+    AtomicHTMLToken aStartToken(HTMLToken::StartTag, aTagLocalName, attributes);
+    AtomicHTMLToken aEndToken(HTMLToken::EndTag, aTagLocalName);
+
+    processStartTag(&aStartToken);
+    m_tree.executeQueuedTasks();
+    m_tree.insertTextNode(string);
+    processEndTag(&aEndToken);
+}
+
+// Locates the phone numbers in the string and deals with it
+// 1. Appends the text before the phone number as a text node.
+// 2. Wraps the phone number in a tel: link.
+// 3. Goes back to step 1 if a phone number is found in the rest of the string.
+// 4. Appends the rest of the string as a text node.
+void HTMLTreeBuilder::linkifyPhoneNumbers(const String& string)
+{
+    static DDDFACacheRef phoneNumbersCache = DDDFACacheCreateFromFramework();
+    if (!phoneNumbersCache) {
+        m_tree.insertTextNode(string);
+        return;
+    }
+
+    static DDDFAScannerRef phoneNumbersScanner = DDDFAScannerCreateFromCache(phoneNumbersCache);
+
+    // relativeStartPosition and relativeEndPosition are the endpoints of the phone number range,
+    // relative to the scannerPosition
+    unsigned length = string.length();
+    unsigned scannerPosition = 0;
+    int relativeStartPosition = 0;
+    int relativeEndPosition = 0;
+
+    // While there's a phone number in the rest of the string...
+    while ((scannerPosition < length) && DDDFAScannerFirstResultInUnicharArray(phoneNumbersScanner, &string.characters()[scannerPosition], length - scannerPosition, &relativeStartPosition, &relativeEndPosition)) {
+        // The convention in the Data Detectors framework is that the end position is the first character NOT in the phone number
+        // (that is, the length of the range is relativeEndPosition - relativeStartPosition). So substract 1 to get the same
+        // convention as the old WebCore phone number parser (so that the rest of the code is still valid if we want to go back
+        // to the old parser).
+        --relativeEndPosition;
+
+        ASSERT(scannerPosition + relativeEndPosition < length);
+
+        m_tree.insertTextNode(string.substring(scannerPosition, relativeStartPosition));
+        insertPhoneNumberLink(string.substring(scannerPosition + relativeStartPosition, relativeEndPosition - relativeStartPosition + 1));
+
+        scannerPosition += relativeEndPosition + 1;
+    }
+
+    // Append the rest as a text node.
+    if (scannerPosition > 0) {
+        if (scannerPosition < length) {
+            String after = string.substring(scannerPosition, length - scannerPosition);
+            m_tree.insertTextNode(after);
+        }
+    } else
+        m_tree.insertTextNode(string);
+}
+
+// Looks at the ancestors of the element to determine whether we're inside an element which disallows parsing phone numbers.
+static inline bool disallowTelephoneNumberParsing(const Node& node)
+{
+    return node.isLink()
+        || node.nodeType() == Node::COMMENT_NODE
+        || node.hasTagName(scriptTag)
+        || (node.isHTMLElement() && toHTMLElement(node).isFormControlElement())
+        || node.hasTagName(styleTag)
+        || node.hasTagName(ttTag)
+        || node.hasTagName(preTag)
+        || node.hasTagName(codeTag);
+}
+
+static inline bool shouldParseTelephoneNumbersInNode(const ContainerNode& node)
+{
+    const ContainerNode* currentNode = &node;
+    do {
+        if (currentNode->isElementNode() && disallowTelephoneNumberParsing(*currentNode))
+            return false;
+        currentNode = currentNode->parentNode();
+    } while (currentNode);
+    return true;
+}
+#endif // PLATFORM(IOS)
+
 void HTMLTreeBuilder::processCharacterBuffer(ExternalCharacterTokenBuffer& buffer)
 {
 ReprocessBuffer:
@@ -2519,7 +2634,15 @@ void HTMLTreeBuilder::processCharacterBufferForInBody(ExternalCharacterTokenBuff
 {
     m_tree.reconstructTheActiveFormattingElements();
     String characters = buffer.takeRemaining();
+#if PLATFORM(IOS)
+    if (!isParsingFragment() && m_tree.isTelephoneNumberParsingEnabled() && shouldParseTelephoneNumbersInNode(*m_tree.currentNode()) && DataDetectorsCoreLibrary())
+        linkifyPhoneNumbers(characters);
+    else
+        m_tree.insertTextNode(characters);
+#else
     m_tree.insertTextNode(characters);
+#endif
+
     if (m_framesetOk && !isAllWhitespaceOrReplacementCharacters(characters))
         m_framesetOk = false;
 }
index b8e7a730dfd04fa72f498bc70b429b5cae1719d9..67c5eff320f772338119159d1a984b1ec1c889f4 100644 (file)
@@ -123,6 +123,11 @@ private:
     HTMLTreeBuilder(HTMLDocumentParser&, HTMLDocument&, ParserContentPolicy, bool reportErrors, const HTMLParserOptions&);
     HTMLTreeBuilder(HTMLDocumentParser&, DocumentFragment&, Element* contextElement, ParserContentPolicy, const HTMLParserOptions&);
 
+#if PLATFORM(IOS)
+    void insertPhoneNumberLink(const String&);
+    void linkifyPhoneNumbers(const String&);
+#endif
+
     void processToken(AtomicHTMLToken*);
 
     void processDoctypeToken(AtomicHTMLToken*);
index d0e24ba7f390281cdd65e806030238a22be8283b..42c53091931c99948309e6535650b7131a28d34a 100644 (file)
@@ -751,8 +751,13 @@ const AtomicString& MediaControlClosedCaptionsContainerElement::shadowPseudoId()
 
 MediaControlClosedCaptionsTrackListElement::MediaControlClosedCaptionsTrackListElement(Document& document, MediaControls* controls)
     : MediaControlDivElement(document, MediaClosedCaptionsTrackList)
+#if ENABLE(VIDEO_TRACK)
     , m_controls(controls)
+#endif
 {
+#if !ENABLE(VIDEO_TRACK)
+    UNUSED_PARAM(controls);
+#endif
 }
 
 PassRefPtr<MediaControlClosedCaptionsTrackListElement> MediaControlClosedCaptionsTrackListElement::create(Document& document, MediaControls* controls)
@@ -794,6 +799,8 @@ void MediaControlClosedCaptionsTrackListElement::defaultEventHandler(Event* even
     }
 
     MediaControlDivElement::defaultEventHandler(event);
+#else
+    UNUSED_PARAM(event);
 #endif
 }
 
@@ -958,6 +965,7 @@ void MediaControlTimelineElement::defaultEventHandler(Event* event)
         m_controls->updateCurrentTimeDisplay();
 }
 
+#if !PLATFORM(IOS)
 bool MediaControlTimelineElement::willRespondToMouseClickEvents()
 {
     if (!attached())
@@ -965,6 +973,7 @@ bool MediaControlTimelineElement::willRespondToMouseClickEvents()
 
     return true;
 }
+#endif // !PLATFORM(IOS)
 
 void MediaControlTimelineElement::setPosition(double currentTime)
 {
index a52ffbc5fb1511e8943e0402a2292312789f3b93..d91e5b19fc91e4e90789080ef8e751cc1ef24348 100644 (file)
@@ -49,8 +49,10 @@ public:
     void makeOpaque();
     void makeTransparent();
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseMoveEvents() OVERRIDE { return true; }
     virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
+#endif
 
 private:
     explicit MediaControlPanelElement(Document&);
@@ -121,7 +123,9 @@ class MediaControlVolumeSliderContainerElement : public MediaControlDivElement {
 public:
     static PassRefPtr<MediaControlVolumeSliderContainerElement> create(Document&);
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseMoveEvents() OVERRIDE { return true; }
+#endif
 
 private:
     explicit MediaControlVolumeSliderContainerElement(Document&);
@@ -154,7 +158,9 @@ class MediaControlPanelMuteButtonElement FINAL : public MediaControlMuteButtonEl
 public:
     static PassRefPtr<MediaControlPanelMuteButtonElement> create(Document&, MediaControls*);
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseMoveEvents() OVERRIDE { return true; }
+#endif
 
 private:
     explicit MediaControlPanelMuteButtonElement(Document&, MediaControls*);
@@ -183,7 +189,10 @@ class MediaControlPlayButtonElement FINAL : public MediaControlInputElement {
 public:
     static PassRefPtr<MediaControlPlayButtonElement> create(Document&);
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
+#endif
+
     virtual void updateDisplayType() OVERRIDE;
 
 private:
@@ -240,7 +249,9 @@ class MediaControlRewindButtonElement : public MediaControlInputElement {
 public:
     static PassRefPtr<MediaControlRewindButtonElement> create(Document&);
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
+#endif
 
 private:
     explicit MediaControlRewindButtonElement(Document&);
@@ -255,7 +266,9 @@ class MediaControlReturnToRealtimeButtonElement : public MediaControlInputElemen
 public:
     static PassRefPtr<MediaControlReturnToRealtimeButtonElement> create(Document&);
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
+#endif
 
 private:
     explicit MediaControlReturnToRealtimeButtonElement(Document&);
@@ -270,7 +283,9 @@ class MediaControlToggleClosedCaptionsButtonElement FINAL : public MediaControlI
 public:
     static PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> create(Document&, MediaControls*);
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
+#endif
 
     virtual void updateDisplayType() OVERRIDE;
 
@@ -291,7 +306,9 @@ class MediaControlClosedCaptionsContainerElement FINAL : public MediaControlDivE
 public:
     static PassRefPtr<MediaControlClosedCaptionsContainerElement> create(Document&);
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
+#endif
 
 private:
     MediaControlClosedCaptionsContainerElement(Document&);
@@ -304,7 +321,9 @@ class MediaControlClosedCaptionsTrackListElement FINAL : public MediaControlDivE
 public:
     static PassRefPtr<MediaControlClosedCaptionsTrackListElement> create(Document&, MediaControls*);
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
+#endif
 
     void updateDisplay();
 
@@ -331,7 +350,9 @@ class MediaControlTimelineElement FINAL : public MediaControlInputElement {
 public:
     static PassRefPtr<MediaControlTimelineElement> create(Document&, MediaControls*);
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseClickEvents() OVERRIDE;
+#endif
 
     void setPosition(double);
     void setDuration(double);
@@ -351,7 +372,9 @@ class MediaControlFullscreenButtonElement FINAL : public MediaControlInputElemen
 public:
     static PassRefPtr<MediaControlFullscreenButtonElement> create(Document&);
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
+#endif
 
     virtual void setIsFullscreen(bool);
 
@@ -389,7 +412,9 @@ class MediaControlFullscreenVolumeMinButtonElement : public MediaControlInputEle
 public:
     static PassRefPtr<MediaControlFullscreenVolumeMinButtonElement> create(Document&);
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
+#endif
 
 private:
     explicit MediaControlFullscreenVolumeMinButtonElement(Document&);
@@ -403,7 +428,9 @@ class MediaControlFullscreenVolumeMaxButtonElement : public MediaControlInputEle
 public:
     static PassRefPtr<MediaControlFullscreenVolumeMaxButtonElement> create(Document&);
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
+#endif
 
 private:
     explicit MediaControlFullscreenVolumeMaxButtonElement(Document&);
index a79e2fd40c143fe493e6f509ded0cfd7b98b60a9..3a03a7d1caa1a5c3634d35ee41198a8396b13e3b 100644 (file)
@@ -93,7 +93,9 @@ class MediaControls : public HTMLDivElement {
     virtual void enteredFullscreen();
     virtual void exitedFullscreen();
 
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseMoveEvents() OVERRIDE { return true; }
+#endif
 
     virtual void hideFullscreenControlsTimerFired(Timer<MediaControls>*);
     virtual void startHideFullscreenControlsTimer();
index b6b8275cfe398cd51c402798feab399e2673c4b9..aeb5face0aa758815d2104a65e45b8bd2c86fe62 100644 (file)
 #include "RenderTheme.h"
 #include "ShadowRoot.h"
 
+#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS)
+#include "Document.h"
+#include "Page.h"
+#include "TouchEvent.h"
+#endif
+
 namespace WebCore {
 
 using namespace HTMLNames;
@@ -189,6 +195,10 @@ void RenderSliderContainer::layout()
 SliderThumbElement::SliderThumbElement(Document& document)
     : HTMLDivElement(HTMLNames::divTag, document)
     , m_inDragMode(false)
+#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS)
+    , m_exclusiveTouchIdentifier(NoIdentifier)
+    , m_isRegisteredAsTouchEventListener(false)
+#endif
 {
     setHasCustomStyleResolveCallbacks();
 }
@@ -234,7 +244,9 @@ void SliderThumbElement::dragFrom(const LayoutPoint& point)
 {
     Ref<SliderThumbElement> protect(*this);
     setPositionFromPoint(point);
+#if !PLATFORM(IOS)
     startDragging();
+#endif
 }
 
 void SliderThumbElement::setPositionFromPoint(const LayoutPoint& absolutePoint)
@@ -321,6 +333,7 @@ void SliderThumbElement::stopDragging()
         renderer()->setNeedsLayout();
 }
 
+#if !PLATFORM(IOS)
 void SliderThumbElement::defaultEventHandler(Event* event)
 {
     if (!event->isMouseEvent()) {
@@ -358,7 +371,9 @@ void SliderThumbElement::defaultEventHandler(Event* event)
 
     HTMLDivElement::defaultEventHandler(event);
 }
+#endif
 
+#if !PLATFORM(IOS)
 bool SliderThumbElement::willRespondToMouseMoveEvents()
 {
     const HTMLInputElement* input = hostInput();
@@ -376,6 +391,7 @@ bool SliderThumbElement::willRespondToMouseClickEvents()
 
     return HTMLDivElement::willRespondToMouseClickEvents();
 }
+#endif // !PLATFORM(IOS)
 
 void SliderThumbElement::willDetachRenderers()
 {
@@ -383,7 +399,160 @@ void SliderThumbElement::willDetachRenderers()
         if (Frame* frame = document().frame())
             frame->eventHandler().setCapturingMouseEventsElement(nullptr);
     }
+#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS)
+    unregisterForTouchEvents();
+#endif
+}
+
+#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS)
+unsigned SliderThumbElement::exclusiveTouchIdentifier() const
+{
+    return m_exclusiveTouchIdentifier;
+}
+
+void SliderThumbElement::setExclusiveTouchIdentifier(unsigned identifier)
+{
+    ASSERT(m_exclusiveTouchIdentifier == NoIdentifier);
+    m_exclusiveTouchIdentifier = identifier;
+}
+
+void SliderThumbElement::clearExclusiveTouchIdentifier()
+{
+    m_exclusiveTouchIdentifier = NoIdentifier;
+}
+
+static Touch* findTouchWithIdentifier(TouchList* list, unsigned identifier)
+{
+    unsigned length = list->length();
+    for (unsigned i = 0; i < length; ++i) {
+        Touch* touch = list->item(i);
+        if (touch->identifier() == identifier)
+            return touch;
+    }
+    return nullptr;
+}
+
+void SliderThumbElement::handleTouchStart(TouchEvent* touchEvent)
+{
+    TouchList* targetTouches = touchEvent->targetTouches();
+    if (targetTouches->length() != 1)
+        return;
+
+    // Ignore the touch if it is not really inside the thumb.
+    Touch* touch = targetTouches->item(0);
+    IntRect boundingBox = renderer()->absoluteBoundingBoxRect();
+    if (!boundingBox.contains(touch->pageX(), touch->pageY()))
+        return;
+
+    setExclusiveTouchIdentifier(touch->identifier());
+
+    startDragging();
+    touchEvent->setDefaultHandled();
+}
+
+void SliderThumbElement::handleTouchMove(TouchEvent* touchEvent)
+{
+    unsigned identifier = exclusiveTouchIdentifier();
+    if (identifier == NoIdentifier)
+        return;
+
+    Touch* touch = findTouchWithIdentifier(touchEvent->targetTouches(), identifier);
+    if (!touch)
+        return;
+
+    if (m_inDragMode)
+        setPositionFromPoint(IntPoint(touch->pageX(), touch->pageY()));
+    touchEvent->setDefaultHandled();
+}
+
+void SliderThumbElement::handleTouchEndAndCancel(TouchEvent* touchEvent)
+{
+    unsigned identifier = exclusiveTouchIdentifier();
+    if (identifier == NoIdentifier)
+        return;
+
+    // If our exclusive touch still exists, it was not the touch
+    // that ended, so we should not stop dragging.
+    Touch* exclusiveTouch = findTouchWithIdentifier(touchEvent->targetTouches(), identifier);
+    if (exclusiveTouch)
+        return;
+
+    clearExclusiveTouchIdentifier();
+
+    stopDragging();
+}
+
+void SliderThumbElement::didAttachRenderers()
+{
+    if (shouldAcceptTouchEvents())
+        registerForTouchEvents();
+}
+
+void SliderThumbElement::handleTouchEvent(TouchEvent* touchEvent)
+{
+    HTMLInputElement* input = hostInput();
+    ASSERT(input);
+    if (input->isReadOnly() || input->isDisabledFormControl()) {
+        clearExclusiveTouchIdentifier();
+        stopDragging();
+        touchEvent->setDefaultHandled();
+        HTMLDivElement::defaultEventHandler(touchEvent);
+        return;
+    }
+
+    const AtomicString& eventType = touchEvent->type();
+    if (eventType == eventNames().touchstartEvent) {
+        handleTouchStart(touchEvent);
+        return;
+    }
+    if (eventType == eventNames().touchendEvent || eventType == eventNames().touchcancelEvent) {
+        handleTouchEndAndCancel(touchEvent);
+        return;
+    }
+    if (eventType == eventNames().touchmoveEvent) {
+        handleTouchMove(touchEvent);
+        return;
+    }
+
+    HTMLDivElement::defaultEventHandler(touchEvent);
+}
+
+bool SliderThumbElement::shouldAcceptTouchEvents()
+{
+    return attached() && !isDisabledFormControl();
+}
+
+void SliderThumbElement::registerForTouchEvents()
+{
+    if (m_isRegisteredAsTouchEventListener)
+        return;
+
+    ASSERT(shouldAcceptTouchEvents());
+
+    document().addTouchEventListener(this);
+    m_isRegisteredAsTouchEventListener = true;
+}
+
+void SliderThumbElement::unregisterForTouchEvents()
+{
+    if (!m_isRegisteredAsTouchEventListener)
+        return;
+
+    clearExclusiveTouchIdentifier();
+    stopDragging();
+
+    document().removeTouchEventListener(this);
+    m_isRegisteredAsTouchEventListener = false;
+}
+
+void SliderThumbElement::disabledAttributeChanged()
+{
+    if (shouldAcceptTouchEvents())
+        registerForTouchEvents();
+    else
+        unregisterForTouchEvents();
 }
+#endif // ENABLE(TOUCH_EVENTS) && PLATFORM(IOS)
 
 HTMLInputElement* SliderThumbElement::hostInput() const
 {
index 3dc21f5a4d27b674797a40a47e9175dee11efaa1..56ceb469b1273004812b8536fabadc2beffce9b0 100644 (file)
@@ -41,6 +41,7 @@ namespace WebCore {
 
 class HTMLInputElement;
 class FloatPoint;
+class TouchEvent;
 
 class SliderThumbElement FINAL : public HTMLDivElement {
 public:
@@ -51,6 +52,12 @@ public:
     HTMLInputElement* hostInput() const;
     void setPositionFromPoint(const LayoutPoint&);
 
+#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS)
+    void handleTouchEvent(TouchEvent*);
+
+    void disabledAttributeChanged();
+#endif
+
 private:
     SliderThumbElement(Document&);
 
@@ -60,16 +67,45 @@ private:
     virtual bool matchesReadOnlyPseudoClass() const OVERRIDE;
     virtual bool matchesReadWritePseudoClass() const OVERRIDE;
     virtual Element* focusDelegate() OVERRIDE;
+#if !PLATFORM(IOS)
     virtual void defaultEventHandler(Event*) OVERRIDE;
     virtual bool willRespondToMouseMoveEvents() OVERRIDE;
     virtual bool willRespondToMouseClickEvents() OVERRIDE;
+#endif
+
+#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS)
+    virtual void didAttachRenderers() OVERRIDE;
+#endif
     virtual void willDetachRenderers() OVERRIDE;
+
     virtual const AtomicString& shadowPseudoId() const OVERRIDE;
 
     void startDragging();
     void stopDragging();
 
+#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS)
+    unsigned exclusiveTouchIdentifier() const;
+    void setExclusiveTouchIdentifier(unsigned);
+    void clearExclusiveTouchIdentifier();
+
+    void handleTouchStart(TouchEvent*);
+    void handleTouchMove(TouchEvent*);
+    void handleTouchEndAndCancel(TouchEvent*);
+
+    bool shouldAcceptTouchEvents();
+    void registerForTouchEvents();
+    void unregisterForTouchEvents();
+#endif
+
     bool m_inDragMode;
+
+#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS)
+    // FIXME: Currently it is safe to use 0, but this may need to change
+    // if touch identifers change in the future and can be 0.
+    static const unsigned NoIdentifier = 0;
+    unsigned m_exclusiveTouchIdentifier;
+    bool m_isRegisteredAsTouchEventListener;
+#endif
 };
 
 inline PassRefPtr<SliderThumbElement> SliderThumbElement::create(Document& document)
index 8f3ff77cc900511dee6aeb484d4947b5582a2b56..a67f8909c925b3c8e397148ea3976a9d60230fb6 100644 (file)
@@ -165,11 +165,13 @@ void SearchFieldResultsButtonElement::defaultEventHandler(Event* event)
     if (input && event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) {
         input->focus();
         input->select();
+#if !PLATFORM(IOS)
         RenderSearchField* renderer = toRenderSearchField(input->renderer());
         if (renderer->popupIsVisible())
             renderer->hidePopup();
         else if (input->maxResults() > 0)
             renderer->showPopup();
+#endif
         event->setDefaultHandled();
     }
 
@@ -177,10 +179,12 @@ void SearchFieldResultsButtonElement::defaultEventHandler(Event* event)
         HTMLDivElement::defaultEventHandler(event);
 }
 
+#if !PLATFORM(IOS)
 bool SearchFieldResultsButtonElement::willRespondToMouseClickEvents()
 {
     return true;
 }
+#endif
 
 // ----------------------------
 
@@ -250,6 +254,7 @@ void SearchFieldCancelButtonElement::defaultEventHandler(Event* event)
         HTMLDivElement::defaultEventHandler(event);
 }
 
+#if !PLATFORM(IOS)
 bool SearchFieldCancelButtonElement::willRespondToMouseClickEvents()
 {
     const HTMLInputElement* input = toHTMLInputElement(shadowHost());
@@ -258,6 +263,7 @@ bool SearchFieldCancelButtonElement::willRespondToMouseClickEvents()
 
     return HTMLDivElement::willRespondToMouseClickEvents();
 }
+#endif
 
 // ----------------------------
 
@@ -348,6 +354,7 @@ void InputFieldSpeechButtonElement::defaultEventHandler(Event* event)
         HTMLDivElement::defaultEventHandler(event);
 }
 
+#if !PLATFORM(IOS)
 bool InputFieldSpeechButtonElement::willRespondToMouseClickEvents()
 {
     const HTMLInputElement* input = toHTMLInputElement(shadowHost());
@@ -356,6 +363,7 @@ bool InputFieldSpeechButtonElement::willRespondToMouseClickEvents()
 
     return HTMLDivElement::willRespondToMouseClickEvents();
 }
+#endif
 
 void InputFieldSpeechButtonElement::setState(SpeechInputState state)
 {
index a325b839b01bec1ad34343584f9f12e8e4bcddc5..20aaad988213e5e44ba2d1c0c59970b8e251c17f 100644 (file)
@@ -81,7 +81,9 @@ public:
     static PassRefPtr<SearchFieldResultsButtonElement> create(Document&);
 
     virtual void defaultEventHandler(Event*) OVERRIDE;
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseClickEvents() OVERRIDE;
+#endif
 
 private:
     SearchFieldResultsButtonElement(Document&);
@@ -95,7 +97,9 @@ public:
 
     virtual void defaultEventHandler(Event*) OVERRIDE;
     virtual bool isSearchFieldCancelButtonElement() const OVERRIDE { return true; }
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseClickEvents() OVERRIDE;
+#endif
 
 private:
     SearchFieldCancelButtonElement(Document&);
@@ -122,7 +126,9 @@ public:
     virtual ~InputFieldSpeechButtonElement();
 
     virtual void defaultEventHandler(Event*);
+#if !PLATFORM(IOS)
     virtual bool willRespondToMouseClickEvents();
+#endif
     virtual bool isInputFieldSpeechButtonElement() const { return true; }
     SpeechInputState state() const { return m_state; }
     void startSpeechInput();
index fd64f2f85e2ff53a5721507b5aa16c0924be2f54..f48b4cd3ab836c095731ebc011e2833dadde2615 100644 (file)
@@ -214,3 +214,6 @@ simpleLineLayoutDebugBordersEnabled initial=false, setNeedsStyleRecalcInAllFrame
 
 backgroundShouldExtendBeyondPage initial=false
 mediaSourceEnabled initial=false
+
+# FIXME: Rename to allowMultiElementImplicitFormSubmission once we upstream the iOS changes to WebView.mm.
+allowMultiElementImplicitSubmission initial=false