Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions lib/src/main/java/com/nextcloud/android/sso/AccountImporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
*/
package com.nextcloud.android.sso;

import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;
import static com.nextcloud.android.sso.Constants.NEXTCLOUD_FILES_ACCOUNT;
import static com.nextcloud.android.sso.Constants.NEXTCLOUD_SSO;
import static com.nextcloud.android.sso.Constants.NEXTCLOUD_SSO_EXCEPTION;
import static com.nextcloud.android.sso.Constants.SSO_SHARED_PREFERENCE;

import android.Manifest;
import android.accounts.Account;
import android.accounts.AccountManager;
Expand All @@ -24,6 +31,10 @@
import android.util.Log;
import android.widget.Toast;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;

import com.nextcloud.android.sso.exceptions.AccountImportCancelledException;
import com.nextcloud.android.sso.exceptions.AndroidGetAccountsPermissionNotGranted;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
Expand All @@ -39,19 +50,9 @@
import java.util.ArrayList;
import java.util.List;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import io.reactivex.annotations.NonNull;
import io.reactivex.annotations.Nullable;

import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;
import static com.nextcloud.android.sso.Constants.NEXTCLOUD_FILES_ACCOUNT;
import static com.nextcloud.android.sso.Constants.NEXTCLOUD_SSO;
import static com.nextcloud.android.sso.Constants.NEXTCLOUD_SSO_EXCEPTION;
import static com.nextcloud.android.sso.Constants.SSO_SHARED_PREFERENCE;

public class AccountImporter {

private static final String TAG = AccountImporter.class.getCanonicalName();
Expand Down Expand Up @@ -120,7 +121,7 @@ private static boolean appInstalledOrNot(Context context) {
PackageManager pm = context.getPackageManager();
for (final var appType : FilesAppTypeRegistry.getInstance().getTypes()) {
try {
pm.getPackageInfo(appType.packageId, PackageManager.GET_ACTIVITIES);
pm.getPackageInfo(appType.packageId(), PackageManager.GET_ACTIVITIES);
returnValue = true;
break;
} catch (PackageManager.NameNotFoundException e) {
Expand Down Expand Up @@ -365,7 +366,7 @@ private static Intent buildRequestAuthTokenIntent(Context context, Intent intent
throw new NextcloudFilesAppAccountPermissionNotGrantedException(context);
}

String componentName = FilesAppTypeRegistry.getInstance().findByAccountType(account.type).packageId;
String componentName = FilesAppTypeRegistry.getInstance().findByAccountType(account.type).packageId();

Intent authIntent = new Intent();
authIntent.setComponent(new ComponentName(componentName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,72 +7,77 @@
*/
package com.nextcloud.android.sso;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.nextcloud.android.sso.model.FilesAppType;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class FilesAppTypeRegistry {
private static final FilesAppTypeRegistry FILES_APP_TYPE_REGISTRY = new FilesAppTypeRegistry();
private final Set<FilesAppType> types = new HashSet<>();
private final Collection<FilesAppType> types = new HashSet<>();

public FilesAppTypeRegistry() {
types.add(new FilesAppType("com.nextcloud.client", "nextcloud", FilesAppType.Type.PROD));
types.add(new FilesAppType("com.nextcloud.android.qa", "nextcloud.qa", FilesAppType.Type.QA));
types.add(new FilesAppType("com.nextcloud.android.beta", "nextcloud.beta", FilesAppType.Type.DEV));
types.add(new FilesAppType("com.nextcloud.client", "nextcloud", FilesAppType.Stage.PROD));
types.add(new FilesAppType("com.nextcloud.android.qa", "nextcloud.qa", FilesAppType.Stage.QA));
types.add(new FilesAppType("com.nextcloud.android.beta", "nextcloud.beta", FilesAppType.Stage.DEV));
}

public static FilesAppTypeRegistry getInstance() {
return FILES_APP_TYPE_REGISTRY;
}

public synchronized void init(FilesAppType type) {
types.clear();

if (type.type != FilesAppType.Type.PROD) {
throw new IllegalArgumentException("If only one FilesAppType added, this must be PROD!");
public synchronized void init(@NonNull FilesAppType type) {
if (type.stage() != FilesAppType.Stage.PROD) {
throw new IllegalArgumentException("If only one " + FilesAppType.class.getSimpleName() + " added, this must be " + FilesAppType.Stage.PROD.name() + "!");
}


types.clear();
types.add(type);
}

public synchronized void init(List<FilesAppType> types) {
this.types.clear();

Optional<FilesAppType> prod = types.stream().filter(t -> t.type == FilesAppType.Type.PROD).findFirst();
if (prod.isEmpty()) {
throw new IllegalArgumentException("One provided FilesAppType must be PROD!");
public synchronized void init(@NonNull Collection<FilesAppType> types) {
if (!types.stream().anyMatch(t -> t.stage() == FilesAppType.Stage.PROD)) {
throw new IllegalArgumentException("At least one provided " + FilesAppType.class.getSimpleName() + " must be " + FilesAppType.Stage.PROD.name() + "!");
}

this.types.clear();
this.types.addAll(types);
}

public Set<FilesAppType> getTypes() {
@NonNull
public Collection<FilesAppType> getTypes() {
return types;
}

@NonNull
public String[] getAccountTypes() {
return types.stream().map(a -> a.accountType).toArray(String[]::new);
return types
.stream()
.map(FilesAppType::accountType)
.toArray(String[]::new);
}


/**
* @return {@link FilesAppType.Type#PROD}, {@link FilesAppType.Type#QA}
* or {@link FilesAppType.Type#DEV} depending on {@param accountType}.
* Uses {@link FilesAppType.Type#PROD} as fallback.
* @return {@link FilesAppType.Stage#PROD}, {@link FilesAppType.Stage#QA}
* or {@link FilesAppType.Stage#DEV} depending on {@param accountType}.
* Uses {@link FilesAppType.Stage#PROD} as fallback.
*/
@NonNull
public FilesAppType findByAccountType(@Nullable String accountType) {
for (final var type : types) {
if (type.accountType.equalsIgnoreCase(accountType)) {
if (type.accountType().equalsIgnoreCase(accountType)) {
return type;
}
}
return types.stream().filter(t -> t.type == FilesAppType.Type.PROD).findFirst().get();

return types
.stream()
.filter(t -> t.stage() == FilesAppType.Stage.PROD)
.findFirst()
.get();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
*/
package com.nextcloud.android.sso.api;

import static com.nextcloud.android.sso.aidl.ParcelFileDescriptorUtil.pipeFrom;
import static com.nextcloud.android.sso.exceptions.SSOException.parseNextcloudCustomException;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
Expand All @@ -20,6 +23,9 @@
import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
import com.nextcloud.android.sso.FilesAppTypeRegistry;
Expand All @@ -38,12 +44,6 @@
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import static com.nextcloud.android.sso.aidl.ParcelFileDescriptorUtil.pipeFrom;
import static com.nextcloud.android.sso.exceptions.SSOException.parseNextcloudCustomException;

public class AidlNetworkRequest extends NetworkRequest {
private static final String TAG = AidlNetworkRequest.class.getCanonicalName();

Expand Down Expand Up @@ -91,7 +91,7 @@ public void connect(String type) {
Log.d(TAG, "[connect] Binding to AccountManagerService for type [" + type + "]");
super.connect(type);

final String componentName = FilesAppTypeRegistry.getInstance().findByAccountType(type).packageId;
final String componentName = FilesAppTypeRegistry.getInstance().findByAccountType(type).packageId();

Log.d(TAG, "[connect] Component name is: [" + componentName + "]");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import android.content.pm.PackageManager;
import android.util.Log;

import androidx.annotation.NonNull;

import com.nextcloud.android.sso.FilesAppTypeRegistry;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotInstalledException;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotSupportedException;
Expand All @@ -20,8 +22,6 @@

import java.util.Optional;

import androidx.annotation.NonNull;

public final class VersionCheckHelper {

private static final String TAG = VersionCheckHelper.class.getCanonicalName();
Expand All @@ -45,7 +45,7 @@ public static boolean verifyMinVersion(@NonNull Context context, int minVersion,
.getInstance()
.getTypes()
.stream()
.filter(t -> t.type == FilesAppType.Type.DEV)
.filter(t -> t.stage() == FilesAppType.Stage.DEV)
.findFirst();
if (dev.isPresent()) {
final int verCode = getNextcloudFilesVersionCode(context, dev.get());
Expand All @@ -66,7 +66,7 @@ public static boolean verifyMinVersion(@NonNull Context context, int minVersion,
}

public static int getNextcloudFilesVersionCode(@NonNull Context context, @NonNull FilesAppType appType) throws PackageManager.NameNotFoundException {
final var packageInfo = context.getPackageManager().getPackageInfo(appType.packageId, 0);
final var packageInfo = context.getPackageManager().getPackageInfo(appType.packageId(), 0);
final int verCode = packageInfo.versionCode;
Log.d("VersionCheckHelper", "Version Code: " + verCode);
return verCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,15 @@

import androidx.annotation.NonNull;

public class FilesAppType {
public final String packageId;
public final String accountType;
public final Type type;
public record FilesAppType(@NonNull String packageId,
@NonNull String accountType,
@NonNull Stage stage) {

public FilesAppType(@NonNull String packageId, @NonNull String accountType, Type type) {
this.packageId = packageId;
this.accountType = accountType;
this.type = type;
public FilesAppType(@NonNull String accountType, @NonNull String packageId) {
this(packageId, accountType, Stage.PROD);
}

public enum Type {
public enum Stage {
PROD, QA, DEV
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,51 +16,53 @@
* <pre>
* {@code
* @GET("/ocs/v2.php/cloud/capabilities?format=json")
* Call<OcsResponse<OcsCapabilities>> getCapabilities();
* Call<OcsResponse < OcsCapabilities>> getCapabilities();
* }
* </pre>
*
* @see <a href="https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-api-overview.html#capabilities-api">Capabilities API</a>
*/
@SuppressWarnings("unused, SpellCheckingInspection")
public class OcsCapabilitiesResponse {
public OcsVersion version;
public OcsCapabilities capabilities;

public static class OcsVersion {
public int major;
public int minor;
public int macro;
public String string;
public String edition;
public boolean extendedSupport;
public record OcsCapabilitiesResponse(
OcsVersion version,
OcsCapabilities capabilities
) {
public record OcsVersion(
int major,
int minor,
int macro,
String string,
String edition,
boolean extendedSupport
) {
}

public static class OcsCapabilities {
public OcsTheming theming;

public static class OcsTheming {
public String name;
public String url;
public String slogan;
public String color;
public record OcsCapabilities(
OcsTheming theming
) {
public record OcsTheming(
String name,
String url,
String slogan,
String color,
@SerializedName("color-text")
public String colorText;
String colorText,
@SerializedName("color-element")
public String colorElement;
String colorElement,
@SerializedName("color-element-bright")
public String colorElementBright;
String colorElementBright,
@SerializedName("color-element-dark")
public String colorElementDark;
public String logo;
public String background;
String colorElementDark,
String logo,
String background,
@SerializedName("background-plain")
public boolean backgroundPlain;
boolean backgroundPlain,
@SerializedName("background-default")
public boolean backgroundDefault;
boolean backgroundDefault,
@SerializedName("logoheader")
public String logoHeader;
public String favicon;
String logoHeader,
String favicon
) {
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,26 @@
* <pre>
* {@code
* @GET("/ocs/v2.php/cloud/capabilities?format=json")
* Call<OcsResponse<OcsCapabilitiesResponse>> getCapabilities();
* Call<OcsResponse < OcsCapabilitiesResponse>> getCapabilities();
* }
* </pre>
*
* @param <T> defines the payload type of this {@link OcsResponse}.
*/
@SuppressWarnings("unused, SpellCheckingInspection")
public class OcsResponse<T> {
public OcsWrapper<T> ocs;

public static class OcsWrapper<T> {
public OcsMeta meta;
public T data;

public static class OcsMeta {
public String status;
public record OcsResponse<T>(
OcsWrapper<T> ocs
) {
public record OcsWrapper<T>(
OcsMeta meta,
T data
) {
public record OcsMeta(
String status,
@SerializedName("statuscode")
public int statusCode;
public String message;
int statusCode,
String message
) {
}
}
}
Loading