Title: [220418] trunk
Revision
220418
Author
wenson_hs...@apple.com
Date
2017-08-08 13:45:21 -0700 (Tue, 08 Aug 2017)

Log Message

[Mac WK2] WebViewImpl should hold a weak pointer to its WKWebView or WKView
https://bugs.webkit.org/show_bug.cgi?id=175302
<rdar://problem/33762116>

Reviewed by Tim Horton.

Source/WebKit:

Refactor WebViewImpl's m_view from a raw pointer to a WeakObjCPtr to ensure that it is automatically cleared out
when the WKWebView or WKView are destroyed, and also changes several places where we implicitly block capture
the WebViewImpl to only capture a WeakPtr to the WebViewImpl. Most of the changes here are boilerplate
adjustments for how m_view is now a weak pointer.

Test: WKWebViewMacEditingTests.DoNotCrashWhenInterpretingKeyEventWhileDeallocatingView.

* Shared/mac/WeakObjCPtr.h:
(WebKit::WeakObjCPtr::operator ValueType * const):
* UIProcess/Cocoa/WebViewImpl.h:
* UIProcess/Cocoa/WebViewImpl.mm:
(WebKit::WebViewImpl::updateTouchBar):
(WebKit::WebViewImpl::updateMediaTouchBar):
(WebKit::WebViewImpl::WebViewImpl):
(WebKit::WebViewImpl::~WebViewImpl):
(WebKit::WebViewImpl::window):
(WebKit::WebViewImpl::resignFirstResponder):
(WebKit::WebViewImpl::isFocused const):
(WebKit::WebViewImpl::renewGState):
(WebKit::WebViewImpl::setFrameAndScrollBy):
(WebKit::WebViewImpl::updateWindowAndViewFrames):
(WebKit::WebViewImpl::updateLayer):
(WebKit::WebViewImpl::printOperationWithPrintInfo):
(WebKit::WebViewImpl::updateContentInsetsIfAutomatic):
(WebKit::WebViewImpl::setLayoutMode):
(WebKit::WebViewImpl::intrinsicDeviceScaleFactor const):
(WebKit::WebViewImpl::windowDidBecomeKey):
(WebKit::WebViewImpl::windowDidResignKey):
(WebKit::WebViewImpl::windowDidChangeScreen):
(WebKit::WebViewImpl::mightBeginDragWhileInactive):
(WebKit::WebViewImpl::acceptsFirstMouse):
(WebKit::WebViewImpl::shouldDelayWindowOrderingForEvent):
(WebKit::WebViewImpl::windowResizeMouseLocationIsInVisibleScrollerThumb):
(WebKit::WebViewImpl::viewWillMoveToWindow):
(WebKit::WebViewImpl::viewDidMoveToWindow):
(WebKit::WebViewImpl::viewDidChangeBackingProperties):
(WebKit::WebViewImpl::hitTest):
(WebKit::WebViewImpl::postFakeMouseMovedEventForFlagsChangedEvent):
(WebKit::WebViewImpl::colorSpace):
(WebKit::WebViewImpl::prepareForMoveToWindow):
(WebKit::WebViewImpl::notifyInputContextAboutDiscardedComposition):
(WebKit::WebViewImpl::pressureChangeWithEvent):
(WebKit::WebViewImpl::fullScreenWindowController):
(WebKit::WebViewImpl::executeSavedCommandBySelector):
(WebKit::WebViewImpl::validRequestorForSendAndReturnTypes):
(WebKit::WebViewImpl::handleRequestedCandidates):
(WebKit::WebViewImpl::preferencesDidChange):
(WebKit::WebViewImpl::setTextIndicator):
(WebKit::WebViewImpl::dismissContentRelativeChildWindowsFromViewOnly):
(WebKit::WebViewImpl::accessibilityRegisterUIProcessTokens):
(WebKit::WebViewImpl::sendToolTipMouseExited):
(WebKit::WebViewImpl::sendToolTipMouseEntered):
(WebKit::WebViewImpl::toolTipChanged):
(WebKit::WebViewImpl::setAcceleratedCompositingRootLayer):
(WebKit::WebViewImpl::updateThumbnailViewLayer):
(WebKit::WebViewImpl::setInspectorAttachmentView):
(WebKit::WebViewImpl::inspectorAttachmentView):
(WebKit::WebViewImpl::draggedImage):
(WebKit::WebViewImpl::draggingEntered):
(WebKit::WebViewImpl::draggingUpdated):
(WebKit::WebViewImpl::draggingExited):
(WebKit::WebViewImpl::performDragOperation):
(WebKit::WebViewImpl::hitTestForDragTypes):
(WebKit::WebViewImpl::startWindowDrag):
(WebKit::WebViewImpl::dragImageForView):
(WebKit::WebViewImpl::setPromisedDataForImage):
(WebKit::WebViewImpl::setPromisedDataForAttachment):
(WebKit::WebViewImpl::takeViewSnapshot):
(WebKit::WebViewImpl::scrollWheel):
(WebKit::WebViewImpl::magnifyWithEvent):
(WebKit::WebViewImpl::rotateWithEvent):
(WebKit::WebViewImpl::doneWithKeyEvent):
(WebKit::WebViewImpl::interpretKeyEvent):
(WebKit::WebViewImpl::firstRectForCharacterRange):
(WebKit::WebViewImpl::characterIndexForPoint):
(WebKit::WebViewImpl::performKeyEquivalent):
(WebKit::WebViewImpl::keyUp):
(WebKit::WebViewImpl::keyDown):
(WebKit::WebViewImpl::mouseMoved):
(WebKit::WebViewImpl::windowIsFrontWindowUnderMouse):
(WebKit::WebViewImpl::userInterfaceLayoutDirection):

Tools:

Adds a new unit test checking that delayed event processing in text input context does not cause unwanted behaviors.
See WebKit ChangeLog for more details.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/TestWebKitAPI/mac/AppKitSPI.h: Renamed from Tools/TestWebKitAPI/Tests/TestWebKitAPI/mac/NSTextInputClientSPI.h.
* TestWebKitAPI/Tests/mac/WKWebViewMacEditingTests.mm: Renamed from Tools/TestWebKitAPI/Tests/mac/WKWebViewSelectionTests.mm.
(-[SlowTextInputContext handleEventByInputMethod:completionHandler:]):
(-[SlowTextInputContext handleEvent:completionHandler:]):
(-[SlowInputWebView inputContext]):
(-[SlowInputWebView _web_superInputContext]):
(TEST):

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (220417 => 220418)


--- trunk/Source/WebKit/ChangeLog	2017-08-08 19:58:26 UTC (rev 220417)
+++ trunk/Source/WebKit/ChangeLog	2017-08-08 20:45:21 UTC (rev 220418)
@@ -1,3 +1,93 @@
+2017-08-08  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [Mac WK2] WebViewImpl should hold a weak pointer to its WKWebView or WKView
+        https://bugs.webkit.org/show_bug.cgi?id=175302
+        <rdar://problem/33762116>
+
+        Reviewed by Tim Horton.
+
+        Refactor WebViewImpl's m_view from a raw pointer to a WeakObjCPtr to ensure that it is automatically cleared out
+        when the WKWebView or WKView are destroyed, and also changes several places where we implicitly block capture
+        the WebViewImpl to only capture a WeakPtr to the WebViewImpl. Most of the changes here are boilerplate
+        adjustments for how m_view is now a weak pointer.
+
+        Test: WKWebViewMacEditingTests.DoNotCrashWhenInterpretingKeyEventWhileDeallocatingView.
+
+        * Shared/mac/WeakObjCPtr.h:
+        (WebKit::WeakObjCPtr::operator ValueType * const):
+        * UIProcess/Cocoa/WebViewImpl.h:
+        * UIProcess/Cocoa/WebViewImpl.mm:
+        (WebKit::WebViewImpl::updateTouchBar):
+        (WebKit::WebViewImpl::updateMediaTouchBar):
+        (WebKit::WebViewImpl::WebViewImpl):
+        (WebKit::WebViewImpl::~WebViewImpl):
+        (WebKit::WebViewImpl::window):
+        (WebKit::WebViewImpl::resignFirstResponder):
+        (WebKit::WebViewImpl::isFocused const):
+        (WebKit::WebViewImpl::renewGState):
+        (WebKit::WebViewImpl::setFrameAndScrollBy):
+        (WebKit::WebViewImpl::updateWindowAndViewFrames):
+        (WebKit::WebViewImpl::updateLayer):
+        (WebKit::WebViewImpl::printOperationWithPrintInfo):
+        (WebKit::WebViewImpl::updateContentInsetsIfAutomatic):
+        (WebKit::WebViewImpl::setLayoutMode):
+        (WebKit::WebViewImpl::intrinsicDeviceScaleFactor const):
+        (WebKit::WebViewImpl::windowDidBecomeKey):
+        (WebKit::WebViewImpl::windowDidResignKey):
+        (WebKit::WebViewImpl::windowDidChangeScreen):
+        (WebKit::WebViewImpl::mightBeginDragWhileInactive):
+        (WebKit::WebViewImpl::acceptsFirstMouse):
+        (WebKit::WebViewImpl::shouldDelayWindowOrderingForEvent):
+        (WebKit::WebViewImpl::windowResizeMouseLocationIsInVisibleScrollerThumb):
+        (WebKit::WebViewImpl::viewWillMoveToWindow):
+        (WebKit::WebViewImpl::viewDidMoveToWindow):
+        (WebKit::WebViewImpl::viewDidChangeBackingProperties):
+        (WebKit::WebViewImpl::hitTest):
+        (WebKit::WebViewImpl::postFakeMouseMovedEventForFlagsChangedEvent):
+        (WebKit::WebViewImpl::colorSpace):
+        (WebKit::WebViewImpl::prepareForMoveToWindow):
+        (WebKit::WebViewImpl::notifyInputContextAboutDiscardedComposition):
+        (WebKit::WebViewImpl::pressureChangeWithEvent):
+        (WebKit::WebViewImpl::fullScreenWindowController):
+        (WebKit::WebViewImpl::executeSavedCommandBySelector):
+        (WebKit::WebViewImpl::validRequestorForSendAndReturnTypes):
+        (WebKit::WebViewImpl::handleRequestedCandidates):
+        (WebKit::WebViewImpl::preferencesDidChange):
+        (WebKit::WebViewImpl::setTextIndicator):
+        (WebKit::WebViewImpl::dismissContentRelativeChildWindowsFromViewOnly):
+        (WebKit::WebViewImpl::accessibilityRegisterUIProcessTokens):
+        (WebKit::WebViewImpl::sendToolTipMouseExited):
+        (WebKit::WebViewImpl::sendToolTipMouseEntered):
+        (WebKit::WebViewImpl::toolTipChanged):
+        (WebKit::WebViewImpl::setAcceleratedCompositingRootLayer):
+        (WebKit::WebViewImpl::updateThumbnailViewLayer):
+        (WebKit::WebViewImpl::setInspectorAttachmentView):
+        (WebKit::WebViewImpl::inspectorAttachmentView):
+        (WebKit::WebViewImpl::draggedImage):
+        (WebKit::WebViewImpl::draggingEntered):
+        (WebKit::WebViewImpl::draggingUpdated):
+        (WebKit::WebViewImpl::draggingExited):
+        (WebKit::WebViewImpl::performDragOperation):
+        (WebKit::WebViewImpl::hitTestForDragTypes):
+        (WebKit::WebViewImpl::startWindowDrag):
+        (WebKit::WebViewImpl::dragImageForView):
+        (WebKit::WebViewImpl::setPromisedDataForImage):
+        (WebKit::WebViewImpl::setPromisedDataForAttachment):
+        (WebKit::WebViewImpl::takeViewSnapshot):
+        (WebKit::WebViewImpl::scrollWheel):
+        (WebKit::WebViewImpl::magnifyWithEvent):
+        (WebKit::WebViewImpl::rotateWithEvent):
+        (WebKit::WebViewImpl::doneWithKeyEvent):
+        (WebKit::WebViewImpl::interpretKeyEvent):
+        (WebKit::WebViewImpl::firstRectForCharacterRange):
+        (WebKit::WebViewImpl::characterIndexForPoint):
+        (WebKit::WebViewImpl::performKeyEquivalent):
+        (WebKit::WebViewImpl::keyUp):
+        (WebKit::WebViewImpl::keyDown):
+        (WebKit::WebViewImpl::mouseMoved):
+        (WebKit::WebViewImpl::windowIsFrontWindowUnderMouse):
+        (WebKit::WebViewImpl::userInterfaceLayoutDirection):
+
 2017-08-08  Filip Pizlo  <fpi...@apple.com>
 
         Baseline JIT should do caging

Modified: trunk/Source/WebKit/Shared/mac/WeakObjCPtr.h (220417 => 220418)


--- trunk/Source/WebKit/Shared/mac/WeakObjCPtr.h	2017-08-08 19:58:26 UTC (rev 220417)
+++ trunk/Source/WebKit/Shared/mac/WeakObjCPtr.h	2017-08-08 20:45:21 UTC (rev 220418)
@@ -95,6 +95,8 @@
         return static_cast<ValueType *>(objc_loadWeak(const_cast<id*>(&m_weakReference)));
     }
 
+    explicit operator ValueType *() const { return getAutoreleased(); }
+
 private:
     id m_weakReference;
 };

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h (220417 => 220418)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h	2017-08-08 19:58:26 UTC (rev 220417)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h	2017-08-08 20:45:21 UTC (rev 220418)
@@ -31,6 +31,7 @@
 #include "PluginComplexTextInputState.h"
 #include "WKDragDestinationAction.h"
 #include "WKLayoutMode.h"
+#include "WeakObjCPtr.h"
 #include "WebPageProxy.h"
 #include "_WKOverlayScrollbarStyle.h"
 #include <WebCore/AVKitSPI.h>
@@ -600,7 +601,7 @@
     void handleRequestedCandidates(NSInteger sequenceNumber, NSArray<NSTextCheckingResult *> *candidates);
 #endif
 
-    NSView <WebViewImplDelegate> *m_view;
+    WeakObjCPtr<NSView<WebViewImplDelegate>> m_view;
     std::unique_ptr<PageClient> m_pageClient;
     Ref<WebPageProxy> m_page;
 

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm (220417 => 220418)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm	2017-08-08 19:58:26 UTC (rev 220417)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm	2017-08-08 20:45:21 UTC (rev 220418)
@@ -889,7 +889,7 @@
             touchBar = [m_mediaTouchBarProvider respondsToSelector:@selector(touchBar)] ? [(id)m_mediaTouchBarProvider.get() touchBar] : [(id)m_mediaTouchBarProvider.get() touchBar];
     } else if ([m_mediaTouchBarProvider playbackControlsController]) {
         if (m_clientWantsMediaPlaybackControlsView) {
-            if ([m_view respondsToSelector:@selector(_web_didRemoveMediaControlsManager)] && m_view == m_view.window.firstResponder)
+            if ([m_view respondsToSelector:@selector(_web_didRemoveMediaControlsManager)] && m_view.getAutoreleased() == [m_view window].firstResponder)
                 [m_view _web_didRemoveMediaControlsManager];
         }
         [m_mediaTouchBarProvider setPlaybackControlsController:nil];
@@ -1202,7 +1202,7 @@
         return;
     }
 
-    if (m_playbackControlsManager && m_view == m_view.window.firstResponder && [m_view respondsToSelector:@selector(_web_didAddMediaControlsManager:)])
+    if (m_playbackControlsManager && m_view.getAutoreleased() == [m_view window].firstResponder && [m_view respondsToSelector:@selector(_web_didAddMediaControlsManager:)])
         [m_view _web_didAddMediaControlsManager:m_mediaPlaybackControlsView.get()];
 #endif
 }
@@ -1272,23 +1272,23 @@
     , m_weakPtrFactory(this)
     , m_needsViewFrameInWindowCoordinates(m_page->preferences().pluginsEnabled())
     , m_intrinsicContentSize(CGSizeMake(NSViewNoInstrinsicMetric, NSViewNoInstrinsicMetric))
-    , m_layoutStrategy([WKViewLayoutStrategy layoutStrategyWithPage:m_page view:m_view viewImpl:*this mode:kWKLayoutModeViewSize])
+    , m_layoutStrategy([WKViewLayoutStrategy layoutStrategyWithPage:m_page view:view viewImpl:*this mode:kWKLayoutModeViewSize])
     , m_undoTarget(adoptNS([[WKEditorUndoTargetObjC alloc] init]))
     , m_windowVisibilityObserver(adoptNS([[WKWindowVisibilityObserver alloc] initWithView:view impl:*this]))
     , m_accessibilitySettingsObserver(adoptNS([[WKAccessibilitySettingsObserver alloc] initWithImpl:*this]))
-    , m_primaryTrackingArea(adoptNS([[NSTrackingArea alloc] initWithRect:m_view.frame options:trackingAreaOptions() owner:m_view userInfo:nil]))
+    , m_primaryTrackingArea(adoptNS([[NSTrackingArea alloc] initWithRect:view.frame options:trackingAreaOptions() owner:view userInfo:nil]))
 {
     static_cast<PageClientImpl&>(*m_pageClient).setImpl(*this);
 
     [NSApp registerServicesMenuSendTypes:PasteboardTypes::forSelection() returnTypes:PasteboardTypes::forEditing()];
 
-    [m_view addTrackingArea:m_primaryTrackingArea.get()];
+    [view addTrackingArea:m_primaryTrackingArea.get()];
 
     m_page->setIntrinsicDeviceScaleFactor(intrinsicDeviceScaleFactor());
 
     if (Class gestureClass = NSClassFromString(@"NSImmediateActionGestureRecognizer")) {
         m_immediateActionGestureRecognizer = adoptNS([(NSImmediateActionGestureRecognizer *)[gestureClass alloc] init]);
-        m_immediateActionController = adoptNS([[WKImmediateActionController alloc] initWithPage:m_page view:m_view viewImpl:*this recognizer:m_immediateActionGestureRecognizer.get()]);
+        m_immediateActionController = adoptNS([[WKImmediateActionController alloc] initWithPage:m_page view:view viewImpl:*this recognizer:m_immediateActionGestureRecognizer.get()]);
         [m_immediateActionGestureRecognizer setDelegate:m_immediateActionController.get()];
         [m_immediateActionGestureRecognizer setDelaysPrimaryMouseButtonEvents:NO];
     }
@@ -1299,13 +1299,13 @@
 
     registerDraggedTypes();
 
-    m_view.wantsLayer = YES;
+    view.wantsLayer = YES;
 
     // Explicitly set the layer contents placement so AppKit will make sure that our layer has masksToBounds set to YES.
-    m_view.layerContentsPlacement = NSViewLayerContentsPlacementTopLeft;
+    view.layerContentsPlacement = NSViewLayerContentsPlacementTopLeft;
 
 #if ENABLE(FULLSCREEN_API) && WK_API_ENABLED
-    m_page->setFullscreenClient(std::make_unique<WebKit::FullscreenClient>((WKWebView *)m_view));
+    m_page->setFullscreenClient(std::make_unique<WebKit::FullscreenClient>(view));
 #endif
 
     WebProcessPool::statistics().wkViewCount++;
@@ -1329,7 +1329,7 @@
 
     [m_layoutStrategy invalidate];
 
-    [m_immediateActionController willDestroyView:m_view];
+    [m_immediateActionController willDestroyView:m_view.getAutoreleased()];
 
 #if HAVE(TOUCH_BAR)
     [m_textTouchBarItemController didDestroyView];
@@ -1347,7 +1347,7 @@
 
 NSWindow *WebViewImpl::window()
 {
-    return m_view.window;
+    return [m_view window];
 }
 
 void WebViewImpl::processDidExit()
@@ -1441,7 +1441,7 @@
     id nextResponder = [[m_view window] _newFirstResponderAfterResigning];
 
     // FIXME: This will probably need to change once WKWebView doesn't contain a WKView.
-    if ([nextResponder isKindOfClass:[WKWebView class]] && m_view.superview == nextResponder) {
+    if ([nextResponder isKindOfClass:[WKWebView class]] && [m_view superview] == nextResponder) {
         m_willBecomeFirstResponderAgain = true;
         return true;
     }
@@ -1472,7 +1472,7 @@
         return true;
     if (m_inResignFirstResponder)
         return false;
-    return m_view.window.firstResponder == m_view;
+    return [m_view window].firstResponder == m_view.getAutoreleased();
 }
 
 void WebViewImpl::viewWillStartLiveResize()
@@ -1495,7 +1495,7 @@
         dismissContentRelativeChildWindowsWithAnimation(false);
 
     // Update the view frame.
-    if (m_view.window)
+    if ([m_view window])
         updateWindowAndViewFrames();
 
     updateContentInsetsIfAutomatic();
@@ -1526,7 +1526,7 @@
     ASSERT(CGSizeEqualToSize(m_resizeScrollOffset, CGSizeZero));
 
     m_resizeScrollOffset = offset;
-    m_view.frame = NSRectFromCGRect(frame);
+    [m_view frame] = NSRectFromCGRect(frame);
 }
 
 void WebViewImpl::updateWindowAndViewFrames()
@@ -1550,7 +1550,7 @@
         NSPoint accessibilityPosition = NSZeroPoint;
 
         if (weakThis->m_needsViewFrameInWindowCoordinates)
-            viewFrameInWindowCoordinates = [weakThis->m_view convertRect:weakThis->m_view.frame toView:nil];
+            viewFrameInWindowCoordinates = [weakThis->m_view convertRect:[weakThis->m_view frame] toView:nil];
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
@@ -1600,7 +1600,7 @@
 
 void WebViewImpl::updateLayer()
 {
-    m_view.layer.backgroundColor = CGColorGetConstantColor(drawsBackground() ? kCGColorWhite : kCGColorClear);
+    [m_view layer].backgroundColor = CGColorGetConstantColor(drawsBackground() ? kCGColorWhite : kCGColorClear);
 
     // If asynchronous geometry updates have been sent by forceAsyncDrawingAreaSizeUpdate,
     // then subsequent calls to setFrameSize should not result in us waiting for the did
@@ -1627,7 +1627,7 @@
 
     // FIXME: If the frame cannot be printed (e.g. if it contains an encrypted PDF that disallows
     // printing), this function should return nil.
-    RetainPtr<WKPrintingView> printingView = adoptNS([[WKPrintingView alloc] initWithFrameProxy:&frame view:m_view]);
+    RetainPtr<WKPrintingView> printingView = adoptNS([[WKPrintingView alloc] initWithFrameProxy:&frame view:m_view.getAutoreleased()]);
     // NSPrintOperation takes ownership of the view.
     NSPrintOperation *printOperation = [NSPrintOperation printOperationWithView:printingView.get() printInfo:printInfo];
     [printOperation setCanSpawnSeparateThread:YES];
@@ -1647,7 +1647,7 @@
     if (!m_automaticallyAdjustsContentInsets)
         return;
 
-    NSWindow *window = m_view.window;
+    NSWindow *window = [m_view window];
     if ((window.styleMask & NSWindowStyleMaskFullSizeContentView) && !window.titlebarAppearsTransparent && ![m_view enclosingScrollView]) {
         NSRect contentLayoutRect = [m_view convertRect:window.contentLayoutRect fromView:nil];
         CGFloat newTopContentInset = NSMaxY(contentLayoutRect) - NSHeight(contentLayoutRect);
@@ -1794,7 +1794,7 @@
         return;
 
     [m_layoutStrategy willChangeLayoutStrategy];
-    m_layoutStrategy = [WKViewLayoutStrategy layoutStrategyWithPage:m_page view:m_view viewImpl:*this mode:layoutMode];
+    m_layoutStrategy = [WKViewLayoutStrategy layoutStrategyWithPage:m_page view:m_view.getAutoreleased() viewImpl:*this mode:layoutMode];
 }
 
 bool WebViewImpl::supportsArbitraryLayoutModes() const
@@ -1848,7 +1848,7 @@
         return m_overrideDeviceScaleFactor;
     if (m_targetWindowForMovePreparation)
         return m_targetWindowForMovePreparation.backingScaleFactor;
-    if (NSWindow *window = m_view.window)
+    if (NSWindow *window = [m_view window])
         return window.backingScaleFactor;
     return [NSScreen mainScreen].backingScaleFactor;
 }
@@ -1865,7 +1865,7 @@
 
 void WebViewImpl::windowDidBecomeKey(NSWindow *keyWindow)
 {
-    if (keyWindow == m_view.window || keyWindow == m_view.window.attachedSheet) {
+    if (keyWindow == [m_view window] || keyWindow == [m_view window].attachedSheet) {
 #if ENABLE(GAMEPAD)
         UIGamepadProvider::singleton().viewBecameActive(m_page.get());
 #endif
@@ -1876,7 +1876,7 @@
 
 void WebViewImpl::windowDidResignKey(NSWindow *formerKeyWindow)
 {
-    if (formerKeyWindow == m_view.window || formerKeyWindow == m_view.window.attachedSheet) {
+    if (formerKeyWindow == [m_view window] || formerKeyWindow == [m_view window].attachedSheet) {
 #if ENABLE(GAMEPAD)
         UIGamepadProvider::singleton().viewBecameInactive(m_page.get());
 #endif
@@ -1916,7 +1916,7 @@
 
 void WebViewImpl::windowDidChangeScreen()
 {
-    NSWindow *window = m_targetWindowForMovePreparation ? m_targetWindowForMovePreparation : m_view.window;
+    NSWindow *window = m_targetWindowForMovePreparation ? m_targetWindowForMovePreparation : [m_view window];
     m_page->windowScreenDidChange([[[[window screen] deviceDescription] objectForKey:@"NSScreenNumber"] intValue]);
 }
 
@@ -1932,7 +1932,7 @@
 
 bool WebViewImpl::mightBeginDragWhileInactive()
 {
-    if (m_view.window.isKeyWindow)
+    if ([m_view window].isKeyWindow)
         return false;
 
     if (m_page->editorState().selectionIsNone || !m_page->editorState().selectionIsRange)
@@ -1969,7 +1969,7 @@
         return false;
 
     setLastMouseDownEvent(event);
-    bool result = m_page->acceptsFirstMouse(event.eventNumber, WebEventFactory::createWebMouseEvent(event, m_lastPressureEvent.get(), m_view));
+    bool result = m_page->acceptsFirstMouse(event.eventNumber, WebEventFactory::createWebMouseEvent(event, m_lastPressureEvent.get(), m_view.getAutoreleased()));
     setLastMouseDownEvent(nil);
     return result;
 }
@@ -1988,7 +1988,7 @@
         return false;
 
     setLastMouseDownEvent(event);
-    bool result = m_page->shouldDelayWindowOrderingForEvent(WebEventFactory::createWebMouseEvent(event, m_lastPressureEvent.get(), m_view));
+    bool result = m_page->shouldDelayWindowOrderingForEvent(WebEventFactory::createWebMouseEvent(event, m_lastPressureEvent.get(), m_view.getAutoreleased()));
     setLastMouseDownEvent(nil);
     return result;
 }
@@ -1997,7 +1997,7 @@
 {
     NSPoint localPoint = [m_view convertPoint:NSPointFromCGPoint(point) fromView:nil];
     NSRect visibleThumbRect = NSRect(m_page->visibleScrollerThumbRect());
-    return NSMouseInRect(localPoint, visibleThumbRect, m_view.isFlipped);
+    return NSMouseInRect(localPoint, visibleThumbRect, [m_view isFlipped]);
 }
 
 void WebViewImpl::viewWillMoveToWindow(NSWindow *window)
@@ -2005,13 +2005,13 @@
     // If we're in the middle of preparing to move to a window, we should only be moved to that window.
     ASSERT(!m_targetWindowForMovePreparation || (m_targetWindowForMovePreparation == window));
 
-    NSWindow *currentWindow = m_view.window;
+    NSWindow *currentWindow = [m_view window];
     if (window == currentWindow)
         return;
 
     clearAllEditCommands();
 
-    NSWindow *stopObservingWindow = m_targetWindowForMovePreparation ? m_targetWindowForMovePreparation : m_view.window;
+    NSWindow *stopObservingWindow = m_targetWindowForMovePreparation ? m_targetWindowForMovePreparation : [m_view window];
     [m_windowVisibilityObserver stopObserving:stopObservingWindow];
     [m_windowVisibilityObserver startObserving:window];
 }
@@ -2018,7 +2018,7 @@
 
 void WebViewImpl::viewDidMoveToWindow()
 {
-    NSWindow *window = m_targetWindowForMovePreparation ? m_targetWindowForMovePreparation : m_view.window;
+    NSWindow *window = m_targetWindowForMovePreparation ? m_targetWindowForMovePreparation : [m_view window];
 
     if (window) {
         windowDidChangeScreen();
@@ -2073,7 +2073,7 @@
 
 void WebViewImpl::viewDidChangeBackingProperties()
 {
-    NSColorSpace *colorSpace = m_view.window.colorSpace;
+    NSColorSpace *colorSpace = [m_view window].colorSpace;
     if ([colorSpace isEqualTo:m_colorSpace.get()])
         return;
 
@@ -2101,7 +2101,7 @@
 {
     NSView *hitView = [m_view _web_superHitTest:NSPointFromCGPoint(point)];
     if (hitView && hitView == m_layerHostingView)
-        hitView = m_view;
+        hitView = m_view.getAutoreleased();
 
     return hitView;
 }
@@ -2111,7 +2111,7 @@
     NSEvent *fakeEvent = [NSEvent mouseEventWithType:NSEventTypeMouseMoved location:flagsChangedEvent.window.mouseLocationOutsideOfEventStream
         modifierFlags:flagsChangedEvent.modifierFlags timestamp:flagsChangedEvent.timestamp windowNumber:flagsChangedEvent.windowNumber
         context:nullptr eventNumber:0 clickCount:0 pressure:0];
-    NativeWebMouseEvent webEvent(fakeEvent, m_lastPressureEvent.get(), m_view);
+    NativeWebMouseEvent webEvent(fakeEvent, m_lastPressureEvent.get(), m_view.getAutoreleased());
     m_page->handleMouseEvent(webEvent);
 }
 
@@ -2120,7 +2120,7 @@
     if (!m_colorSpace) {
         if (m_targetWindowForMovePreparation)
             m_colorSpace = m_targetWindowForMovePreparation.colorSpace;
-        else if (NSWindow *window = m_view.window)
+        else if (NSWindow *window = [m_view window])
             m_colorSpace = window.colorSpace;
         else
             m_colorSpace = [NSScreen mainScreen].colorSpace;
@@ -2223,7 +2223,7 @@
         if (!weakThis)
             return;
 
-        ASSERT(weakThis->m_view.window == weakThis->m_targetWindowForMovePreparation);
+        ASSERT(weakThis->[m_view window] == weakThis->m_targetWindowForMovePreparation);
         weakThis->m_targetWindowForMovePreparation = nil;
     });
 
@@ -2273,7 +2273,7 @@
     // <rdar://problem/9359055>: -discardMarkedText can only be called for active contexts.
     // FIXME: We fail to ever notify the input context if something (e.g. a navigation) happens while the window is not key.
     // This is not a problem when the window is key, because we discard marked text on resigning first responder.
-    if (![[m_view window] isKeyWindow] || m_view != [[m_view window] firstResponder])
+    if (![[m_view window] isKeyWindow] || m_view.getAutoreleased() != [[m_view window] firstResponder])
         return;
 
     LOG(TextInput, "-> discardMarkedText");
@@ -2416,7 +2416,7 @@
     if (event.phase != NSEventPhaseChanged && event.phase != NSEventPhaseBegan && event.phase != NSEventPhaseEnded)
         return;
 
-    NativeWebMouseEvent webEvent(event, m_lastPressureEvent.get(), m_view);
+    NativeWebMouseEvent webEvent(event, m_lastPressureEvent.get(), m_view.getAutoreleased());
     m_page->handleMouseEvent(webEvent);
 
     m_lastPressureEvent = event;
@@ -2432,7 +2432,7 @@
 WKFullScreenWindowController *WebViewImpl::fullScreenWindowController()
 {
     if (!m_fullScreenWindowController)
-        m_fullScreenWindowController = adoptNS([[WKFullScreenWindowController alloc] initWithWindow:createFullScreenWindow() webView:m_view page:m_page]);
+        m_fullScreenWindowController = adoptNS([[WKFullScreenWindowController alloc] initWithWindow:createFullScreenWindow() webView:m_view.getAutoreleased() page:m_page]);
 
     return m_fullScreenWindowController.get();
 }
@@ -2524,7 +2524,7 @@
     LOG(TextInput, "Executing previously saved command %s", sel_getName(selector));
     // The sink does two things: 1) Tells us if the responder went unhandled, and
     // 2) prevents any NSBeep; we don't ever want to beep here.
-    RetainPtr<WKResponderChainSink> sink = adoptNS([[WKResponderChainSink alloc] initWithResponderChain:m_view]);
+    RetainPtr<WKResponderChainSink> sink = adoptNS([[WKResponderChainSink alloc] initWithResponderChain:m_view.getAutoreleased()]);
     [m_view _web_superDoCommandBySelector:selector];
     [sink detach];
     return ![sink didReceiveUnhandledCommand];
@@ -2591,7 +2591,7 @@
         isValidReturnType = editorState.isContentRichlyEditable || [returnType isEqualToString:NSStringPboardType];
     }
     if (isValidSendType && isValidReturnType)
-        return m_view;
+        return m_view.getAutoreleased();
     return [[m_view nextResponder] validRequestorForSendType:sendType returnType:returnType];
 }
 
@@ -3037,7 +3037,7 @@
     WebCore::IntRect offsetSelectionRect = postLayoutData.selectionClipRect;
     offsetSelectionRect.move(0, offsetSelectionRect.height());
 
-    [candidateListTouchBarItem() setCandidates:candidates forSelectedRange:selectedRange inString:postLayoutData.paragraphContextForCandidateRequest rect:offsetSelectionRect view:m_view completionHandler:nil];
+    [candidateListTouchBarItem() setCandidates:candidates forSelectedRange:selectedRange inString:postLayoutData.paragraphContextForCandidateRequest rect:offsetSelectionRect view:m_view.getAutoreleased() completionHandler:nil];
 #else
     UNUSED_PARAM(candidates);
 #endif
@@ -3107,7 +3107,7 @@
         return;
 
     m_needsViewFrameInWindowCoordinates = needsViewFrameInWindowCoordinates;
-    if (m_view.window)
+    if ([m_view window])
         updateWindowAndViewFrames();
 }
 
@@ -3114,9 +3114,9 @@
 void WebViewImpl::setTextIndicator(WebCore::TextIndicator& textIndicator, WebCore::TextIndicatorWindowLifetime lifetime)
 {
     if (!m_textIndicatorWindow)
-        m_textIndicatorWindow = std::make_unique<WebCore::TextIndicatorWindow>(m_view);
+        m_textIndicatorWindow = std::make_unique<WebCore::TextIndicatorWindow>(m_view.getAutoreleased());
 
-    NSRect textBoundingRectInScreenCoordinates = [m_view.window convertRectToScreen:[m_view convertRect:textIndicator.textBoundingRectInRootViewCoordinates() toView:nil]];
+    NSRect textBoundingRectInScreenCoordinates = [[m_view window] convertRectToScreen:[m_view convertRect:textIndicator.textBoundingRectInRootViewCoordinates() toView:nil]];
     m_textIndicatorWindow->setTextIndicator(textIndicator, NSRectToCGRect(textBoundingRectInScreenCoordinates), lifetime);
 }
 
@@ -3153,7 +3153,7 @@
     hasActiveImmediateAction = [m_immediateActionController hasActiveImmediateAction];
 
     // FIXME: We don't know which panel we are dismissing, it may not even be in the current page (see <rdar://problem/13875766>).
-    if (m_view.window.isKeyWindow || hasActiveImmediateAction) {
+    if ([m_view window].isKeyWindow || hasActiveImmediateAction) {
         WebCore::DictionaryLookup::hidePopup();
 
         if (DataDetectorsLibrary())
@@ -3305,8 +3305,8 @@
 void WebViewImpl::accessibilityRegisterUIProcessTokens()
 {
     // Initialize remote accessibility when the window connection has been established.
-    NSData *remoteElementToken = WKAXRemoteTokenForElement(m_view);
-    NSData *remoteWindowToken = WKAXRemoteTokenForElement(m_view.window);
+    NSData *remoteElementToken = WKAXRemoteTokenForElement(m_view.getAutoreleased());
+    NSData *remoteWindowToken = WKAXRemoteTokenForElement([m_view window]);
     IPC::DataReference elementToken = IPC::DataReference(reinterpret_cast<const uint8_t*>([remoteElementToken bytes]), [remoteElementToken length]);
     IPC::DataReference windowToken = IPC::DataReference(reinterpret_cast<const uint8_t*>([remoteWindowToken bytes]), [remoteWindowToken length]);
     m_page->registerUIProcessAccessibilityTokens(elementToken, windowToken);
@@ -3436,7 +3436,7 @@
                                                 location:NSMakePoint(0, 0)
                                            modifierFlags:0
                                                timestamp:0
-                                            windowNumber:m_view.window.windowNumber
+                                            windowNumber:[m_view window].windowNumber
                                                  context:NULL
                                              eventNumber:0
                                           trackingNumber:TRACKING_RECT_TAG
@@ -3451,7 +3451,7 @@
                                                 location:NSMakePoint(0, 0)
                                            modifierFlags:0
                                                timestamp:0
-                                            windowNumber:m_view.window.windowNumber
+                                            windowNumber:[m_view window].windowNumber
                                                  context:NULL
                                              eventNumber:0
                                           trackingNumber:TRACKING_RECT_TAG
@@ -3473,7 +3473,7 @@
         // See radar 3500217 for why we remove all tooltips rather than just the single one we created.
         [m_view removeAllToolTips];
         NSRect wideOpenRect = NSMakeRect(-100000, -100000, 200000, 200000);
-        m_lastToolTipTag = [m_view addToolTipRect:wideOpenRect owner:m_view userData:NULL];
+        m_lastToolTipTag = [m_view addToolTipRect:wideOpenRect owner:m_view.getAutoreleased() userData:NULL];
         sendToolTipMouseEntered();
     }
 }
@@ -3497,7 +3497,7 @@
     if (rootLayer) {
         if (!m_layerHostingView) {
             // Create an NSView that will host our layer tree.
-            m_layerHostingView = adoptNS([[WKFlippedView alloc] initWithFrame:m_view.bounds]);
+            m_layerHostingView = adoptNS([[WKFlippedView alloc] initWithFrame:[m_view bounds]]);
             [m_layerHostingView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
 
             [m_view addSubview:m_layerHostingView.get() positioned:NSWindowBelow relativeTo:nil];
@@ -3548,7 +3548,7 @@
     _WKThumbnailView *thumbnailView = m_thumbnailView;
     ASSERT(thumbnailView);
 
-    if (thumbnailView._waitingForSnapshot && m_view.window)
+    if (thumbnailView._waitingForSnapshot && [m_view window])
         reparentLayerTreeInThumbnailView();
 }
 
@@ -3559,13 +3559,13 @@
         return;
 
     m_inspectorAttachmentView = newView;
-    m_page->inspector()->attachmentViewDidChange(oldView ? oldView : m_view, newView ? newView : m_view);
+    m_page->inspector()->attachmentViewDidChange(oldView ? oldView : m_view.getAutoreleased(), newView ? newView : m_view.getAutoreleased());
 }
 
 NSView *WebViewImpl::inspectorAttachmentView()
 {
     NSView *attachmentView = m_inspectorAttachmentView.get();
-    return attachmentView ? attachmentView : m_view;
+    return attachmentView ? attachmentView : m_view.getAutoreleased();
 }
 
 _WKRemoteObjectRegistry *WebViewImpl::remoteObjectRegistry()
@@ -3592,7 +3592,7 @@
 {
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
-    NSPoint windowImageLoc = [m_view.window convertScreenToBase:NSPointFromCGPoint(endPoint)];
+    NSPoint windowImageLoc = [[m_view window] convertScreenToBase:NSPointFromCGPoint(endPoint)];
 #pragma clang diagnostic pop
     NSPoint windowMouseLoc = windowImageLoc;
 
@@ -3599,7 +3599,7 @@
     // Prevent queued mouseDragged events from coming after the drag and fake mouseUp event.
     m_ignoresMouseDraggedEvents = true;
 
-    m_page->dragEnded(WebCore::IntPoint(windowMouseLoc), WebCore::IntPoint(WebCore::globalPoint(windowMouseLoc, m_view.window)), operation);
+    m_page->dragEnded(WebCore::IntPoint(windowMouseLoc), WebCore::IntPoint(WebCore::globalPoint(windowMouseLoc, [m_view window])), operation);
 }
 
 static WebCore::DragApplicationFlags applicationFlagsForDrag(NSView *view, id <NSDraggingInfo> draggingInfo)
@@ -3620,13 +3620,13 @@
 NSDragOperation WebViewImpl::draggingEntered(id <NSDraggingInfo> draggingInfo)
 {
     WebCore::IntPoint client([m_view convertPoint:draggingInfo.draggingLocation fromView:nil]);
-    WebCore::IntPoint global(WebCore::globalPoint(draggingInfo.draggingLocation, m_view.window));
+    WebCore::IntPoint global(WebCore::globalPoint(draggingInfo.draggingLocation, [m_view window]));
 #if WK_API_ENABLED
     auto dragDestinationAction = static_cast<WebCore::DragDestinationAction>([m_view _web_dragDestinationActionForDraggingInfo:draggingInfo]);
 #else
     auto dragDestinationAction = WebCore::DragDestinationActionAny;
 #endif
-    WebCore::DragData dragData(draggingInfo, client, global, static_cast<WebCore::DragOperation>(draggingInfo.draggingSourceOperationMask), applicationFlagsForDrag(m_view, draggingInfo), dragDestinationAction);
+    WebCore::DragData dragData(draggingInfo, client, global, static_cast<WebCore::DragOperation>(draggingInfo.draggingSourceOperationMask), applicationFlagsForDrag(m_view.getAutoreleased(), draggingInfo), dragDestinationAction);
 
     m_page->resetCurrentDragInformation();
     m_page->dragEntered(dragData, draggingInfo.draggingPasteboard.name);
@@ -3637,13 +3637,13 @@
 NSDragOperation WebViewImpl::draggingUpdated(id <NSDraggingInfo> draggingInfo)
 {
     WebCore::IntPoint client([m_view convertPoint:draggingInfo.draggingLocation fromView:nil]);
-    WebCore::IntPoint global(WebCore::globalPoint(draggingInfo.draggingLocation, m_view.window));
+    WebCore::IntPoint global(WebCore::globalPoint(draggingInfo.draggingLocation, [m_view window]));
 #if WK_API_ENABLED
     auto dragDestinationAction = static_cast<WebCore::DragDestinationAction>([m_view _web_dragDestinationActionForDraggingInfo:draggingInfo]);
 #else
     auto dragDestinationAction = WebCore::DragDestinationActionAny;
 #endif
-    WebCore::DragData dragData(draggingInfo, client, global, static_cast<WebCore::DragOperation>(draggingInfo.draggingSourceOperationMask), applicationFlagsForDrag(m_view, draggingInfo), dragDestinationAction);
+    WebCore::DragData dragData(draggingInfo, client, global, static_cast<WebCore::DragOperation>(draggingInfo.draggingSourceOperationMask), applicationFlagsForDrag(m_view.getAutoreleased(), draggingInfo), dragDestinationAction);
     m_page->dragUpdated(dragData, draggingInfo.draggingPasteboard.name);
 
     NSInteger numberOfValidItemsForDrop = m_page->currentDragNumberOfFilesToBeAccepted();
@@ -3666,8 +3666,8 @@
 void WebViewImpl::draggingExited(id <NSDraggingInfo> draggingInfo)
 {
     WebCore::IntPoint client([m_view convertPoint:draggingInfo.draggingLocation fromView:nil]);
-    WebCore::IntPoint global(WebCore::globalPoint(draggingInfo.draggingLocation, m_view.window));
-    WebCore::DragData dragData(draggingInfo, client, global, static_cast<WebCore::DragOperation>(draggingInfo.draggingSourceOperationMask), applicationFlagsForDrag(m_view, draggingInfo));
+    WebCore::IntPoint global(WebCore::globalPoint(draggingInfo.draggingLocation, [m_view window]));
+    WebCore::DragData dragData(draggingInfo, client, global, static_cast<WebCore::DragOperation>(draggingInfo.draggingSourceOperationMask), applicationFlagsForDrag(m_view.getAutoreleased(), draggingInfo));
     m_page->dragExited(dragData, draggingInfo.draggingPasteboard.name);
     m_page->resetCurrentDragInformation();
     draggingInfo.numberOfValidItemsForDrop = m_initialNumberOfValidItemsForDrop;
@@ -3682,8 +3682,8 @@
 bool WebViewImpl::performDragOperation(id <NSDraggingInfo> draggingInfo)
 {
     WebCore::IntPoint client([m_view convertPoint:draggingInfo.draggingLocation fromView:nil]);
-    WebCore::IntPoint global(WebCore::globalPoint(draggingInfo.draggingLocation, m_view.window));
-    WebCore::DragData *dragData = new WebCore::DragData(draggingInfo, client, global, static_cast<WebCore::DragOperation>(draggingInfo.draggingSourceOperationMask), applicationFlagsForDrag(m_view, draggingInfo));
+    WebCore::IntPoint global(WebCore::globalPoint(draggingInfo.draggingLocation, [m_view window]));
+    WebCore::DragData *dragData = new WebCore::DragData(draggingInfo, client, global, static_cast<WebCore::DragOperation>(draggingInfo.draggingSourceOperationMask), applicationFlagsForDrag(m_view.getAutoreleased(), draggingInfo));
 
     NSArray *types = draggingInfo.draggingPasteboard.types;
     SandboxExtension::Handle sandboxExtensionHandle;
@@ -3713,7 +3713,7 @@
         Vector<String> *fileNames = new Vector<String>;
         NSURL *dropLocation = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
         String pasteboardName = draggingInfo.draggingPasteboard.name;
-        [draggingInfo enumerateDraggingItemsWithOptions:0 forView:m_view classes:@[[NSFilePromiseReceiver class]] searchOptions:@{ } usingBlock:^(NSDraggingItem * __nonnull draggingItem, NSInteger idx, BOOL * __nonnull stop) {
+        [draggingInfo enumerateDraggingItemsWithOptions:0 forView:m_view.getAutoreleased() classes:@[[NSFilePromiseReceiver class]] searchOptions:@{ } usingBlock:^(NSDraggingItem * __nonnull draggingItem, NSInteger idx, BOOL * __nonnull stop) {
             NSFilePromiseReceiver *item = draggingItem.item;
             NSDictionary *options = @{ };
 
@@ -3753,7 +3753,7 @@
     // This is the case for elements that do not place content
     // in the drag pasteboard automatically when the drag start (i.e. dragging a DIV element).
     if ([[m_view superview] mouse:NSPointFromCGPoint(point) inRect:[m_view frame]])
-        return m_view;
+        return m_view.getAutoreleased();
     return nil;
 }
 
@@ -3768,13 +3768,13 @@
 
 void WebViewImpl::startWindowDrag()
 {
-    [m_view.window performWindowDragWithEvent:m_lastMouseDownEvent.get()];
+    [[m_view window] performWindowDragWithEvent:m_lastMouseDownEvent.get()];
 }
 
 void WebViewImpl::dragImageForView(NSView *view, NSImage *image, CGPoint clientPoint, bool)
 {
     // The call below could release the view.
-    RetainPtr<NSView> protector(m_view);
+    auto protector = m_view.get();
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
     NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
@@ -3787,7 +3787,7 @@
              offset:NSZeroSize
               event:m_lastMouseDownEvent.get()
          pasteboard:pasteboard
-             source:m_view
+             source:m_view.getAutoreleased()
           slideBack:YES];
 #pragma clang diagnostic pop
 }
@@ -3819,7 +3819,7 @@
     RetainPtr<NSMutableArray> types = adoptNS([[NSMutableArray alloc] initWithObjects:NSFilesPromisePboardType, nil]);
 
     [types addObjectsFromArray:archiveBuffer ? PasteboardTypes::forImagesWithArchive() : PasteboardTypes::forImages()];
-    [pasteboard declareTypes:types.get() owner:m_view];
+    [pasteboard declareTypes:types.get() owner:m_view.getAutoreleased()];
     setFileAndURLTypes(filename, extension, title, url, visibleURL, pasteboard);
 
     if (archiveBuffer)
@@ -3834,7 +3834,7 @@
     NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:pasteboardName];
     RetainPtr<NSMutableArray> types = adoptNS([[NSMutableArray alloc] initWithObjects:NSFilesPromisePboardType, nil]);
     [types addObjectsFromArray:PasteboardTypes::forURL()];
-    [pasteboard declareTypes:types.get() owner:m_view];
+    [pasteboard declareTypes:types.get() owner:m_view.getAutoreleased()];
     setFileAndURLTypes(filename, extension, title, url, visibleURL, pasteboard);
     [pasteboard setPropertyList:@[title] forType:NSFilenamesPboardType];
 
@@ -3947,7 +3947,7 @@
 
 RefPtr<ViewSnapshot> WebViewImpl::takeViewSnapshot()
 {
-    NSWindow *window = m_view.window;
+    NSWindow *window = [m_view window];
 
     CGSWindowID windowID = (CGSWindowID)window.windowNumber;
     if (!windowID || !window.isVisible)
@@ -3972,7 +3972,7 @@
     if (!boundsForCustomSwipeViews.isEmpty())
         windowCaptureRect = boundsForCustomSwipeViews;
     else {
-        NSRect unobscuredBounds = m_view.bounds;
+        NSRect unobscuredBounds = [m_view bounds];
         float topContentInset = m_page->topContentInset();
         unobscuredBounds.origin.y += topContentInset;
         unobscuredBounds.size.height -= topContentInset;
@@ -4110,7 +4110,7 @@
     if (m_allowsBackForwardNavigationGestures && ensureGestureController().handleScrollWheelEvent(event))
         return;
 
-    NativeWebWheelEvent webEvent = NativeWebWheelEvent(event, m_view);
+    NativeWebWheelEvent webEvent = NativeWebWheelEvent(event, m_view.getAutoreleased());
     m_page->handleWheelEvent(webEvent);
 }
 
@@ -4136,7 +4136,7 @@
 {
     if (!m_allowsMagnification) {
 #if ENABLE(MAC_GESTURE_EVENTS)
-        NativeWebGestureEvent webEvent = NativeWebGestureEvent(event, m_view);
+        NativeWebGestureEvent webEvent = NativeWebGestureEvent(event, m_view.getAutoreleased());
         m_page->handleGestureEvent(webEvent);
 #endif
         [m_view _web_superMagnifyWithEvent:event];
@@ -4153,7 +4153,7 @@
         return;
     }
 
-    NativeWebGestureEvent webEvent = NativeWebGestureEvent(event, m_view);
+    NativeWebGestureEvent webEvent = NativeWebGestureEvent(event, m_view.getAutoreleased());
     m_page->handleGestureEvent(webEvent);
 #else
     gestureController.handleMagnificationGestureEvent(event, [m_view convertPoint:event.locationInWindow fromView:nil]);
@@ -4185,7 +4185,7 @@
 #if ENABLE(MAC_GESTURE_EVENTS)
 void WebViewImpl::rotateWithEvent(NSEvent *event)
 {
-    NativeWebGestureEvent webEvent = NativeWebGestureEvent(event, m_view);
+    NativeWebGestureEvent webEvent = NativeWebGestureEvent(event, m_view.getAutoreleased());
     m_page->handleGestureEvent(webEvent);
 }
 #endif
@@ -4223,7 +4223,7 @@
     }
 
     // resending the event may destroy this WKView
-    RetainPtr<NSView> protector(m_view);
+    auto protector = m_view.get();
 
     ASSERT(!m_keyDownEventBeingResent);
     m_keyDownEventBeingResent = event;
@@ -4320,16 +4320,20 @@
     }
 
     LOG(TextInput, "-> handleEventByInputMethod:%p %@", event, event);
-    [inputContext() handleEventByInputMethod:event completionHandler:^(BOOL handled) {
-        
+    [inputContext() handleEventByInputMethod:event completionHandler:[weakThis = createWeakPtr(), capturedEvent = retainPtr(event), capturedBlock = makeBlockPtr(completionHandler)](BOOL handled) {
+        if (!weakThis) {
+            capturedBlock(NO, { });
+            return;
+        }
+
         LOG(TextInput, "... handleEventByInputMethod%s handled", handled ? "" : " not");
         if (handled) {
-            completionHandler(YES, { });
+            capturedBlock(YES, { });
             return;
         }
 
-        auto commands = collectKeyboardLayoutCommandsForEvent(event);
-        completionHandler(NO, commands);
+        auto commands = weakThis->collectKeyboardLayoutCommandsForEvent(capturedEvent.get());
+        capturedBlock(NO, commands);
     }];
 }
 
@@ -4512,10 +4516,13 @@
 
     auto weakThis = createWeakPtr();
     m_page->firstRectForCharacterRangeAsync(range, [weakThis, completionHandler](const WebCore::IntRect& rect, const EditingRange& actualRange, WebKit::CallbackBase::Error error) {
-        if (!weakThis)
+        auto completionHandlerBlock = (void (^)(NSRect, NSRange))completionHandler.get();
+        if (!weakThis) {
+            LOG(TextInput, "    ...firstRectForCharacterRange failed (WebViewImpl was destroyed).");
+            completionHandlerBlock(NSZeroRect, NSMakeRange(NSNotFound, 0));
             return;
+        }
 
-        void (^completionHandlerBlock)(NSRect, NSRange) = (void (^)(NSRect, NSRange))completionHandler.get();
         if (error != WebKit::CallbackBase::Error::None) {
             LOG(TextInput, "    ...firstRectForCharacterRange failed.");
             completionHandlerBlock(NSZeroRect, NSMakeRange(NSNotFound, 0));
@@ -4523,7 +4530,7 @@
         }
 
         NSRect resultRect = [weakThis->m_view convertRect:rect toView:nil];
-        resultRect = [weakThis->m_view.window convertRectToScreen:resultRect];
+        resultRect = [[weakThis->m_view window] convertRectToScreen:resultRect];
 
         LOG(TextInput, "    -> firstRectForCharacterRange returned (%f, %f, %f, %f)", resultRect.origin.x, resultRect.origin.y, resultRect.size.width, resultRect.size.height);
         completionHandlerBlock(resultRect, actualRange);
@@ -4536,7 +4543,7 @@
 
     LOG(TextInput, "characterIndexForPoint:(%f, %f)", point.x, point.y);
 
-    NSWindow *window = m_view.window;
+    NSWindow *window = [m_view window];
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
@@ -4679,9 +4686,10 @@
     // Pass key combos through WebCore if there is a key binding available for
     // this event. This lets webpages have a crack at intercepting key-modified keypresses.
     // FIXME: Why is the firstResponder check needed?
-    if (m_view == m_view.window.firstResponder) {
-        interpretKeyEvent(event, ^(BOOL handledByInputMethod, const Vector<WebCore::KeypressCommand>& commands) {
-            m_page->handleKeyboardEvent(NativeWebKeyboardEvent(event, handledByInputMethod, false, commands));
+    if (m_view.getAutoreleased() == [m_view window].firstResponder) {
+        interpretKeyEvent(event, [weakThis = createWeakPtr(), capturedEvent = retainPtr(event)](BOOL handledByInputMethod, const Vector<WebCore::KeypressCommand>& commands) {
+            if (weakThis)
+                weakThis->m_page->handleKeyboardEvent(NativeWebKeyboardEvent(capturedEvent.get(), handledByInputMethod, false, commands));
         });
         return YES;
     }
@@ -4697,9 +4705,10 @@
     LOG(TextInput, "keyUp:%p %@", event, event);
 
     m_isTextInsertionReplacingSoftSpace = false;
-    interpretKeyEvent(event, ^(BOOL handledByInputMethod, const Vector<WebCore::KeypressCommand>& commands) {
+    interpretKeyEvent(event, [weakThis = createWeakPtr(), capturedEvent = retainPtr(event)](BOOL handledByInputMethod, const Vector<WebCore::KeypressCommand>& commands) {
         ASSERT(!handledByInputMethod || commands.isEmpty());
-        m_page->handleKeyboardEvent(NativeWebKeyboardEvent(event, handledByInputMethod, m_isTextInsertionReplacingSoftSpace, commands));
+        if (weakThis)
+            weakThis->m_page->handleKeyboardEvent(NativeWebKeyboardEvent(capturedEvent.get(), handledByInputMethod, weakThis->m_isTextInsertionReplacingSoftSpace, commands));
     });
 }
 
@@ -4725,9 +4734,10 @@
     }
 
     m_isTextInsertionReplacingSoftSpace = false;
-    interpretKeyEvent(event, ^(BOOL handledByInputMethod, const Vector<WebCore::KeypressCommand>& commands) {
+    interpretKeyEvent(event, [weakThis = createWeakPtr(), capturedEvent = retainPtr(event)](BOOL handledByInputMethod, const Vector<WebCore::KeypressCommand>& commands) {
         ASSERT(!handledByInputMethod || commands.isEmpty());
-        m_page->handleKeyboardEvent(NativeWebKeyboardEvent(event, handledByInputMethod, m_isTextInsertionReplacingSoftSpace, commands));
+        if (weakThis)
+            weakThis->m_page->handleKeyboardEvent(NativeWebKeyboardEvent(capturedEvent.get(), handledByInputMethod, weakThis->m_isTextInsertionReplacingSoftSpace, commands));
     });
 }
 
@@ -4752,7 +4762,7 @@
     { \
         if (m_ignoresNonWheelEvents) \
             return; \
-        if (NSTextInputContext *context = m_view.inputContext) { \
+        if (NSTextInputContext *context = [m_view inputContext]) { \
             auto weakThis = createWeakPtr(); \
             RetainPtr<NSEvent> retainedEvent = event; \
             [context handleEvent:event completionHandler:[weakThis, retainedEvent] (BOOL handled) { \
@@ -4761,13 +4771,13 @@
                 if (handled) \
                     LOG(TextInput, "%s was handled by text input context", String(#EventName).substring(0, String(#EventName).find("Internal")).ascii().data()); \
                 else { \
-                    NativeWebMouseEvent webEvent(retainedEvent.get(), weakThis->m_lastPressureEvent.get(), weakThis->m_view); \
+                    NativeWebMouseEvent webEvent(retainedEvent.get(), weakThis->m_lastPressureEvent.get(), weakThis->m_view.getAutoreleased()); \
                     weakThis->m_page->handleMouseEvent(webEvent); \
                 } \
             }]; \
             return; \
         } \
-        NativeWebMouseEvent webEvent(event, m_lastPressureEvent.get(), m_view); \
+        NativeWebMouseEvent webEvent(event, m_lastPressureEvent.get(), m_view.getAutoreleased()); \
         m_page->handleMouseEvent(webEvent); \
     }
 #define NATIVE_MOUSE_EVENT_HANDLER_INTERNAL(EventName) \
@@ -4775,7 +4785,7 @@
     { \
         if (m_ignoresNonWheelEvents) \
             return; \
-        if (NSTextInputContext *context = m_view.inputContext) { \
+        if (NSTextInputContext *context = [m_view inputContext]) { \
             auto weakThis = createWeakPtr(); \
             RetainPtr<NSEvent> retainedEvent = event; \
             [context handleEvent:event completionHandler:[weakThis, retainedEvent] (BOOL handled) { \
@@ -4784,13 +4794,13 @@
                 if (handled) \
                     LOG(TextInput, "%s was handled by text input context", String(#EventName).substring(0, String(#EventName).find("Internal")).ascii().data()); \
                 else { \
-                    NativeWebMouseEvent webEvent(retainedEvent.get(), weakThis->m_lastPressureEvent.get(), weakThis->m_view); \
+                    NativeWebMouseEvent webEvent(retainedEvent.get(), weakThis->m_lastPressureEvent.get(), weakThis->m_view.getAutoreleased()); \
                     weakThis->m_page->handleMouseEvent(webEvent); \
                 } \
             }]; \
             return; \
         } \
-        NativeWebMouseEvent webEvent(event, m_lastPressureEvent.get(), m_view); \
+        NativeWebMouseEvent webEvent(event, m_lastPressureEvent.get(), m_view.getAutoreleased()); \
         m_page->handleMouseEvent(webEvent); \
     }
 
@@ -4817,7 +4827,7 @@
         return;
 
     // When a view is first responder, it gets mouse moved events even when the mouse is outside its visible rect.
-    if (m_view == m_view.window.firstResponder && !NSPointInRect([m_view convertPoint:[event locationInWindow] fromView:nil], m_view.visibleRect))
+    if (m_view.getAutoreleased() == [m_view window].firstResponder && !NSPointInRect([m_view convertPoint:[event locationInWindow] fromView:nil], [m_view visibleRect]))
         return;
 
     mouseMovedInternal(event);
@@ -4855,10 +4865,10 @@
 
 bool WebViewImpl::windowIsFrontWindowUnderMouse(NSEvent *event)
 {
-    NSRect eventScreenPosition = [m_view.window convertRectToScreen:NSMakeRect(event.locationInWindow.x, event.locationInWindow.y, 0, 0)];
+    NSRect eventScreenPosition = [[m_view window] convertRectToScreen:NSMakeRect(event.locationInWindow.x, event.locationInWindow.y, 0, 0)];
     NSInteger eventWindowNumber = [NSWindow windowNumberAtPoint:eventScreenPosition.origin belowWindowWithWindowNumber:0];
         
-    return m_view.window.windowNumber != eventWindowNumber;
+    return [m_view window].windowNumber != eventWindowNumber;
 }
 
 static WebCore::UserInterfaceLayoutDirection toUserInterfaceLayoutDirection(NSUserInterfaceLayoutDirection direction)
@@ -4876,7 +4886,7 @@
 
 WebCore::UserInterfaceLayoutDirection WebViewImpl::userInterfaceLayoutDirection()
 {
-    return toUserInterfaceLayoutDirection(m_view.userInterfaceLayoutDirection);
+    return toUserInterfaceLayoutDirection([m_view userInterfaceLayoutDirection]);
 }
 
 void WebViewImpl::setUserInterfaceLayoutDirection(NSUserInterfaceLayoutDirection direction)

Modified: trunk/Tools/ChangeLog (220417 => 220418)


--- trunk/Tools/ChangeLog	2017-08-08 19:58:26 UTC (rev 220417)
+++ trunk/Tools/ChangeLog	2017-08-08 20:45:21 UTC (rev 220418)
@@ -1,3 +1,23 @@
+2017-08-08  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [Mac WK2] WebViewImpl should hold a weak pointer to its WKWebView or WKView
+        https://bugs.webkit.org/show_bug.cgi?id=175302
+        <rdar://problem/33762116>
+
+        Reviewed by Tim Horton.
+
+        Adds a new unit test checking that delayed event processing in text input context does not cause unwanted behaviors.
+        See WebKit ChangeLog for more details.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/TestWebKitAPI/mac/AppKitSPI.h: Renamed from Tools/TestWebKitAPI/Tests/TestWebKitAPI/mac/NSTextInputClientSPI.h.
+        * TestWebKitAPI/Tests/mac/WKWebViewMacEditingTests.mm: Renamed from Tools/TestWebKitAPI/Tests/mac/WKWebViewSelectionTests.mm.
+        (-[SlowTextInputContext handleEventByInputMethod:completionHandler:]):
+        (-[SlowTextInputContext handleEvent:completionHandler:]):
+        (-[SlowInputWebView inputContext]):
+        (-[SlowInputWebView _web_superInputContext]):
+        (TEST):
+
 2017-08-08  John Wilander  <wilan...@apple.com>
 
         Resource Load Statistics: Clear web processes' state on history removal

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (220417 => 220418)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-08-08 19:58:26 UTC (rev 220417)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-08-08 20:45:21 UTC (rev 220418)
@@ -687,7 +687,7 @@
 		F4F137921D9B683E002BEC57 /* large-video-test-now-playing.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4F137911D9B6832002BEC57 /* large-video-test-now-playing.html */; };
 		F4F405BC1D4C0D1C007A9707 /* full-size-autoplaying-video-with-audio.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4F405BA1D4C0CF8007A9707 /* full-size-autoplaying-video-with-audio.html */; };
 		F4F405BD1D4C0D1C007A9707 /* skinny-autoplaying-video-with-audio.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4F405BB1D4C0CF8007A9707 /* skinny-autoplaying-video-with-audio.html */; };
-		F4FA91811E61849B007B8C1D /* WKWebViewSelectionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4FA917F1E61849B007B8C1D /* WKWebViewSelectionTests.mm */; };
+		F4FA91811E61849B007B8C1D /* WKWebViewMacEditingTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4FA917F1E61849B007B8C1D /* WKWebViewMacEditingTests.mm */; };
 		F4FA91831E61857B007B8C1D /* double-click-does-not-select-trailing-space.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4FA91821E618566007B8C1D /* double-click-does-not-select-trailing-space.html */; };
 		F660AA1115A5F631003A1243 /* GetInjectedBundleInitializationUserDataCallback_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F660AA0F15A5F624003A1243 /* GetInjectedBundleInitializationUserDataCallback_Bundle.cpp */; };
 		F660AA1515A61ABF003A1243 /* InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F660AA1415A61ABF003A1243 /* InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp */; };
@@ -1110,7 +1110,7 @@
 		2E691AF21D79E75400129407 /* large-video-playing-scroll-away.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-playing-scroll-away.html"; sourceTree = "<group>"; };
 		2E7765CC16C4D80A00BA2BB1 /* mainIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = mainIOS.mm; sourceTree = "<group>"; };
 		2E7765CE16C4D81100BA2BB1 /* mainMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = mainMac.mm; sourceTree = "<group>"; };
-		2E7EF7AC1F266A8100DFB67C /* NSTextInputClientSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSTextInputClientSPI.h; sourceTree = "<group>"; };
+		2E7EF7AC1F266A8100DFB67C /* AppKitSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppKitSPI.h; sourceTree = "<group>"; };
 		2E9896141D8F092B00739892 /* text-and-password-inputs.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "text-and-password-inputs.html"; sourceTree = "<group>"; };
 		2ECFF5541D9B12F800B55394 /* NowPlayingControlsTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NowPlayingControlsTests.mm; sourceTree = "<group>"; };
 		2EFF06C21D8862120004BB30 /* large-video-offscreen.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-offscreen.html"; sourceTree = "<group>"; };
@@ -1703,7 +1703,7 @@
 		F4F137911D9B6832002BEC57 /* large-video-test-now-playing.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-test-now-playing.html"; sourceTree = "<group>"; };
 		F4F405BA1D4C0CF8007A9707 /* full-size-autoplaying-video-with-audio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "full-size-autoplaying-video-with-audio.html"; sourceTree = "<group>"; };
 		F4F405BB1D4C0CF8007A9707 /* skinny-autoplaying-video-with-audio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "skinny-autoplaying-video-with-audio.html"; sourceTree = "<group>"; };
-		F4FA917F1E61849B007B8C1D /* WKWebViewSelectionTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewSelectionTests.mm; sourceTree = "<group>"; };
+		F4FA917F1E61849B007B8C1D /* WKWebViewMacEditingTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewMacEditingTests.mm; sourceTree = "<group>"; };
 		F4FA91821E618566007B8C1D /* double-click-does-not-select-trailing-space.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = "double-click-does-not-select-trailing-space.html"; path = "Tests/WebKit2Cocoa/double-click-does-not-select-trailing-space.html"; sourceTree = SOURCE_ROOT; };
 		F660AA0C15A5F061003A1243 /* GetInjectedBundleInitializationUserDataCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetInjectedBundleInitializationUserDataCallback.cpp; sourceTree = "<group>"; };
 		F660AA0F15A5F624003A1243 /* GetInjectedBundleInitializationUserDataCallback_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetInjectedBundleInitializationUserDataCallback_Bundle.cpp; sourceTree = "<group>"; };
@@ -2651,7 +2651,7 @@
 				CE32C7C718184C4900CD8C28 /* WillPerformClientRedirectToURLCrash.mm */,
 				1A7BFC0A171A0BDB00BC5F64 /* WillSendSubmitEvent.mm */,
 				A5E2027215B2181900C13E14 /* WindowlessWebViewWithMedia.mm */,
-				F4FA917F1E61849B007B8C1D /* WKWebViewSelectionTests.mm */,
+				F4FA917F1E61849B007B8C1D /* WKWebViewMacEditingTests.mm */,
 				764322D51B61CCA40024F801 /* WordBoundaryTypingAttributes.mm */,
 			);
 			path = mac;
@@ -2706,8 +2706,8 @@
 		C08587FA13FEC39B001EF4E5 /* mac */ = {
 			isa = PBXGroup;
 			children = (
+				2E7EF7AC1F266A8100DFB67C /* AppKitSPI.h */,
 				C08587FB13FEC39B001EF4E5 /* InstanceMethodSwizzler.mm */,
-				2E7EF7AC1F266A8100DFB67C /* NSTextInputClientSPI.h */,
 			);
 			path = mac;
 			sourceTree = "<group>";
@@ -3362,7 +3362,7 @@
 				46E66A901F0D75590026D83C /* WKWebViewDiagnosticLogging.mm in Sources */,
 				0F3B94A71A77267400DE3272 /* WKWebViewEvaluateJavaScript.mm in Sources */,
 				D34E08761E4E42E1005FF14A /* WKWebViewGetContents.mm in Sources */,
-				F4FA91811E61849B007B8C1D /* WKWebViewSelectionTests.mm in Sources */,
+				F4FA91811E61849B007B8C1D /* WKWebViewMacEditingTests.mm in Sources */,
 				93F56DA91E5F919D003EDE84 /* WKWebViewSnapshot.mm in Sources */,
 				9984FACC1CFFAF60008D198C /* WKWebViewTextInput.mm in Sources */,
 				764322D71B61CCC30024F801 /* WordBoundaryTypingAttributes.mm in Sources */,

Copied: trunk/Tools/TestWebKitAPI/Tests/TestWebKitAPI/mac/AppKitSPI.h (from rev 220417, trunk/Tools/TestWebKitAPI/Tests/TestWebKitAPI/mac/NSTextInputClientSPI.h) (0 => 220418)


--- trunk/Tools/TestWebKitAPI/Tests/TestWebKitAPI/mac/AppKitSPI.h	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/TestWebKitAPI/mac/AppKitSPI.h	2017-08-08 20:45:21 UTC (rev 220418)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if PLATFORM(MAC)
+
+#if USE(APPLE_INTERNAL_SDK)
+
+#import <AppKit/NSTextInputClient_Private.h>
+#import <AppKit/NSTextInputContext_Private.h>
+
+#else
+
+@protocol NSTextInputClient_Async
+- (void)selectedRangeWithCompletionHandler:(void(^)(NSRange selectedRange))completionHandler;
+- (void)markedRangeWithCompletionHandler:(void(^)(NSRange markedRange))completionHandler;
+- (void)hasMarkedTextWithCompletionHandler:(void(^)(BOOL hasMarkedText))completionHandler;
+@end
+
+@interface NSTextInputContext (WebKitSupport)
+- (void)handleEvent:(NSEvent *)event completionHandler:(void(^)(BOOL handled))completionHandler;
+- (void)handleEventByInputMethod:(NSEvent *)event completionHandler:(void(^)(BOOL handled))completionHandler;
+@end
+
+#endif
+
+#endif // PLATFORM(MAC)

Deleted: trunk/Tools/TestWebKitAPI/Tests/TestWebKitAPI/mac/NSTextInputClientSPI.h (220417 => 220418)


--- trunk/Tools/TestWebKitAPI/Tests/TestWebKitAPI/mac/NSTextInputClientSPI.h	2017-08-08 19:58:26 UTC (rev 220417)
+++ trunk/Tools/TestWebKitAPI/Tests/TestWebKitAPI/mac/NSTextInputClientSPI.h	2017-08-08 20:45:21 UTC (rev 220418)
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if PLATFORM(MAC)
-
-#if USE(APPLE_INTERNAL_SDK)
-
-#import <AppKit/NSTextInputClient_Private.h>
-
-#else
-
-@protocol NSTextInputClient_Async
-- (void)selectedRangeWithCompletionHandler:(void(^)(NSRange selectedRange))completionHandler;
-- (void)markedRangeWithCompletionHandler:(void(^)(NSRange markedRange))completionHandler;
-- (void)hasMarkedTextWithCompletionHandler:(void(^)(BOOL hasMarkedText))completionHandler;
-@end
-
-#endif
-
-#endif // PLATFORM(MAC)

Copied: trunk/Tools/TestWebKitAPI/Tests/mac/WKWebViewMacEditingTests.mm (from rev 220417, trunk/Tools/TestWebKitAPI/Tests/mac/WKWebViewSelectionTests.mm) (0 => 220418)


--- trunk/Tools/TestWebKitAPI/Tests/mac/WKWebViewMacEditingTests.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/mac/WKWebViewMacEditingTests.mm	2017-08-08 20:45:21 UTC (rev 220418)
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_API_ENABLED && PLATFORM(MAC)
+
+#import "AppKitSPI.h"
+#import "PlatformUtilities.h"
+#import "TestWKWebView.h"
+#import <wtf/BlockPtr.h>
+#import <wtf/RetainPtr.h>
+
+@interface SlowTextInputContext : NSTextInputContext
+@property (nonatomic) BlockPtr<void()> handledInputMethodEventBlock;
+@end
+
+@implementation SlowTextInputContext
+
+- (void)handleEventByInputMethod:(NSEvent *)event completionHandler:(void(^)(BOOL handled))completionHandler
+{
+    [super handleEventByInputMethod:event completionHandler:^(BOOL handled) {
+        dispatch_async(dispatch_get_main_queue(), ^() {
+            completionHandler(handled);
+            if (_handledInputMethodEventBlock)
+                _handledInputMethodEventBlock();
+        });
+    }];
+}
+
+- (void)handleEvent:(NSEvent *)event completionHandler:(void(^)(BOOL handled))completionHandler
+{
+    [super handleEvent:event completionHandler:^(BOOL handled) {
+        dispatch_async(dispatch_get_main_queue(), ^() {
+            completionHandler(handled);
+        });
+    }];
+}
+
+@end
+
+@interface SlowInputWebView : TestWKWebView {
+    RetainPtr<SlowTextInputContext> _slowInputContext;
+}
+@end
+
+@implementation SlowInputWebView
+
+- (NSTextInputContext *)inputContext
+{
+    return self._web_superInputContext;
+}
+
+- (SlowTextInputContext *)_web_superInputContext
+{
+    if (!_slowInputContext)
+        _slowInputContext = adoptNS([[SlowTextInputContext alloc] initWithClient:(id<NSTextInputClient>)self]);
+    return _slowInputContext.get();
+}
+
+@end
+
+TEST(WKWebViewMacEditingTests, DoubleClickDoesNotSelectTrailingSpace)
+{
+    RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
+    [webView synchronouslyLoadTestPageNamed:@"double-click-does-not-select-trailing-space"];
+
+    __block bool finishedSelectingText = false;
+    [webView performAfterReceivingMessage:@"selected" action:^() {
+        finishedSelectingText = true;
+    }];
+    [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:2];
+    TestWebKitAPI::Util::run(&finishedSelectingText);
+
+    NSString *selectedText = [webView stringByEvaluatingJavaScript:@"getSelection().getRangeAt(0).toString()"];
+    EXPECT_STREQ("Hello", selectedText.UTF8String);
+}
+
+TEST(WKWebViewMacEditingTests, DoNotCrashWhenCallingTextInputClientMethodsWhileDeallocatingView)
+{
+    NSString *textContent = @"This test should not cause us to dereference null.";
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
+    [webView synchronouslyLoadHTMLString:[NSString stringWithFormat:@"<p>%@</p>", textContent]];
+    [webView removeFromSuperview];
+
+    __unsafe_unretained id <NSTextInputClient_Async> inputClient = (id <NSTextInputClient_Async>)webView.get();
+    [inputClient hasMarkedTextWithCompletionHandler:^(BOOL) {
+        [inputClient selectedRangeWithCompletionHandler:^(NSRange) {
+            [inputClient markedRangeWithCompletionHandler:^(NSRange) { }];
+        }];
+    }];
+
+    EXPECT_WK_STREQ(textContent, [webView stringByEvaluatingJavaScript:@"document.body.textContent"]);
+}
+
+TEST(WKWebViewMacEditingTests, DoNotCrashWhenInterpretingKeyEventWhileDeallocatingView)
+{
+    __block bool isDone = false;
+
+    @autoreleasepool {
+        SlowInputWebView *webView = [[[SlowInputWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)] autorelease];
+        [webView synchronouslyLoadHTMLString:[NSString stringWithFormat:@"<body contenteditable>Hello world</body>"]];
+        [webView stringByEvaluatingJavaScript:@"document.body.focus()"];
+        [webView removeFromSuperview];
+        [webView typeCharacter:'a'];
+
+        webView._web_superInputContext.handledInputMethodEventBlock = ^() {
+            isDone = true;
+        };
+    }
+
+    TestWebKitAPI::Util::run(&isDone);
+}
+
+#endif // WK_API_ENABLED && PLATFORM(MAC)

Deleted: trunk/Tools/TestWebKitAPI/Tests/mac/WKWebViewSelectionTests.mm (220417 => 220418)


--- trunk/Tools/TestWebKitAPI/Tests/mac/WKWebViewSelectionTests.mm	2017-08-08 19:58:26 UTC (rev 220417)
+++ trunk/Tools/TestWebKitAPI/Tests/mac/WKWebViewSelectionTests.mm	2017-08-08 20:45:21 UTC (rev 220418)
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if WK_API_ENABLED && PLATFORM(MAC)
-
-#import "NSTextInputClientSPI.h"
-#import "PlatformUtilities.h"
-#import "TestWKWebView.h"
-
-TEST(WKWebViewSelectionTests, DoubleClickDoesNotSelectTrailingSpace)
-{
-    RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
-    [webView synchronouslyLoadTestPageNamed:@"double-click-does-not-select-trailing-space"];
-
-    __block bool finishedSelectingText = false;
-    [webView performAfterReceivingMessage:@"selected" action:^() {
-        finishedSelectingText = true;
-    }];
-    [webView sendClicksAtPoint:NSMakePoint(200, 200) numberOfClicks:2];
-    TestWebKitAPI::Util::run(&finishedSelectingText);
-
-    NSString *selectedText = [webView stringByEvaluatingJavaScript:@"getSelection().getRangeAt(0).toString()"];
-    EXPECT_STREQ("Hello", selectedText.UTF8String);
-}
-
-TEST(WKWebViewSelectionTests, DoNotCrashWhenCallingTextInputClientMethodsWhileDeallocatingView)
-{
-    NSString *textContent = @"This test should not cause us to dereference null.";
-
-    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
-    [webView synchronouslyLoadHTMLString:[NSString stringWithFormat:@"<p>%@</p>", textContent]];
-    [webView removeFromSuperview];
-
-    __unsafe_unretained id <NSTextInputClient_Async> inputClient = (id <NSTextInputClient_Async>)webView.get();
-    [inputClient hasMarkedTextWithCompletionHandler:^(BOOL) {
-        [inputClient selectedRangeWithCompletionHandler:^(NSRange) {
-            [inputClient markedRangeWithCompletionHandler:^(NSRange) { }];
-        }];
-    }];
-
-    EXPECT_WK_STREQ(textContent, [webView stringByEvaluatingJavaScript:@"document.body.textContent"]);
-}
-
-#endif // WK_API_ENABLED && PLATFORM(MAC)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to