- add sources.
[platform/framework/web/crosswalk.git] / src / content / public / test / android / javatests / src / org / chromium / content / browser / test / NestedSystemMessageHandler.java
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.browser.test;
6
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;
12
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;
18
19 /**
20  * Handles processing messages in nested run loops.
21  *
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
24  * and dispatch them.
25  */
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();
32
33     private NestedSystemMessageHandler() {
34     }
35
36     /**
37      * Processes messages from the current MessageQueue till the queue becomes idle.
38      */
39     @SuppressWarnings("unused")
40     @CalledByNative
41     private boolean runNestedLoopTillIdle() {
42         boolean quitLoop = false;
43
44         MessageQueue queue = Looper.myQueue();
45         queue.addIdleHandler(new MessageQueue.IdleHandler() {
46             @Override
47             public boolean queueIdle() {
48                 mHandler.sendMessage(mHandler.obtainMessage(QUIT_MESSAGE));
49                 return false;
50             }
51         });
52
53         Class<?> messageQueueClazz = queue.getClass();
54         Method nextMethod = null;
55         try {
56             nextMethod = messageQueueClazz.getDeclaredMethod("next");
57         } catch (SecurityException e) {
58             e.printStackTrace();
59             return false;
60         } catch (NoSuchMethodException e) {
61             e.printStackTrace();
62             return false;
63         }
64         nextMethod.setAccessible(true);
65
66         while (!quitLoop) {
67             Message msg = null;
68             try {
69                 msg = (Message)nextMethod.invoke(queue);
70             } catch (IllegalArgumentException e) {
71                 e.printStackTrace();
72                 return false;
73             } catch (IllegalAccessException e) {
74                 e.printStackTrace();
75                 return false;
76             } catch (InvocationTargetException e) {
77                 e.printStackTrace();
78                 return false;
79             }
80
81             if (msg != null) {
82                 if (msg.what == QUIT_MESSAGE) {
83                     quitLoop = true;
84                 }
85                 Class messageClazz = msg.getClass();
86                 Field targetFiled = null;
87                 try {
88                     targetFiled = messageClazz.getDeclaredField("target");
89                 } catch (SecurityException e) {
90                     e.printStackTrace();
91                     return false;
92                 } catch (NoSuchFieldException e) {
93                     e.printStackTrace();
94                     return false;
95                 }
96                 targetFiled.setAccessible(true);
97
98                 Handler target = null;
99                 try {
100                     target = (Handler) targetFiled.get(msg);
101                 } catch (IllegalArgumentException e) {
102                     e.printStackTrace();
103                     return false;
104                 } catch (IllegalAccessException e) {
105                     e.printStackTrace();
106                     return false;
107                 }
108
109                 if (target == null) {
110                     // No target is a magic identifier for the quit message.
111                     quitLoop = true;
112                 }
113
114                 target.dispatchMessage(msg);
115                 msg.recycle();
116             } else {
117                 quitLoop = true;
118             }
119         }
120         return true;
121     }
122
123     @SuppressWarnings("unused")
124     @CalledByNative
125     private static NestedSystemMessageHandler create() {
126         return new NestedSystemMessageHandler();
127     }
128 }