| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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. | |
| 4 | |
| 5 #import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h" | |
| 6 | |
| 7 #import <objc/runtime.h> | |
| 8 | |
| 9 #include "base/auto_reset.h" | |
| 10 #import "base/ios/crb_protocol_observers.h" | |
| 11 #include "base/mac/foundation_util.h" | |
| 12 #import "base/mac/scoped_nsobject.h" | |
| 13 | |
| 14 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
| 15 #error "This file requires ARC support." | |
| 16 #endif | |
| 17 | |
| 18 @interface CRWWebViewScrollViewProxy () { | |
| 19 __weak UIScrollView* _scrollView; | |
| 20 base::scoped_nsobject<id> _observers; | |
| 21 } | |
| 22 | |
| 23 // Returns the key paths that need to be observed for UIScrollView. | |
| 24 + (NSArray*)scrollViewObserverKeyPaths; | |
| 25 | |
| 26 // Adds and removes |self| as an observer for |scrollView| with key paths | |
| 27 // returned by |+scrollViewObserverKeyPaths|. | |
| 28 - (void)startObservingScrollView:(UIScrollView*)scrollView; | |
| 29 - (void)stopObservingScrollView:(UIScrollView*)scrollView; | |
| 30 | |
| 31 @end | |
| 32 | |
| 33 @implementation CRWWebViewScrollViewProxy | |
| 34 | |
| 35 - (instancetype)init { | |
| 36 self = [super init]; | |
| 37 if (self) { | |
| 38 Protocol* protocol = @protocol(CRWWebViewScrollViewProxyObserver); | |
| 39 _observers.reset([CRBProtocolObservers observersWithProtocol:protocol]); | |
| 40 } | |
| 41 return self; | |
| 42 } | |
| 43 | |
| 44 - (void)dealloc { | |
| 45 [self stopObservingScrollView:_scrollView]; | |
| 46 } | |
| 47 | |
| 48 - (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer { | |
| 49 [_scrollView addGestureRecognizer:gestureRecognizer]; | |
| 50 } | |
| 51 | |
| 52 - (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer { | |
| 53 [_scrollView removeGestureRecognizer:gestureRecognizer]; | |
| 54 } | |
| 55 | |
| 56 - (void)addObserver:(id<CRWWebViewScrollViewProxyObserver>)observer { | |
| 57 [_observers addObserver:observer]; | |
| 58 } | |
| 59 | |
| 60 - (void)removeObserver:(id<CRWWebViewScrollViewProxyObserver>)observer { | |
| 61 [_observers removeObserver:observer]; | |
| 62 } | |
| 63 | |
| 64 - (void)setScrollView:(UIScrollView*)scrollView { | |
| 65 if (_scrollView == scrollView) | |
| 66 return; | |
| 67 [_scrollView setDelegate:nil]; | |
| 68 [self stopObservingScrollView:_scrollView]; | |
| 69 DCHECK(!scrollView.delegate); | |
| 70 scrollView.delegate = self; | |
| 71 [self startObservingScrollView:scrollView]; | |
| 72 _scrollView = scrollView; | |
| 73 [_observers webViewScrollViewProxyDidSetScrollView:self]; | |
| 74 } | |
| 75 | |
| 76 - (CGRect)frame { | |
| 77 return _scrollView ? [_scrollView frame] : CGRectZero; | |
| 78 } | |
| 79 | |
| 80 - (BOOL)isScrollEnabled { | |
| 81 return [_scrollView isScrollEnabled]; | |
| 82 } | |
| 83 | |
| 84 - (void)setScrollEnabled:(BOOL)scrollEnabled { | |
| 85 [_scrollView setScrollEnabled:scrollEnabled]; | |
| 86 } | |
| 87 | |
| 88 - (BOOL)bounces { | |
| 89 return [_scrollView bounces]; | |
| 90 } | |
| 91 | |
| 92 - (void)setBounces:(BOOL)bounces { | |
| 93 [_scrollView setBounces:bounces]; | |
| 94 } | |
| 95 | |
| 96 - (BOOL)isZooming { | |
| 97 return [_scrollView isZooming]; | |
| 98 } | |
| 99 | |
| 100 - (CGFloat)zoomScale { | |
| 101 return [_scrollView zoomScale]; | |
| 102 } | |
| 103 | |
| 104 - (void)setContentOffset:(CGPoint)contentOffset { | |
| 105 [_scrollView setContentOffset:contentOffset]; | |
| 106 } | |
| 107 | |
| 108 - (CGPoint)contentOffset { | |
| 109 return _scrollView ? [_scrollView contentOffset] : CGPointZero; | |
| 110 } | |
| 111 | |
| 112 - (void)setContentInset:(UIEdgeInsets)contentInset { | |
| 113 [_scrollView setContentInset:contentInset]; | |
| 114 } | |
| 115 | |
| 116 - (UIEdgeInsets)contentInset { | |
| 117 return _scrollView ? [_scrollView contentInset] : UIEdgeInsetsZero; | |
| 118 } | |
| 119 | |
| 120 - (void)setScrollIndicatorInsets:(UIEdgeInsets)scrollIndicatorInsets { | |
| 121 [_scrollView setScrollIndicatorInsets:scrollIndicatorInsets]; | |
| 122 } | |
| 123 | |
| 124 - (UIEdgeInsets)scrollIndicatorInsets { | |
| 125 return _scrollView ? [_scrollView scrollIndicatorInsets] : UIEdgeInsetsZero; | |
| 126 } | |
| 127 | |
| 128 - (void)setContentSize:(CGSize)contentSize { | |
| 129 [_scrollView setContentSize:contentSize]; | |
| 130 } | |
| 131 | |
| 132 - (CGSize)contentSize { | |
| 133 return _scrollView ? [_scrollView contentSize] : CGSizeZero; | |
| 134 } | |
| 135 | |
| 136 - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated { | |
| 137 [_scrollView setContentOffset:contentOffset animated:animated]; | |
| 138 } | |
| 139 | |
| 140 - (UIPanGestureRecognizer*)panGestureRecognizer { | |
| 141 return [_scrollView panGestureRecognizer]; | |
| 142 } | |
| 143 | |
| 144 - (NSArray*)gestureRecognizers { | |
| 145 return [_scrollView gestureRecognizers]; | |
| 146 } | |
| 147 | |
| 148 #pragma mark - | |
| 149 #pragma mark UIScrollViewDelegate callbacks | |
| 150 | |
| 151 - (void)scrollViewDidScroll:(UIScrollView*)scrollView { | |
| 152 DCHECK_EQ(_scrollView, scrollView); | |
| 153 [_observers webViewScrollViewDidScroll:self]; | |
| 154 } | |
| 155 | |
| 156 - (void)scrollViewWillBeginDragging:(UIScrollView*)scrollView { | |
| 157 DCHECK_EQ(_scrollView, scrollView); | |
| 158 [_observers webViewScrollViewWillBeginDragging:self]; | |
| 159 | |
| 160 // TODO(crbug.com/555723) Remove this once the fix to | |
| 161 // https://bugs.webkit.org/show_bug.cgi?id=148086 makes it's way in to iOS. | |
| 162 scrollView.decelerationRate = UIScrollViewDecelerationRateNormal; | |
| 163 } | |
| 164 | |
| 165 - (void)scrollViewWillEndDragging:(UIScrollView*)scrollView | |
| 166 withVelocity:(CGPoint)velocity | |
| 167 targetContentOffset:(inout CGPoint*)targetContentOffset { | |
| 168 DCHECK_EQ(_scrollView, scrollView); | |
| 169 [_observers webViewScrollViewWillEndDragging:self | |
| 170 withVelocity:velocity | |
| 171 targetContentOffset:targetContentOffset]; | |
| 172 } | |
| 173 | |
| 174 - (void)scrollViewDidEndDragging:(UIScrollView*)scrollView | |
| 175 willDecelerate:(BOOL)decelerate { | |
| 176 DCHECK_EQ(_scrollView, scrollView); | |
| 177 [_observers webViewScrollViewDidEndDragging:self willDecelerate:decelerate]; | |
| 178 } | |
| 179 | |
| 180 - (void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView { | |
| 181 DCHECK_EQ(_scrollView, scrollView); | |
| 182 [_observers webViewScrollViewDidEndDecelerating:self]; | |
| 183 } | |
| 184 | |
| 185 - (void)scrollViewDidEndScrollingAnimation:(UIScrollView*)scrollView { | |
| 186 DCHECK_EQ(_scrollView, scrollView); | |
| 187 [_observers webViewScrollViewDidEndScrollingAnimation:self]; | |
| 188 } | |
| 189 | |
| 190 - (BOOL)scrollViewShouldScrollToTop:(UIScrollView*)scrollView { | |
| 191 DCHECK_EQ(_scrollView, scrollView); | |
| 192 __block BOOL shouldScrollToTop = YES; | |
| 193 [_observers executeOnObservers:^(id observer) { | |
| 194 if ([observer respondsToSelector:@selector( | |
| 195 webViewScrollViewShouldScrollToTop:)]) { | |
| 196 shouldScrollToTop = shouldScrollToTop && | |
| 197 [observer webViewScrollViewShouldScrollToTop:self]; | |
| 198 } | |
| 199 }]; | |
| 200 return shouldScrollToTop; | |
| 201 } | |
| 202 | |
| 203 - (void)scrollViewDidZoom:(UIScrollView*)scrollView { | |
| 204 DCHECK_EQ(_scrollView, scrollView); | |
| 205 [_observers webViewScrollViewDidZoom:self]; | |
| 206 } | |
| 207 | |
| 208 #pragma mark - | |
| 209 | |
| 210 + (NSArray*)scrollViewObserverKeyPaths { | |
| 211 return @[ @"contentSize" ]; | |
| 212 } | |
| 213 | |
| 214 - (void)startObservingScrollView:(UIScrollView*)scrollView { | |
| 215 for (NSString* keyPath in [[self class] scrollViewObserverKeyPaths]) | |
| 216 [scrollView addObserver:self forKeyPath:keyPath options:0 context:nil]; | |
| 217 } | |
| 218 | |
| 219 - (void)stopObservingScrollView:(UIScrollView*)scrollView { | |
| 220 for (NSString* keyPath in [[self class] scrollViewObserverKeyPaths]) | |
| 221 [scrollView removeObserver:self forKeyPath:keyPath]; | |
| 222 } | |
| 223 | |
| 224 - (void)observeValueForKeyPath:(NSString*)keyPath | |
| 225 ofObject:(id)object | |
| 226 change:(NSDictionary*)change | |
| 227 context:(void*)context { | |
| 228 DCHECK_EQ(object, _scrollView); | |
| 229 if ([keyPath isEqualToString:@"contentSize"]) | |
| 230 [_observers webViewScrollViewDidResetContentSize:self]; | |
| 231 } | |
| 232 | |
| 233 @end | |
| OLD | NEW |