18
18
import java .util .List ;
19
19
import java .util .Queue ;
20
20
import java .util .concurrent .LinkedBlockingQueue ;
21
+ import java .util .concurrent .atomic .AtomicBoolean ;
21
22
22
23
import fi .iki .elonen .NanoHTTPD ;
23
24
import fi .iki .elonen .NanoWSD ;
@@ -26,23 +27,32 @@ class AndroidJsV8Inspector {
26
27
private static boolean DEBUG_LOG_ENABLED = false ;
27
28
28
29
private JsV8InspectorServer server ;
29
- private Context context ;
30
- private static String applicationDir ;
30
+ private static String ApplicationDir ;
31
+ private String packageName ;
31
32
32
33
protected native final void init ();
33
34
34
35
protected native final void connect (Object connection );
35
36
37
+ private native void scheduleBreak ();
38
+
36
39
protected static native void disconnect ();
37
40
38
41
protected native final void dispatchMessage (String message );
39
42
40
43
private Handler mainHandler ;
44
+
45
+ private final Object debugBrkLock ;
46
+
47
+ private static AtomicBoolean DebugInitialized = new AtomicBoolean (false );
48
+
41
49
private LinkedBlockingQueue <String > inspectorMessages = new LinkedBlockingQueue <String >();
50
+ private LinkedBlockingQueue <String > pendingInspectorMessages = new LinkedBlockingQueue <String >();
42
51
43
- AndroidJsV8Inspector (Context context , Logger logger ) {
44
- this .context = context ;
45
- applicationDir = context .getFilesDir ().getAbsolutePath ();
52
+ AndroidJsV8Inspector (String filesDir , String packageName ) {
53
+ ApplicationDir = filesDir ;
54
+ this .packageName = packageName ;
55
+ this .debugBrkLock = new Object ();
46
56
}
47
57
48
58
public void start () throws IOException {
@@ -51,7 +61,7 @@ public void start() throws IOException {
51
61
52
62
mainHandler = currentRuntime .getHandler ();
53
63
54
- this .server = new JsV8InspectorServer (this .context . getPackageName () + "-inspectorServer" );
64
+ this .server = new JsV8InspectorServer (this .packageName + "-inspectorServer" );
55
65
this .server .start (-1 );
56
66
57
67
if (DEBUG_LOG_ENABLED ) {
@@ -82,9 +92,7 @@ private static void sendToDevToolsConsole(Object connection, String message, Str
82
92
String sendingText = consoleMessage .toString ();
83
93
AndroidJsV8Inspector .send (connection , sendingText );
84
94
85
- } catch (JSONException e ) {
86
- e .printStackTrace ();
87
- } catch (IOException e ) {
95
+ } catch (JSONException | IOException e ) {
88
96
e .printStackTrace ();
89
97
}
90
98
}
@@ -102,11 +110,11 @@ private static String getInspectorMessage(Object connection) {
102
110
@ RuntimeCallable
103
111
public static Pair <String , String >[] getPageResources () {
104
112
// necessary to align the data dir returned by context (emulator) and that used by the v8 inspector
105
- if (applicationDir .startsWith ("/data/user/0/" )) {
106
- applicationDir = applicationDir .replaceFirst ("/data/user/0/" , "/data/data/" );
113
+ if (ApplicationDir .startsWith ("/data/user/0/" )) {
114
+ ApplicationDir = ApplicationDir .replaceFirst ("/data/user/0/" , "/data/data/" );
107
115
}
108
116
109
- String dataDir = applicationDir ;
117
+ String dataDir = ApplicationDir ;
110
118
File rootFilesDir = new File (dataDir , "app" );
111
119
112
120
@@ -168,8 +176,41 @@ private static String getMimeType(String url) {
168
176
return type ;
169
177
}
170
178
171
- class JsV8InspectorServer extends NanoWSD {
172
- public JsV8InspectorServer (String name ) {
179
+ // pause the main thread for 30 seconds (30 * 1000 ms)
180
+ // allowing the devtools frontend to establish connection with the inspector
181
+ protected void waitForDebugger (boolean shouldBreak ) {
182
+ if (shouldBreak ) {
183
+ synchronized (this .debugBrkLock ) {
184
+ try {
185
+ this .debugBrkLock .wait (1000 * 30 );
186
+ } catch (InterruptedException e ) {
187
+ e .printStackTrace ();
188
+ } finally {
189
+ AndroidJsV8Inspector .DebugInitialized .getAndSet (true );
190
+ this .processDebugBreak ();
191
+ }
192
+ }
193
+ } else {
194
+ AndroidJsV8Inspector .DebugInitialized .getAndSet (true );
195
+ }
196
+ }
197
+
198
+ // process all messages coming front the frontend necessary to initialize the inspector backend
199
+ // schedule a debug line break at first convenience
200
+ private void processDebugBreak () {
201
+ processDebugBreakMessages ();
202
+ scheduleBreak ();
203
+ }
204
+
205
+ private void processDebugBreakMessages () {
206
+ while (!pendingInspectorMessages .isEmpty ()) {
207
+ String inspectorMessage = pendingInspectorMessages .poll ();
208
+ dispatchMessage (inspectorMessage );
209
+ }
210
+ }
211
+
212
+ private class JsV8InspectorServer extends NanoWSD {
213
+ JsV8InspectorServer (String name ) {
173
214
super (name );
174
215
}
175
216
@@ -187,9 +228,8 @@ protected WebSocket openWebSocket(IHTTPSession handshake) {
187
228
}
188
229
}
189
230
190
- class JsV8InspectorWebSocket extends NanoWSD .WebSocket {
191
-
192
- public JsV8InspectorWebSocket (NanoHTTPD .IHTTPSession handshakeRequest ) {
231
+ private class JsV8InspectorWebSocket extends NanoWSD .WebSocket {
232
+ JsV8InspectorWebSocket (NanoHTTPD .IHTTPSession handshakeRequest ) {
193
233
super (handshakeRequest );
194
234
}
195
235
@@ -199,16 +239,7 @@ protected void onOpen() {
199
239
Log .d ("V8Inspector" , "onOpen: ThreadID: " + Thread .currentThread ().getId ());
200
240
}
201
241
202
- mainHandler .post (new Runnable () {
203
- @ Override
204
- public void run () {
205
- if (DEBUG_LOG_ENABLED ) {
206
- Log .d ("V8Inspector" , "Connecting. threadID : " + Thread .currentThread ().getId ());
207
- }
208
-
209
- connect (JsV8InspectorWebSocket .this );
210
- }
211
- });
242
+ connect (JsV8InspectorWebSocket .this );
212
243
}
213
244
214
245
@ Override
@@ -236,16 +267,30 @@ protected void onMessage(final NanoWSD.WebSocketFrame message) {
236
267
237
268
inspectorMessages .offer (message .getTextPayload ());
238
269
239
- mainHandler .post (new Runnable () {
240
- @ Override
241
- public void run () {
242
- String nextMessage = inspectorMessages .poll ();
243
- while (nextMessage != null ) {
244
- dispatchMessage (nextMessage );
245
- nextMessage = inspectorMessages .poll ();
270
+ if (!AndroidJsV8Inspector .DebugInitialized .get ()) {
271
+ String nextMessage = inspectorMessages .poll ();
272
+ while (nextMessage != null ) {
273
+ pendingInspectorMessages .offer (nextMessage );
274
+ nextMessage = inspectorMessages .poll ();
275
+ }
276
+
277
+ if (message .getTextPayload ().contains ("Debugger.enable" )) {
278
+ synchronized (debugBrkLock ) {
279
+ debugBrkLock .notify ();
246
280
}
247
281
}
248
- });
282
+ } else {
283
+ mainHandler .postAtFrontOfQueue (new Runnable () {
284
+ @ Override
285
+ public void run () {
286
+ String nextMessage = inspectorMessages .poll ();
287
+ while (nextMessage != null ) {
288
+ dispatchMessage (nextMessage );
289
+ nextMessage = inspectorMessages .poll ();
290
+ }
291
+ }
292
+ });
293
+ }
249
294
}
250
295
251
296
@ Override
@@ -259,8 +304,7 @@ public void send(String payload) throws IOException {
259
304
260
305
public String getInspectorMessage () {
261
306
try {
262
- String message = inspectorMessages .take ();
263
- return message ;
307
+ return inspectorMessages .take ();
264
308
} catch (InterruptedException e ) {
265
309
e .printStackTrace ();
266
310
}
0 commit comments