Commit 1b20baa1 authored by Side Yilmaz's avatar Side Yilmaz Committed by Commit Bot

Remove singleton pattern from ImageFectherBridge.

This CL changes ImageFetcherBridge behaviour for different profiles.
Today, ImageFectherBridge is singleton, so there is only one instance
created for one regular and multiple incognito profiles on Android. To
avoid data leak between profiles, we need to create different instances
for each profile.

By this CL;
- Each call to |ImageFectherBridge#getForProfile| function creates an
instance of ImageFectherBridge that stores profile as member variable.
- Each call to any other function of ImageFectherBridge will directly
hit the native services through native bridge.
- Native image_fetcher_bridge is a wrapper to reach the service that
belongs to the given profile. There is no member functions anymore, but
all are static.

Bug: 1075562, 1041781, 1083923

Change-Id: Ic96d1c8fa1a7bd093abcf8939375f8934fd3cd92
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2231124
Commit-Queue: Side YILMAZ <sideyilmaz@chromium.org>
Reviewed-by: default avatarFilip Gorski <fgorski@chromium.org>
Reviewed-by: default avatarRamin Halavati <rhalavati@chromium.org>
Cr-Commit-Position: refs/heads/master@{#779817}
parent f8dec579
...@@ -8,7 +8,6 @@ import static org.mockito.ArgumentMatchers.anyInt; ...@@ -8,7 +8,6 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import android.graphics.Bitmap; import android.graphics.Bitmap;
...@@ -37,7 +36,6 @@ import jp.tomorrowkey.android.gifplayer.BaseGifImage; ...@@ -37,7 +36,6 @@ import jp.tomorrowkey.android.gifplayer.BaseGifImage;
@RunWith(BaseRobolectricTestRunner.class) @RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE) @Config(manifest = Config.NONE)
public class ImageFetcherBridgeTest { public class ImageFetcherBridgeTest {
private static long sNativePointer = 100L;
private static final int WIDTH_PX = 10; private static final int WIDTH_PX = 10;
private static final int HEIGHT_PX = 20; private static final int HEIGHT_PX = 20;
private static final int EXPIRATION_INTERVAL_MINS = 60; private static final int EXPIRATION_INTERVAL_MINS = 60;
...@@ -59,37 +57,11 @@ public class ImageFetcherBridgeTest { ...@@ -59,37 +57,11 @@ public class ImageFetcherBridgeTest {
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
doReturn(sNativePointer).when(mNatives).init(mProfile);
ImageFetcherBridgeJni.TEST_HOOKS.setInstanceForTesting(mNatives); ImageFetcherBridgeJni.TEST_HOOKS.setInstanceForTesting(mNatives);
mBridge = new ImageFetcherBridge(mProfile); mBridge = new ImageFetcherBridge(mProfile);
} }
@Test
public void testDestroy() {
mBridge.destroy();
verify(mNatives).destroy(sNativePointer, mBridge);
// Check that calling methods after destroy throw AssertionErrors.
mExpectedException.expect(AssertionError.class);
mExpectedException.expectMessage("destroy called twice");
mBridge.destroy();
mExpectedException.expectMessage("getFilePath called after destroy");
mBridge.getFilePath("");
mExpectedException.expectMessage("fetchGif called after destroy");
mBridge.fetchGif(-1, ImageFetcher.Params.create("", ""), null);
mExpectedException.expectMessage("fetchImage called after destroy");
mBridge.fetchImage(-1, ImageFetcher.Params.create("", "", 100, 100), null);
mExpectedException.expectMessage("fetchImage called after destroy");
mBridge.fetchImage(-1, ImageFetcher.Params.create("", "", 100, 100), null);
mExpectedException.expectMessage("reportEvent called after destroy");
mBridge.reportEvent("", -1);
mExpectedException.expectMessage("reportCacheHitTime called after destroy");
mBridge.reportCacheHitTime("", -1L);
mExpectedException.expectMessage("reportTotalFetchTimeFromNative called after destroy");
mBridge.reportTotalFetchTimeFromNative("", -1L);
}
@Test @Test
public void testFetchImage() { public void testFetchImage() {
ArgumentCaptor<Callback<Bitmap>> callbackCaptor = ArgumentCaptor.forClass(Callback.class); ArgumentCaptor<Callback<Bitmap>> callbackCaptor = ArgumentCaptor.forClass(Callback.class);
...@@ -99,8 +71,8 @@ public class ImageFetcherBridgeTest { ...@@ -99,8 +71,8 @@ public class ImageFetcherBridgeTest {
return null; return null;
}) })
.when(mNatives) .when(mNatives)
.fetchImage(eq(sNativePointer), eq(mBridge), anyInt(), anyString(), anyString(), .fetchImage(eq(mProfile), anyInt(), anyString(), anyString(), eq(0),
eq(0), callbackCaptor.capture()); callbackCaptor.capture());
mBridge.fetchImage( mBridge.fetchImage(
-1, ImageFetcher.Params.create("", "", WIDTH_PX, HEIGHT_PX), mBitmapCallback); -1, ImageFetcher.Params.create("", "", WIDTH_PX, HEIGHT_PX), mBitmapCallback);
...@@ -116,7 +88,7 @@ public class ImageFetcherBridgeTest { ...@@ -116,7 +88,7 @@ public class ImageFetcherBridgeTest {
return null; return null;
}) })
.when(mNatives) .when(mNatives)
.fetchImage(eq(sNativePointer), eq(mBridge), anyInt(), anyString(), anyString(), .fetchImage(eq(mProfile), anyInt(), anyString(), anyString(),
eq(EXPIRATION_INTERVAL_MINS), callbackCaptor.capture()); eq(EXPIRATION_INTERVAL_MINS), callbackCaptor.capture());
mBridge.fetchImage(-1, mBridge.fetchImage(-1,
...@@ -135,8 +107,8 @@ public class ImageFetcherBridgeTest { ...@@ -135,8 +107,8 @@ public class ImageFetcherBridgeTest {
return null; return null;
}) })
.when(mNatives) .when(mNatives)
.fetchImage(eq(sNativePointer), eq(mBridge), anyInt(), anyString(), anyString(), .fetchImage(eq(mProfile), anyInt(), anyString(), anyString(), eq(0),
eq(0), callbackCaptor.capture()); callbackCaptor.capture());
mBridge.fetchImage(-1, ImageFetcher.Params.create("", "", 100, 100), mBitmapCallback); mBridge.fetchImage(-1, ImageFetcher.Params.create("", "", 100, 100), mBitmapCallback);
ArgumentCaptor<Bitmap> bitmapCaptor = ArgumentCaptor.forClass(Bitmap.class); ArgumentCaptor<Bitmap> bitmapCaptor = ArgumentCaptor.forClass(Bitmap.class);
...@@ -157,8 +129,8 @@ public class ImageFetcherBridgeTest { ...@@ -157,8 +129,8 @@ public class ImageFetcherBridgeTest {
return null; return null;
}) })
.when(mNatives) .when(mNatives)
.fetchImageData(eq(sNativePointer), eq(mBridge), anyInt(), anyString(), anyString(), .fetchImageData(eq(mProfile), anyInt(), anyString(), anyString(), eq(0),
eq(0), callbackCaptor.capture()); callbackCaptor.capture());
mBridge.fetchGif(-1, ImageFetcher.Params.create("", ""), mGifCallback); mBridge.fetchGif(-1, ImageFetcher.Params.create("", ""), mGifCallback);
ArgumentCaptor<BaseGifImage> gifCaptor = ArgumentCaptor.forClass(BaseGifImage.class); ArgumentCaptor<BaseGifImage> gifCaptor = ArgumentCaptor.forClass(BaseGifImage.class);
...@@ -175,8 +147,8 @@ public class ImageFetcherBridgeTest { ...@@ -175,8 +147,8 @@ public class ImageFetcherBridgeTest {
return null; return null;
}) })
.when(mNatives) .when(mNatives)
.fetchImageData(eq(sNativePointer), eq(mBridge), anyInt(), anyString(), anyString(), .fetchImageData(eq(mProfile), anyInt(), anyString(), anyString(), eq(0),
eq(0), callbackCaptor.capture()); callbackCaptor.capture());
mBridge.fetchGif(-1, ImageFetcher.Params.create("", ""), mGifCallback); mBridge.fetchGif(-1, ImageFetcher.Params.create("", ""), mGifCallback);
verify(mGifCallback).onResult(null); verify(mGifCallback).onResult(null);
...@@ -185,30 +157,31 @@ public class ImageFetcherBridgeTest { ...@@ -185,30 +157,31 @@ public class ImageFetcherBridgeTest {
@Test @Test
public void testGetFilePath() { public void testGetFilePath() {
mBridge.getFilePath("testing is cool"); mBridge.getFilePath("testing is cool");
verify(mNatives).getFilePath(sNativePointer, mBridge, "testing is cool"); verify(mNatives).getFilePath(mProfile, "testing is cool");
} }
@Test @Test
public void testReportEvent() { public void testReportEvent() {
mBridge.reportEvent("client", 10); mBridge.reportEvent("client", 10);
verify(mNatives).reportEvent(sNativePointer, mBridge, "client", 10); verify(mNatives).reportEvent("client", 10);
} }
@Test @Test
public void testReportCacheHitTime() { public void testReportCacheHitTime() {
mBridge.reportCacheHitTime("client", 10L); mBridge.reportCacheHitTime("client", 10L);
verify(mNatives).reportCacheHitTime(sNativePointer, mBridge, "client", 10L); verify(mNatives).reportCacheHitTime("client", 10L);
} }
@Test @Test
public void testReportTotalFetchTimeFromNative() { public void testReportTotalFetchTimeFromNative() {
mBridge.reportTotalFetchTimeFromNative("client", 10L); mBridge.reportTotalFetchTimeFromNative("client", 10L);
verify(mNatives).reportTotalFetchTimeFromNative(sNativePointer, mBridge, "client", 10L); verify(mNatives).reportTotalFetchTimeFromNative("client", 10L);
} }
@Test @Test
public void testSetupForTesting() { public void testSetupForTesting() {
ImageFetcherBridge.setupForTesting(mBridge); // Since ImageFetcherBridge creates different instance on each call of getForProfile
Assert.assertEquals(mBridge, ImageFetcherBridge.getInstance()); // function, two instances below should not be equal.
Assert.assertNotEquals(mBridge, ImageFetcherBridge.getForProfile(mProfile));
} }
} }
\ No newline at end of file
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
package org.chromium.chrome.browser.image_fetcher; package org.chromium.chrome.browser.image_fetcher;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import android.support.test.filters.SmallTest; import android.support.test.filters.SmallTest;
...@@ -17,6 +19,7 @@ import org.robolectric.annotation.Config; ...@@ -17,6 +19,7 @@ import org.robolectric.annotation.Config;
import org.chromium.base.DiscardableReferencePool; import org.chromium.base.DiscardableReferencePool;
import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.chrome.browser.profiles.Profile;
/** /**
* Test for ImageFetcherFactory. * Test for ImageFetcherFactory.
...@@ -28,6 +31,8 @@ public class ImageFetcherFactoryTest { ...@@ -28,6 +31,8 @@ public class ImageFetcherFactoryTest {
ImageFetcherBridge mImageFetcherBridge; ImageFetcherBridge mImageFetcherBridge;
@Mock @Mock
DiscardableReferencePool mReferencePool; DiscardableReferencePool mReferencePool;
@Mock
Profile mProfile;
@Before @Before
public void setUp() { public void setUp() {
...@@ -59,4 +64,25 @@ public class ImageFetcherFactoryTest { ...@@ -59,4 +64,25 @@ public class ImageFetcherFactoryTest {
InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE) InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE)
.getConfig()); .getConfig());
} }
@Test
@SmallTest
public void testCreateImageFetcher() {
int config = ImageFetcherConfig.NETWORK_ONLY;
ImageFetcher imageFetcher = ImageFetcherFactory.createImageFetcher(config, mProfile);
assertNotNull(imageFetcher);
assertNotEquals(mImageFetcherBridge, imageFetcher.getImageFetcherBridge());
ImageFetcher imageFetcherWithRefPool =
ImageFetcherFactory.createImageFetcher(config, mProfile, mReferencePool);
assertNotNull(imageFetcherWithRefPool);
assertNotEquals(mImageFetcherBridge, imageFetcherWithRefPool.getImageFetcherBridge());
ImageFetcher imageFetcherWithRefPoolAndCacheSize = ImageFetcherFactory.createImageFetcher(
config, mProfile, mReferencePool, InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE);
assertNotNull(imageFetcherWithRefPoolAndCacheSize);
assertNotEquals(
mImageFetcherBridge, imageFetcherWithRefPoolAndCacheSize.getImageFetcherBridge());
}
} }
...@@ -21,63 +21,63 @@ class ImageFetcherService; ...@@ -21,63 +21,63 @@ class ImageFetcherService;
// Native counterpart of ImageFetcherBridge.java. // Native counterpart of ImageFetcherBridge.java.
class ImageFetcherBridge { class ImageFetcherBridge {
public: public:
ImageFetcherBridge(ImageFetcherService* image_fetcher_service, ImageFetcherBridge();
base::FilePath base_file_path);
~ImageFetcherBridge(); ~ImageFetcherBridge();
void Destroy(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this); static base::android::ScopedJavaLocalRef<jstring> GetFilePath(
JNIEnv* j_env,
const base::android::JavaParamRef<jobject>& j_profile,
const base::android::JavaParamRef<jstring>& j_url);
base::android::ScopedJavaLocalRef<jstring> GetFilePath( static void FetchImageData(
JNIEnv* j_env,
const base::android::JavaParamRef<jobject>& j_profile,
const jint j_image_fetcher_config,
const base::android::JavaParamRef<jstring>& j_url,
const base::android::JavaParamRef<jstring>& j_client_name,
const jint j_expiration_interval_mins,
const base::android::JavaParamRef<jobject>& j_callback);
static void FetchImage(
JNIEnv* j_env, JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this, const base::android::JavaParamRef<jobject>& j_profile,
const base::android::JavaRef<jstring>& j_url); const jint j_image_fetcher_config,
const base::android::JavaParamRef<jstring>& j_url,
void FetchImageData(JNIEnv* j_env, const base::android::JavaParamRef<jstring>& j_client_name,
const base::android::JavaRef<jobject>& j_this, const jint j_expiration_interval_mins,
const jint j_image_fetcher_config, const base::android::JavaParamRef<jobject>& j_callback);
const base::android::JavaRef<jstring>& j_url,
const base::android::JavaRef<jstring>& j_client_name, static void ReportEvent(
const jint j_expiration_interval_mins, JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_callback); const base::android::JavaParamRef<jstring>& j_client_name,
const jint j_event_id);
void FetchImage(JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this, static void ReportCacheHitTime(
const jint j_image_fetcher_config, JNIEnv* j_env,
const base::android::JavaRef<jstring>& j_url, const base::android::JavaParamRef<jstring>& j_client_name,
const base::android::JavaRef<jstring>& j_client_name, const jlong start_time_millis);
const jint j_expiration_interval_mins,
const base::android::JavaRef<jobject>& j_callback); static void ReportTotalFetchTimeFromNative(
void ReportEvent(JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const base::android::JavaRef<jstring>& j_client_name,
const jint j_event_id);
void ReportCacheHitTime(JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const base::android::JavaRef<jstring>& j_client_name,
const jlong start_time_millis);
void ReportTotalFetchTimeFromNative(
JNIEnv* j_env, JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this, const base::android::JavaParamRef<jstring>& j_client_name,
const base::android::JavaRef<jstring>& j_client_name,
const jlong start_time_millis); const jlong start_time_millis);
private: private:
void OnImageDataFetched(base::android::ScopedJavaGlobalRef<jobject> callback, static void OnImageDataFetched(
const std::string& image_data, base::android::ScopedJavaGlobalRef<jobject> callback,
const RequestMetadata& request_metadata); const std::string& image_data,
const RequestMetadata& request_metadata);
void OnImageFetched(base::android::ScopedJavaGlobalRef<jobject> callback, static void OnImageFetched(
const gfx::Image& image, base::android::ScopedJavaGlobalRef<jobject> callback,
const RequestMetadata& request_metadata); const gfx::Image& image,
const RequestMetadata& request_metadata);
// This service outlives the bridge. static ImageFetcherService* GetImageFetcherServiceForProfile(
ImageFetcherService* image_fetcher_service_; const base::android::JavaParamRef<jobject>& j_profile);
base::FilePath base_file_path_;
base::WeakPtrFactory<ImageFetcherBridge> weak_ptr_factory_{this}; static base::FilePath GetFilePathForProfile(
const base::android::JavaParamRef<jobject>& j_profile);
DISALLOW_COPY_AND_ASSIGN(ImageFetcherBridge); DISALLOW_COPY_AND_ASSIGN(ImageFetcherBridge);
}; };
......
...@@ -9,6 +9,7 @@ import android.graphics.Bitmap; ...@@ -9,6 +9,7 @@ import android.graphics.Bitmap;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import org.chromium.base.Callback; import org.chromium.base.Callback;
import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
...@@ -20,36 +21,28 @@ import jp.tomorrowkey.android.gifplayer.BaseGifImage; ...@@ -20,36 +21,28 @@ import jp.tomorrowkey.android.gifplayer.BaseGifImage;
*/ */
@JNINamespace("image_fetcher") @JNINamespace("image_fetcher")
public class ImageFetcherBridge { public class ImageFetcherBridge {
private static ImageFetcherBridge sImageFetcherBridge; private Profile mProfile;
private long mNativeImageFetcherBridge; /**
* Get the ImageFetcherBridge for the given profile.
// Get the instance of the ImageFetcherBridge. If used before browser initialization, this will *
// throw an IllegalStateException. * @param profile The profile for which the ImageFetcherBridge is returned.
public static ImageFetcherBridge getInstance() { * @return The ImageFetcherBridge for the given profile.
if (sImageFetcherBridge == null) { */
// TODO(https://crbug.com/1041781): Use the current profile (i.e., regular profile or public static ImageFetcherBridge getForProfile(Profile profile) {
// incognito profile) instead of always using regular profile. ThreadUtils.assertOnUiThread();
Profile profile = Profile.getLastUsedRegularProfile();
sImageFetcherBridge = new ImageFetcherBridge(profile);
}
return sImageFetcherBridge; return new ImageFetcherBridge(profile);
} }
/** /**
* Creates a ImageFetcherBridge for accessing the native ImageFetcher implementation. * Creates a ImageFetcherBridge for the given profile.
*
* @param profile The profile to reach regarding image_fetcher_service on native side.
*/ */
@VisibleForTesting @VisibleForTesting
ImageFetcherBridge(Profile profile) { ImageFetcherBridge(Profile profile) {
mNativeImageFetcherBridge = ImageFetcherBridgeJni.get().init(profile); mProfile = profile;
}
/** Cleans up native half of bridge. */
public void destroy() {
assert mNativeImageFetcherBridge != 0 : "destroy called twice";
ImageFetcherBridgeJni.get().destroy(mNativeImageFetcherBridge, ImageFetcherBridge.this);
mNativeImageFetcherBridge = 0;
} }
/** /**
...@@ -59,23 +52,20 @@ public class ImageFetcherBridge { ...@@ -59,23 +52,20 @@ public class ImageFetcherBridge {
* @return The full path to the resource on disk. * @return The full path to the resource on disk.
*/ */
public String getFilePath(String url) { public String getFilePath(String url) {
assert mNativeImageFetcherBridge != 0 : "getFilePath called after destroy"; return ImageFetcherBridgeJni.get().getFilePath(mProfile, url);
return ImageFetcherBridgeJni.get().getFilePath(
mNativeImageFetcherBridge, ImageFetcherBridge.this, url);
} }
/** /**
* Fetch a gif from native or null if the gif can't be fetched or decoded. * Fetch a gif from native or null if the gif can't be fetched or decoded.
* *
* @param config The configuration of the image fetcher.
* @param params The parameters to specify image fetching details. * @param params The parameters to specify image fetching details.
* @param callback The callback to call when the gif is ready. The callback will be invoked on * @param callback The callback to call when the gif is ready. The callback will be invoked on
* the same thread it was called on. * the same thread it was called on.
*/ */
public void fetchGif(@ImageFetcherConfig int config, final ImageFetcher.Params params, public void fetchGif(@ImageFetcherConfig int config, final ImageFetcher.Params params,
Callback<BaseGifImage> callback) { Callback<BaseGifImage> callback) {
assert mNativeImageFetcherBridge != 0 : "fetchGif called after destroy"; ImageFetcherBridgeJni.get().fetchImageData(mProfile, config, params.url, params.clientName,
ImageFetcherBridgeJni.get().fetchImageData(mNativeImageFetcherBridge,
ImageFetcherBridge.this, config, params.url, params.clientName,
params.expirationIntervalMinutes, (byte[] data) -> { params.expirationIntervalMinutes, (byte[] data) -> {
if (data == null || data.length == 0) { if (data == null || data.length == 0) {
callback.onResult(null); callback.onResult(null);
...@@ -96,10 +86,8 @@ public class ImageFetcherBridge { ...@@ -96,10 +86,8 @@ public class ImageFetcherBridge {
*/ */
public void fetchImage(@ImageFetcherConfig int config, final ImageFetcher.Params params, public void fetchImage(@ImageFetcherConfig int config, final ImageFetcher.Params params,
Callback<Bitmap> callback) { Callback<Bitmap> callback) {
assert mNativeImageFetcherBridge != 0 : "fetchImage called after destroy"; ImageFetcherBridgeJni.get().fetchImage(mProfile, config, params.url, params.clientName,
ImageFetcherBridgeJni.get().fetchImage(mNativeImageFetcherBridge, ImageFetcherBridge.this, params.expirationIntervalMinutes, (bitmap) -> {
config, params.url, params.clientName, params.expirationIntervalMinutes,
(bitmap) -> {
callback.onResult( callback.onResult(
ImageFetcher.resizeImage(bitmap, params.width, params.height)); ImageFetcher.resizeImage(bitmap, params.width, params.height));
}); });
...@@ -112,9 +100,7 @@ public class ImageFetcherBridge { ...@@ -112,9 +100,7 @@ public class ImageFetcherBridge {
* @param eventId The event to report. * @param eventId The event to report.
*/ */
public void reportEvent(String clientName, @ImageFetcherEvent int eventId) { public void reportEvent(String clientName, @ImageFetcherEvent int eventId) {
assert mNativeImageFetcherBridge != 0 : "reportEvent called after destroy"; ImageFetcherBridgeJni.get().reportEvent(clientName, eventId);
ImageFetcherBridgeJni.get().reportEvent(
mNativeImageFetcherBridge, ImageFetcherBridge.this, clientName, eventId);
} }
/** /**
...@@ -125,9 +111,7 @@ public class ImageFetcherBridge { ...@@ -125,9 +111,7 @@ public class ImageFetcherBridge {
* total duration. * total duration.
*/ */
public void reportCacheHitTime(String clientName, long startTimeMillis) { public void reportCacheHitTime(String clientName, long startTimeMillis) {
assert mNativeImageFetcherBridge != 0 : "reportCacheHitTime called after destroy"; ImageFetcherBridgeJni.get().reportCacheHitTime(clientName, startTimeMillis);
ImageFetcherBridgeJni.get().reportCacheHitTime(
mNativeImageFetcherBridge, ImageFetcherBridge.this, clientName, startTimeMillis);
} }
/** /**
...@@ -138,38 +122,19 @@ public class ImageFetcherBridge { ...@@ -138,38 +122,19 @@ public class ImageFetcherBridge {
* total duration. * total duration.
*/ */
public void reportTotalFetchTimeFromNative(String clientName, long startTimeMillis) { public void reportTotalFetchTimeFromNative(String clientName, long startTimeMillis) {
assert mNativeImageFetcherBridge ImageFetcherBridgeJni.get().reportTotalFetchTimeFromNative(clientName, startTimeMillis);
!= 0 : "reportTotalFetchTimeFromNative called after destroy";
ImageFetcherBridgeJni.get().reportTotalFetchTimeFromNative(
mNativeImageFetcherBridge, ImageFetcherBridge.this, clientName, startTimeMillis);
}
/**
* Setup the bridge for testing.
* @param imageFetcherBridge The bridge used for testing.
*/
public static void setupForTesting(ImageFetcherBridge imageFetcherBridge) {
sImageFetcherBridge = imageFetcherBridge;
} }
@NativeMethods @NativeMethods
interface Natives { interface Natives {
// Native methods // Native methods
long init(Profile profile); String getFilePath(Profile profile, String url);
void fetchImageData(Profile profile, @ImageFetcherConfig int config, String url,
void destroy(long nativeImageFetcherBridge, ImageFetcherBridge caller); String clientName, int expirationIntervalMinutes, Callback<byte[]> callback);
String getFilePath(long nativeImageFetcherBridge, ImageFetcherBridge caller, String url); void fetchImage(Profile profile, @ImageFetcherConfig int config, String url,
void fetchImageData(long nativeImageFetcherBridge, ImageFetcherBridge caller, String clientName, int expirationIntervalMinutes, Callback<Bitmap> callback);
@ImageFetcherConfig int config, String url, String clientName, void reportEvent(String clientName, int eventId);
int expirationIntervalMinutes, Callback<byte[]> callback); void reportCacheHitTime(String clientName, long startTimeMillis);
void fetchImage(long nativeImageFetcherBridge, ImageFetcherBridge caller, void reportTotalFetchTimeFromNative(String clientName, long startTimeMillis);
@ImageFetcherConfig int config, String url, String clientName,
int expirationIntervalMinutes, Callback<Bitmap> callback);
void reportEvent(long nativeImageFetcherBridge, ImageFetcherBridge caller,
String clientName, int eventId);
void reportCacheHitTime(long nativeImageFetcherBridge, ImageFetcherBridge caller,
String clientName, long startTimeMillis);
void reportTotalFetchTimeFromNative(long nativeImageFetcherBridge,
ImageFetcherBridge caller, String clientName, long startTimeMillis);
} }
} }
...@@ -5,44 +5,95 @@ ...@@ -5,44 +5,95 @@
package org.chromium.chrome.browser.image_fetcher; package org.chromium.chrome.browser.image_fetcher;
import org.chromium.base.DiscardableReferencePool; import org.chromium.base.DiscardableReferencePool;
import org.chromium.chrome.browser.profiles.Profile;
/** /**
* Factory to provide the image fetcher best suited for the given config. * Factory to provide the image fetcher best suited for the given config.
*/ */
public class ImageFetcherFactory { public class ImageFetcherFactory {
// Store static references to singleton image fetchers.
private static CachedImageFetcher sCachedImageFetcher;
private static NetworkImageFetcher sNetworkImageFetcher;
/** /**
* Alias for createImageFetcher below. * Alias for createImageFetcher below. If used before browser initialization, this will throw an
* IllegalStateException. This method always uses regular profile to get ImageFetcherBridge.
*
* https://crbug.com/1083923: Remove after replacing all use cases.
*
* @deprecated use {@link ImageFetcherFactory#createImageFetcher(int, Profile)} instead.
*/ */
@Deprecated
public static ImageFetcher createImageFetcher(@ImageFetcherConfig int config) { public static ImageFetcher createImageFetcher(@ImageFetcherConfig int config) {
return createImageFetcher(config, ImageFetcherBridge.getInstance(), null, ImageFetcherBridge bridge =
InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE); ImageFetcherBridge.getForProfile(Profile.getLastUsedRegularProfile());
return createImageFetcher(
config, bridge, null, InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE);
} }
/** /**
* Alias for createImageFetcher below. * Alias for createImageFetcher below. If used before browser initialization, this will throw an
* IllegalStateException. This method always uses regular profile to get ImageFetcherBridge.
*
* https://crbug.com/1083923: Remove after replacing all use cases.
*
* @deprecated use {@link ImageFetcherFactory#createImageFetcher(int, DiscardableReferencePool,
* Profile)} instead.
*/ */
@Deprecated
public static ImageFetcher createImageFetcher( public static ImageFetcher createImageFetcher(
@ImageFetcherConfig int config, DiscardableReferencePool discardableReferencePool) { @ImageFetcherConfig int config, DiscardableReferencePool discardableReferencePool) {
return createImageFetcher(config, ImageFetcherBridge.getInstance(), ImageFetcherBridge bridge =
discardableReferencePool, InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE); ImageFetcherBridge.getForProfile(Profile.getLastUsedRegularProfile());
return createImageFetcher(config, bridge, discardableReferencePool,
InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE);
} }
/** /**
* Alias for createImageFetcher below. * Alias for createImageFetcher below. If used before browser initialization, this will throw an
* IllegalStateException. This method always uses regular profile to get ImageFetcherBridge.
*
* https://crbug.com/1083923: Remove after replacing all use cases.
*
* @deprecated use {@link ImageFetcherFactory#createImageFetcher(int, DiscardableReferencePool,
* int, Profile)} instead.
*/ */
@Deprecated
public static ImageFetcher createImageFetcher(@ImageFetcherConfig int config, public static ImageFetcher createImageFetcher(@ImageFetcherConfig int config,
DiscardableReferencePool discardableReferencePool, int inMemoryCacheSize) { DiscardableReferencePool discardableReferencePool, int inMemoryCacheSize) {
return createImageFetcher(config, ImageFetcherBridge.getInstance(), ImageFetcherBridge bridge =
discardableReferencePool, inMemoryCacheSize); ImageFetcherBridge.getForProfile(Profile.getLastUsedRegularProfile());
return createImageFetcher(config, bridge, discardableReferencePool, inMemoryCacheSize);
}
/**
* Alias for createImageFetcher below.
*/
public static ImageFetcher createImageFetcher(@ImageFetcherConfig int config, Profile profile) {
ImageFetcherBridge bridge = ImageFetcherBridge.getForProfile(profile);
return createImageFetcher(
config, bridge, null, InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE);
}
/**
* Alias for createImageFetcher below.
*/
public static ImageFetcher createImageFetcher(@ImageFetcherConfig int config, Profile profile,
DiscardableReferencePool discardableReferencePool) {
ImageFetcherBridge bridge = ImageFetcherBridge.getForProfile(profile);
return createImageFetcher(config, bridge, discardableReferencePool,
InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE);
}
/**
* Alias for createImageFetcher below.
*/
public static ImageFetcher createImageFetcher(@ImageFetcherConfig int config, Profile profile,
DiscardableReferencePool discardableReferencePool, int inMemoryCacheSize) {
ImageFetcherBridge bridge = ImageFetcherBridge.getForProfile(profile);
return createImageFetcher(config, bridge, discardableReferencePool, inMemoryCacheSize);
} }
/** /**
* Return the image fetcher that matches the given config. This will return an image fetcher * Return the image fetcher that matches the given config. This will return an image fetcher
* config that you must destroy. * config that you must destroy. This function is only used for functions above and tests in
* this package.
* *
* @param config The type of ImageFetcher you need. * @param config The type of ImageFetcher you need.
* @param imageFetcherBridge Bridge to use. * @param imageFetcherBridge Bridge to use.
...@@ -50,22 +101,16 @@ public class ImageFetcherFactory { ...@@ -50,22 +101,16 @@ public class ImageFetcherFactory {
* @param inMemoryCacheSize The size of the in memory cache (in bytes). * @param inMemoryCacheSize The size of the in memory cache (in bytes).
* @return The correct ImageFetcher according to the provided config. * @return The correct ImageFetcher according to the provided config.
*/ */
public static ImageFetcher createImageFetcher(@ImageFetcherConfig int config, static ImageFetcher createImageFetcher(@ImageFetcherConfig int config,
ImageFetcherBridge imageFetcherBridge, ImageFetcherBridge imageFetcherBridge,
DiscardableReferencePool discardableReferencePool, int inMemoryCacheSize) { DiscardableReferencePool discardableReferencePool, int inMemoryCacheSize) {
// TODO(crbug.com/947191):Allow server-side configuration image fetcher clients. // TODO(crbug.com/947191):Allow server-side configuration image fetcher clients.
switch (config) { switch (config) {
case ImageFetcherConfig.NETWORK_ONLY: case ImageFetcherConfig.NETWORK_ONLY:
if (sNetworkImageFetcher == null) { return new NetworkImageFetcher(imageFetcherBridge);
sNetworkImageFetcher = new NetworkImageFetcher(imageFetcherBridge);
}
return sNetworkImageFetcher;
case ImageFetcherConfig.DISK_CACHE_ONLY: case ImageFetcherConfig.DISK_CACHE_ONLY:
if (sCachedImageFetcher == null) { return new CachedImageFetcher(
sCachedImageFetcher = new CachedImageFetcher( imageFetcherBridge, new CachedImageFetcher.ImageLoader());
imageFetcherBridge, new CachedImageFetcher.ImageLoader());
}
return sCachedImageFetcher;
case ImageFetcherConfig.IN_MEMORY_ONLY: case ImageFetcherConfig.IN_MEMORY_ONLY:
assert discardableReferencePool != null; assert discardableReferencePool != null;
return new InMemoryCachedImageFetcher( return new InMemoryCachedImageFetcher(
......
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