Fix #666 Glide does not use SSO network stack

Signed-off-by: stefan-niedermann <info@niedermann.it>
This commit is contained in:
stefan-niedermann 2020-02-10 13:50:38 +01:00
parent 0125009abc
commit 0bcfc0b14f
3 changed files with 199 additions and 0 deletions

View file

@ -0,0 +1,29 @@
package it.niedermann.owncloud.notes.util.glide;
import android.content.Context;
import androidx.annotation.NonNull;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Registry;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.module.AppGlideModule;
import com.bumptech.glide.module.LibraryGlideModule;
import java.io.InputStream;
/**
* Registers OkHttp related classes via Glide's annotation processor.
*
* <p>For Applications that depend on this library and include an {@link AppGlideModule} and Glide's
* annotation processor, this class will be automatically included.
*/
@GlideModule
public final class SingleSignOnLibraryGlideModule extends LibraryGlideModule {
@Override
public void registerComponents(
@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
registry.replace(GlideUrl.class, InputStream.class, new SingleSignOnUrlLoader.Factory(context));
}
}

View file

@ -0,0 +1,80 @@
package it.niedermann.owncloud.notes.util.glide;
import androidx.annotation.NonNull;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.model.GlideUrl;
import com.nextcloud.android.sso.aidl.NextcloudRequest;
import com.nextcloud.android.sso.api.NextcloudAPI;
import com.nextcloud.android.sso.api.Response;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Fetches an {@link InputStream} using the sso library.
*/
public class SingleSignOnStreamFetcher implements DataFetcher<InputStream> {
private final NextcloudAPI client;
private final GlideUrl url;
// Public API.
@SuppressWarnings("WeakerAccess")
public SingleSignOnStreamFetcher(NextcloudAPI client, GlideUrl url) {
this.client = client;
this.url = url;
}
@Override
public void loadData(@NonNull Priority priority, @NonNull final DataCallback<? super InputStream> callback) {
NextcloudRequest.Builder requestBuilder = null;
try {
requestBuilder = new NextcloudRequest.Builder()
.setMethod("GET")
.setUrl(url.toURL().getPath());
Map<String, List<String>> header = new HashMap<>();
for (Map.Entry<String, String> headerEntry : url.getHeaders().entrySet()) {
header.put(headerEntry.getKey(), Collections.singletonList(headerEntry.getValue()));
}
requestBuilder.setHeader(header);
NextcloudRequest nextcloudRequest = requestBuilder.build();
Response response = client.performNetworkRequestV2(nextcloudRequest);
callback.onDataReady(response.getBody());
} catch (MalformedURLException e) {
callback.onLoadFailed(e);
} catch (Exception e) {
callback.onLoadFailed(e);
}
}
@Override
public void cleanup() {
}
@Override
public void cancel() {
}
@NonNull
@Override
public Class<InputStream> getDataClass() {
return InputStream.class;
}
@NonNull
@Override
public DataSource getDataSource() {
return DataSource.REMOTE;
}
}

View file

@ -0,0 +1,90 @@
package it.niedermann.owncloud.notes.util.glide;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.model.ModelLoaderFactory;
import com.bumptech.glide.load.model.MultiModelLoaderFactory;
import com.google.gson.GsonBuilder;
import com.nextcloud.android.sso.api.NextcloudAPI;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
import com.nextcloud.android.sso.helper.SingleAccountHelper;
import java.io.InputStream;
/**
* A simple model loader for fetching media over http/https using OkHttp.
*/
public class SingleSignOnUrlLoader implements ModelLoader<GlideUrl, InputStream> {
private static final String TAG = SingleSignOnUrlLoader.class.getCanonicalName();
private final NextcloudAPI client;
// Public API.
@SuppressWarnings("WeakerAccess")
public SingleSignOnUrlLoader(@NonNull NextcloudAPI client) {
this.client = client;
}
@Override
public boolean handles(@NonNull GlideUrl url) {
return true;
}
@Override
public LoadData<InputStream> buildLoadData(
@NonNull GlideUrl model, int width, int height, @NonNull Options options) {
return new LoadData<>(model, new SingleSignOnStreamFetcher(client, model));
}
/**
* The default factory for {@link SingleSignOnUrlLoader}s.
*/
// Public API.
@SuppressWarnings("WeakerAccess")
public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
private boolean isConnected = false;
private SingleSignOnUrlLoader loader;
/**
* Constructor for a new Factory that runs requests using given client.
*/
public Factory(@NonNull Context context) {
try {
loader = new SingleSignOnUrlLoader(new NextcloudAPI(context, SingleAccountHelper.getCurrentSingleSignOnAccount(context), new GsonBuilder().create(), new NextcloudAPI.ApiConnectedListener() {
@Override
public void onConnected() {
isConnected = true;
Log.v(TAG, "success: init SSO-Api");
}
@Override
public void onError(Exception ex) {
Log.e(TAG, ex.getMessage(), ex);
}
}));
} catch (NextcloudFilesAppAccountNotFoundException e) {
e.printStackTrace();
} catch (NoCurrentAccountSelectedException e) {
e.printStackTrace();
}
}
@NonNull
@Override
public ModelLoader<GlideUrl, InputStream> build(MultiModelLoaderFactory multiFactory) {
return loader;
}
@Override
public void teardown() {
// Do nothing, this instance doesn't own the client.
}
}
}