Commit 750261de authored by Patrick Noland's avatar Patrick Noland Committed by Commit Bot

[Feed] Fix crash when clearing cached data after being disabled

The Feed can be disabled and destroyed without warning, meaning
calls to FeedProcessScopeFactory#getFoo() can return null. This CL
guards against that for FeedLifecycleBridge

Bug: 902123
Change-Id: Iff4fb6eb1c1e19358637159558d1983e774a42a2
Reviewed-on: https://chromium-review.googlesource.com/c/1327550
Commit-Queue: Patrick Noland <pnoland@chromium.org>
Reviewed-by: default avatarSky Malice <skym@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607355}
parent 3fd0264f
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.feed; package org.chromium.chrome.browser.feed;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.JNINamespace;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
...@@ -34,16 +35,22 @@ public class FeedLifecycleBridge { ...@@ -34,16 +35,22 @@ public class FeedLifecycleBridge {
mNativeBridge = 0; mNativeBridge = 0;
} }
@VisibleForTesting
@CalledByNative @CalledByNative
private static void onCachedDataCleared() { static void onCachedDataCleared() {
FeedProcessScopeFactory.getFeedAppLifecycle().onCachedDataCleared(); FeedAppLifecycle lifecycle = FeedProcessScopeFactory.getFeedAppLifecycle();
if (lifecycle != null) {
lifecycle.onCachedDataCleared();
}
} }
// This would ordinarily be non-static, but there's no instance state, so for simplicity it's @VisibleForTesting
// isomorphic to onCachedDataCleared.
@CalledByNative @CalledByNative
private static void onHistoryDeleted() { static void onHistoryDeleted() {
FeedProcessScopeFactory.getFeedAppLifecycle().onHistoryDeleted(); FeedAppLifecycle lifecycle = FeedProcessScopeFactory.getFeedAppLifecycle();
if (lifecycle != null) {
lifecycle.onHistoryDeleted();
}
} }
private native long nativeInit(Profile profile); private native long nativeInit(Profile profile);
......
...@@ -42,6 +42,8 @@ import org.chromium.chrome.browser.feed.FeedAppLifecycle.AppLifecycleEvent; ...@@ -42,6 +42,8 @@ import org.chromium.chrome.browser.feed.FeedAppLifecycle.AppLifecycleEvent;
import org.chromium.chrome.browser.init.ChromeBrowserInitializer; import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
import org.chromium.chrome.browser.multiwindow.MultiWindowTestHelper; import org.chromium.chrome.browser.multiwindow.MultiWindowTestHelper;
import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
...@@ -61,8 +63,6 @@ public class FeedAppLifecycleTest { ...@@ -61,8 +63,6 @@ public class FeedAppLifecycleTest {
@Rule @Rule
public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
@Mock @Mock
private FeedLifecycleBridge mLifecycleBridge;
@Mock
private FeedScheduler mFeedScheduler; private FeedScheduler mFeedScheduler;
@Mock @Mock
private NetworkClient mNetworkClient; private NetworkClient mNetworkClient;
...@@ -74,6 +74,7 @@ public class FeedAppLifecycleTest { ...@@ -74,6 +74,7 @@ public class FeedAppLifecycleTest {
private Map<String, Boolean> mMockFeatureList; private Map<String, Boolean> mMockFeatureList;
private ChromeTabbedActivity mActivity; private ChromeTabbedActivity mActivity;
private FeedAppLifecycle mAppLifecycle; private FeedAppLifecycle mAppLifecycle;
private FeedLifecycleBridge mLifecycleBridge;
private final String mHistogramAppLifecycleEvents = private final String mHistogramAppLifecycleEvents =
"ContentSuggestions.Feed.AppLifecycle.Events"; "ContentSuggestions.Feed.AppLifecycle.Events";
...@@ -89,14 +90,15 @@ public class FeedAppLifecycleTest { ...@@ -89,14 +90,15 @@ public class FeedAppLifecycleTest {
} catch (ProcessInitException e) { } catch (ProcessInitException e) {
Assert.fail("Native initialization failed"); Assert.fail("Native initialization failed");
} }
Profile profile = Profile.getLastUsedProfile().getOriginalProfile();
mLifecycleBridge = new FeedLifecycleBridge(profile);
mAppLifecycle = mAppLifecycle =
new FeedAppLifecycle(mAppLifecycleListener, mLifecycleBridge, mFeedScheduler); new FeedAppLifecycle(mAppLifecycleListener, mLifecycleBridge, mFeedScheduler);
FeedProcessScopeFactory.createFeedProcessScopeForTesting(mFeedScheduler, mNetworkClient, FeedProcessScopeFactory.createFeedProcessScopeForTesting(mFeedScheduler, mNetworkClient,
mOfflineIndicator, mAppLifecycle, mOfflineIndicator, mAppLifecycle,
new FeedAppLifecycleListener( new FeedAppLifecycleListener(
new com.google.android.libraries.feed.api.common.ThreadUtils()), new com.google.android.libraries.feed.api.common.ThreadUtils()),
new FeedLoggingBridge(Profile.getLastUsedProfile().getOriginalProfile())); new FeedLoggingBridge(profile));
}); });
mActivityTestRule.startMainActivityOnBlankPage(); mActivityTestRule.startMainActivityOnBlankPage();
...@@ -246,6 +248,18 @@ public class FeedAppLifecycleTest { ...@@ -246,6 +248,18 @@ public class FeedAppLifecycleTest {
verify(mFeedScheduler, times(2)).onForegrounded(); verify(mFeedScheduler, times(2)).onForegrounded();
} }
@Test
@SmallTest
@Feature({"InterestFeedContentSuggestions"})
public void clear_data_after_disabling_does_not_crash() {
ThreadUtils.runOnUiThreadBlocking(() -> {
FeedProcessScopeFactory.clearFeedProcessScopeForTesting();
PrefServiceBridge.getInstance().setBoolean(Pref.NTP_ARTICLES_SECTION_ENABLED, false);
FeedLifecycleBridge.onCachedDataCleared();
FeedLifecycleBridge.onHistoryDeleted();
});
}
private void signalActivityStart(Activity activity) private void signalActivityStart(Activity activity)
throws InterruptedException, TimeoutException { throws InterruptedException, TimeoutException {
signalActivityState(activity, ActivityState.STARTED); signalActivityState(activity, ActivityState.STARTED);
......
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