Prevent app list doodle from being pinch-to-zoomed.
[chromium-blink-merge.git] / ios / web / web_state / crw_web_view_proxy_impl.mm
blobadb13c8b80916bf806101fbbc89eb1eaa498ec23
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "ios/web/web_state/crw_web_view_proxy_impl.h"
7 #include "base/ios/weak_nsobject.h"
8 #include "base/mac/scoped_nsobject.h"
9 #import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h"
10 #import "ios/web/web_state/ui/crw_web_controller.h"
12 namespace {
14 // Returns the first responder in the subviews of |view|, or nil if no view in
15 // the subtree is the first responder.
16 UIView* GetFirstResponderSubview(UIView* view) {
17   if ([view isFirstResponder])
18     return view;
20   for (UIView* subview in [view subviews]) {
21     UIView* firstResponder = GetFirstResponderSubview(subview);
22     if (firstResponder)
23       return firstResponder;
24   }
26   return nil;
29 }  // namespace
31 @interface CRWWebViewScrollViewProxy (ContentInsetsAlgebra)
32 // Adds the given insets to the current content insets and scroll indicator
33 // insets of the receiver.
34 - (void)cr_addInsets:(UIEdgeInsets)insets;
35 // Removes the given insets to the current content insets and scroll indicator
36 // insets of the receiver.
37 - (void)cr_removeInsets:(UIEdgeInsets)insets;
38 @end
40 @implementation CRWWebViewScrollViewProxy (ContentInsetsAlgebra)
42 - (void)cr_addInsets:(UIEdgeInsets)insets {
43   if (UIEdgeInsetsEqualToEdgeInsets(insets, UIEdgeInsetsZero))
44     return;
46   UIEdgeInsets currentInsets = [self contentInset];
47   currentInsets.top += insets.top;
48   currentInsets.left += insets.left;
49   currentInsets.bottom += insets.bottom;
50   currentInsets.right += insets.right;
51   [self setContentInset:currentInsets];
52   [self setScrollIndicatorInsets:currentInsets];
55 - (void)cr_removeInsets:(UIEdgeInsets)insets {
56   UIEdgeInsets negativeInsets = UIEdgeInsetsZero;
57   negativeInsets.top = -insets.top;
58   negativeInsets.left = -insets.left;
59   negativeInsets.bottom = -insets.bottom;
60   negativeInsets.right = -insets.right;
61   [self cr_addInsets:negativeInsets];
64 @end
66 @implementation CRWWebViewProxyImpl {
67   base::WeakNSObject<UIView> _webView;
68   base::WeakNSObject<CRWWebController> _webController;
69   base::scoped_nsobject<NSMutableDictionary> _registeredInsets;
70   // The WebViewScrollViewProxy is a wrapper around the UIWebView's
71   // UIScrollView to give components access in a limited and controlled manner.
72   base::scoped_nsobject<CRWWebViewScrollViewProxy> _webViewScrollViewProxy;
75 - (instancetype)initWithWebController:(CRWWebController*)webController {
76   self = [super init];
77   if (self) {
78     DCHECK(webController);
79     _registeredInsets.reset([[NSMutableDictionary alloc] init]);
80     _webController.reset(webController);
81     _webViewScrollViewProxy.reset([[CRWWebViewScrollViewProxy alloc] init]);
82   }
83   return self;
86 - (CRWWebViewScrollViewProxy*)scrollViewProxy {
87   return _webViewScrollViewProxy.get();
90 - (CGRect)bounds {
91   return [_webView bounds];
94 - (NSArray*)gestureRecognizers {
95   return [_webView gestureRecognizers];
98 - (web::WebViewType)webViewType {
99   return [_webController webViewType];
102 - (void)registerInsets:(UIEdgeInsets)insets forCaller:(id)caller {
103   NSValue* callerValue = [NSValue valueWithNonretainedObject:caller];
104   if ([_registeredInsets objectForKey:callerValue])
105     [self unregisterInsetsForCaller:caller];
106   [self.scrollViewProxy cr_addInsets:insets];
107   [_registeredInsets setObject:[NSValue valueWithUIEdgeInsets:insets]
108                         forKey:callerValue];
111 - (void)unregisterInsetsForCaller:(id)caller {
112   NSValue* callerValue = [NSValue valueWithNonretainedObject:caller];
113   NSValue* insetsValue = [_registeredInsets objectForKey:callerValue];
114   [self.scrollViewProxy cr_removeInsets:[insetsValue UIEdgeInsetsValue]];
115   [_registeredInsets removeObjectForKey:callerValue];
118 - (void)setWebView:(UIView*)webView scrollView:(UIScrollView*)scrollView {
119   _webView.reset(webView);
120   if (webView)
121     DCHECK(scrollView);
122   [_webViewScrollViewProxy setScrollView:scrollView];
125 - (void)addSubview:(UIView*)view {
126   return [_webView addSubview:view];
129 - (BOOL)hasSearchableTextContent {
130   return _webView != nil && [_webController contentIsHTML];
133 - (UIView*)getKeyboardAccessory {
134   if (!_webView)
135     return nil;
136   UIView* firstResponder = GetFirstResponderSubview(_webView);
137   return firstResponder.inputAccessoryView;
140 - (BOOL)keyboardDisplayRequiresUserAction {
141   return [_webController keyboardDisplayRequiresUserAction];
144 - (void)setKeyboardDisplayRequiresUserAction:
145         (BOOL)keyboardDisplayRequiresUserAction {
146   [_webController
147       setKeyboardDisplayRequiresUserAction:keyboardDisplayRequiresUserAction];
150 @end