Title: [175081] trunk/Source/WebKit2
Revision
175081
Author
[email protected]
Date
2014-10-22 19:40:07 -0700 (Wed, 22 Oct 2014)

Log Message

[iOS WK2] Protect WKWebView dynamic viewport change against empty sizes
https://bugs.webkit.org/show_bug.cgi?id=137988
rdar://problem/17785162

Patch by Benjamin Poulain <[email protected]> on 2014-10-22
Reviewed by Simon Fraser.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _beginAnimatedResizeWithUpdates:]):
The algorithm behind dynamic size update finds the best content area to put in the viewport
after a viewport change. If an initial size or a target size is empty, it is impossible to
compute a reasonable area to keep in the view. We end up handling NaN scales
and/or sizes and CoreAnimation raises an exception when applying that value.

This patch add early exits when that occurs and fallback to the common code.

On Input, things are easy. If any of the initial values is empty, we just execute the updateBlock
without attempting any of the dynamic behaviors.

For the target values, things are trickier. We do not know what the values are going to be before we execute
the block. But once we executed the block, we have already skipped all the setters that call the web process.

To handle that, every value is set manually on WebPageProxy. This is a bit unfortunate because the setters
get yet another entry point.

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (175080 => 175081)


--- trunk/Source/WebKit2/ChangeLog	2014-10-23 02:39:14 UTC (rev 175080)
+++ trunk/Source/WebKit2/ChangeLog	2014-10-23 02:40:07 UTC (rev 175081)
@@ -1,3 +1,29 @@
+2014-10-22  Benjamin Poulain  <[email protected]>
+
+        [iOS WK2] Protect WKWebView dynamic viewport change against empty sizes
+        https://bugs.webkit.org/show_bug.cgi?id=137988
+        rdar://problem/17785162
+
+        Reviewed by Simon Fraser.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _beginAnimatedResizeWithUpdates:]):
+        The algorithm behind dynamic size update finds the best content area to put in the viewport
+        after a viewport change. If an initial size or a target size is empty, it is impossible to
+        compute a reasonable area to keep in the view. We end up handling NaN scales
+        and/or sizes and CoreAnimation raises an exception when applying that value.
+
+        This patch add early exits when that occurs and fallback to the common code.
+
+        On Input, things are easy. If any of the initial values is empty, we just execute the updateBlock
+        without attempting any of the dynamic behaviors.
+
+        For the target values, things are trickier. We do not know what the values are going to be before we execute
+        the block. But once we executed the block, we have already skipped all the setters that call the web process.
+
+        To handle that, every value is set manually on WebPageProxy. This is a bit unfortunate because the setters
+        get yet another entry point.
+
 2014-10-22  Gyuyoung Kim  <[email protected]>
 
         EFL and GTK ports have broken since r175075

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (175080 => 175081)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm	2014-10-23 02:39:14 UTC (rev 175080)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm	2014-10-23 02:40:07 UTC (rev 175081)
@@ -2197,20 +2197,21 @@
 
 - (void)_beginAnimatedResizeWithUpdates:(void (^)(void))updateBlock
 {
-    if (_customContentView || !_hasCommittedLoadForMainFrame) {
+    CGRect oldBounds = self.bounds;
+    WebCore::FloatRect oldUnobscuredContentRect = _page->unobscuredContentRect();
+
+    if (_customContentView || !_hasCommittedLoadForMainFrame || CGRectIsEmpty(oldBounds) || oldUnobscuredContentRect.isEmpty()) {
         updateBlock();
         return;
     }
 
     _dynamicViewportUpdateMode = DynamicViewportUpdateMode::ResizingWithAnimation;
 
-    CGRect oldBounds = self.bounds;
     WebCore::FloatSize oldMinimumLayoutSize = activeMinimumLayoutSize(self, oldBounds);
     WebCore::FloatSize oldMinimumLayoutSizeForMinimalUI = activeMinimumLayoutSizeForMinimalUI(self, oldMinimumLayoutSize);
     WebCore::FloatSize oldMaximumUnobscuredSize = activeMaximumUnobscuredSize(self, oldBounds);
     int32_t oldOrientation = activeOrientation(self);
     UIEdgeInsets oldObscuredInsets = _obscuredInsets;
-    WebCore::FloatRect oldUnobscuredContentRect = _page->unobscuredContentRect();
 
     updateBlock();
 
@@ -2220,7 +2221,25 @@
     WebCore::FloatSize newMaximumUnobscuredSize = activeMaximumUnobscuredSize(self, newBounds);
     int32_t newOrientation = activeOrientation(self);
     UIEdgeInsets newObscuredInsets = _obscuredInsets;
+    CGRect futureUnobscuredRectInSelfCoordinates = UIEdgeInsetsInsetRect(newBounds, _obscuredInsets);
 
+    ASSERT_WITH_MESSAGE(!(_overridesMinimumLayoutSize && newMinimumLayoutSize.isEmpty()), "Clients controlling the layout size should maintain a valid layout size to minimize layouts.");
+    ASSERT_WITH_MESSAGE(!(_overridesMinimumLayoutSizeForMinimalUI && newMinimumLayoutSizeForMinimalUI.isEmpty()), "Clients controlling the layout size should maintain a valid layout size for minimal UI to minimize layouts.");
+    if (CGRectIsEmpty(newBounds) || newMinimumLayoutSize.isEmpty() || newMinimumLayoutSizeForMinimalUI.isEmpty() || CGRectIsEmpty(futureUnobscuredRectInSelfCoordinates)) {
+        _dynamicViewportUpdateMode = DynamicViewportUpdateMode::NotResizing;
+        [self _frameOrBoundsChanged];
+        if (_overridesMinimumLayoutSize)
+            _page->setViewportConfigurationMinimumLayoutSize(WebCore::FloatSize(newMinimumLayoutSize));
+        if (_overridesMinimumLayoutSizeForMinimalUI)
+            _page->setViewportConfigurationMinimumLayoutSizeForMinimalUI(WebCore::FloatSize(newMinimumLayoutSizeForMinimalUI));
+        if (_overridesMaximumUnobscuredSize)
+            _page->setMaximumUnobscuredSize(WebCore::FloatSize(newMaximumUnobscuredSize));
+        if (_overridesInterfaceOrientation)
+            _page->setDeviceOrientation(newOrientation);
+        [self _updateVisibleContentRects];
+        return;
+    }
+
     if (CGRectEqualToRect(oldBounds, newBounds)
         && oldMinimumLayoutSize == newMinimumLayoutSize
         && oldMinimumLayoutSizeForMinimalUI == newMinimumLayoutSizeForMinimalUI
@@ -2254,7 +2273,6 @@
     // Compute a new position to keep the content centered.
     CGPoint originalContentCenter = oldUnobscuredContentRect.center();
     CGPoint originalContentCenterInSelfCoordinates = [self convertPoint:originalContentCenter fromView:_contentView.get()];
-    CGRect futureUnobscuredRectInSelfCoordinates = UIEdgeInsetsInsetRect(newBounds, _obscuredInsets);
     CGPoint futureUnobscuredRectCenterInSelfCoordinates = CGPointMake(futureUnobscuredRectInSelfCoordinates.origin.x + futureUnobscuredRectInSelfCoordinates.size.width / 2, futureUnobscuredRectInSelfCoordinates.origin.y + futureUnobscuredRectInSelfCoordinates.size.height / 2);
 
     CGPoint originalContentOffset = [_scrollView contentOffset];
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to