1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.content_public.browser.test;
6 
7 import android.os.Handler;
8 
9 import org.chromium.base.annotations.CalledByNative;
10 import org.chromium.base.annotations.JNINamespace;
11 import org.chromium.base.test.util.LooperUtils;
12 
13 import java.lang.reflect.InvocationTargetException;
14 
15 /**
16  * Handles processing messages in nested run loops.
17  *
18  * Android does not support nested run loops by default. While running
19  * in nested mode, we use reflection to retreive messages from the MessageQueue
20  * and dispatch them.
21  */
22 @JNINamespace("content")
23 public class NestedSystemMessageHandler {
24     private static final int QUIT_MESSAGE = 10;
25     private static final Handler sHandler = new Handler();
26 
NestedSystemMessageHandler()27     private NestedSystemMessageHandler() {}
28 
29     /**
30      * Dispatches the first message from the current MessageQueue, blocking
31      * until a task becomes available if the queue is empty. Callbacks for
32      * other event handlers registered to the thread's looper (e.g.,
33      * MessagePumpAndroid) may also be processed as a side-effect.
34      *
35      * Returns true if task dispatching succeeded, or false if an exception was
36      * thrown.
37      */
38     @SuppressWarnings("unused")
39     @CalledByNative
dispatchOneMessage()40     private static boolean dispatchOneMessage() {
41         try {
42             LooperUtils.runSingleNestedLooperTask();
43         } catch (IllegalArgumentException | IllegalAccessException | SecurityException
44                 | InvocationTargetException e) {
45             e.printStackTrace();
46             return false;
47         }
48         return true;
49     }
50 
51     /*
52      * Causes a previous call to dispatchOneMessage() to stop blocking and
53      * return.
54      */
55     @SuppressWarnings("unused")
56     @CalledByNative
postQuitMessage()57     private static void postQuitMessage() {
58         // Causes MessageQueue.next() to return in case it was blocking waiting
59         // for more messages.
60         sHandler.sendMessage(sHandler.obtainMessage(QUIT_MESSAGE));
61     }
62 }
63