Title: [168588] trunk/Source/WebKit2
Revision
168588
Author
[email protected]
Date
2014-05-10 17:30:19 -0700 (Sat, 10 May 2014)

Log Message

ASSERTION FAILED: !m_connection under RunJavaScriptAlert
https://bugs.webkit.org/show_bug.cgi?id=132792
<rdar://problem/16691138>

Reviewed by Dan Bernstein.

Detect if someone implementing a UI delegate method with a completion handler never calls the completion
handler and raise an exception instead of asserting.

* UIProcess/Cocoa/UIDelegate.mm:
(WebKit::CompletionHandlerCallChecker::create):
(WebKit::CompletionHandlerCallChecker::~CompletionHandlerCallChecker):
(WebKit::CompletionHandlerCallChecker::didCallCompletionHandler):
(WebKit::CompletionHandlerCallChecker::CompletionHandlerCallChecker):
(WebKit::CompletionHandlerCallChecker::classImplementingDelegateMethod):
(WebKit::UIDelegate::UIClient::runJavaScriptAlert):
(WebKit::UIDelegate::UIClient::runJavaScriptConfirm):
(WebKit::UIDelegate::UIClient::runJavaScriptPrompt):

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (168587 => 168588)


--- trunk/Source/WebKit2/ChangeLog	2014-05-11 00:09:04 UTC (rev 168587)
+++ trunk/Source/WebKit2/ChangeLog	2014-05-11 00:30:19 UTC (rev 168588)
@@ -1,5 +1,26 @@
 2014-05-10  Anders Carlsson  <[email protected]>
 
+        ASSERTION FAILED: !m_connection under RunJavaScriptAlert
+        https://bugs.webkit.org/show_bug.cgi?id=132792
+        <rdar://problem/16691138>
+
+        Reviewed by Dan Bernstein.
+
+        Detect if someone implementing a UI delegate method with a completion handler never calls the completion
+        handler and raise an exception instead of asserting.
+
+        * UIProcess/Cocoa/UIDelegate.mm:
+        (WebKit::CompletionHandlerCallChecker::create):
+        (WebKit::CompletionHandlerCallChecker::~CompletionHandlerCallChecker):
+        (WebKit::CompletionHandlerCallChecker::didCallCompletionHandler):
+        (WebKit::CompletionHandlerCallChecker::CompletionHandlerCallChecker):
+        (WebKit::CompletionHandlerCallChecker::classImplementingDelegateMethod):
+        (WebKit::UIDelegate::UIClient::runJavaScriptAlert):
+        (WebKit::UIDelegate::UIClient::runJavaScriptConfirm):
+        (WebKit::UIDelegate::UIClient::runJavaScriptPrompt):
+
+2014-05-10  Anders Carlsson  <[email protected]>
+
         Use xpc_connection_kill for killing child processes where appropriate
         https://bugs.webkit.org/show_bug.cgi?id=132788
         <rdar://problem/16664185>

Modified: trunk/Source/WebKit2/UIProcess/Cocoa/UIDelegate.mm (168587 => 168588)


--- trunk/Source/WebKit2/UIProcess/Cocoa/UIDelegate.mm	2014-05-11 00:09:04 UTC (rev 168587)
+++ trunk/Source/WebKit2/UIProcess/Cocoa/UIDelegate.mm	2014-05-11 00:30:19 UTC (rev 168588)
@@ -38,6 +38,57 @@
 
 namespace WebKit {
 
+class CompletionHandlerCallChecker : public WTF::ThreadSafeRefCounted<CompletionHandlerCallChecker> {
+public:
+    static PassRefPtr<CompletionHandlerCallChecker> create(id delegate, SEL delegateMethodSelector)
+    {
+        return adoptRef(new CompletionHandlerCallChecker(object_getClass(delegate), delegateMethodSelector));
+    }
+
+    ~CompletionHandlerCallChecker()
+    {
+        if (m_didCallCompletionHandler)
+            return;
+
+        Class delegateClass = classImplementingDelegateMethod();
+        [NSException raise:NSInternalInconsistencyException format:@"Completion handler passed to %c[%@ %@] was not called", class_isMetaClass(delegateClass) ? '+' : '-', NSStringFromClass(delegateClass), NSStringFromSelector(m_delegateMethodSelector)];
+    }
+
+    void didCallCompletionHandler()
+    {
+        ASSERT(!m_didCallCompletionHandler);
+        m_didCallCompletionHandler = true;
+    }
+
+private:
+    CompletionHandlerCallChecker(Class delegateClass, SEL delegateMethodSelector)
+        : m_delegateClass(delegateClass)
+        , m_delegateMethodSelector(delegateMethodSelector)
+        , m_didCallCompletionHandler(false)
+    {
+    }
+
+    Class classImplementingDelegateMethod() const
+    {
+        Class delegateClass = m_delegateClass;
+        Method delegateMethod = class_getInstanceMethod(delegateClass, m_delegateMethodSelector);
+
+        for (Class superclass = class_getSuperclass(delegateClass); superclass; superclass = class_getSuperclass(superclass)) {
+            if (class_getInstanceMethod(superclass, m_delegateMethodSelector) != delegateMethod)
+                break;
+
+            delegateClass = superclass;
+        }
+
+        return delegateClass;
+    }
+
+    Class m_delegateClass;
+    SEL m_delegateMethodSelector;
+    bool m_didCallCompletionHandler;
+};
+
+
 UIDelegate::UIDelegate(WKWebView *webView)
     : m_webView(webView)
 {
@@ -123,8 +174,10 @@
         return;
     }
 
-    [delegate webView:m_uiDelegate.m_webView runJavaScriptAlertPanelWithMessage:message initiatedByFrame:adoptNS([[WKFrameInfo alloc] initWithWebFrameProxy:*webFrameProxy]).get() completionHandler:[completionHandler] {
+    RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:));
+    [delegate webView:m_uiDelegate.m_webView runJavaScriptAlertPanelWithMessage:message initiatedByFrame:adoptNS([[WKFrameInfo alloc] initWithWebFrameProxy:*webFrameProxy]).get() completionHandler:[completionHandler, checker] {
         completionHandler();
+        checker->didCallCompletionHandler();
     }];
 }
 
@@ -141,8 +194,10 @@
         return;
     }
 
-    [delegate webView:m_uiDelegate.m_webView runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:adoptNS([[WKFrameInfo alloc] initWithWebFrameProxy:*webFrameProxy]).get() completionHandler:[completionHandler](BOOL result) {
+    RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:));
+    [delegate webView:m_uiDelegate.m_webView runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:adoptNS([[WKFrameInfo alloc] initWithWebFrameProxy:*webFrameProxy]).get() completionHandler:[completionHandler, checker](BOOL result) {
         completionHandler(result);
+        checker->didCallCompletionHandler();
     }];
 }
 
@@ -159,8 +214,10 @@
         return;
     }
 
-    [delegate webView:m_uiDelegate.m_webView runJavaScriptTextInputPanelWithPrompt:message defaultText:defaultValue initiatedByFrame:adoptNS([[WKFrameInfo alloc] initWithWebFrameProxy:*webFrameProxy]).get() completionHandler:[completionHandler](NSString *result) {
+    RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:));
+    [delegate webView:m_uiDelegate.m_webView runJavaScriptTextInputPanelWithPrompt:message defaultText:defaultValue initiatedByFrame:adoptNS([[WKFrameInfo alloc] initWithWebFrameProxy:*webFrameProxy]).get() completionHandler:[completionHandler, checker](NSString *result) {
         completionHandler(result);
+        checker->didCallCompletionHandler();
     }];
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to