Ensure favicon images are correctly used and downloaded when syncing bookmark apps.
[chromium-blink-merge.git] / ios / web / web_state / crw_web_view_proxy_impl.mm
blobc8d6142ab8180eecc016c676da2dfc04e8ebad6c
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/public/web_state/ui/crw_content_view.h"
11 #import "ios/web/web_state/ui/crw_web_controller.h"
13 namespace {
15 // Returns the first responder in the subviews of |view|, or nil if no view in
16 // the subtree is the first responder.
17 UIView* GetFirstResponderSubview(UIView* view) {
18   if ([view isFirstResponder])
19     return view;
21   for (UIView* subview in [view subviews]) {
22     UIView* firstResponder = GetFirstResponderSubview(subview);
23     if (firstResponder)
24       return firstResponder;
25   }
27   return nil;
30 }  // namespace
32 @interface CRWWebViewScrollViewProxy (ContentInsetsAlgebra)
33 // Adds the given insets to the current content insets and scroll indicator
34 // insets of the receiver.
35 - (void)cr_addInsets:(UIEdgeInsets)insets;
36 // Removes the given insets to the current content insets and scroll indicator
37 // insets of the receiver.
38 - (void)cr_removeInsets:(UIEdgeInsets)insets;
39 @end
41 @implementation CRWWebViewScrollViewProxy (ContentInsetsAlgebra)
43 - (void)cr_addInsets:(UIEdgeInsets)insets {
44   if (UIEdgeInsetsEqualToEdgeInsets(insets, UIEdgeInsetsZero))
45     return;
47   UIEdgeInsets currentInsets = [self contentInset];
48   currentInsets.top += insets.top;
49   currentInsets.left += insets.left;
50   currentInsets.bottom += insets.bottom;
51   currentInsets.right += insets.right;
52   [self setContentInset:currentInsets];
53   [self setScrollIndicatorInsets:currentInsets];
56 - (void)cr_removeInsets:(UIEdgeInsets)insets {
57   UIEdgeInsets negativeInsets = UIEdgeInsetsZero;
58   negativeInsets.top = -insets.top;
59   negativeInsets.left = -insets.left;
60   negativeInsets.bottom = -insets.bottom;
61   negativeInsets.right = -insets.right;
62   [self cr_addInsets:negativeInsets];
65 @end
67 @implementation CRWWebViewProxyImpl {
68   base::WeakNSObject<CRWContentView> _contentView;
69   base::WeakNSObject<CRWWebController> _webController;
70   base::scoped_nsobject<NSMutableDictionary> _registeredInsets;
71   // The WebViewScrollViewProxy is a wrapper around the UIWebView's
72   // UIScrollView to give components access in a limited and controlled manner.
73   base::scoped_nsobject<CRWWebViewScrollViewProxy> _contentViewScrollViewProxy;
76 - (instancetype)initWithWebController:(CRWWebController*)webController {
77   self = [super init];
78   if (self) {
79     DCHECK(webController);
80     _registeredInsets.reset([[NSMutableDictionary alloc] init]);
81     _webController.reset(webController);
82     _contentViewScrollViewProxy.reset([[CRWWebViewScrollViewProxy alloc] init]);
83   }
84   return self;
87 - (CRWWebViewScrollViewProxy*)scrollViewProxy {
88   return _contentViewScrollViewProxy.get();
91 - (CGRect)bounds {
92   return [_contentView bounds];
95 - (NSArray*)gestureRecognizers {
96   return [_contentView gestureRecognizers];
99 - (web::WebViewType)webViewType {
100   return [_webController webViewType];
103 - (void)registerInsets:(UIEdgeInsets)insets forCaller:(id)caller {
104   NSValue* callerValue = [NSValue valueWithNonretainedObject:caller];
105   if ([_registeredInsets objectForKey:callerValue])
106     [self unregisterInsetsForCaller:caller];
107   [self.scrollViewProxy cr_addInsets:insets];
108   [_registeredInsets setObject:[NSValue valueWithUIEdgeInsets:insets]
109                         forKey:callerValue];
112 - (void)unregisterInsetsForCaller:(id)caller {
113   NSValue* callerValue = [NSValue valueWithNonretainedObject:caller];
114   NSValue* insetsValue = [_registeredInsets objectForKey:callerValue];
115   [self.scrollViewProxy cr_removeInsets:[insetsValue UIEdgeInsetsValue]];
116   [_registeredInsets removeObjectForKey:callerValue];
119 - (CRWContentView*)contentView {
120   return _contentView.get();
123 - (void)setContentView:(CRWContentView*)contentView {
124   _contentView.reset(contentView);
125   [_contentViewScrollViewProxy setScrollView:contentView.scrollView];
128 - (void)addSubview:(UIView*)view {
129   return [_contentView addSubview:view];
132 - (BOOL)hasSearchableTextContent {
133   return _contentView != nil && [_webController contentIsHTML];
136 - (UIView*)getKeyboardAccessory {
137   if (!_contentView)
138     return nil;
139   UIView* firstResponder = GetFirstResponderSubview(_contentView);
140   return firstResponder.inputAccessoryView;
143 - (BOOL)keyboardDisplayRequiresUserAction {
144   return [_webController keyboardDisplayRequiresUserAction];
147 - (void)setKeyboardDisplayRequiresUserAction:
148         (BOOL)keyboardDisplayRequiresUserAction {
149   [_webController
150       setKeyboardDisplayRequiresUserAction:keyboardDisplayRequiresUserAction];
153 @end