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.
5 package org.chromium.content.browser.test;
7 import android.os.Handler;
8 import android.os.Looper;
9 import android.os.Message;
10 import android.os.MessageQueue;
11 import android.util.Log;
13 import org.chromium.base.CalledByNative;
14 import org.chromium.base.JNINamespace;
15 import java.lang.reflect.Method;
16 import java.lang.reflect.Field;
17 import java.lang.reflect.InvocationTargetException;
20 * Handles processing messages in nested run loops.
22 * Android does not support nested message loops by default. While running
23 * in nested mode, we use reflection to retreive messages from the MessageQueue
26 @JNINamespace("content")
27 class NestedSystemMessageHandler {
28 // See org.chromium.base.SystemMessageHandler for more message ids.
29 // The id here should not conflict with the ones in SystemMessageHandler.
30 private static final int QUIT_MESSAGE = 10;
31 private static final Handler mHandler = new Handler();
33 private NestedSystemMessageHandler() {
37 * Processes messages from the current MessageQueue till the queue becomes idle.
39 @SuppressWarnings("unused")
41 private boolean runNestedLoopTillIdle() {
42 boolean quitLoop = false;
44 MessageQueue queue = Looper.myQueue();
45 queue.addIdleHandler(new MessageQueue.IdleHandler() {
47 public boolean queueIdle() {
48 mHandler.sendMessage(mHandler.obtainMessage(QUIT_MESSAGE));
53 Class<?> messageQueueClazz = queue.getClass();
54 Method nextMethod = null;
56 nextMethod = messageQueueClazz.getDeclaredMethod("next");
57 } catch (SecurityException e) {
60 } catch (NoSuchMethodException e) {
64 nextMethod.setAccessible(true);
69 msg = (Message)nextMethod.invoke(queue);
70 } catch (IllegalArgumentException e) {
73 } catch (IllegalAccessException e) {
76 } catch (InvocationTargetException e) {
82 if (msg.what == QUIT_MESSAGE) {
85 Class messageClazz = msg.getClass();
86 Field targetFiled = null;
88 targetFiled = messageClazz.getDeclaredField("target");
89 } catch (SecurityException e) {
92 } catch (NoSuchFieldException e) {
96 targetFiled.setAccessible(true);
98 Handler target = null;
100 target = (Handler) targetFiled.get(msg);
101 } catch (IllegalArgumentException e) {
104 } catch (IllegalAccessException e) {
109 if (target == null) {
110 // No target is a magic identifier for the quit message.
114 target.dispatchMessage(msg);
123 @SuppressWarnings("unused")
125 private static NestedSystemMessageHandler create() {
126 return new NestedSystemMessageHandler();