Skip to content

Commit

Permalink
Prevent Cronet code from bypassing test Context
Browse files Browse the repository at this point in the history
The test code sets up the CronetEngineBuilder with a special Context,
but the CronetEngineBuilderImpl immediately calls
getApplicationContext() on it, which returns the original application
context, thereby defeating the entire point.

Change-Id: I0593e66bf4cbe68429263b198f27f4f2306b2329
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4813316
Reviewed-by: Stefano Duo <stefanoduo@google.com>
Commit-Queue: Etienne Dechamps <edechamps@google.com>
Auto-Submit: Etienne Dechamps <edechamps@google.com>
Cr-Commit-Position: refs/heads/main@{#1189531}
  • Loading branch information
edechamps-Google authored and Chromium LUCI CQ committed Aug 29, 2023
1 parent 8c2a7b5 commit c5f0ac9
Showing 1 changed file with 23 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,21 @@ private void setImplementationUnderTest(CronetImplementation implementation) {
* Creates and holds pointer to CronetEngine.
*/
public static class CronetTestFramework implements AutoCloseable {
// This is the Context that Cronet will use. The specific Context instance can never change
// because that would break ContextUtils.initApplicationContext(). We work around this by
// using a static MutableContextWrapper whose identity is constant, but the wrapped
// Context isn't.
@SuppressWarnings("StaticFieldLeak")
private static final MutableContextWrapper sContextWrapper =
new MutableContextWrapper(null) {
@Override
public Context getApplicationContext() {
// Ensure the code under test (in particular, the CronetEngineBuilderImpl
// constructor) cannot use this method to "escape" context interception.
return this;
}
};

private final CronetImplementation mImplementation;
private final ExperimentalCronetEngine.Builder mBuilder;
private final MutableContextWrapper mContextWrapper;
Expand All @@ -311,13 +326,15 @@ public static class CronetTestFramework implements AutoCloseable {
private CronetTestFramework(CronetImplementation implementation) {
this.mContextWrapper =
new MutableContextWrapper(ApplicationProvider.getApplicationContext());
this.mBuilder = implementation.createBuilder(mContextWrapper)
.setUserAgent(UserAgent.from(mContextWrapper))
assert sContextWrapper.getBaseContext() == null;
sContextWrapper.setBaseContext(mContextWrapper);
this.mBuilder = implementation.createBuilder(sContextWrapper)
.setUserAgent(UserAgent.from(sContextWrapper))
.enableQuic(true);
this.mImplementation = implementation;

System.loadLibrary("cronet_tests");
ContextUtils.initApplicationContext(getContext().getApplicationContext());
ContextUtils.initApplicationContext(sContextWrapper);
PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
prepareTestStorage(getContext());
mOldVmPolicy = StrictMode.getVmPolicy();
Expand Down Expand Up @@ -358,7 +375,7 @@ public void interceptContext(ContextInterceptor contextInterceptor) {
*/
public Context getContext() {
checkNotClosed();
return mContextWrapper;
return sContextWrapper;
}

public CronetEngine.Builder enableDiskCache(CronetEngine.Builder cronetEngineBuilder) {
Expand Down Expand Up @@ -433,6 +450,8 @@ public void close() {
return;
}
shutdownEngine();
assert sContextWrapper.getBaseContext() == mContextWrapper;
sContextWrapper.setBaseContext(null);
mClosed = true;

try {
Expand Down

0 comments on commit c5f0ac9

Please sign in to comment.