Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TIMOB-25663] Android: HttpClient.cache. ImageView.cache #9719

Closed
wants to merge 12 commits into from

Conversation

drauggres
Copy link
Contributor

JIRA: https://jira.appcelerator.org/browse/TIMOB-25663

Add Ti.Android.HttpResponseCache module
Add Ti.Network.HTTPClient cache property
Add Ti.UI.ImageView cache property

@build
Copy link
Contributor

build commented Jan 11, 2018

Messages
📖

🎉 Another contribution from our awesome community member, drauggres! Thanks again for helping us make Titanium SDK better. 👍

Generated by 🚫 dangerJS

@hansemannn
Copy link
Collaborator

@drauggres Thanks for all your work on this! We will schedule this for the next release now. Can you please re-sign the Axway CLA? It was changed lately to migrate the legal part of the swaggy open source community to our legal team.

@hansemannn hansemannn added this to the 7.4.0 milestone Jun 28, 2018
@build
Copy link
Contributor

build commented Jun 28, 2018

Messages
📖

🎉 Another contribution from our awesome community member, drauggres! Thanks again for helping us make Titanium SDK better. 👍

Generated by 🚫 dangerJS

'use strict';
var should = require('./utilities/assertions');

describe('Titanium.Android.HttpResponseCache', function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can just do describe.android('Titanium.Android.HttpResponseCache', function () { and all the nested tests all be limited to android, so that you don't need to ad date filter to each it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

require('./ti.accelerometer.test');
require('./ti.analytics.test');
require('./ti.api.test');
require('./ti.android.httpresponsecache.test');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once I merge to the full test suite, I'd modify the app.js like this, but for PRs the easier way to avoid it is to simply ensure your additional tests are named ti.whatever.addontest.js and they'll get picked up automatically. The addontest.js suffix is what gets it picked up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove app.js
Probably someone should update README

xhr.send();
});

it.android('HttpResponseCache xhr.cache custom', function (finish) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, you can just add an "add-on test" to add new unit tests to the suite and not have to copy/override the existing API test file. Makes it easier for you and for us to see the new tests added.

Copying and modifying is what's necessary for modifying existing tests (say fixing a test we skip on a given platform and re-enabling it).

So anyways, for next time, you could just create a ti.network.httpclient.addontest.js and add these two new tests to it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

{
HttpResponseCache cache = HttpResponseCache.getInstalled();
if (cache != null) {
cache.getNetworkCount();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing return here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

// clang-format off
@Kroll.method
@Kroll.getProperty
public long getHttpCacheSize()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not real fond of the long name here. I assume it was used to not clash with the size() method?

Why not just mirror the underlying API's use of maxSize for the property/method name?

Additionally, please note that we're going to be moving away from getter/setter methods that just wrap properties in favor of using typical JS property accessors. So in this case, that'd be removing the @Kroll.method annotation and just assigning this method to be the backing impl for cache.httpCacheSize calls in JS. (Or hopefully cache.maxSize if the property is renamed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maxSize it is

// clang-format off
@Kroll.method
@Kroll.setProperty
public void setHttpCachePath(String value)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, not fond of the long name. Why not just use path as the property?

Also, the setter method would be deprecated in 8.0.0 immediately anyhow. So maybe just use this as the @Kroll.setProperty impl backing cache.path = 'whatever'; calls. (i.e. remove @Kroll.method)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

httpCachePath -> path, property only

Copy link
Contributor

@sgtcoolguy sgtcoolguy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a very nice API addition that could be very helpful for app developers. Thanks, @drauggres !

My first concern is that the path set is only a relative path and doesn't offer control whether the cache gets put in the external cache or the app cache dir, which can have security/data privacy issues. I think the property should be the full path so the dev has control to explicitly choose that (though perhaps it could default to app cache directory or something). To enable that we may need to expose the external cache dir in our APIs.

I'm also concerned that this is very Android-specific, as I believe iOS could also implement something similar as well here.

@hansemannn Can you please take a look and see if we couldn't make this a more general API cross-platform? Maybe hang it off Ti.Network.Cache or something?

// clang-format off
@Kroll.method
@Kroll.setProperty
public void setHttpCacheSize(long value)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setMaxSize(long value)?

// clang-format off
@Kroll.method
@Kroll.getProperty
public String getHttpCachePath()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getPath()? Remove the @Kroll.method annotation (and then the clang-format comments are unnecessary too)?

if (cache != null) {
return cache.size();
}
return 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this return -1? Or do we want to have differing values for "no cache installed" versus "cache installed, but unable to determine size"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or do we want to have differing values for "no cache installed" versus "cache installed, but unable to determine size"?

I think, we shouldn't mix it.

@@ -163,7 +165,14 @@ public static TiDrawableReference fromUrl(KrollProxy proxy, String url)
if (url == null || url.length() == 0 || url.trim().length() == 0) {
return new TiDrawableReference(proxy.getActivity(), DrawableReferenceType.NULL);
}
return fromUrl(proxy.getActivity(), proxy.resolveUrl(null, url));
boolean useCaches = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can shorten this to:

boolean useCaches = TiConvert.toBoolean(proxy.getProperty(TiC.PROPERTY_CACHE), false);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@@ -239,8 +248,15 @@ public static TiDrawableReference fromObject(KrollProxy proxy, Object object)
object = proxy.resolveUrl(null, (String) object);
}

boolean useCaches = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, you can shrink this down to a one-liner

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

extends: Titanium.Proxy
platforms: [android]
createable: false
since: "7.1.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, we clearly missed this release. This will need to be updated for whatever release we can get this in. master is currently targeting 7.4.0, but I think feature freeze may be happening for that real soon.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to 7.4.0


- name: httpCacheSize
summary: Maximum cache size in bytes.
description: |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maye want to add some details/notes that this needs to be set before #install() and once that's called this can't be changed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add this note:

To apply changes of this property to existing HttpResponseCache instance, you should call [install](Titanium.Android.HttpResponseCache.install) method.

- name: httpCachePath
summary: Relative path for cache
description: |
HTTP response cache will be stored on external storage if it exists on moment
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, maybe more more explicit that this property is consulted at time #install() is called, but changing later won't do anything. (In fact we may even want to spit out some warning logs in the impl if they get called after #install()).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add this note:

To apply changes of this property to existing HttpResponseCache instance, you should call [install](Titanium.Android.HttpResponseCache.install) method.

cache.close();
}
TiApplication tiApp = TiApplication.getInstance();
File dir = tiApp.getApplicationContext().getExternalCacheDir();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not have the path (or httpCacheDir) property value determine the directory and relative path to store the cache?

I'm worried here because the Android docs point out that if the requests contain private data, the external cache dir is a bad place to stick the cache due to access controls not being enforced on external storage.

I'm assuming it's because we don't actually expose the external cache dir anywhere in our APIs? cc @garymathews @jquick-axway

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming it's because we don't actually expose the external cache dir anywhere in our APIs?

Yes. Also this is how currently cacheDir calculated for TiResponseCache.

@drauggres
Copy link
Contributor Author

@sgtcoolguy Thanks for thorough code review.

My first concern is that the path set is only a relative path and doesn't offer control whether the cache gets put in the external cache or the app cache dir, which can have security/data privacy issues. I think the property should be the full path so the dev has control to explicitly choose that (though perhaps it could default to app cache directory or something). To enable that we may need to expose the external cache dir in our APIs.

What about additional boolean property (smth like preferExternalCacheDir) with default value false? It will be much easier to implement.

@jquick-axway
Copy link
Contributor

I have to agree with @hansemannn comment here that the API to control the response cache (deletion, size, location, etc.) should be redesigned to so that it can work on both Android and iOS.

I also don't like the idea of replacing our TiResponseCache with Google's HttpResponseCache. We've added additional APIs to our class to have better control over it and to better handle "redirect" cache handling. Whatever feature we're missing should be added to TiResponseCache.

I do agree that we should add "cache" property support to HTTPClient. That is best done via a separate simpler PR. I've already written a ticket for it here: TIMOB-26501

I'd prefer to keep our ImageView simple. Especially from a portability standpoint. If you want greater control over HTTP handling when loading images, then that is best done via our HTTPClient and the downloaded image can then be applied to ImageView.

@drauggres
Copy link
Contributor Author

Resume:

  • Ti.Network.HTTPClient cache property on Android: see TIMOB-26501
  • image cache control: load remote images via HTTPClient and control caching manually (or use To.ImageCache)
  • general HttpResponseCache control and statistics: need to implement it in TiResponseCache

@drauggres drauggres closed this Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants