Allow launching inspector from dev menu

Reviewed By: davidaurelio

Differential Revision: D4095356

fbshipit-source-id: 46e43578cdcd663316efb82dffde27b77294c5c0
This commit is contained in:
Alexander Blom 2016-11-15 08:55:39 -08:00 committed by Facebook Github Bot
parent 18184a83f1
commit f571d28e68
7 changed files with 102 additions and 26 deletions

View File

@ -19,6 +19,16 @@ public class Inspector {
private final HybridData mHybridData;
public static boolean isSupported() {
try {
// This isn't a very nice way to do this but it works :|
instance().getPagesNative();
return true;
} catch (UnsatisfiedLinkError e) {
return false;
}
}
public static List<Page> getPages() {
try {
return Arrays.asList(instance().getPagesNative());

View File

@ -162,6 +162,12 @@ public class DevServerHelper {
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void openInspector(String id) {
if (mInspectorPackagerConnection != null) {
mInspectorPackagerConnection.sendOpenEvent(id);
}
}
public void closeInspectorConnection() {
new AsyncTask<Void, Void, Void>() {
@Override

View File

@ -42,6 +42,7 @@ import com.facebook.infer.annotation.Assertions;
import com.facebook.react.R;
import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.DefaultNativeModuleCallExceptionHandler;
import com.facebook.react.bridge.Inspector;
import com.facebook.react.bridge.JavaJSExecutor;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray;
@ -358,6 +359,19 @@ public class DevSupportManagerImpl implements DevSupportManager, PackagerCommand
handleReloadJS();
}
});
if (Inspector.isSupported()) {
options.put(
"Debug JS on-device (experimental)", new DevOptionHandler() {
@Override
public void onOptionSelected() {
List<Inspector.Page> pages = Inspector.getPages();
if (pages.size() > 0) {
// TODO: We should get the actual page id instead of the first one.
mDevServerHelper.openInspector(String.valueOf(pages.get(0).getId()));
}
}
});
}
options.put(
mDevSettings.isReloadOnJSChangeEnabled()
? mApplicationContext.getString(R.string.catalyst_live_reload_off)

View File

@ -48,6 +48,15 @@ public class InspectorPackagerConnection {
mConnection.close();
}
public void sendOpenEvent(String pageId) {
try {
JSONObject payload = makePageIdPayload(pageId);
sendEvent("open", payload);
} catch (JSONException | IOException e) {
FLog.e(TAG, "Failed to open page", e);
}
}
void handleProxyMessage(JSONObject message)
throws JSONException, IOException {
String event = message.getString("event");

View File

@ -8,31 +8,16 @@
*/
'use strict';
var child_process = require('child_process');
var execFile = require('child_process').execFile;
var fs = require('fs');
var opn = require('opn');
var path = require('path');
function getChromeAppName() {
switch (process.platform) {
case 'darwin':
return 'google chrome';
case 'win32':
return 'chrome';
default:
return 'google-chrome';
}
}
const child_process = require('child_process');
const execFile = require('child_process').execFile;
const fs = require('fs');
const path = require('path');
const launchChrome = require('../util/launchChrome');
function launchChromeDevTools(port) {
var debuggerURL = 'http://localhost:' + port + '/debugger-ui';
console.log('Launching Dev Tools...');
opn(debuggerURL, {app: [getChromeAppName()]}, function(err) {
if (err) {
console.error('Google Chrome exited with error:', err);
}
});
launchChrome(debuggerURL);
}
function escapePath(path) {
@ -77,7 +62,7 @@ module.exports = function(options, isChromeConnected) {
// TODO: Remove this case in the future
console.log(
'The method /launch-chrome-devtools is deprecated. You are ' +
' probably using an application created with an older CLI with the ' +
' probably using an application created with an older CLI with the ' +
' packager of a newer CLI. Please upgrade your application: ' +
'https://facebook.github.io/react-native/docs/upgrading.html');
launchDevTools(options, isChromeConnected);

View File

@ -46,6 +46,7 @@ const parseUrl = require('url').parse;
const WebSocket = require('ws');
const debug = require('debug')('ReactNativePackager:InspectorProxy');
const launchChrome = require('./launchChrome');
type DevicePage = {
id: string,
@ -80,6 +81,10 @@ type DisconnectEvent = Message<'disconnect', {
pageId?: string,
}>;
type OpenEvent = Message<'open', {
pageId?: string,
}>;
type GetPages = Message<'getPages', ?Array<DevicePage>>;
type Event = WrappedEvent | ConnectEvent | DisconnectEvent | GetPages;
@ -178,6 +183,8 @@ class Device {
this._handleWrappedEvent(message);
} else if (message.event === 'disconnect') {
this._handleDisconnect(message);
} else if (message.event === 'open') {
this._handleOpen(message);
}
}
@ -197,6 +204,13 @@ class Device {
this._removeConnection(pageId);
}
_handleOpen(event: OpenEvent) {
const payload = nullthrows(event.payload);
const pageId = nullthrows(payload.pageId);
const url = DEVTOOLS_URL_BASE + makeInspectorPageUrl(this._id, pageId);
launchChrome(url);
}
_removeConnection(pageId: string) {
const socket = this._connections.get(pageId);
if (socket) {
@ -229,10 +243,7 @@ class InspectorProxy {
}
_makePage(server: Address, deviceId: string, deviceName: string, devicePage: DevicePage): Page {
// The inspector frontend doesn't handle urlencoded params so we
// manually urlencode it and decode it on the other side in _createPageHandler
const query = querystring.escape(`device=${deviceId}&page=${devicePage.id}`);
const wsUrl = `localhost:${server.port}/inspector/page?${query}`;
const wsUrl = makeInspectorPageUrl(deviceId, devicePage.id);
return {
id: `${deviceId}-${devicePage.id}`,
title: devicePage.title,
@ -393,6 +404,13 @@ function escapeHtmlSpecialChar(char: string): string {
);
}
function makeInspectorPageUrl(deviceId: string, pageId: string): string {
// The inspector frontend doesn't handle urlencoded params so we
// manually urlencode it and decode it on the other side in _createPageHandler
const query = querystring.escape(`device=${deviceId}&page=${pageId}`);
return `localhost:8081/inspector/page?${query}`;
}
function attachToServer(server: http.Server, pathPrefix: string): InspectorProxy {
const proxy = new InspectorProxy();
proxy.attachToServer(server, pathPrefix);

View File

@ -0,0 +1,34 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
*/
'use strict';
const opn = require('opn');
function getChromeAppName(): string {
switch (process.platform) {
case 'darwin':
return 'google chrome';
case 'win32':
return 'chrome';
default:
return 'google-chrome';
}
}
function launchChrome(url: string) {
opn(url, {app: [getChromeAppName()]}, function(err) {
if (err) {
console.error('Google Chrome exited with error:', err);
}
});
}
module.exports = launchChrome;