Commit 31f4a641 authored by Wei-Yin Chen (陳威尹)'s avatar Wei-Yin Chen (陳威尹) Committed by Commit Bot

Show on-disk thumbnail before live content is captured

This is a follow up for https://crrev.com/c/1525627.

Before this CL, the thumbnail of the current tab is requested,
and is shown in Grid Tab Switcher when captured. However, the latency
of this pipeline is a bit long, and this leads to a visible flash
if the thumbnail has been cleared when recycled, which is done in
https://crrev.com/c/1595128.

This CL shows the on-disk thumbnail first, and updates that with
the newly requested screenshot of the live content if available.

Bug: 959054
Change-Id: I15a44d8a6e7bef4f71ae429b4ec1136697e53246
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1612230Reviewed-by: default avatarMatthew Jones <mdjones@chromium.org>
Reviewed-by: default avatarYusuf Ozuysal <yusufo@chromium.org>
Commit-Queue: Wei-Yin Chen (陳威尹) <wychen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#661156}
parent 8b4baa14
...@@ -28,6 +28,7 @@ import org.chromium.content_public.browser.UiThreadTaskTraits; ...@@ -28,6 +28,7 @@ import org.chromium.content_public.browser.UiThreadTaskTraits;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/** /**
* A {@link TabListMediator.ThumbnailProvider} that will create a single Bitmap Thumbnail for all * A {@link TabListMediator.ThumbnailProvider} that will create a single Bitmap Thumbnail for all
...@@ -106,18 +107,22 @@ public class MultiThumbnailCardProvider implements TabListMediator.ThumbnailProv ...@@ -106,18 +107,22 @@ public class MultiThumbnailCardProvider implements TabListMediator.ThumbnailProv
final int index = i; final int index = i;
final String url = mTabs.get(i).getUrl(); final String url = mTabs.get(i).getUrl();
final boolean isIncognito = mTabs.get(i).isIncognito(); final boolean isIncognito = mTabs.get(i).isIncognito();
// getTabThumbnailWithCallback() might call the callback up to twice,
// so use |lastFavicon| to avoid fetching the favicon the second time.
// Fetching the favicon after getting the live thumbnail would lead to
// visible flicker.
final AtomicReference<Drawable> lastFavicon = new AtomicReference<>();
mTabContentManager.getTabThumbnailWithCallback(mTabs.get(i), thumbnail -> { mTabContentManager.getTabThumbnailWithCallback(mTabs.get(i), thumbnail -> {
drawThumbnailBitmapOnCanvasWithFrame(thumbnail, index); drawThumbnailBitmapOnCanvasWithFrame(thumbnail, index);
mTabListFaviconProvider.getFaviconForUrlAsync( if (lastFavicon.get() != null) {
url, isIncognito, (Drawable favicon) -> { drawFaviconThenMaybeSendBack(lastFavicon.get(), index);
drawFaviconDrawableOnCanvasWithFrame(favicon, index); } else {
if (mThumbnailsToFetch.decrementAndGet() == 0) { mTabListFaviconProvider.getFaviconForUrlAsync(
PostTask.postTask(UiThreadTaskTraits.USER_VISIBLE, url, isIncognito, (Drawable favicon) -> {
() lastFavicon.set(favicon);
-> mFinalCallback.onResult( drawFaviconThenMaybeSendBack(favicon, index);
mMultiThumbnailBitmap)); });
} }
});
}, mForceUpdate && i == 0); }, mForceUpdate && i == 0);
} else { } else {
drawThumbnailBitmapOnCanvasWithFrame(null, i); drawThumbnailBitmapOnCanvasWithFrame(null, i);
...@@ -164,6 +169,14 @@ public class MultiThumbnailCardProvider implements TabListMediator.ThumbnailProv ...@@ -164,6 +169,14 @@ public class MultiThumbnailCardProvider implements TabListMediator.ThumbnailProv
favicon.draw(mCanvas); favicon.draw(mCanvas);
} }
private void drawFaviconThenMaybeSendBack(Drawable favicon, int index) {
drawFaviconDrawableOnCanvasWithFrame(favicon, index);
if (mThumbnailsToFetch.decrementAndGet() == 0) {
PostTask.postTask(UiThreadTaskTraits.USER_VISIBLE,
() -> mFinalCallback.onResult(mMultiThumbnailBitmap));
}
}
private void fetch() { private void fetch() {
initializeAndStartFetching(mInitialTab); initializeAndStartFetching(mInitialTab);
} }
......
...@@ -256,24 +256,28 @@ public class TabContentManager { ...@@ -256,24 +256,28 @@ public class TabContentManager {
* TODO(yusufo): Change the plumbing so that at the least a {@link android.net.Uri} is sent * TODO(yusufo): Change the plumbing so that at the least a {@link android.net.Uri} is sent
* over JNI of an uncompressed file on disk. * over JNI of an uncompressed file on disk.
* @param tab The tab to get the thumbnail for. * @param tab The tab to get the thumbnail for.
* @param callback The callback to send the {@link Bitmap} with. * @param callback The callback to send the {@link Bitmap} with. Can be called up to twice when
* forceUpdate; otherwise always called exactly once.
* @param forceUpdate Whether to obtain the thumbnail from the live content.
*/ */
public void getTabThumbnailWithCallback( public void getTabThumbnailWithCallback(
Tab tab, Callback<Bitmap> callback, boolean forceUpdate) { Tab tab, Callback<Bitmap> callback, boolean forceUpdate) {
if (mNativeTabContentManager == 0 || !mSnapshotsEnabled) return; if (mNativeTabContentManager == 0 || !mSnapshotsEnabled) return;
// Reading thumbnail from disk is faster than taking screenshot from live Tab, so fetch
// that first even if |forceUpdate|.
nativeGetTabThumbnailWithCallback(mNativeTabContentManager, tab.getId(), callback);
if (forceUpdate) { if (forceUpdate) {
cacheTabThumbnail(tab, (bitmap) -> { cacheTabThumbnail(tab, (bitmap) -> {
// Null check to avoid having a Bitmap from nativeGetTabThumbnailWithCallback() but
// cleared here.
// If invalidation is not needed, cacheTabThumbnail() might not do anything and
// send back null.
if (bitmap != null) { if (bitmap != null) {
callback.onResult(bitmap); callback.onResult(bitmap);
return;
} }
// If invalidation is not needed, cacheTabThumbnail() might not do anything, so we
// need to fall back to reading from disk.
nativeGetTabThumbnailWithCallback(mNativeTabContentManager, tab.getId(), callback);
}); });
} else {
nativeGetTabThumbnailWithCallback(mNativeTabContentManager, tab.getId(), callback);
} }
} }
......
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