Add a WKWebView input delegate SPI
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Oct 2015 23:47:10 +0000 (23:47 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Oct 2015 23:47:10 +0000 (23:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=149646

Reviewed by Dan Bernstein.

Renames the existing _WKFormDelegate to _WKInputDelegate and adds a new delegate SPI method
-[_WKInputDelegate _webView:focusShouldStartInputSession:] that allows clients to allow or
disallow showing up the keyboard. To make this decision, clients are given a
_WKFocusedElementInfo, which contains information about the focused element prior to the
keyboard showing up so the client will be able to override default assistance behavior.

While the information contained in a _WKFocusedElementInfo currently seems like overkill for
_webView:focusShouldStartInputSession, our intentions are to give WebKit clients control over more
details of how node assistance works, such as being able to use a custom editor for certain
types of nodes.

* Shared/API/Cocoa/WebKitPrivate.h: Added new header _WKFocusedElementInfo.h.
* UIProcess/API/Cocoa/WKWebView.h:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _inputDelegate]):
(-[WKWebView _formDelegate]):
(-[WKWebView _setInputDelegate:]):
(-[WKWebView _setFormDelegate:]):
(-[WKWebView initWithFrame:configuration:]): Deleted canAssistOnProgrammaticFocus flag.
(-[WKWebView canAssistOnProgrammaticFocus]): Ditto.
(-[WKWebView setCanAssistOnProgrammaticFocus:]): Ditto.
* UIProcess/API/Cocoa/WKWebViewConfiguration.h:
* UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
(-[WKWebViewConfiguration init]): Deleted.
(-[WKWebViewConfiguration _canAssistOnProgrammaticFocus]): Deleted canAssistOnProgrammaticFocus flag.
(-[WKWebViewConfiguration _setCanAssistOnProgrammaticFocus:]): Ditto.
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/API/Cocoa/_WKFocusedElementInfo.h: Added.
* UIProcess/API/Cocoa/_WKFormDelegate.h:
* UIProcess/API/Cocoa/_WKInputDelegate.h: Copied from Source/WebKit2/UIProcess/API/Cocoa/_WKFormDelegate.h.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKFocusedElementInfo initWithAssistedNodeInformation:isInteracting:]):
(-[WKFocusedElementInfo type]):
(-[WKFocusedElementInfo value]):
(-[WKFocusedElementInfo isUserInitiated]):
(-[WKContentView accessoryAutoFill]):
(-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:userObject:]): If the input delegate responds to
    shouldStartInputSession, consult it to see if we should bring up the keyboard; otherwise, use our default behavior.
* WebKit2.xcodeproj/project.pbxproj:

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

12 files changed:
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/API/Cocoa/WebKitPrivate.h
Source/WebKit2/UIProcess/API/Cocoa/WKWebView.h
Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit2/UIProcess/API/Cocoa/WKWebViewConfiguration.h
Source/WebKit2/UIProcess/API/Cocoa/WKWebViewConfiguration.mm
Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h
Source/WebKit2/UIProcess/API/Cocoa/_WKFocusedElementInfo.h [new file with mode: 0644]
Source/WebKit2/UIProcess/API/Cocoa/_WKFormDelegate.h
Source/WebKit2/UIProcess/API/Cocoa/_WKInputDelegate.h [new file with mode: 0644]
Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj

index ddc74ac..a07ed98 100644 (file)
@@ -1,3 +1,50 @@
+2015-10-16  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Add a WKWebView input delegate SPI
+        https://bugs.webkit.org/show_bug.cgi?id=149646
+
+        Reviewed by Dan Bernstein.
+
+        Renames the existing _WKFormDelegate to _WKInputDelegate and adds a new delegate SPI method
+        -[_WKInputDelegate _webView:focusShouldStartInputSession:] that allows clients to allow or
+        disallow showing up the keyboard. To make this decision, clients are given a
+        _WKFocusedElementInfo, which contains information about the focused element prior to the
+        keyboard showing up so the client will be able to override default assistance behavior.
+
+        While the information contained in a _WKFocusedElementInfo currently seems like overkill for
+        _webView:focusShouldStartInputSession, our intentions are to give WebKit clients control over more
+        details of how node assistance works, such as being able to use a custom editor for certain
+        types of nodes.
+
+        * Shared/API/Cocoa/WebKitPrivate.h: Added new header _WKFocusedElementInfo.h.
+        * UIProcess/API/Cocoa/WKWebView.h:
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _inputDelegate]):
+        (-[WKWebView _formDelegate]):
+        (-[WKWebView _setInputDelegate:]):
+        (-[WKWebView _setFormDelegate:]):
+        (-[WKWebView initWithFrame:configuration:]): Deleted canAssistOnProgrammaticFocus flag.
+        (-[WKWebView canAssistOnProgrammaticFocus]): Ditto.
+        (-[WKWebView setCanAssistOnProgrammaticFocus:]): Ditto.
+        * UIProcess/API/Cocoa/WKWebViewConfiguration.h:
+        * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
+        (-[WKWebViewConfiguration init]): Deleted.
+        (-[WKWebViewConfiguration _canAssistOnProgrammaticFocus]): Deleted canAssistOnProgrammaticFocus flag.
+        (-[WKWebViewConfiguration _setCanAssistOnProgrammaticFocus:]): Ditto.
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        * UIProcess/API/Cocoa/_WKFocusedElementInfo.h: Added.
+        * UIProcess/API/Cocoa/_WKFormDelegate.h:
+        * UIProcess/API/Cocoa/_WKInputDelegate.h: Copied from Source/WebKit2/UIProcess/API/Cocoa/_WKFormDelegate.h.
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKFocusedElementInfo initWithAssistedNodeInformation:isInteracting:]):
+        (-[WKFocusedElementInfo type]):
+        (-[WKFocusedElementInfo value]):
+        (-[WKFocusedElementInfo isUserInitiated]):
+        (-[WKContentView accessoryAutoFill]):
+        (-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:userObject:]): If the input delegate responds to
+            shouldStartInputSession, consult it to see if we should bring up the keyboard; otherwise, use our default behavior.
+        * WebKit2.xcodeproj/project.pbxproj:
+
 2015-10-16  Simon Fraser  <simon.fraser@apple.com>
 
         Make TextStream the canonical way to log classes in WebCore
index acf8624..75c2aab 100644 (file)
 #import <WebKit/WKWebViewPrivate.h>
 #import <WebKit/_WKActivatedElementInfo.h>
 #import <WebKit/_WKElementAction.h>
+#import <WebKit/_WKFocusedElementInfo.h>
 #import <WebKit/_WKFormDelegate.h>
 #import <WebKit/_WKFormInputSession.h>
+#import <WebKit/_WKInputDelegate.h>
 #import <WebKit/_WKProcessPoolConfiguration.h>
 #import <WebKit/_WKThumbnailView.h>
 #import <WebKit/_WKVisitedLinkStore.h>
index 4a7dec7..55debea 100644 (file)
@@ -241,11 +241,6 @@ WK_CLASS_AVAILABLE(10_10, 8_0)
 /*! @abstract The scroll view associated with the web view.
  */
 @property (nonatomic, readonly, strong) UIScrollView *scrollView;
-
-/*! @abstract A Boolean value indicating whether programmatic focus on
- an element is allowed to trigger assistance.
- */
-@property (nonatomic) BOOL canAssistOnProgrammaticFocus;
 #endif
 
 #if !TARGET_OS_IPHONE
index 64516b3..1d9078f 100644 (file)
@@ -74,6 +74,7 @@
 #import "_WKDiagnosticLoggingDelegate.h"
 #import "_WKFindDelegate.h"
 #import "_WKFormDelegate.h"
+#import "_WKInputDelegate.h"
 #import "_WKRemoteObjectRegistryInternal.h"
 #import "_WKSessionStateInternal.h"
 #import "_WKVisitedLinkStoreInternal.h"
@@ -159,7 +160,7 @@ WKWebView* fromWebPageProxy(WebKit::WebPageProxy& page)
     RetainPtr<_WKRemoteObjectRegistry> _remoteObjectRegistry;
     _WKRenderingProgressEvents _observedRenderingProgressEvents;
 
-    WebKit::WeakObjCPtr<id <_WKFormDelegate>> _formDelegate;
+    WebKit::WeakObjCPtr<id <_WKInputDelegate>> _inputDelegate;
 
 #if PLATFORM(IOS)
     RetainPtr<WKScrollView> _scrollView;
@@ -212,8 +213,6 @@ WKWebView* fromWebPageProxy(WebKit::WebPageProxy& page)
     BOOL _pageIsPrintingToPDF;
     RetainPtr<CGPDFDocumentRef> _printedDocument;
     Vector<std::function<void ()>> _snapshotsDeferredDuringResize;
-
-    BOOL _canAssistOnProgrammaticFocus;
 #endif
 #if PLATFORM(MAC)
     RetainPtr<WKView> _wkView;
@@ -366,8 +365,6 @@ static bool shouldAllowPictureInPictureMediaPlayback()
     _page->contentSizeCategoryDidChange([self _contentSizeCategory]);
 
     [[_configuration _contentProviderRegistry] addPage:*_page];
-
-    [self setCanAssistOnProgrammaticFocus:[_configuration canAssistOnProgrammaticFocus]];
 #endif
 
 #if PLATFORM(MAC)
@@ -724,16 +721,6 @@ static WKErrorCode callbackErrorCode(WebKit::CallbackBase::Error error)
     return _scrollView.get();
 }
 
-- (BOOL)canAssistOnProgrammaticFocus
-{
-    return _canAssistOnProgrammaticFocus;
-}
-
-- (void)setCanAssistOnProgrammaticFocus:(BOOL)canAssistOnProgrammaticFocus
-{
-    _canAssistOnProgrammaticFocus = canAssistOnProgrammaticFocus;
-}
-
 - (WKBrowsingContextController *)browsingContextController
 {
     return [_contentView browsingContextController];
@@ -2476,14 +2463,19 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
     _page->recordNavigationSnapshot(item._item);
 }
 
+- (id <_WKInputDelegate>)_inputDelegate
+{
+    return _inputDelegate.getAutoreleased();
+}
+
 - (id <_WKFormDelegate>)_formDelegate
 {
-    return _formDelegate.getAutoreleased();
+    return (id <_WKFormDelegate>)[self _inputDelegate];
 }
 
-- (void)_setFormDelegate:(id <_WKFormDelegate>)formDelegate
+- (void)_setInputDelegate:(id <_WKInputDelegate>)inputDelegate
 {
-    _formDelegate = formDelegate;
+    _inputDelegate = inputDelegate;
 
     class FormClient : public API::FormClient {
     public:
@@ -2503,9 +2495,9 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
                 return;
             }
 
-            auto formDelegate = m_webView->_formDelegate.get();
+            auto inputDelegate = m_webView->_inputDelegate.get();
 
-            if (![formDelegate respondsToSelector:@selector(_webView:willSubmitFormValues:userObject:submissionHandler:)]) {
+            if (![inputDelegate respondsToSelector:@selector(_webView:willSubmitFormValues:userObject:submissionHandler:)]) {
                 listener->continueSubmission();
                 return;
             }
@@ -2527,8 +2519,8 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
             }
 
             RefPtr<WebKit::WebFormSubmissionListenerProxy> localListener = WTF::move(listener);
-            RefPtr<WebKit::CompletionHandlerCallChecker> checker = WebKit::CompletionHandlerCallChecker::create(formDelegate.get(), @selector(_webView:willSubmitFormValues:userObject:submissionHandler:));
-            [formDelegate _webView:m_webView willSubmitFormValues:valueMap.get() userObject:userObject submissionHandler:[localListener, checker] {
+            RefPtr<WebKit::CompletionHandlerCallChecker> checker = WebKit::CompletionHandlerCallChecker::create(inputDelegate.get(), @selector(_webView:willSubmitFormValues:userObject:submissionHandler:));
+            [inputDelegate _webView:m_webView willSubmitFormValues:valueMap.get() userObject:userObject submissionHandler:[localListener, checker] {
                 checker->didCallCompletionHandler();
                 localListener->continueSubmission();
             }];
@@ -2538,12 +2530,17 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
         WKWebView *m_webView;
     };
 
-    if (formDelegate)
+    if (inputDelegate)
         _page->setFormClient(std::make_unique<FormClient>(self));
     else
         _page->setFormClient(nullptr);
 }
 
+- (void)_setFormDelegate:(id <_WKFormDelegate>)formDelegate
+{
+    [self _setInputDelegate:(id <_WKInputDelegate>)formDelegate];
+}
+
 - (BOOL)_isDisplayingStandaloneImageDocument
 {
     if (auto* mainFrame = _page->mainFrame())
index dbdf2d1..fe7ac78 100644 (file)
@@ -119,12 +119,6 @@ WK_CLASS_AVAILABLE(10_10, 8_0)
  */
 @property (nonatomic) BOOL allowsPictureInPictureMediaPlayback WK_AVAILABLE(NA, 9_0);
 
-/*! @abstract A Boolean value indicating whether programmatic focus on
- an element is allowed to trigger assistance.
- @discussion The default value is NO.
- */
-@property (nonatomic) BOOL canAssistOnProgrammaticFocus;
-
 #endif
 
 @end
index a2308d3..f657e24 100644 (file)
@@ -112,7 +112,6 @@ private:
     _allowsInlineMediaPlayback = WKGetDeviceClass() == WKDeviceClassiPad;
     _inlineMediaPlaybackRequiresPlaysInlineAttribute = !_allowsInlineMediaPlayback;
     _mediaDataLoadsAutomatically = NO;
-    _canAssistOnProgrammaticFocus = NO;
 #endif
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
@@ -365,16 +364,6 @@ static NSString *defaultApplicationNameForUserAgent()
 {
     _mediaDataLoadsAutomatically = mediaDataLoadsAutomatically;
 }
-
-- (BOOL)_canAssistOnProgrammaticFocus
-{
-    return _canAssistOnProgrammaticFocus;
-}
-
-- (void)_setCanAssistOnProgrammaticFocus:(BOOL)canAssistOnProgrammaticFocus
-{
-    _canAssistOnProgrammaticFocus = canAssistOnProgrammaticFocus;
-}
 #endif
 
 @end
index 87ea6e2..96f5f9b 100644 (file)
@@ -58,6 +58,7 @@ typedef NS_ENUM(NSInteger, _WKImmediateActionType) {
 @protocol _WKDiagnosticLoggingDelegate;
 @protocol _WKFindDelegate;
 @protocol _WKFormDelegate;
+@protocol _WKInputDelegate;
 
 @interface WKWebView (WKPrivate)
 
@@ -216,7 +217,8 @@ typedef NS_ENUM(NSInteger, _WKImmediateActionType) {
 - (void)_countStringMatches:(NSString *)string options:(_WKFindOptions)options maxCount:(NSUInteger)maxCount;
 - (void)_hideFindUI;
 
-@property (nonatomic, weak, setter=_setFormDelegate:) id <_WKFormDelegate> _formDelegate;
+@property (nonatomic, weak, setter=_setFormDelegate:) id <_WKFormDelegate> _formDelegate WK_DEPRECATED(10_10, WK_MAC_TBA, 8_0, WK_IOS_TBA, "use _inputDelegate");
+@property (nonatomic, weak, setter=_setInputDelegate:) id <_WKInputDelegate> _inputDelegate WK_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
 
 @property (nonatomic, readonly, getter=_isDisplayingStandaloneImageDocument) BOOL _displayingStandaloneImageDocument;
 @property (nonatomic, readonly, getter=_isDisplayingStandaloneMediaDocument) BOOL _displayingStandaloneMediaDocument;
diff --git a/Source/WebKit2/UIProcess/API/Cocoa/_WKFocusedElementInfo.h b/Source/WebKit2/UIProcess/API/Cocoa/_WKFocusedElementInfo.h
new file mode 100644 (file)
index 0000000..b6fa457
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2015 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#import <WebKit/WKFoundation.h>
+
+#if WK_API_ENABLED
+
+#import <Foundation/Foundation.h>
+
+/**
+ * WKInputType exposes a subset of all known input types enumerated in
+ * WebKit::InputType. While there is currently a one-to-one mapping, we
+ * need to consider how we should expose certain input types.
+ */
+typedef NS_ENUM(NSInteger, WKInputType) {
+    WKInputTypeNone,
+    WKInputTypeContentEditable,
+    WKInputTypeText,
+    WKInputTypePassword,
+    WKInputTypeTextArea,
+    WKInputTypeSearch,
+    WKInputTypeEmail,
+    WKInputTypeURL,
+    WKInputTypePhone,
+    WKInputTypeNumber,
+    WKInputTypeNumberPad,
+    WKInputTypeDate,
+    WKInputTypeDateTime,
+    WKInputTypeDateTimeLocal,
+    WKInputTypeMonth,
+    WKInputTypeWeek,
+    WKInputTypeTime,
+    WKInputTypeSelect
+};
+
+/**
+ * The _WKFocusedElementInfo provides basic information about an element
+ * that has been focused (either programmatically or through user interaction)
+ * but has not yet been assisted.
+ */
+@protocol _WKFocusedElementInfo <NSObject>
+
+/* The type of the input element that was focused. */
+@property (nonatomic, readonly) WKInputType type;
+
+/* The value of the input at the time it was focused. */
+@property (nonatomic, readonly, copy) NSString *value;
+
+/**
+ * Whether the element was focused due to user interaction. NO indicates that
+ * the element was focused programmatically, e.g. by calling focus() in JavaScript
+ * or by using the autofocus attribute.
+ */
+@property (nonatomic, readonly, getter=isUserInitiated) BOOL userInitiated;
+
+@end
+
+#endif // WK_API_ENABLED
index 7eafcf8..7d021ff 100644 (file)
 
 #if WK_API_ENABLED
 
-#import <Foundation/Foundation.h>
-
-@class WKWebView;
-@protocol _WKFormInputSession;
-
-@protocol _WKFormDelegate <NSObject>
-
-@optional
-
-- (void)_webView:(WKWebView *)webView didStartInputSession:(id <_WKFormInputSession>)inputSession;
-- (void)_webView:(WKWebView *)webView willSubmitFormValues:(NSDictionary *)values userObject:(NSObject <NSSecureCoding> *)userObject submissionHandler:(void (^)(void))submissionHandler;
-
-#if TARGET_OS_IPHONE
-- (void)_webView:(WKWebView *)webView accessoryViewCustomButtonTappedInFormInputSession:(id <_WKFormInputSession>)inputSession;
-- (BOOL)_webView:(WKWebView *)webView hasSuggestionsForCurrentStringInInputSession:(id <_WKFormInputSession>)inputSession;
-- (NSArray *)_webView:(WKWebView *)webView suggestionsForString:(NSString *)string inInputSession:(id <_WKFormInputSession>)inputSession;
-#endif
+#import <WebKit/_WKInputDelegate.h>
 
+/**
+ * We are transitioning _WKFormDelegate to _WKInputDelegate. This header is here temporarily for source compatibility and
+ * should be removed when we are ready to make the switch.
+ */
+@protocol _WKFormDelegate <_WKInputDelegate>
 @end
 
 #endif // WK_API_ENABLED
diff --git a/Source/WebKit2/UIProcess/API/Cocoa/_WKInputDelegate.h b/Source/WebKit2/UIProcess/API/Cocoa/_WKInputDelegate.h
new file mode 100644 (file)
index 0000000..ae12177
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#import <WebKit/WKFoundation.h>
+
+#if WK_API_ENABLED
+
+#import <Foundation/Foundation.h>
+
+@class WKWebView;
+@protocol _WKFocusedElementInfo;
+@protocol _WKFormInputSession;
+
+@protocol _WKInputDelegate <NSObject>
+
+@optional
+
+- (void)_webView:(WKWebView *)webView didStartInputSession:(id <_WKFormInputSession>)inputSession;
+- (void)_webView:(WKWebView *)webView willSubmitFormValues:(NSDictionary *)values userObject:(NSObject <NSSecureCoding> *)userObject submissionHandler:(void (^)(void))submissionHandler;
+
+#if TARGET_OS_IPHONE
+- (BOOL)_webView:(WKWebView *)webView focusShouldStartInputSession:(id <_WKFocusedElementInfo>)info;
+- (void)_webView:(WKWebView *)webView accessoryViewCustomButtonTappedInFormInputSession:(id <_WKFormInputSession>)inputSession;
+- (BOOL)_webView:(WKWebView *)webView hasSuggestionsForCurrentStringInInputSession:(id <_WKFormInputSession>)inputSession;
+- (NSArray *)_webView:(WKWebView *)webView suggestionsForString:(NSString *)string inInputSession:(id <_WKFormInputSession>)inputSession;
+#endif
+
+@end
+
+#endif // WK_API_ENABLED
index c91d228..879a7e6 100644 (file)
@@ -53,8 +53,9 @@
 #import "WebPageMessages.h"
 #import "WebProcessProxy.h"
 #import "_WKActivatedElementInfoInternal.h"
-#import "_WKFormDelegate.h"
+#import "_WKFocusedElementInfo.h"
 #import "_WKFormInputSession.h"
+#import "_WKInputDelegate.h"
 #import <CoreText/CTFont.h>
 #import <CoreText/CTFontDescriptor.h>
 #import <MobileCoreServices/UTCoreTypes.h>
@@ -277,6 +278,98 @@ const CGFloat minimumTapHighlightRadius = 2.0;
 
 @end
 
+@interface WKFocusedElementInfo : NSObject <_WKFocusedElementInfo>
+- (instancetype)initWithAssistedNodeInformation:(const AssistedNodeInformation&)information isUserInitiated:(BOOL)isUserInitiated;
+@end
+
+@implementation WKFocusedElementInfo {
+    WKInputType _type;
+    RetainPtr<NSString> _value;
+    BOOL _isUserInitiated;
+}
+
+- (instancetype)initWithAssistedNodeInformation:(const AssistedNodeInformation&)information isUserInitiated:(BOOL)isUserInitiated
+{
+    if (!(self = [super init]))
+        return nil;
+
+    switch (information.elementType) {
+    case WebKit::InputType::ContentEditable:
+        _type = WKInputTypeContentEditable;
+        break;
+    case WebKit::InputType::Text:
+        _type = WKInputTypeText;
+        break;
+    case WebKit::InputType::Password:
+        _type = WKInputTypePassword;
+        break;
+    case WebKit::InputType::TextArea:
+        _type = WKInputTypeTextArea;
+        break;
+    case WebKit::InputType::Search:
+        _type = WKInputTypeSearch;
+        break;
+    case WebKit::InputType::Email:
+        _type = WKInputTypeEmail;
+        break;
+    case WebKit::InputType::URL:
+        _type = WKInputTypeURL;
+        break;
+    case WebKit::InputType::Phone:
+        _type = WKInputTypePhone;
+        break;
+    case WebKit::InputType::Number:
+        _type = WKInputTypeNumber;
+        break;
+    case WebKit::InputType::NumberPad:
+        _type = WKInputTypeNumberPad;
+        break;
+    case WebKit::InputType::Date:
+        _type = WKInputTypeDate;
+        break;
+    case WebKit::InputType::DateTime:
+        _type = WKInputTypeDateTime;
+        break;
+    case WebKit::InputType::DateTimeLocal:
+        _type = WKInputTypeDateTimeLocal;
+        break;
+    case WebKit::InputType::Month:
+        _type = WKInputTypeMonth;
+        break;
+    case WebKit::InputType::Week:
+        _type = WKInputTypeWeek;
+        break;
+    case WebKit::InputType::Time:
+        _type = WKInputTypeTime;
+        break;
+    case WebKit::InputType::Select:
+        _type = WKInputTypeSelect;
+        break;
+    case WebKit::InputType::None:
+        _type = WKInputTypeNone;
+        break;
+    }
+    _value = information.value;
+    _isUserInitiated = isUserInitiated;
+    return self;
+}
+
+- (WKInputType)type
+{
+    return _type;
+}
+
+- (NSString *)value
+{
+    return _value.get();
+}
+
+- (BOOL)isUserInitiated
+{
+    return _isUserInitiated;
+}
+@end
+
 @interface WKContentView (WKInteractionPrivate)
 - (void)accessibilitySpeakSelectionSetContent:(NSString *)string;
 @end
@@ -2258,9 +2351,9 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
 
 - (void)accessoryAutoFill
 {
-    id <_WKFormDelegate> formDelegate = [_webView _formDelegate];
-    if ([formDelegate respondsToSelector:@selector(_webView:accessoryViewCustomButtonTappedInFormInputSession:)])
-        [formDelegate _webView:_webView accessoryViewCustomButtonTappedInFormInputSession:_formInputSession.get()];
+    id <_WKInputDelegate> inputDelegate = [_webView _inputDelegate];
+    if ([inputDelegate respondsToSelector:@selector(_webView:accessoryViewCustomButtonTappedInFormInputSession:)])
+        [inputDelegate _webView:_webView accessoryViewCustomButtonTappedInFormInputSession:_formInputSession.get()];
 }
 
 - (void)accessoryClear
@@ -3028,9 +3121,16 @@ static bool isAssistableInputType(InputType type)
 
 - (void)_startAssistingNode:(const AssistedNodeInformation&)information userIsInteracting:(BOOL)userIsInteracting blurPreviousNode:(BOOL)blurPreviousNode userObject:(NSObject <NSSecureCoding> *)userObject
 {
-    // FIXME: This is a temporary workaround for <rdar://problem/22126518>. The real fix will involve refactoring
-    // the way we assist programmatically focused nodes.
-    if (!userIsInteracting && !_textSelectionAssistant && !_webView.canAssistOnProgrammaticFocus)
+    id <_WKInputDelegate> inputDelegate = [_webView _inputDelegate];
+    BOOL shouldShowKeyboard;
+    if ([inputDelegate respondsToSelector:@selector(_webView:focusShouldStartInputSession:)]) {
+        RetainPtr<WKFocusedElementInfo> focusedElementInfo = adoptNS([[WKFocusedElementInfo alloc] initWithAssistedNodeInformation:information isUserInitiated:userIsInteracting]);
+        shouldShowKeyboard = [inputDelegate _webView:_webView focusShouldStartInputSession:focusedElementInfo.get()];
+    } else {
+        // The default behavior is to allow node assistance if the user is interacting or the keyboard is already active.
+        shouldShowKeyboard = userIsInteracting || _textSelectionAssistant;
+    }
+    if (!shouldShowKeyboard)
         return;
 
     if (blurPreviousNode)
@@ -3073,10 +3173,9 @@ static bool isAssistableInputType(InputType type)
     // _inputPeripheral has been initialized in inputView called by reloadInputViews.
     [_inputPeripheral beginEditing];
 
-    id <_WKFormDelegate> formDelegate = [_webView _formDelegate];
-    if ([formDelegate respondsToSelector:@selector(_webView:didStartInputSession:)]) {
+    if ([inputDelegate respondsToSelector:@selector(_webView:didStartInputSession:)]) {
         _formInputSession = adoptNS([[WKFormInputSession alloc] initWithContentView:self userObject:userObject]);
-        [formDelegate _webView:_webView didStartInputSession:_formInputSession.get()];
+        [inputDelegate _webView:_webView didStartInputSession:_formInputSession.get()];
     }
 }
 
index 00fa5e9..d05de1f 100644 (file)
                2DF9EEE81A78245500B6CFBE /* WKFrameInfoInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DF9EEE71A78245500B6CFBE /* WKFrameInfoInternal.h */; };
                2DF9EEEC1A7836EE00B6CFBE /* APINavigationAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DF9EEEA1A7836EE00B6CFBE /* APINavigationAction.h */; };
                2DF9EEEE1A786EAD00B6CFBE /* APINavigationResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DF9EEED1A786EAD00B6CFBE /* APINavigationResponse.h */; };
+               2E0B8A7A1BC59A590044B32D /* _WKFormDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E0B8A791BC59A590044B32D /* _WKFormDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               2E7A944A1BBD97C300945547 /* _WKFocusedElementInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E7A94491BBD95C600945547 /* _WKFocusedElementInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                31099973146C75A20029DEB9 /* WebNotificationClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 31099971146C759B0029DEB9 /* WebNotificationClient.cpp */; };
                310999C7146C9E3D0029DEB9 /* WebNotificationClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 31099968146C71F50029DEB9 /* WebNotificationClient.h */; };
                312C0C4A146DDC8A0016C911 /* WKNotificationProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 312C0C49146DDC8A0016C911 /* WKNotificationProvider.h */; settings = {ATTRIBUTES = (Private, ); }; };
                379A873C18BBFF0700588AF2 /* _WKElementActionInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 379A873B18BBFF0700588AF2 /* _WKElementActionInternal.h */; };
                37A5E01318BBF937000A081E /* _WKActivatedElementInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37A5E01118BBF937000A081E /* _WKActivatedElementInfo.mm */; };
                37A5E01418BBF93F000A081E /* _WKActivatedElementInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 37A5E01218BBF937000A081E /* _WKActivatedElementInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               37A64E5518F38E3C00EB30F1 /* _WKFormDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 37A64E5418F38E3C00EB30F1 /* _WKFormDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               37A64E5518F38E3C00EB30F1 /* _WKInputDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 37A64E5418F38E3C00EB30F1 /* _WKInputDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                37A64E5718F38F4600EB30F1 /* _WKFormInputSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 37A64E5618F38F4600EB30F1 /* _WKFormInputSession.h */; settings = {ATTRIBUTES = (Private, ); }; };
                37B5045219EEF31300CE2CF8 /* WKErrorPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 37B5045119EEF31300CE2CF8 /* WKErrorPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                37BEC4DD1948FC6A008B4286 /* WebCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1AA1C79A100E7FC50078DEBC /* WebCore.framework */; };
                2DF9EEE71A78245500B6CFBE /* WKFrameInfoInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKFrameInfoInternal.h; sourceTree = "<group>"; };
                2DF9EEEA1A7836EE00B6CFBE /* APINavigationAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APINavigationAction.h; sourceTree = "<group>"; };
                2DF9EEED1A786EAD00B6CFBE /* APINavigationResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APINavigationResponse.h; sourceTree = "<group>"; };
+               2E0B8A791BC59A590044B32D /* _WKFormDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKFormDelegate.h; sourceTree = "<group>"; };
+               2E7A94491BBD95C600945547 /* _WKFocusedElementInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKFocusedElementInfo.h; sourceTree = "<group>"; };
                31099968146C71F50029DEB9 /* WebNotificationClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebNotificationClient.h; sourceTree = "<group>"; };
                31099971146C759B0029DEB9 /* WebNotificationClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebNotificationClient.cpp; sourceTree = "<group>"; };
                312C0C49146DDC8A0016C911 /* WKNotificationProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKNotificationProvider.h; sourceTree = "<group>"; };
                379A873B18BBFF0700588AF2 /* _WKElementActionInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKElementActionInternal.h; sourceTree = "<group>"; };
                37A5E01118BBF937000A081E /* _WKActivatedElementInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKActivatedElementInfo.mm; sourceTree = "<group>"; };
                37A5E01218BBF937000A081E /* _WKActivatedElementInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKActivatedElementInfo.h; sourceTree = "<group>"; };
-               37A64E5418F38E3C00EB30F1 /* _WKFormDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKFormDelegate.h; sourceTree = "<group>"; };
+               37A64E5418F38E3C00EB30F1 /* _WKInputDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKInputDelegate.h; sourceTree = "<group>"; };
                37A64E5618F38F4600EB30F1 /* _WKFormInputSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKFormInputSession.h; sourceTree = "<group>"; };
                37B5045119EEF31300CE2CF8 /* WKErrorPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKErrorPrivate.h; sourceTree = "<group>"; };
                37BEC4DE19491486008B4286 /* CompletionHandlerCallChecker.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CompletionHandlerCallChecker.mm; sourceTree = "<group>"; };
                                1AD01BC61905D37E00C9C45F /* _WKErrorRecoveryAttempting.mm */,
                                005D158E18E4C4EB00734619 /* _WKFindDelegate.h */,
                                2DEAC5CE1AC368BB00A195D8 /* _WKFindOptions.h */,
-                               37A64E5418F38E3C00EB30F1 /* _WKFormDelegate.h */,
+                               2E7A94491BBD95C600945547 /* _WKFocusedElementInfo.h */,
+                               2E0B8A791BC59A590044B32D /* _WKFormDelegate.h */,
                                37A64E5618F38F4600EB30F1 /* _WKFormInputSession.h */,
+                               37A64E5418F38E3C00EB30F1 /* _WKInputDelegate.h */,
                                2D790A9C1AD7050D00AB90B3 /* _WKLayoutMode.h */,
                                9323611D1B015DA800FA9232 /* _WKOverlayScrollbarStyle.h */,
                                1A43E828188F3CDC009E4D30 /* _WKProcessPoolConfiguration.h */,
                                1AD01BC91905D37E00C9C45F /* _WKErrorRecoveryAttempting.h in Headers */,
                                005D158F18E4C4EB00734619 /* _WKFindDelegate.h in Headers */,
                                2DEAC5CF1AC368BB00A195D8 /* _WKFindOptions.h in Headers */,
-                               37A64E5518F38E3C00EB30F1 /* _WKFormDelegate.h in Headers */,
+                               2E7A944A1BBD97C300945547 /* _WKFocusedElementInfo.h in Headers */,
+                               2E0B8A7A1BC59A590044B32D /* _WKFormDelegate.h in Headers */,
                                37A64E5718F38F4600EB30F1 /* _WKFormInputSession.h in Headers */,
                                373D122318A473010066D9CC /* _WKFrameHandle.h in Headers */,
                                373D122718A473F60066D9CC /* _WKFrameHandleInternal.h in Headers */,
+                               37A64E5518F38E3C00EB30F1 /* _WKInputDelegate.h in Headers */,
                                2D790A9D1AD7050D00AB90B3 /* _WKLayoutMode.h in Headers */,
                                A118A9F31908B8EA00F7C92B /* _WKNSFileManagerExtras.h in Headers */,
                                9323611E1B015DA800FA9232 /* _WKOverlayScrollbarStyle.h in Headers */,