summaryrefslogtreecommitdiffstats
path: root/ios
diff options
context:
space:
mode:
authorKurt Horimoto <kkhorimoto@chromium.org>2016-02-02 11:50:22 -0800
committerKurt Horimoto <kkhorimoto@chromium.org>2016-02-02 19:52:45 +0000
commit71fef383bd38c982f1393d18b95a44b8581507dc (patch)
tree908c797eeeb78fc7599342b82556438e6b82f698 /ios
parentcbb0ba3c8163792aec3504ca268b42a1849d8efa (diff)
downloadchromium_src-71fef383bd38c982f1393d18b95a44b8581507dc.zip
chromium_src-71fef383bd38c982f1393d18b95a44b8581507dc.tar.gz
chromium_src-71fef383bd38c982f1393d18b95a44b8581507dc.tar.bz2
Ignore renderer-initiated scrolls with no user interaction.
This CL adds |updatingThroughProxy| to CRWWebViewScrollViewProxy, which allows CRWWebViewScrollViewObservers to differentiate between renderer- initiated actions and updates that occur through the proxy API. CRWWebController should reset the content offset of the scroll view if WKWebView erroneously updates the scroll position, as occurs with the repro steps in the referenced bug. BUG=574996 TBR=eugenebut@chromium.org Review URL: https://codereview.chromium.org/1607973002 Cr-Commit-Position: refs/heads/master@{#370351} (cherry picked from commit 07f24cbae05f5ef11430902cd9dd7e9075db2710) Review URL: https://codereview.chromium.org/1659143002 . Cr-Commit-Position: refs/branch-heads/2623@{#243} Cr-Branched-From: 92d77538a86529ca35f9220bd3cd512cbea1f086-refs/heads/master@{#369907}
Diffstat (limited to 'ios')
-rw-r--r--ios/web/public/web_state/crw_web_view_scroll_view_proxy.h6
-rw-r--r--ios/web/web_state/crw_web_view_scroll_view_proxy.mm16
-rw-r--r--ios/web/web_state/ui/crw_web_controller.mm29
3 files changed, 44 insertions, 7 deletions
diff --git a/ios/web/public/web_state/crw_web_view_scroll_view_proxy.h b/ios/web/public/web_state/crw_web_view_scroll_view_proxy.h
index 7b49f89..54af234 100644
--- a/ios/web/public/web_state/crw_web_view_scroll_view_proxy.h
+++ b/ios/web/public/web_state/crw_web_view_scroll_view_proxy.h
@@ -35,6 +35,12 @@
// Returns the scrollview's gesture recognizers.
@property(nonatomic, readonly) NSArray* gestureRecognizers;
+// Returns YES if the UIScrollView is currently being updated through the proxy.
+// This can be used by CRWWebViewScrollViewObserver to differentiate renderer-
+// initiated updates from those caused by the proxy API.
+@property(nonatomic, readonly, getter=isUpdatingThroughProxy)
+ BOOL updatingThroughProxy;
+
// Calls UIScrollView's implementation of setContentInset: directly. This
// bypasses a very slow update path in UIWebView.
- (void)setContentInsetFast:(UIEdgeInsets)contentInset;
diff --git a/ios/web/web_state/crw_web_view_scroll_view_proxy.mm b/ios/web/web_state/crw_web_view_scroll_view_proxy.mm
index 306a9ca..3f263a0 100644
--- a/ios/web/web_state/crw_web_view_scroll_view_proxy.mm
+++ b/ios/web/web_state/crw_web_view_scroll_view_proxy.mm
@@ -18,6 +18,8 @@
// update and reset the contentOffset to force a fast update. These updates
// should be a no-op for the contentOffset, so the callbacks can be ignored.
BOOL _ignoreScroll;
+ // The number of calls through the proxy API in the current stack.
+ NSUInteger _proxyCallCount;
}
// Returns the key paths that need to be observed for UIScrollView.
@@ -84,6 +86,7 @@
}
- (void)setScrollEnabled:(BOOL)scrollEnabled {
+ base::AutoReset<NSUInteger> autoReset(&_proxyCallCount, _proxyCallCount + 1);
[_scrollView setScrollEnabled:scrollEnabled];
}
@@ -92,6 +95,7 @@
}
- (void)setBounces:(BOOL)bounces {
+ base::AutoReset<NSUInteger> autoReset(&_proxyCallCount, _proxyCallCount + 1);
[_scrollView setBounces:bounces];
}
@@ -104,6 +108,7 @@
}
- (void)setContentOffset:(CGPoint)contentOffset {
+ base::AutoReset<NSUInteger> autoReset(&_proxyCallCount, _proxyCallCount + 1);
[_scrollView setContentOffset:contentOffset];
}
@@ -112,6 +117,7 @@
}
- (void)setContentInsetFast:(UIEdgeInsets)contentInset {
+ base::AutoReset<NSUInteger> autoReset(&_proxyCallCount, _proxyCallCount + 1);
if (!_scrollView)
return;
@@ -139,7 +145,7 @@
// contentOffset will cause the -scrollViewDidScroll callback to fire.
// Because we are eventually setting the contentOffset back to it's original
// position, we can ignore these calls.
- base::AutoReset<BOOL> autoReset(&_ignoreScroll, YES);
+ base::AutoReset<BOOL> ignoreScrollAutoReset(&_ignoreScroll, YES);
CGPoint contentOffset = [_scrollView contentOffset];
_scrollView.get().contentOffset =
CGPointMake(contentOffset.x, contentOffset.y + 1);
@@ -147,6 +153,7 @@
}
- (void)setContentInset:(UIEdgeInsets)contentInset {
+ base::AutoReset<NSUInteger> autoReset(&_proxyCallCount, _proxyCallCount + 1);
[_scrollView setContentInset:contentInset];
}
@@ -155,6 +162,7 @@
}
- (void)setScrollIndicatorInsets:(UIEdgeInsets)scrollIndicatorInsets {
+ base::AutoReset<NSUInteger> autoReset(&_proxyCallCount, _proxyCallCount + 1);
[_scrollView setScrollIndicatorInsets:scrollIndicatorInsets];
}
@@ -163,6 +171,7 @@
}
- (void)setContentSize:(CGSize)contentSize {
+ base::AutoReset<NSUInteger> autoReset(&_proxyCallCount, _proxyCallCount + 1);
[_scrollView setContentSize:contentSize];
}
@@ -171,6 +180,7 @@
}
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated {
+ base::AutoReset<NSUInteger> autoReset(&_proxyCallCount, _proxyCallCount + 1);
[_scrollView setContentOffset:contentOffset animated:animated];
}
@@ -182,6 +192,10 @@
return [_scrollView gestureRecognizers];
}
+- (BOOL)isUpdatingThroughProxy {
+ return _proxyCallCount > 0;
+}
+
#pragma mark -
#pragma mark UIScrollViewDelegate callbacks
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 4561448..78f1e3a 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -282,6 +282,9 @@ void CancelAllTouches(UIScrollView* web_scroll_view) {
// The receiver of JavaScripts.
base::scoped_nsobject<CRWJSInjectionReceiver> _jsInjectionReceiver;
+
+ // The last recorded content offset of |webScrollView|.
+ CGPoint _lastContentOffset;
}
// The container view. The container view should be accessed through this
@@ -2666,6 +2669,7 @@ const NSTimeInterval kSnapshotOverlayTransition = 0.5;
self.userInteractionRegistered = NO;
_pageHasZoomed = NO;
+ _lastContentOffset = CGPointZero;
[[self sessionController] commitPendingEntry];
_webStateImpl->GetRequestTracker()->StartPageLoad(
@@ -3339,6 +3343,19 @@ const NSTimeInterval kSnapshotOverlayTransition = 0.5;
#pragma mark -
#pragma mark CRWWebViewScrollViewProxyObserver
+- (void)webViewScrollViewDidScroll:
+ (CRWWebViewScrollViewProxy*)webViewScrollViewProxy {
+ BOOL isRendererInitiated =
+ !webViewScrollViewProxy.updatingThroughProxy && !_applyingPageState;
+ if (isRendererInitiated && !self.userInteractionRegistered) {
+ // Ignore renderer-initiated scrolling that does not correspond with a user
+ // interaction.
+ webViewScrollViewProxy.contentOffset = _lastContentOffset;
+ } else {
+ _lastContentOffset = webViewScrollViewProxy.contentOffset;
+ }
+}
+
- (void)webViewScrollViewDidZoom:
(CRWWebViewScrollViewProxy*)webViewScrollViewProxy {
_pageHasZoomed = YES;
@@ -3353,13 +3370,13 @@ const NSTimeInterval kSnapshotOverlayTransition = 0.5;
if (contentSize.width < CGRectGetWidth(webViewScrollViewProxy.frame)) {
// The renderer incorrectly resized the content area. Resetting the scroll
// view's zoom scale will force a re-rendering. rdar://23963992
- _applyingPageState = YES;
- web::PageZoomState zoomState =
- currentItem->GetPageDisplayState().zoom_state();
+ web::PageDisplayState displayState = currentItem->GetPageDisplayState();
+ displayState.set_scroll_state(
+ web::PageScrollState(_lastContentOffset.x, _lastContentOffset.y));
+ const web::PageZoomState& zoomState = displayState.zoom_state();
if (!zoomState.IsValid() || zoomState.IsLegacyFormat())
- zoomState = web::PageZoomState(1.0, 1.0, 1.0);
- [self applyWebViewScrollZoomScaleFromZoomState:zoomState];
- _applyingPageState = NO;
+ displayState.set_zoom_state(web::PageZoomState(1.0, 1.0, 1.0));
+ [self applyPageDisplayState:displayState];
}
}
#pragma mark -