Commit 5a35917b authored by mgersh's avatar mgersh Committed by Commit bot

Add API for custom library loading

Loading the native library can cause a crash on some older versions of
Android. This CL provides a way for embedders to implement custom library
loading logic that works around the issue.

BUG=550584
R=xunjieli@chromium.org

Committed: https://crrev.com/12d01cb35ec0ed7a259c19dd1390b5a486d61a9d
Cr-Commit-Position: refs/heads/master@{#371319}

Review URL: https://codereview.chromium.org/1619673004

Cr-Commit-Position: refs/heads/master@{#371571}
parent bb916413
...@@ -41,6 +41,21 @@ public abstract class CronetEngine { ...@@ -41,6 +41,21 @@ public abstract class CronetEngine {
* then {@link #build} is called to create the {@code CronetEngine}. * then {@link #build} is called to create the {@code CronetEngine}.
*/ */
public static class Builder { public static class Builder {
/**
* A class which provides a method for loading the cronet native library. Apps needing to
* implement custom library loading logic can inherit from this class and pass an instance
* to {@link CronetEngine.Builder#setLibraryLoader}. For example, this might be required
* to work around {@code UnsatisfiedLinkError}s caused by flaky installation on certain
* older devices.
*/
public abstract static class LibraryLoader {
/**
* Loads the native library.
* @param libName name of the library to load
*/
public abstract void loadLibrary(String libName);
}
// A hint that a host supports QUIC. // A hint that a host supports QUIC.
static class QuicHint { static class QuicHint {
// The host. // The host.
...@@ -86,6 +101,7 @@ public abstract class CronetEngine { ...@@ -86,6 +101,7 @@ public abstract class CronetEngine {
private String mUserAgent; private String mUserAgent;
private String mStoragePath; private String mStoragePath;
private boolean mLegacyModeEnabled; private boolean mLegacyModeEnabled;
private LibraryLoader mLibraryLoader;
private String mLibraryName; private String mLibraryName;
private boolean mQuicEnabled; private boolean mQuicEnabled;
private boolean mHttp2Enabled; private boolean mHttp2Enabled;
...@@ -187,8 +203,22 @@ public abstract class CronetEngine { ...@@ -187,8 +203,22 @@ public abstract class CronetEngine {
return this; return this;
} }
String libraryName() { /**
return mLibraryName; * Sets a {@link LibraryLoader} to be used to load the native library.
* If not set, the library will be loaded using {@link System#loadLibrary}.
* @return the builder to facilitate chaining.
*/
public Builder setLibraryLoader(LibraryLoader loader) {
mLibraryLoader = loader;
return this;
}
void loadLibrary() {
if (mLibraryLoader == null) {
System.loadLibrary(mLibraryName);
} else {
mLibraryLoader.loadLibrary(mLibraryName);
}
} }
/** /**
......
...@@ -32,7 +32,7 @@ class CronetLibraryLoader { ...@@ -32,7 +32,7 @@ class CronetLibraryLoader {
if (sInitTaskPosted) { if (sInitTaskPosted) {
return; return;
} }
System.loadLibrary(builder.libraryName()); builder.loadLibrary();
if (!Version.CRONET_VERSION.equals(nativeGetCronetVersion())) { if (!Version.CRONET_VERSION.equals(nativeGetCronetVersion())) {
throw new RuntimeException(String.format( throw new RuntimeException(String.format(
"Expected Cronet version number %s, " "Expected Cronet version number %s, "
...@@ -74,7 +74,7 @@ class CronetLibraryLoader { ...@@ -74,7 +74,7 @@ class CronetLibraryLoader {
nativeCronetInitOnMainThread(); nativeCronetInitOnMainThread();
} }
// Native methods are implemented in cronet_loader.cc. // Native methods are implemented in cronet_library_loader.cc.
private static native void nativeCronetInitOnMainThread(); private static native void nativeCronetInitOnMainThread();
private static native String nativeGetCronetVersion(); private static native String nativeGetCronetVersion();
} }
...@@ -960,4 +960,33 @@ public class CronetUrlRequestContextTest extends CronetTestBase { ...@@ -960,4 +960,33 @@ public class CronetUrlRequestContextTest extends CronetTestBase {
// Verifies that CronetEngine.Builder config from testCronetEngineBuilderConfig() is properly // Verifies that CronetEngine.Builder config from testCronetEngineBuilderConfig() is properly
// translated to a native UrlRequestContextConfig. // translated to a native UrlRequestContextConfig.
private static native void nativeVerifyUrlRequestContextConfig(long config, String storagePath); private static native void nativeVerifyUrlRequestContextConfig(long config, String storagePath);
private static class TestBadLibraryLoader extends CronetEngine.Builder.LibraryLoader {
private boolean mWasCalled = false;
public void loadLibrary(String libName) {
// Report that this method was called, but don't load the library
mWasCalled = true;
}
boolean wasCalled() {
return mWasCalled;
}
}
@SmallTest
@Feature({"Cronet"})
public void testSkipLibraryLoading() throws Exception {
CronetEngine.Builder builder = new CronetEngine.Builder(getContext());
TestBadLibraryLoader loader = new TestBadLibraryLoader();
builder.setLibraryLoader(loader).setLibraryName("cronet_tests");
try {
// ensureInitialized() calls native code to check the version right after library load
// and will error with the message below if library loading was skipped
CronetLibraryLoader.ensureInitialized(getContext(), builder);
fail("Native library should not be loaded");
} catch (UnsatisfiedLinkError e) {
assertTrue(loader.wasCalled());
}
}
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment