Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 00d5bf7e authored by John Reck's avatar John Reck
Browse files

Fixup handling destroy

 Bug: 5002925
 White list certain messages that can be handled after WebViewCore
 was destroyed (specificially pause/resumeTimers, which are per process)
 and reject all other messages. This avoids using the undocumented
 removeCallbacksAndMessages(null) trick, as well as makes sure PAUSE_TIMERS
 and RESUME_TIMERS are processed in the correct order the correct number
 of times.

Change-Id: I8c51172e015f923ffeb0816a8ee2ab63219d0f96
parent caed51bc
Loading
Loading
Loading
Loading
+24 −24
Original line number Original line Diff line number Diff line
@@ -1069,6 +1069,15 @@ public final class WebViewCore {
                                + " arg1=" + msg.arg1 + " arg2=" + msg.arg2
                                + " arg1=" + msg.arg1 + " arg2=" + msg.arg2
                                + " obj=" + msg.obj);
                                + " obj=" + msg.obj);
                    }
                    }
                    if (mWebView == null
                            && msg.what != EventHub.RESUME_TIMERS
                            && msg.what != EventHub.PAUSE_TIMERS) {
                        if (DebugFlags.WEB_VIEW_CORE) {
                            Log.v(LOGTAG, "Rejecting message " + msg.what
                                    + " because we are destroyed");
                        }
                        return;
                    }
                    switch (msg.what) {
                    switch (msg.what) {
                        case WEBKIT_DRAW:
                        case WEBKIT_DRAW:
                            webkitDraw();
                            webkitDraw();
@@ -1757,30 +1766,17 @@ public final class WebViewCore {
    }
    }


    /**
    /**
     * Removes pending messages and trigger a DESTROY message to send to
     * Sends a DESTROY message to WebCore.
     * WebCore.
     * Called from UI thread.
     * Called from UI thread.
     */
     */
    void destroy() {
    void destroy() {
        // We don't want anyone to post a message between removing pending
        // messages and sending the destroy message.
        synchronized (mEventHub) {
        synchronized (mEventHub) {
            // RESUME_TIMERS and PAUSE_TIMERS are per process base. They need to
            // Do not call removeMessages as then we risk removing PAUSE_TIMERS
            // be preserved even the WebView is destroyed.
            // or RESUME_TIMERS messages, which we must still handle as they
            // Note: we should not have more than one RESUME_TIMERS/PAUSE_TIMERS
            // are per process. DESTROY will instead trigger a white list in
            boolean hasResume = mEventHub.hasMessages(EventHub.RESUME_TIMERS);
            // mEventHub, skipping any remaining messages in the queue
            boolean hasPause = mEventHub.hasMessages(EventHub.PAUSE_TIMERS);
            mEventHub.removeMessages();
            mEventHub.sendMessageAtFrontOfQueue(
            mEventHub.sendMessageAtFrontOfQueue(
                    Message.obtain(null, EventHub.DESTROY));
                    Message.obtain(null, EventHub.DESTROY));
            if (hasPause) {
                mEventHub.sendMessageAtFrontOfQueue(
                        Message.obtain(null, EventHub.PAUSE_TIMERS));
            }
            if (hasResume) {
                mEventHub.sendMessageAtFrontOfQueue(
                        Message.obtain(null, EventHub.RESUME_TIMERS));
            }
            mEventHub.blockMessages();
            mEventHub.blockMessages();
        }
        }
    }
    }
@@ -2113,13 +2109,17 @@ public final class WebViewCore {


    // called from JNI or WebView thread
    // called from JNI or WebView thread
    /* package */ void contentDraw() {
    /* package */ void contentDraw() {
        synchronized (this) {
            if (mWebView == null || mBrowserFrame == null) {
                // We were destroyed
                return;
            }
            // don't update the Picture until we have an initial width and finish
            // don't update the Picture until we have an initial width and finish
            // the first layout
            // the first layout
            if (mCurrentViewWidth == 0 || !mBrowserFrame.firstLayoutDone()) {
            if (mCurrentViewWidth == 0 || !mBrowserFrame.firstLayoutDone()) {
                return;
                return;
            }
            }
            // only fire an event if this is our first request
            // only fire an event if this is our first request
        synchronized (this) {
            if (mDrawIsScheduled) return;
            if (mDrawIsScheduled) return;
            mDrawIsScheduled = true;
            mDrawIsScheduled = true;
            if (mDrawIsPaused) return;
            if (mDrawIsPaused) return;