cache all downloads based on canonical URL, not download URL

This makes the download cache be shared across all mirrors used to download
rather than having a cache per-mirror.
This commit is contained in:
Hans-Christoph Steiner 2019-02-19 14:26:13 +01:00
parent dd14b9e315
commit 14b4a7e00a
4 changed files with 15 additions and 13 deletions

View File

@ -115,7 +115,8 @@ public class ApkCache {
/** /**
* Get the full path for where an APK URL will be downloaded into. * Get the full path for where an APK URL will be downloaded into.
*/ */
public static SanitizedFile getApkDownloadPath(Context context, Uri uri) { public static SanitizedFile getApkDownloadPath(Context context, String urlString) {
Uri uri = Uri.parse(urlString);
File dir = new File(getApkCacheDir(context), uri.getHost() + "-" + uri.getPort()); File dir = new File(getApkCacheDir(context), uri.getHost() + "-" + uri.getPort());
if (!dir.exists()) { if (!dir.exists()) {
dir.mkdirs(); dir.mkdirs();

View File

@ -209,7 +209,7 @@ public class InstallManagerService extends Service {
getObb(urlString, apk.getMainObbUrl(), apk.getMainObbFile(), apk.obbMainFileSha256); getObb(urlString, apk.getMainObbUrl(), apk.getMainObbFile(), apk.obbMainFileSha256);
getObb(urlString, apk.getPatchObbUrl(), apk.getPatchObbFile(), apk.obbPatchFileSha256); getObb(urlString, apk.getPatchObbUrl(), apk.getPatchObbFile(), apk.obbPatchFileSha256);
File apkFilePath = ApkCache.getApkDownloadPath(this, intent.getData()); File apkFilePath = ApkCache.getApkDownloadPath(this, apk.getUrl());
long apkFileSize = apkFilePath.length(); long apkFileSize = apkFilePath.length();
if (!apkFilePath.exists() || apkFileSize < apk.size) { if (!apkFilePath.exists() || apkFileSize < apk.size) {
Utils.debugLog(TAG, "download " + urlString + " " + apkFilePath); Utils.debugLog(TAG, "download " + urlString + " " + apkFilePath);

View File

@ -198,10 +198,10 @@ public class DownloaderService extends Service {
*/ */
private void handleIntent(Intent intent) { private void handleIntent(Intent intent) {
final Uri uri = intent.getData(); final Uri uri = intent.getData();
final SanitizedFile localFile = ApkCache.getApkDownloadPath(this, uri);
long repoId = intent.getLongExtra(Downloader.EXTRA_REPO_ID, 0); long repoId = intent.getLongExtra(Downloader.EXTRA_REPO_ID, 0);
String originalUrlString = intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL); String canonicalUrlString = intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL);
sendBroadcast(uri, Downloader.ACTION_STARTED, localFile, repoId, originalUrlString); final SanitizedFile localFile = ApkCache.getApkDownloadPath(this, canonicalUrlString);
sendBroadcast(uri, Downloader.ACTION_STARTED, localFile, repoId, canonicalUrlString);
try { try {
downloader = DownloaderFactory.create(this, uri, localFile); downloader = DownloaderFactory.create(this, uri, localFile);
@ -219,22 +219,22 @@ public class DownloaderService extends Service {
downloader.download(); downloader.download();
if (downloader.isNotFound()) { if (downloader.isNotFound()) {
sendBroadcast(uri, Downloader.ACTION_INTERRUPTED, localFile, getString(R.string.download_404), sendBroadcast(uri, Downloader.ACTION_INTERRUPTED, localFile, getString(R.string.download_404),
repoId, originalUrlString); repoId, canonicalUrlString);
} else { } else {
sendBroadcast(uri, Downloader.ACTION_COMPLETE, localFile, repoId, originalUrlString); sendBroadcast(uri, Downloader.ACTION_COMPLETE, localFile, repoId, canonicalUrlString);
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
sendBroadcast(uri, Downloader.ACTION_INTERRUPTED, localFile, repoId, originalUrlString); sendBroadcast(uri, Downloader.ACTION_INTERRUPTED, localFile, repoId, canonicalUrlString);
} catch (ConnectException | HttpRetryException | NoRouteToHostException | SocketTimeoutException } catch (ConnectException | HttpRetryException | NoRouteToHostException | SocketTimeoutException
| SSLHandshakeException | SSLKeyException | SSLPeerUnverifiedException | SSLProtocolException | SSLHandshakeException | SSLKeyException | SSLPeerUnverifiedException | SSLProtocolException
| ProtocolException | UnknownHostException e) { | ProtocolException | UnknownHostException e) {
// if the above list of exceptions changes, also change it in IndexV1Updater.update() // if the above list of exceptions changes, also change it in IndexV1Updater.update()
Log.e(TAG, e.getLocalizedMessage()); Log.e(TAG, e.getLocalizedMessage());
sendBroadcast(uri, Downloader.ACTION_CONNECTION_FAILED, localFile, repoId, originalUrlString); sendBroadcast(uri, Downloader.ACTION_CONNECTION_FAILED, localFile, repoId, canonicalUrlString);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
sendBroadcast(uri, Downloader.ACTION_INTERRUPTED, localFile, sendBroadcast(uri, Downloader.ACTION_INTERRUPTED, localFile,
e.getLocalizedMessage(), repoId, originalUrlString); e.getLocalizedMessage(), repoId, canonicalUrlString);
} finally { } finally {
if (downloader != null) { if (downloader != null) {
downloader.close(); downloader.close();

View File

@ -27,7 +27,6 @@ import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoader;
import org.fdroid.fdroid.views.AppDetailsActivity;
import org.fdroid.fdroid.AppUpdateStatusManager; import org.fdroid.fdroid.AppUpdateStatusManager;
import org.fdroid.fdroid.AppUpdateStatusManager.AppUpdateStatus; import org.fdroid.fdroid.AppUpdateStatusManager.AppUpdateStatus;
import org.fdroid.fdroid.R; import org.fdroid.fdroid.R;
@ -39,6 +38,7 @@ import org.fdroid.fdroid.installer.ApkCache;
import org.fdroid.fdroid.installer.InstallManagerService; import org.fdroid.fdroid.installer.InstallManagerService;
import org.fdroid.fdroid.installer.Installer; import org.fdroid.fdroid.installer.Installer;
import org.fdroid.fdroid.installer.InstallerFactory; import org.fdroid.fdroid.installer.InstallerFactory;
import org.fdroid.fdroid.views.AppDetailsActivity;
import org.fdroid.fdroid.views.updates.DismissResult; import org.fdroid.fdroid.views.updates.DismissResult;
import java.io.File; import java.io.File;
@ -483,8 +483,8 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
} }
if (currentStatus != null && currentStatus.status == AppUpdateStatusManager.Status.ReadyToInstall) { if (currentStatus != null && currentStatus.status == AppUpdateStatusManager.Status.ReadyToInstall) {
Uri apkDownloadUri = Uri.parse(currentStatus.apk.getUrl()); String urlString = currentStatus.apk.getUrl();
File apkFilePath = ApkCache.getApkDownloadPath(activity, apkDownloadUri); File apkFilePath = ApkCache.getApkDownloadPath(activity, urlString);
Utils.debugLog(TAG, "skip download, we have already downloaded " + currentStatus.apk.getUrl() + Utils.debugLog(TAG, "skip download, we have already downloaded " + currentStatus.apk.getUrl() +
" to " + apkFilePath); " to " + apkFilePath);
@ -505,6 +505,7 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
} }
}; };
Uri apkDownloadUri = Uri.parse(urlString);
broadcastManager.registerReceiver(receiver, Installer.getInstallIntentFilter(apkDownloadUri)); broadcastManager.registerReceiver(receiver, Installer.getInstallIntentFilter(apkDownloadUri));
Installer installer = InstallerFactory.create(activity, currentStatus.apk); Installer installer = InstallerFactory.create(activity, currentStatus.apk);
installer.installPackage(Uri.parse(apkFilePath.toURI().toString()), apkDownloadUri); installer.installPackage(Uri.parse(apkFilePath.toURI().toString()), apkDownloadUri);