Skip to content

Commit

Permalink
Stop unwrapping Contexts if the base has a null application Context.
Browse files Browse the repository at this point in the history
The Context#createPackageContext API returns Context without an Application
instance attached, causing #getApplicationContext to return null. If this is
overridden to a non-null value using a ContextWrapper, stop unwrapping so that
code relying on #getApplicationContext will still work.

PiperOrigin-RevId: 259036178
  • Loading branch information
daniel-google authored and glide-copybara-robot committed Jul 19, 2019
1 parent 61a8a6d commit 31b501d
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,11 @@ public RequestManager get(@NonNull Context context) {
return get((FragmentActivity) context);
} else if (context instanceof Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper) {
} else if (context instanceof ContextWrapper
// Only unwrap a ContextWrapper if the baseContext has a non-null application context.
// Context#createPackageContext may return a Context without an Application instance,
// in which case a ContextWrapper may be used to attach one.
&& ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
return get(((ContextWrapper) context).getBaseContext());
}
}
Expand Down
1 change: 1 addition & 0 deletions library/test/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ dependencies {
testImplementation "org.robolectric:robolectric:${ROBOLECTRIC_VERSION}"
testImplementation "com.squareup.okhttp3:mockwebserver:${MOCKWEBSERVER_VERSION}"
testImplementation "androidx.legacy:legacy-support-v4:${ANDROID_X_VERSION}"
testImplementation "androidx.test:core:${ANDROID_X_VERSION}"
}

tasks.withType(JavaCompile) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.test.core.app.ApplicationProvider;
import com.bumptech.glide.RequestManager;
import com.bumptech.glide.tests.BackgroundUtil.BackgroundTester;
import com.bumptech.glide.tests.GlideShadowLooper;
Expand All @@ -30,7 +31,6 @@
import org.mockito.Mockito;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
Expand All @@ -41,12 +41,15 @@ public class RequestManagerRetrieverTest {
@Rule public TearDownGlide tearDownGlide = new TearDownGlide();

private static final String PARENT_TAG = "parent";
private Context appContext;
private RetrieverHarness[] harnesses;
private RequestManagerRetriever retriever;
private int initialSdkVersion;

@Before
public void setUp() {
appContext = ApplicationProvider.getApplicationContext();

retriever = new RequestManagerRetriever(null /*factory*/);

harnesses =
Expand Down Expand Up @@ -271,28 +274,53 @@ public void testHandlesContextWrappersForActivities() {

@Test
public void testHandlesContextWrappersForApplication() {
ContextWrapper contextWrapper = new ContextWrapper(RuntimeEnvironment.application);
RequestManager requestManager = retriever.get(RuntimeEnvironment.application);
ContextWrapper contextWrapper = new ContextWrapper(appContext);
RequestManager requestManager = retriever.get(appContext);

assertEquals(requestManager, retriever.get(contextWrapper));
}

@Test
public void testHandlesContextWrapperWithoutApplication() throws Exception {
// Create a Context which is not associated with an Application instance.
Context baseContext =
appContext.createPackageContext(appContext.getPackageName(), /*flags=*/ 0);

// Sanity-check that Robolectric behaves the same as the framework.
assertThat(baseContext.getApplicationContext()).isNull();

// If a wrapper provides a non-null application Context, unwrapping should terminate at this
// wrapper so that the returned Context has a non-null #getApplicationContext.
Context contextWithApplicationContext =
new ContextWrapper(baseContext) {
@Override
public Context getApplicationContext() {
return this;
}
};

Context wrappedContext = new ContextWrapper(contextWithApplicationContext);
RequestManager requestManager = retriever.get(appContext);

assertEquals(requestManager, retriever.get(wrappedContext));
}

@Test
public void testReturnsNonNullManagerIfGivenApplicationContext() {
assertNotNull(retriever.get(RuntimeEnvironment.application));
assertNotNull(retriever.get(appContext));
}

@Test
public void testApplicationRequestManagerIsNotPausedWhenRetrieved() {
RequestManager manager = retriever.get(RuntimeEnvironment.application);
RequestManager manager = retriever.get(appContext);
assertFalse(manager.isPaused());
}

@Test
public void testApplicationRequestManagerIsNotReResumedAfterFirstRetrieval() {
RequestManager manager = retriever.get(RuntimeEnvironment.application);
RequestManager manager = retriever.get(appContext);
manager.pauseRequests();
manager = retriever.get(RuntimeEnvironment.application);
manager = retriever.get(appContext);
assertTrue(manager.isPaused());
}

Expand All @@ -303,7 +331,7 @@ public void testDoesNotThrowWhenGetWithContextCalledFromBackgroundThread()
new BackgroundTester() {
@Override
public void runTest() {
retriever.get(RuntimeEnvironment.application);
retriever.get(appContext);
}
});
}
Expand Down

0 comments on commit 31b501d

Please sign in to comment.