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
69 changes: 51 additions & 18 deletions src/main/java/com/nextcloud/android/sso/api/NextcloudAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.Looper;
import android.os.NetworkOnMainThreadException;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
Expand All @@ -34,6 +35,7 @@
import com.nextcloud.android.sso.aidl.IThreadListener;
import com.nextcloud.android.sso.aidl.NextcloudRequest;
import com.nextcloud.android.sso.aidl.ParcelFileDescriptorUtil;
import com.nextcloud.android.sso.exceptions.NextcloudApiNotRespondingException;
import com.nextcloud.android.sso.helper.ExponentialBackoff;
import com.nextcloud.android.sso.model.SingleSignOnAccount;

Expand All @@ -49,6 +51,7 @@
import java.io.ObjectOutputStream;
import java.io.Reader;
import java.lang.reflect.Type;
import java.util.concurrent.atomic.AtomicBoolean;

import io.reactivex.Observable;
import io.reactivex.annotations.NonNull;
Expand All @@ -57,9 +60,20 @@

public class NextcloudAPI {

private static final String TAG = NextcloudAPI.class.getCanonicalName();

private Gson gson;
private IInputStreamService mService = null;
private final AtomicBoolean mBound = new AtomicBoolean(false); // Flag indicating whether we have called bind on the service
private boolean mDestroyed = false; // Flag indicating if API is destroyed
private SingleSignOnAccount mAccount;
private ApiConnectedListener mCallback;
private Context mContext;



public interface ApiConnectedListener {
void onConnected();

void onError(Exception ex);
}

Expand All @@ -72,17 +86,6 @@ public NextcloudAPI(Context context, SingleSignOnAccount account, Gson gson, Api
connectApiWithBackoff();
}

private static final String TAG = NextcloudAPI.class.getCanonicalName();

private Gson gson;
private IInputStreamService mService = null;
private boolean mBound = false; // Flag indicating whether we have called bind on the service
private boolean mDestroyed = false; // Flag indicating if API is destroyed
private SingleSignOnAccount mAccount;
private ApiConnectedListener mCallback;
private Context mContext;


private String getAccountName() {
return mAccount.name;
}
Expand All @@ -106,7 +109,7 @@ private void connect() {
}

// Disconnect if connected
if (mBound) {
if (mBound.get()) {
stop();
}

Expand All @@ -132,13 +135,13 @@ public void stop() {
mCallback = null;

// Unbind from the service
if (mBound) {
if (mBound.get()) {
if (mContext != null) {
mContext.unbindService(mConnection);
} else {
Log.e(TAG, "Context was null, cannot unbind nextcloud single sign-on service connection!");
}
mBound = false;
mBound.set(false);
mContext = null;
}
}
Expand All @@ -152,7 +155,10 @@ public void onServiceConnected(ComponentName className, IBinder service) {
Log.i(TAG, "Nextcloud Single sign-on: onServiceConnected");

mService = IInputStreamService.Stub.asInterface(service);
mBound = true;
mBound.set(true);
synchronized (mBound) {
mBound.notifyAll();
}
mCallback.onConnected();
}

Expand All @@ -161,14 +167,32 @@ public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mBound = false;
mBound.set(false);

if (!mDestroyed) {
connectApiWithBackoff();
}
}
};

private void waitForApi() throws NextcloudApiNotRespondingException {
synchronized (mBound) {
// If service is not bound yet.. wait
if(!mBound.get()) {
Log.v(TAG, "[waitForApi] - api not ready yet.. waiting [" + Thread.currentThread().getName() + "]");
try {
mBound.wait(10000); // wait up to 10 seconds

// If api is still not bound after 10 seconds.. throw an exception
if(!mBound.get()) {
throw new NextcloudApiNotRespondingException();
}
} catch (InterruptedException ex) {
Log.e(TAG, "WaitForAPI failed", ex);
}
}
}
}

public <T> Observable<T> performRequestObservable(final Type type, final NextcloudRequest request) {
return Observable.fromPublisher(new Publisher<T>() {
Expand Down Expand Up @@ -249,7 +273,16 @@ public InputStream performNetworkRequest(NextcloudRequest request) throws Except
* @throws IOException
*/
private ParcelFileDescriptor performAidlNetworkRequest(NextcloudRequest request)
throws IOException, RemoteException {
throws IOException, RemoteException, NextcloudApiNotRespondingException {

// Check if we are on the main thread
if(Looper.myLooper() == Looper.getMainLooper()) {
throw new NetworkOnMainThreadException();
}

// Wait for api to be initialized
waitForApi();

// Log.d(TAG, request.url);
request.setAccountName(getAccountName());
request.setToken(getAccountToken());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.nextcloud.android.sso.exceptions;

import android.content.Context;

import com.nextcloud.android.sso.R;
import com.nextcloud.android.sso.model.ExceptionMessage;

public class NextcloudApiNotRespondingException extends SSOException {

@Override
public void loadExceptionMessage(Context context) {
this.em = new ExceptionMessage(
context.getString(R.string.nextcloud_files_api_not_responsing_title),
context.getString(R.string.nextcloud_files_api_not_responsing_message)
);
}

}
4 changes: 4 additions & 0 deletions src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
<string name="nextcloud_files_app_not_supported_title">Error</string>
<string name="nextcloud_files_app_not_supported_message" formatted="true">Your nextcloud files app currently does not support the single sign on feature. Please update it: %1$s</string>


<string name="nextcloud_files_api_not_responsing_title">Error</string>
<string name="nextcloud_files_api_not_responsing_message">Nextcloud files app api is not responding. Please report this issue.</string>

<string name="select_account_unknown_error_toast">Something went wrong.. please try again</string>

</resources>