diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java index ce9ea690e..bfd8d0403 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java @@ -17,6 +17,7 @@ import android.preference.PreferenceManager; import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.react.modules.debug.interfaces.DeveloperSettings; +import com.facebook.react.packagerconnection.PackagerConnectionSettings; /** * Helper class for accessing developers settings that should not be accessed outside of the package @@ -31,7 +32,6 @@ public class DevInternalSettings implements private static final String PREFS_FPS_DEBUG_KEY = "fps_debug"; private static final String PREFS_JS_DEV_MODE_DEBUG_KEY = "js_dev_mode_debug"; private static final String PREFS_JS_MINIFY_DEBUG_KEY = "js_minify_debug"; - private static final String PREFS_DEBUG_SERVER_HOST_KEY = "debug_http_host"; private static final String PREFS_ANIMATIONS_DEBUG_KEY = "animations_debug"; private static final String PREFS_RELOAD_ON_JS_CHANGE_KEY = "reload_on_js_change"; private static final String PREFS_INSPECTOR_DEBUG_KEY = "inspector_debug"; @@ -40,6 +40,7 @@ public class DevInternalSettings implements private final SharedPreferences mPreferences; private final Listener mListener; + private final PackagerConnectionSettings mPackagerConnectionSettings; public DevInternalSettings( Context applicationContext, @@ -47,6 +48,11 @@ public class DevInternalSettings implements mListener = listener; mPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext); mPreferences.registerOnSharedPreferenceChangeListener(this); + mPackagerConnectionSettings = new PackagerConnectionSettings(applicationContext); + } + + public PackagerConnectionSettings getPackagerConnectionSettings() { + return mPackagerConnectionSettings; } @Override @@ -73,10 +79,6 @@ public class DevInternalSettings implements return mPreferences.getBoolean(PREFS_JS_MINIFY_DEBUG_KEY, false); } - public @Nullable String getDebugServerHost() { - return mPreferences.getString(PREFS_DEBUG_SERVER_HOST_KEY, null); - } - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (mListener != null) { if (PREFS_FPS_DEBUG_KEY.equals(key) || diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java index 5c3750dfe..b102002d8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java @@ -73,7 +73,6 @@ public class DevServerHelper { private static final String ONCHANGE_ENDPOINT_URL_FORMAT = "http://%s/onchange"; private static final String WEBSOCKET_PROXY_URL_FORMAT = "ws://%s/debugger-proxy?role=client"; - private static final String PACKAGER_CONNECTION_URL_FORMAT = "ws://%s/message?role=android-rn-devserverhelper"; private static final String PACKAGER_STATUS_URL_FORMAT = "http://%s/status"; private static final String HEAP_CAPTURE_UPLOAD_URL_FORMAT = "http://%s/jscheapcaptureupload"; private static final String INSPECTOR_DEVICE_URL_FORMAT = "http://%s/inspector/device?name=%s"; @@ -152,7 +151,7 @@ public class DevServerHelper { }); handlers.putAll(new FileIoHandler().handlers()); - mPackagerClient = new JSPackagerClient(getPackagerConnectionURL(), handlers); + mPackagerClient = new JSPackagerClient("devserverhelper", mSettings.getPackagerConnectionSettings(), handlers); mPackagerClient.init(); return null; @@ -213,22 +212,18 @@ public class DevServerHelper { } public String getWebsocketProxyURL() { - return String.format(Locale.US, WEBSOCKET_PROXY_URL_FORMAT, getDebugServerHost()); - } - - private String getPackagerConnectionURL() { - return String.format(Locale.US, PACKAGER_CONNECTION_URL_FORMAT, getDebugServerHost()); + return String.format(Locale.US, WEBSOCKET_PROXY_URL_FORMAT, mSettings.getPackagerConnectionSettings().getDebugServerHost()); } public String getHeapCaptureUploadUrl() { - return String.format(Locale.US, HEAP_CAPTURE_UPLOAD_URL_FORMAT, getDebugServerHost()); + return String.format(Locale.US, HEAP_CAPTURE_UPLOAD_URL_FORMAT, mSettings.getPackagerConnectionSettings().getDebugServerHost()); } public String getInspectorDeviceUrl() { return String.format( Locale.US, INSPECTOR_DEVICE_URL_FORMAT, - getDebugServerHost(), + mSettings.getPackagerConnectionSettings().getDebugServerHost(), AndroidInfoHelpers.getFriendlyDeviceName()); } @@ -260,30 +255,6 @@ public class DevServerHelper { return mSettings.isHotModuleReplacementEnabled(); } - /** - * @return the host to use when connecting to the bundle server. - */ - private String getDebugServerHost() { - // Check debug server host setting first. If empty try to detect emulator type and use default - // hostname for those - String hostFromSettings = mSettings.getDebugServerHost(); - - if (!TextUtils.isEmpty(hostFromSettings)) { - return Assertions.assertNotNull(hostFromSettings); - } - - String host = AndroidInfoHelpers.getServerHost(); - - if (host.equals(AndroidInfoHelpers.DEVICE_LOCALHOST)) { - FLog.w( - ReactConstants.TAG, - "You seem to be running on device. Run 'adb reverse tcp:8081 tcp:8081' " + - "to forward the debug server's port to the device."); - } - - return host; - } - private static String createBundleURL(String host, String jsModulePath, boolean devMode, boolean hmr, boolean jsMinify) { return String.format(Locale.US, BUNDLE_URL_FORMAT, host, jsModulePath, devMode, hmr, jsMinify); } @@ -294,7 +265,7 @@ public class DevServerHelper { public String getDevServerBundleURL(final String jsModulePath) { return createBundleURL( - getDebugServerHost(), + mSettings.getPackagerConnectionSettings().getDebugServerHost(), jsModulePath, getDevMode(), getHMR(), @@ -438,7 +409,7 @@ public class DevServerHelper { } public void isPackagerRunning(final PackagerStatusCallback callback) { - String statusURL = createPackagerStatusURL(getDebugServerHost()); + String statusURL = createPackagerStatusURL(mSettings.getPackagerConnectionSettings().getDebugServerHost()); Request request = new Request.Builder() .url(statusURL) .build(); @@ -558,11 +529,11 @@ public class DevServerHelper { } private String createOnChangeEndpointUrl() { - return String.format(Locale.US, ONCHANGE_ENDPOINT_URL_FORMAT, getDebugServerHost()); + return String.format(Locale.US, ONCHANGE_ENDPOINT_URL_FORMAT, mSettings.getPackagerConnectionSettings().getDebugServerHost()); } private String createLaunchJSDevtoolsCommandUrl() { - return String.format(Locale.US, LAUNCH_JS_DEVTOOLS_COMMAND_URL_FORMAT, getDebugServerHost()); + return String.format(Locale.US, LAUNCH_JS_DEVTOOLS_COMMAND_URL_FORMAT, mSettings.getPackagerConnectionSettings().getDebugServerHost()); } public void launchJSDevtools() { @@ -584,11 +555,11 @@ public class DevServerHelper { } public String getSourceMapUrl(String mainModuleName) { - return String.format(Locale.US, SOURCE_MAP_URL_FORMAT, getDebugServerHost(), mainModuleName, getDevMode(), getHMR(), getJSMinifyMode()); + return String.format(Locale.US, SOURCE_MAP_URL_FORMAT, mSettings.getPackagerConnectionSettings().getDebugServerHost(), mainModuleName, getDevMode(), getHMR(), getJSMinifyMode()); } public String getSourceUrl(String mainModuleName) { - return String.format(Locale.US, BUNDLE_URL_FORMAT, getDebugServerHost(), mainModuleName, getDevMode(), getHMR(), getJSMinifyMode()); + return String.format(Locale.US, BUNDLE_URL_FORMAT, mSettings.getPackagerConnectionSettings().getDebugServerHost(), mainModuleName, getDevMode(), getHMR(), getJSMinifyMode()); } public String getJSBundleURLForRemoteDebugging(String mainModuleName) { @@ -607,7 +578,7 @@ public class DevServerHelper { public @Nullable File downloadBundleResourceFromUrlSync( final String resourcePath, final File outputFile) { - final String resourceURL = createResourceURL(getDebugServerHost(), resourcePath); + final String resourceURL = createResourceURL(mSettings.getPackagerConnectionSettings().getDebugServerHost(), resourcePath); final Request request = new Request.Builder() .url(resourceURL) .build(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/BUCK index cdbc287a7..9d59eff81 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/BUCK @@ -2,15 +2,33 @@ include_defs("//ReactAndroid/DEFS") android_library( name = "systeminfo", - srcs = glob(["**/*.java"]), + srcs = [ + "AndroidInfoModule.java", + ], + exported_deps = [ + ":systeminfo-moduleless", + ], visibility = [ "PUBLIC", ], deps = [ - react_native_dep("third-party/java/infer-annotations:infer-annotations"), react_native_dep("third-party/java/jsr-305:jsr-305"), react_native_target("java/com/facebook/react/bridge:bridge"), react_native_target("java/com/facebook/react/common:common"), react_native_target("java/com/facebook/react/module/annotations:annotations"), ], ) + +android_library( + name = "systeminfo-moduleless", + srcs = [ + "AndroidInfoHelpers.java", + ], + visibility = [ + "PUBLIC", + ], + deps = [ + react_native_dep("third-party/java/infer-annotations:infer-annotations"), + react_native_dep("third-party/java/jsr-305:jsr-305"), + ], +) diff --git a/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/BUCK b/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/BUCK index 125fa76df..25f321388 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/BUCK @@ -13,5 +13,6 @@ android_library( react_native_dep("third-party/java/okhttp:okhttp3"), react_native_dep("third-party/java/okhttp:okhttp3-ws"), react_native_dep("third-party/java/okio:okio"), + react_native_target("java/com/facebook/react/modules/systeminfo:systeminfo-moduleless"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/JSPackagerClient.java b/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/JSPackagerClient.java index d8cdc6544..2568ca9ea 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/JSPackagerClient.java +++ b/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/JSPackagerClient.java @@ -13,7 +13,10 @@ import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; +import android.net.Uri; + import com.facebook.common.logging.FLog; +import com.facebook.react.modules.systeminfo.AndroidInfoHelpers; import okhttp3.RequestBody; import okhttp3.ResponseBody; @@ -26,6 +29,7 @@ import org.json.JSONObject; */ final public class JSPackagerClient implements ReconnectingWebSocket.MessageCallback { private static final String TAG = JSPackagerClient.class.getSimpleName(); + private static final String PACKAGER_CONNECTION_URL_FORMAT = "ws://%s/message?device=%s&app=%s&context=%s"; private static final int PROTOCOL_VERSION = 2; public class Responder { @@ -83,8 +87,18 @@ final public class JSPackagerClient implements ReconnectingWebSocket.MessageCall private ReconnectingWebSocket mWebSocket; private Map mRequestHandlers; - public JSPackagerClient(String url, Map requestHandlers) { + public JSPackagerClient(String clientId, PackagerConnectionSettings settings, Map requestHandlers) { super(); + + Uri.Builder builder = new Uri.Builder(); + builder.scheme("ws") + .encodedAuthority(settings.getDebugServerHost()) + .appendPath("message") + .appendQueryParameter("device", AndroidInfoHelpers.getFriendlyDeviceName()) + .appendQueryParameter("app", settings.getPackageName()) + .appendQueryParameter("clientid", clientId); + String url = builder.build().toString(); + mWebSocket = new ReconnectingWebSocket(url, this); mRequestHandlers = requestHandlers; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/PackagerConnectionSettings.java b/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/PackagerConnectionSettings.java new file mode 100644 index 000000000..668931dd9 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/PackagerConnectionSettings.java @@ -0,0 +1,59 @@ +/** + * 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. + */ + +package com.facebook.react.packagerconnection; + +import javax.annotation.Nullable; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.text.TextUtils; + +import com.facebook.common.logging.FLog; +import com.facebook.infer.annotation.Assertions; +import com.facebook.react.modules.systeminfo.AndroidInfoHelpers; + +public class PackagerConnectionSettings { + private static final String TAG = PackagerConnectionSettings.class.getSimpleName(); + private static final String PREFS_DEBUG_SERVER_HOST_KEY = "debug_http_host"; + + private final SharedPreferences mPreferences; + private final String mPackageName; + + public PackagerConnectionSettings(Context applicationContext) { + mPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext); + mPackageName = applicationContext.getPackageName(); + } + + public String getDebugServerHost() { + // Check host setting first. If empty try to detect emulator type and use default + // hostname for those + String hostFromSettings = mPreferences.getString(PREFS_DEBUG_SERVER_HOST_KEY, null); + + if (!TextUtils.isEmpty(hostFromSettings)) { + return Assertions.assertNotNull(hostFromSettings); + } + + String host = AndroidInfoHelpers.getServerHost(); + + if (host.equals(AndroidInfoHelpers.DEVICE_LOCALHOST)) { + FLog.w( + TAG, + "You seem to be running on device. Run 'adb reverse tcp:8081 tcp:8081' " + + "to forward the debug server's port to the device."); + } + + return host; + } + + public @Nullable String getPackageName() { + return mPackageName; + } +} diff --git a/ReactAndroid/src/test/java/com/facebook/react/packagerconnection/JSPackagerClientTest.java b/ReactAndroid/src/test/java/com/facebook/react/packagerconnection/JSPackagerClientTest.java index 6c67780e0..d930384a3 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/packagerconnection/JSPackagerClientTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/packagerconnection/JSPackagerClientTest.java @@ -9,6 +9,7 @@ package com.facebook.react.packagerconnection; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,11 +33,19 @@ public class JSPackagerClientTest { return m; } + private PackagerConnectionSettings mSettings; + + @Before + public void setUp() { + mSettings = mock(PackagerConnectionSettings.class); + when(mSettings.getDebugServerHost()).thenReturn("ws://not_needed"); + when(mSettings.getPackageName()).thenReturn("my_test_package"); + } + @Test public void test_onMessage_ShouldTriggerNotification() throws IOException { JSPackagerClient.RequestHandler handler = mock(JSPackagerClient.RequestHandler.class); - final JSPackagerClient client = new JSPackagerClient("ws://not_needed", createRH("methodValue", handler)); - WebSocket webSocket = mock(WebSocket.class); + final JSPackagerClient client = new JSPackagerClient("test_client", mSettings, createRH("methodValue", handler)); client.onMessage( ResponseBody.create( @@ -49,8 +58,7 @@ public class JSPackagerClientTest { @Test public void test_onMessage_ShouldTriggerRequest() throws IOException { JSPackagerClient.RequestHandler handler = mock(JSPackagerClient.RequestHandler.class); - final JSPackagerClient client = new JSPackagerClient("ws://not_needed", createRH("methodValue", handler)); - WebSocket webSocket = mock(WebSocket.class); + final JSPackagerClient client = new JSPackagerClient("test_client", mSettings, createRH("methodValue", handler)); client.onMessage( ResponseBody.create( @@ -63,8 +71,7 @@ public class JSPackagerClientTest { @Test public void test_onMessage_WithoutParams_ShouldTriggerNotification() throws IOException { JSPackagerClient.RequestHandler handler = mock(JSPackagerClient.RequestHandler.class); - final JSPackagerClient client = new JSPackagerClient("ws://not_needed", createRH("methodValue", handler)); - WebSocket webSocket = mock(WebSocket.class); + final JSPackagerClient client = new JSPackagerClient("test_client", mSettings, createRH("methodValue", handler)); client.onMessage( ResponseBody.create( @@ -77,8 +84,7 @@ public class JSPackagerClientTest { @Test public void test_onMessage_WithInvalidContentType_ShouldNotTriggerCallback() throws IOException { JSPackagerClient.RequestHandler handler = mock(JSPackagerClient.RequestHandler.class); - final JSPackagerClient client = new JSPackagerClient("ws://not_needed", createRH("methodValue", handler)); - WebSocket webSocket = mock(WebSocket.class); + final JSPackagerClient client = new JSPackagerClient("test_client", mSettings, createRH("methodValue", handler)); client.onMessage( ResponseBody.create( @@ -91,8 +97,7 @@ public class JSPackagerClientTest { @Test public void test_onMessage_WithoutMethod_ShouldNotTriggerCallback() throws IOException { JSPackagerClient.RequestHandler handler = mock(JSPackagerClient.RequestHandler.class); - final JSPackagerClient client = new JSPackagerClient("ws://not_needed", createRH("methodValue", handler)); - WebSocket webSocket = mock(WebSocket.class); + final JSPackagerClient client = new JSPackagerClient("test_client", mSettings, createRH("methodValue", handler)); client.onMessage( ResponseBody.create( @@ -105,8 +110,7 @@ public class JSPackagerClientTest { @Test public void test_onMessage_With_Null_Action_ShouldNotTriggerCallback() throws IOException { JSPackagerClient.RequestHandler handler = mock(JSPackagerClient.RequestHandler.class); - final JSPackagerClient client = new JSPackagerClient("ws://not_needed", createRH("methodValue", handler)); - WebSocket webSocket = mock(WebSocket.class); + final JSPackagerClient client = new JSPackagerClient("test_client", mSettings, createRH("methodValue", handler)); client.onMessage( ResponseBody.create( @@ -119,8 +123,7 @@ public class JSPackagerClientTest { @Test public void test_onMessage_WithInvalidMethod_ShouldNotTriggerCallback() throws IOException { JSPackagerClient.RequestHandler handler = mock(JSPackagerClient.RequestHandler.class); - final JSPackagerClient client = new JSPackagerClient("ws://not_needed", createRH("methodValue", handler)); - WebSocket webSocket = mock(WebSocket.class); + final JSPackagerClient client = new JSPackagerClient("test_client", mSettings, createRH("methodValue", handler)); client.onMessage( ResponseBody.create( @@ -133,8 +136,7 @@ public class JSPackagerClientTest { @Test public void test_onMessage_WrongVersion_ShouldNotTriggerCallback() throws IOException { JSPackagerClient.RequestHandler handler = mock(JSPackagerClient.RequestHandler.class); - final JSPackagerClient client = new JSPackagerClient("ws://not_needed", createRH("methodValue", handler)); - WebSocket webSocket = mock(WebSocket.class); + final JSPackagerClient client = new JSPackagerClient("test_client", mSettings, createRH("methodValue", handler)); client.onMessage( ResponseBody.create( diff --git a/local-cli/server/util/messageSocket.js b/local-cli/server/util/messageSocket.js index 45f9b0660..94b6eea1b 100644 --- a/local-cli/server/util/messageSocket.js +++ b/local-cli/server/util/messageSocket.js @@ -130,7 +130,7 @@ function attachToServer(server, path) { result = {}; clients.forEach((otherWs, otherId) => { if (clientId !== otherId) { - result[otherId] = url.parse(otherWs.upgradeReq.url).query; + result[otherId] = url.parse(otherWs.upgradeReq.url, true).query; } }); break;