Block UI events not to be sent to the WebProcess while js popup is displayed.
authorByungwoo Lee <bw80.lee@samsung.com>
Thu, 6 Sep 2012 06:14:36 +0000 (15:14 +0900)
committerByungwoo Lee <bw80.lee@samsung.com>
Thu, 6 Sep 2012 09:02:02 +0000 (18:02 +0900)
[Title] Block UI events not to be sent to the WebProcess while js popup is displayed.
[Issue#] N_SE-8944 / N_SE-8828 / N_SE-8867 / N_SE-8935 / N_SE-8935 (tizendev.org/bugs)
[Problem] UI Process is terminated when js popup is displayed.
[Cause] Not permitted IPC messages about user event (touch, mouse, guesture, keyboard)
        can be sent to the WebProcess while js popup is displayed
[Solution] Add blocking code for the events while js popup is displayed.
[Developer] bw80.lee

Change-Id: Ieb7f91760db7c3a22389409b537064ce26d7b756

Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/efl/WebPageProxyEfl.cpp

index fd6b7fc..87f7110 100755 (executable)
@@ -1167,6 +1167,27 @@ void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
     
     LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
 
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+    if (!isWaitingForJavaScriptPopupReply()) {
+        m_keyEventQueue.append(event);
+
+        process()->responsivenessTimer()->start();
+        if (m_shouldSendEventsSynchronously) {
+            bool handled = false;
+            process()->sendSync(Messages::WebPage::KeyEventSyncForTesting(event), Messages::WebPage::KeyEventSyncForTesting::Reply(handled), m_pageID);
+            didReceiveEvent(event.type(), handled);
+        } else
+            process()->send(Messages::WebPage::KeyEvent(event), m_pageID);
+    } else {
+        if (m_keyEventQueue.isEmpty()) {
+            bool handled = false;
+            didReceiveEvent(event.type(), handled);
+        } else {
+            QueuedUIEvents<NativeWebKeyboardEvent>& lastEvent = m_keyEventQueue.last();
+            lastEvent.deferredEvents.append(event);
+        }
+    }
+#else
     m_keyEventQueue.append(event);
 
     process()->responsivenessTimer()->start();
@@ -1176,6 +1197,7 @@ void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
         didReceiveEvent(event.type(), handled);
     } else
         process()->send(Messages::WebPage::KeyEvent(event), m_pageID);
+#endif
 }
 
 #if ENABLE(GESTURE_EVENTS)
@@ -1184,10 +1206,27 @@ void WebPageProxy::handleGestureEvent(const WebGestureEvent& event)
     if (!isValid())
         return;
 
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+    if (!isWaitingForJavaScriptPopupReply()) {
+        m_gestureEventQueue.append(event);
+
+        process()->responsivenessTimer()->start();
+        process()->send(Messages::EventDispatcher::GestureEvent(m_pageID, event), 0);
+    } else {
+        if (m_gestureEventQueue.isEmpty()) {
+            bool isEventHandled = false;
+            m_pageClient->doneWithGestureEvent(event, handled);
+        } else {
+            QueuedUIEvents<WebGestureEvent>& lastEvent = m_gestureEventQueue.last();
+            lastEvent.deferredEvents.append(event);
+        }
+    }
+#else
     m_gestureEventQueue.append(event);
 
     process()->responsivenessTimer()->start();
     process()->send(Messages::EventDispatcher::GestureEvent(m_pageID, event), 0);
+#endif
 }
 #endif
 
@@ -1207,7 +1246,11 @@ void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
     // If the page is suspended, which should be the case during panning, pinching
     // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
     // we do not send any of the events to the page even if is has listeners.
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+    if (m_needTouchEvents && !m_isPageSuspended && !isWaitingForJavaScriptPopupReply()) {
+#else
     if (m_needTouchEvents && !m_isPageSuspended) {
+#endif
 #if OS(TIZEN)
         // Do not send the TouchMove event if last TouchMove is not processed yet.
         // TouchMove event will be sent too many times without below codes,
@@ -1232,8 +1275,13 @@ void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
         } else {
             // We attach the incoming events to the newest queued event so that all
             // the events are delivered in the correct order when the event is dequed.
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+            QueuedUIEvents<NativeWebTouchEvent>& lastEvent = m_touchEventQueue.last();
+            lastEvent.deferredEvents.append(event);
+#else
             QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
             lastEvent.deferredTouchEvents.append(event);
+#endif
         }
     }
 }
@@ -2468,6 +2516,13 @@ void WebPageProxy::closePage(bool stopResponsivenessTimer)
     m_uiClient.close(this);
 }
 
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+bool WebPageProxy::isWaitingForJavaScriptPopupReply()
+{
+    return m_alertReply || m_confirmReply || m_promptReply;
+}
+#endif
+
 #if OS(TIZEN)
 void WebPageProxy::runJavaScriptAlert(uint64_t frameID, const String& message, PassRefPtr<Messages::WebPageProxy::RunJavaScriptAlert::DelayedReply> reply)
 {
@@ -3440,11 +3495,23 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
     case WebEvent::GestureScrollBegin:
     case WebEvent::GestureScrollEnd:
     case WebEvent::GestureSingleTap: {
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+        QueuedUIEvents<WebGestureEvent> queuedEvents = m_gestureEventQueue.first();
+        MESSAGE_CHECK(type == queuedEvents.forwardedEvent.type());
+        m_gestureEventQueue.removeFirst();
+
+        m_pageClient->doneWithGestureEvent(queuedEvents.forwardedEvent, handled);
+        for (size_t i = 0; i < queuedEvents.deferredEvents.size(); ++i) {
+            bool isEventHandled = false;
+            m_pageClient->doneWithGuestureEvent(queuedEvents.deferredEvents.at(i), isEventHandled);
+        }
+#else
         WebGestureEvent event = m_gestureEventQueue.first();
         MESSAGE_CHECK(type == event.type());
 
         m_gestureEventQueue.removeFirst();
         m_pageClient->doneWithGestureEvent(event, handled);
+#endif
         break;
     }
 #endif
@@ -3472,6 +3539,27 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
     case WebEvent::Char: {
         LOG(KeyHandling, "WebPageProxy::didReceiveEvent: %s", webKeyboardEventTypeString(type));
 
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+        QueuedUIEvents<NativeWebKeyboardEvent> queuedEvents = m_keyEventQueue.first();
+        MESSAGE_CHECK(type == queuedEvents.forwardedEvent.type());
+        m_keyEventQueue.removeFirst();
+
+        m_pageClient->doneWithKeyEvent(queuedEvents.forwardedEvent, handled);
+
+        if (!handled) {
+            if (m_uiClient.implementsDidNotHandleKeyEvent())
+                m_uiClient.didNotHandleKeyEvent(this, queuedEvents.forwardedEvent);
+#if PLATFORM(WIN)
+            else
+                ::TranslateMessage(queuedEvents.forwardedEvent.nativeEvent());
+#endif
+        }
+
+        for (size_t i = 0; i < queuedEvents.deferredEvents.size(); ++i) {
+            bool isEventHandled = false;
+            m_pageClient->doneWithKeyEvent(queuedEvents.deferredEvents.at(i), isEventHandled);
+        }
+#else
         NativeWebKeyboardEvent event = m_keyEventQueue.first();
         MESSAGE_CHECK(type == event.type());
 
@@ -3488,6 +3576,7 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
         else
             ::TranslateMessage(event.nativeEvent());
 #endif
+#endif // #if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
         break;
     }
 #if ENABLE(TOUCH_EVENTS)
@@ -3495,6 +3584,17 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
     case WebEvent::TouchMove:
     case WebEvent::TouchEnd:
     case WebEvent::TouchCancel: {
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+        QueuedUIEvents<NativeWebTouchEvent> queuedEvents = m_touchEventQueue.first();
+        MESSAGE_CHECK(type == queuedEvents.forwardedEvent.type());
+        m_touchEventQueue.removeFirst();
+
+        m_pageClient->doneWithTouchEvent(queuedEvents.forwardedEvent, handled);
+        for (size_t i = 0; i < queuedEvents.deferredEvents.size(); ++i) {
+            bool isEventHandled = false;
+            m_pageClient->doneWithTouchEvent(queuedEvents.deferredEvents.at(i), isEventHandled);
+        }
+#else
         QueuedTouchEvents queuedEvents = m_touchEventQueue.first();
         MESSAGE_CHECK(type == queuedEvents.forwardedEvent.type());
         m_touchEventQueue.removeFirst();
@@ -3504,6 +3604,7 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
             bool isEventHandled = false;
             m_pageClient->doneWithTouchEvent(queuedEvents.deferredTouchEvents.at(i), isEventHandled);
         }
+#endif
         break;
     }
 #endif
index 700104a..f377a15 100755 (executable)
@@ -35,6 +35,9 @@
 #if ENABLE(TOUCH_EVENTS)
 #include "NativeWebTouchEvent.h"
 #endif
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+#include "NativeWebKeyboardEvent.h"
+#endif
 #if PLATFORM(QT)
 #include "QtNetworkRequestData.h"
 #endif
@@ -134,7 +137,9 @@ class WKView;
 
 namespace WebKit {
 
+#if !ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
 class NativeWebKeyboardEvent;
+#endif
 class NativeWebMouseEvent;
 class NativeWebWheelEvent;
 class PageClient;
@@ -183,6 +188,17 @@ typedef GenericCallback<WKUInt32Ref> WebStorageQuotaCallback;
 typedef GenericCallback<WKErrorRef> PrintFinishedCallback;
 #endif
 
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+template<typename T>
+struct QueuedUIEvents {
+    QueuedUIEvents(const T& event)
+        : forwardedEvent(event)
+    {
+    }
+    T forwardedEvent;
+    Vector<T> deferredEvents;
+};
+#else
 #if ENABLE(TOUCH_EVENTS)
 struct QueuedTouchEvents {
     QueuedTouchEvents(const NativeWebTouchEvent& event)
@@ -193,6 +209,7 @@ struct QueuedTouchEvents {
     Vector<NativeWebTouchEvent> deferredTouchEvents;
 };
 #endif
+#endif
 
 // FIXME: Make a version of CallbackBase with three arguments, and define ValidateCommandCallback as a specialization.
 class ValidateCommandCallback : public CallbackBase {
@@ -1202,6 +1219,10 @@ private:
     void decidePolicyForCertificateError(bool isTrusted, const String& url, const String& certificate, int error, bool& canContinue);
 #endif
 
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+    bool isWaitingForJavaScriptPopupReply();
+#endif
+
     PageClient* m_pageClient;
     WebLoaderClient m_loaderClient;
     WebPolicyClient m_policyClient;
@@ -1332,10 +1353,17 @@ private:
     WebCore::PolicyAction m_syncNavigationActionPolicyAction;
     uint64_t m_syncNavigationActionPolicyDownloadID;
 
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+#if ENABLE(GESTURE_EVENTS)
+    Deque<QueuedUIEvents<WebGestureEvent> > m_gestureEventQueue;
+#endif
+    Deque<QueuedUIEvents<NativeWebKeyboardEvent> > m_keyEventQueue;
+#else
 #if ENABLE(GESTURE_EVENTS)
     Deque<WebGestureEvent> m_gestureEventQueue;
 #endif
     Deque<NativeWebKeyboardEvent> m_keyEventQueue;
+#endif
     Deque<NativeWebWheelEvent> m_wheelEventQueue;
     Deque<OwnPtr<Vector<NativeWebWheelEvent> > > m_currentlyProcessedWheelEvents;
 
@@ -1345,8 +1373,12 @@ private:
 
 #if ENABLE(TOUCH_EVENTS)
     bool m_needTouchEvents;
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+    Deque<QueuedUIEvents<NativeWebTouchEvent> > m_touchEventQueue;
+#else
     Deque<QueuedTouchEvents> m_touchEventQueue;
 #endif
+#endif
 #if ENABLE(INPUT_TYPE_COLOR)
     RefPtr<WebColorChooserProxy> m_colorChooser;
 #endif
index 273bdb6..62e8393 100755 (executable)
@@ -268,7 +268,11 @@ void WebPageProxy::handleInputMethodKeydown(bool& handled)
     static_cast<PageClientImpl*>(m_pageClient)->handleInputMethodKeydown();
 
 #if ENABLE(TIZEN_ISF_PORT)
+#if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
+    NativeWebKeyboardEvent event = m_keyEventQueue.first().forwardedEvent;
+#else
     NativeWebKeyboardEvent event = m_keyEventQueue.first();
+#endif
     handled = event.isFiltered();
 #endif
 }