Commit cc76379d authored by Javier Ernesto Flores Robles's avatar Javier Ernesto Flores Robles Committed by Chromium LUCI CQ

[iOS][MF] Add Form Input APIs to Web View

Expose APIs to replace the input view and input accessory view in web
view.

Bug: 1163967
Change-Id: I98c5dce1cc1f06bbebaf97c881a8520280567b8b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2611903
Commit-Queue: Javier Flores <javierrobles@chromium.org>
Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843198}
parent ecb8fb27
...@@ -7,6 +7,7 @@ import("//ios/build/config.gni") ...@@ -7,6 +7,7 @@ import("//ios/build/config.gni")
source_set("common") { source_set("common") {
sources = [ sources = [
"crw_content_view.h", "crw_content_view.h",
"crw_input_view_provider.h",
"crw_viewport_adjustment.h", "crw_viewport_adjustment.h",
"crw_viewport_adjustment_container.h", "crw_viewport_adjustment_container.h",
"crw_web_view_content_view.h", "crw_web_view_content_view.h",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_WEB_COMMON_CRW_INPUT_VIEW_PROVIDER_H_
#define IOS_WEB_COMMON_CRW_INPUT_VIEW_PROVIDER_H_
#import <UIKit/UIKit.h>
// Subset of UIResponder's APIs. Includes APIs related to inputView and
// inputAccessoryView.
@protocol CRWResponderInputView <NSObject>
@optional
// APIs to show custom input views. These mimic the ones in UIResponder. Refer
// to Apple's documentation for more information.
- (UIView*)inputView;
- (UIInputViewController*)inputViewController;
- (UIView*)inputAccessoryView;
- (UIInputViewController*)inputAccessoryViewController;
@end
// Any object that adopts this protocol can provide an id<CRWResponderInputView>
// to show custom input views.
@protocol CRWInputViewProvider <NSObject>
// The actual object implementing the input view methods.
@property(nonatomic, readonly) id<CRWResponderInputView> responderInputView;
@end
#endif // IOS_WEB_COMMON_CRW_INPUT_VIEW_PROVIDER_H_
...@@ -21,7 +21,7 @@ WKWebView* BuildWKWebView(CGRect frame, BrowserState* browser_state) { ...@@ -21,7 +21,7 @@ WKWebView* BuildWKWebView(CGRect frame, BrowserState* browser_state) {
WKWebViewConfigurationProvider& config_provider = WKWebViewConfigurationProvider& config_provider =
WKWebViewConfigurationProvider::FromBrowserState(browser_state); WKWebViewConfigurationProvider::FromBrowserState(browser_state);
return BuildWKWebView(frame, config_provider.GetWebViewConfiguration(), return BuildWKWebView(frame, config_provider.GetWebViewConfiguration(),
browser_state, UserAgentType::MOBILE); browser_state, UserAgentType::MOBILE, nil);
} }
WKWebView* BuildWKWebViewForQueries(BrowserState* browser_state) { WKWebView* BuildWKWebViewForQueries(BrowserState* browser_state) {
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/callback.h" #include "base/callback.h"
#import "ios/web/public/web_state.h" #import "ios/web/public/web_state.h"
@protocol CRWResponderInputView;
@class UIViewController; @class UIViewController;
namespace web { namespace web {
...@@ -117,6 +118,10 @@ class WebStateDelegate { ...@@ -117,6 +118,10 @@ class WebStateDelegate {
virtual void ContextMenuWillPresent(WebState* source, const GURL& link_url) virtual void ContextMenuWillPresent(WebState* source, const GURL& link_url)
API_AVAILABLE(ios(13.0)); API_AVAILABLE(ios(13.0));
// UIResponder Form Input APIs, consult Apple's UIResponder documentation for
// more info.
virtual id<CRWResponderInputView> GetResponderInputView(WebState* source);
protected: protected:
virtual ~WebStateDelegate(); virtual ~WebStateDelegate();
......
...@@ -111,6 +111,9 @@ ...@@ -111,6 +111,9 @@
contextMenuDidEndForLinkWithURL:(const GURL&)linkURL contextMenuDidEndForLinkWithURL:(const GURL&)linkURL
API_AVAILABLE(ios(13.0)); API_AVAILABLE(ios(13.0));
// This API can be used to show custom input views in the web view.
- (id<CRWResponderInputView>)webStateInputViewProvider:(web::WebState*)webState;
@end @end
namespace web { namespace web {
...@@ -163,6 +166,8 @@ class WebStateDelegateBridge : public web::WebStateDelegate { ...@@ -163,6 +166,8 @@ class WebStateDelegateBridge : public web::WebStateDelegate {
void ContextMenuWillPresent(WebState* source, const GURL& link_url) void ContextMenuWillPresent(WebState* source, const GURL& link_url)
API_AVAILABLE(ios(13.0)) override; API_AVAILABLE(ios(13.0)) override;
id<CRWResponderInputView> GetResponderInputView(WebState* source) override;
private: private:
// CRWWebStateDelegate which receives forwarded calls. // CRWWebStateDelegate which receives forwarded calls.
__weak id<CRWWebStateDelegate> delegate_ = nil; __weak id<CRWWebStateDelegate> delegate_ = nil;
......
...@@ -79,6 +79,7 @@ source_set("page_viewport_state") { ...@@ -79,6 +79,7 @@ source_set("page_viewport_state") {
source_set("web_view_internal_creation_util") { source_set("web_view_internal_creation_util") {
deps = [ deps = [
"//base", "//base",
"//ios/web/common",
"//ios/web/common:user_agent", "//ios/web/common:user_agent",
"//ios/web/public", "//ios/web/public",
"//ios/web/web_state/ui:crw_context_menu_controller", "//ios/web/web_state/ui:crw_context_menu_controller",
...@@ -86,6 +87,8 @@ source_set("web_view_internal_creation_util") { ...@@ -86,6 +87,8 @@ source_set("web_view_internal_creation_util") {
] ]
sources = [ sources = [
"crw_web_view.h",
"crw_web_view.mm",
"web_view_internal_creation_util.h", "web_view_internal_creation_util.h",
"web_view_internal_creation_util.mm", "web_view_internal_creation_util.mm",
] ]
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_WEB_WEB_STATE_CRW_WEB_VIEW_H_
#define IOS_WEB_WEB_STATE_CRW_WEB_VIEW_H_
#import <WebKit/WebKit.h>
@protocol CRWInputViewProvider;
// Subclass of WKWebView which supports custom input views.
@interface CRWWebView : WKWebView
// Provider for custom input views and their respective view controllers.
@property(nonatomic, weak) id<CRWInputViewProvider> inputViewProvider;
@end
#endif // IOS_WEB_WEB_STATE_CRW_WEB_VIEW_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/web/web_state/crw_web_view.h"
#import "ios/web/common/crw_input_view_provider.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@implementation CRWWebView
#pragma mark - UIResponder
- (UIView*)inputView {
id<CRWResponderInputView> responderInputView =
self.inputViewProvider.responderInputView;
if ([responderInputView respondsToSelector:@selector(inputView)]) {
return [responderInputView inputView];
}
return [super inputView];
}
- (UIInputViewController*)inputViewController {
id<CRWResponderInputView> responderInputView =
self.inputViewProvider.responderInputView;
if ([responderInputView respondsToSelector:@selector(inputViewController)]) {
return [responderInputView inputViewController];
}
return [super inputViewController];
}
- (UIView*)inputAccessoryView {
id<CRWResponderInputView> responderInputView =
self.inputViewProvider.responderInputView;
if ([responderInputView respondsToSelector:@selector(inputAccessoryView)]) {
return [responderInputView inputAccessoryView];
}
return [super inputAccessoryView];
}
- (UIInputViewController*)inputAccessoryViewController {
id<CRWResponderInputView> responderInputView =
self.inputViewProvider.responderInputView;
if ([responderInputView
respondsToSelector:@selector(inputAccessoryViewController)]) {
return [responderInputView inputAccessoryViewController];
}
return [super inputAccessoryViewController];
}
@end
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "base/metrics/user_metrics_action.h" #include "base/metrics/user_metrics_action.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#import "ios/web/browsing_data/browsing_data_remover.h" #import "ios/web/browsing_data/browsing_data_remover.h"
#import "ios/web/common/crw_input_view_provider.h"
#import "ios/web/common/crw_web_view_content_view.h" #import "ios/web/common/crw_web_view_content_view.h"
#include "ios/web/common/features.h" #include "ios/web/common/features.h"
#import "ios/web/common/uikit_ui_util.h" #import "ios/web/common/uikit_ui_util.h"
...@@ -95,6 +96,7 @@ NSString* const kSessionRestoreScriptMessageName = @"session_restore"; ...@@ -95,6 +96,7 @@ NSString* const kSessionRestoreScriptMessageName = @"session_restore";
} // namespace } // namespace
@interface CRWWebController () <CRWWKNavigationHandlerDelegate, @interface CRWWebController () <CRWWKNavigationHandlerDelegate,
CRWInputViewProvider,
CRWJSInjectorDelegate, CRWJSInjectorDelegate,
CRWSSLStatusUpdaterDataSource, CRWSSLStatusUpdaterDataSource,
CRWSSLStatusUpdaterDelegate, CRWSSLStatusUpdaterDelegate,
...@@ -1603,8 +1605,9 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*); ...@@ -1603,8 +1605,9 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*);
web::GetWebClient()->GetDefaultUserAgent(_containerView, GURL()); web::GetWebClient()->GetDefaultUserAgent(_containerView, GURL());
} }
return web::BuildWKWebView( return web::BuildWKWebView(CGRectZero, config,
CGRectZero, config, self.webStateImpl->GetBrowserState(), userAgentType); self.webStateImpl->GetBrowserState(),
userAgentType, self);
} }
// Wraps the web view in a CRWWebViewContentView and adds it to the container // Wraps the web view in a CRWWebViewContentView and adds it to the container
...@@ -2046,6 +2049,17 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*); ...@@ -2046,6 +2049,17 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*);
return self.navigationHandler; return self.navigationHandler;
} }
#pragma mark - CRWInputViewProvider
- (id<CRWResponderInputView>)responderInputView {
web::WebState* webState = self.webStateImpl;
web::WebStateDelegate* webStateDelegate = webState->GetDelegate();
if (webStateDelegate) {
return webStateDelegate->GetResponderInputView(webState);
}
return nil;
}
#pragma mark - CRWJSNavigationHandlerDelegate #pragma mark - CRWJSNavigationHandlerDelegate
- (GURL)currentURLForJSNavigationHandler: - (GURL)currentURLForJSNavigationHandler:
......
...@@ -106,4 +106,9 @@ void WebStateDelegate::ContextMenuWillPresent(WebState* source, ...@@ -106,4 +106,9 @@ void WebStateDelegate::ContextMenuWillPresent(WebState* source,
const GURL& link_url) const GURL& link_url)
API_AVAILABLE(ios(13.0)) {} API_AVAILABLE(ios(13.0)) {}
id<CRWResponderInputView> WebStateDelegate::GetResponderInputView(
WebState* source) {
return nil;
}
} // web } // web
...@@ -189,4 +189,12 @@ void WebStateDelegateBridge::ContextMenuWillPresent(WebState* source, ...@@ -189,4 +189,12 @@ void WebStateDelegateBridge::ContextMenuWillPresent(WebState* source,
} }
} }
id<CRWResponderInputView> WebStateDelegateBridge::GetResponderInputView(
WebState* source) {
if ([delegate_ respondsToSelector:@selector(webStateInputViewProvider:)]) {
return [delegate_ webStateInputViewProvider:source];
}
return nil;
}
} // web } // web
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include "ios/web/common/user_agent.h" #include "ios/web/common/user_agent.h"
@protocol CRWInputViewProvider;
// This file is a collection of functions that vend web views. // This file is a collection of functions that vend web views.
namespace web { namespace web {
class BrowserState; class BrowserState;
...@@ -31,7 +33,8 @@ WKWebView* BuildWKWebViewForQueries(WKWebViewConfiguration* configuration, ...@@ -31,7 +33,8 @@ WKWebView* BuildWKWebViewForQueries(WKWebViewConfiguration* configuration,
WKWebView* BuildWKWebView(CGRect frame, WKWebView* BuildWKWebView(CGRect frame,
WKWebViewConfiguration* configuration, WKWebViewConfiguration* configuration,
BrowserState* browser_state, BrowserState* browser_state,
UserAgentType user_agent_type); UserAgentType user_agent_type,
id<CRWInputViewProvider> input_view_provider);
// Creates and returns a new WKWebView for displaying regular web content. // Creates and returns a new WKWebView for displaying regular web content.
// The preconditions for the creation of a WKWebView are the same as the // The preconditions for the creation of a WKWebView are the same as the
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/check_op.h" #include "base/check_op.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#import "ios/web/public/web_client.h" #import "ios/web/public/web_client.h"
#import "ios/web/web_state/crw_web_view.h"
#import "ios/web/web_state/ui/wk_web_view_configuration_provider.h" #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h"
#if !defined(__has_feature) || !__has_feature(objc_arc) #if !defined(__has_feature) || !__has_feature(objc_arc)
...@@ -43,13 +44,15 @@ WKWebView* BuildWKWebViewForQueries(WKWebViewConfiguration* configuration, ...@@ -43,13 +44,15 @@ WKWebView* BuildWKWebViewForQueries(WKWebViewConfiguration* configuration,
WKWebView* BuildWKWebView(CGRect frame, WKWebView* BuildWKWebView(CGRect frame,
WKWebViewConfiguration* configuration, WKWebViewConfiguration* configuration,
BrowserState* browser_state, BrowserState* browser_state,
UserAgentType user_agent_type) { UserAgentType user_agent_type,
id<CRWInputViewProvider> input_view_provider) {
VerifyWKWebViewCreationPreConditions(browser_state, configuration); VerifyWKWebViewCreationPreConditions(browser_state, configuration);
GetWebClient()->PreWebViewCreation(); GetWebClient()->PreWebViewCreation();
WKWebView* web_view = CRWWebView* web_view = [[CRWWebView alloc] initWithFrame:frame
[[WKWebView alloc] initWithFrame:frame configuration:configuration]; configuration:configuration];
web_view.inputViewProvider = input_view_provider;
// Set the user agent type. // Set the user agent type.
if (user_agent_type != web::UserAgentType::NONE) { if (user_agent_type != web::UserAgentType::NONE) {
...@@ -72,7 +75,7 @@ WKWebView* BuildWKWebView(CGRect frame, ...@@ -72,7 +75,7 @@ WKWebView* BuildWKWebView(CGRect frame,
WKWebViewConfiguration* configuration, WKWebViewConfiguration* configuration,
BrowserState* browser_state) { BrowserState* browser_state) {
return BuildWKWebView(frame, configuration, browser_state, return BuildWKWebView(frame, configuration, browser_state,
UserAgentType::MOBILE); UserAgentType::MOBILE, nil);
} }
} // namespace web } // namespace web
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment