Prevent exception from being serialized in ErrorInfo
The wrong @Decorator was put in the wrong place to mark the throwable fieldd as transient, now this is fixed and the exception is not serialized. So if a non-serializable throwable is passed, that's not an issue, since it's not going to be serialized. The need for EnsureExceptionSerializable is also gone.
This commit is contained in:
parent
09d137f740
commit
397f93b079
|
@ -38,7 +38,6 @@ public class AcraReportSender implements ReportSender {
|
||||||
UserAction.UI_ERROR,
|
UserAction.UI_ERROR,
|
||||||
ErrorInfo.SERVICE_NONE,
|
ErrorInfo.SERVICE_NONE,
|
||||||
"ACRA report",
|
"ACRA report",
|
||||||
R.string.app_ui_crash,
|
R.string.app_ui_crash));
|
||||||
null));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,103 +0,0 @@
|
||||||
package org.schabi.newpipe.error;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectOutputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures that a Exception is serializable.
|
|
||||||
* This is
|
|
||||||
*/
|
|
||||||
public final class EnsureExceptionSerializable {
|
|
||||||
private static final String TAG = "EnsureExSerializable";
|
|
||||||
|
|
||||||
private EnsureExceptionSerializable() {
|
|
||||||
// No instance
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures that an exception is serializable.
|
|
||||||
* <br/>
|
|
||||||
* If that is not the case a {@link WorkaroundNotSerializableException} is created.
|
|
||||||
*
|
|
||||||
* @param exception
|
|
||||||
* @return if an exception is not serializable a new {@link WorkaroundNotSerializableException}
|
|
||||||
* otherwise the exception from the parameter
|
|
||||||
*/
|
|
||||||
public static Exception ensureSerializable(@NonNull final Exception exception) {
|
|
||||||
return checkIfSerializable(exception)
|
|
||||||
? exception
|
|
||||||
: WorkaroundNotSerializableException.create(exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean checkIfSerializable(@NonNull final Exception exception) {
|
|
||||||
try {
|
|
||||||
// Check by creating a new ObjectOutputStream which does the serialization
|
|
||||||
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
ObjectOutputStream oos = new ObjectOutputStream(bos)
|
|
||||||
) {
|
|
||||||
oos.writeObject(exception);
|
|
||||||
oos.flush();
|
|
||||||
|
|
||||||
bos.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (final IOException ex) {
|
|
||||||
Log.d(TAG, "Exception is not serializable", ex);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class WorkaroundNotSerializableException extends Exception {
|
|
||||||
protected WorkaroundNotSerializableException(
|
|
||||||
final Throwable notSerializableException,
|
|
||||||
final Throwable cause) {
|
|
||||||
super(notSerializableException.toString(), cause);
|
|
||||||
setStackTrace(notSerializableException.getStackTrace());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected WorkaroundNotSerializableException(final Throwable notSerializableException) {
|
|
||||||
super(notSerializableException.toString());
|
|
||||||
setStackTrace(notSerializableException.getStackTrace());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static WorkaroundNotSerializableException create(
|
|
||||||
@NonNull final Exception notSerializableException
|
|
||||||
) {
|
|
||||||
// Build a list of the exception + all causes
|
|
||||||
final List<Throwable> throwableList = new ArrayList<>();
|
|
||||||
|
|
||||||
int pos = 0;
|
|
||||||
Throwable throwableToProcess = notSerializableException;
|
|
||||||
|
|
||||||
while (throwableToProcess != null) {
|
|
||||||
throwableList.add(throwableToProcess);
|
|
||||||
|
|
||||||
pos++;
|
|
||||||
throwableToProcess = throwableToProcess.getCause();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reverse list so that it starts with the last one
|
|
||||||
Collections.reverse(throwableList);
|
|
||||||
|
|
||||||
// Build exception stack
|
|
||||||
WorkaroundNotSerializableException cause = null;
|
|
||||||
for (final Throwable t : throwableList) {
|
|
||||||
cause = cause == null
|
|
||||||
? new WorkaroundNotSerializableException(t)
|
|
||||||
: new WorkaroundNotSerializableException(t, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cause;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,6 +2,7 @@ package org.schabi.newpipe.error
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
|
import kotlinx.parcelize.IgnoredOnParcel
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import org.schabi.newpipe.R
|
import org.schabi.newpipe.R
|
||||||
import org.schabi.newpipe.extractor.Info
|
import org.schabi.newpipe.extractor.Info
|
||||||
|
@ -21,11 +22,14 @@ class ErrorInfo(
|
||||||
val userAction: UserAction,
|
val userAction: UserAction,
|
||||||
val serviceName: String,
|
val serviceName: String,
|
||||||
val request: String,
|
val request: String,
|
||||||
val messageStringId: Int,
|
val messageStringId: Int
|
||||||
@Transient // no need to store throwable, all data for report is in other variables
|
|
||||||
var throwable: Throwable? = null
|
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
|
|
||||||
|
// no need to store throwable, all data for report is in other variables
|
||||||
|
// also, the throwable might not be serializable, see TeamNewPipe/NewPipe#7302
|
||||||
|
@IgnoredOnParcel
|
||||||
|
var throwable: Throwable? = null
|
||||||
|
|
||||||
private constructor(
|
private constructor(
|
||||||
throwable: Throwable,
|
throwable: Throwable,
|
||||||
userAction: UserAction,
|
userAction: UserAction,
|
||||||
|
@ -36,9 +40,10 @@ class ErrorInfo(
|
||||||
userAction,
|
userAction,
|
||||||
serviceName,
|
serviceName,
|
||||||
request,
|
request,
|
||||||
getMessageStringId(throwable, userAction),
|
getMessageStringId(throwable, userAction)
|
||||||
throwable
|
) {
|
||||||
)
|
this.throwable = throwable
|
||||||
|
}
|
||||||
|
|
||||||
private constructor(
|
private constructor(
|
||||||
throwable: List<Throwable>,
|
throwable: List<Throwable>,
|
||||||
|
@ -50,9 +55,10 @@ class ErrorInfo(
|
||||||
userAction,
|
userAction,
|
||||||
serviceName,
|
serviceName,
|
||||||
request,
|
request,
|
||||||
getMessageStringId(throwable.firstOrNull(), userAction),
|
getMessageStringId(throwable.firstOrNull(), userAction)
|
||||||
throwable.firstOrNull()
|
) {
|
||||||
)
|
this.throwable = throwable.firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
// constructors with single throwable
|
// constructors with single throwable
|
||||||
constructor(throwable: Throwable, userAction: UserAction, request: String) :
|
constructor(throwable: Throwable, userAction: UserAction, request: String) :
|
||||||
|
|
|
@ -20,10 +20,6 @@ class ErrorUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reports a new error by starting a new activity.
|
* Reports a new error by starting a new activity.
|
||||||
* <br></br>
|
|
||||||
* Ensure that the data within errorInfo is serializable otherwise
|
|
||||||
* an exception will be thrown!<br></br>
|
|
||||||
* [EnsureExceptionSerializable] might help.
|
|
||||||
*
|
*
|
||||||
* @param context
|
* @param context
|
||||||
* @param errorInfo
|
* @param errorInfo
|
||||||
|
|
|
@ -90,8 +90,7 @@ public class SubscriptionsImportFragment extends BaseFragment {
|
||||||
new ErrorInfo(new String[]{}, UserAction.SUBSCRIPTION_IMPORT_EXPORT,
|
new ErrorInfo(new String[]{}, UserAction.SUBSCRIPTION_IMPORT_EXPORT,
|
||||||
NewPipe.getNameOfService(currentServiceId),
|
NewPipe.getNameOfService(currentServiceId),
|
||||||
"Service does not support importing subscriptions",
|
"Service does not support importing subscriptions",
|
||||||
R.string.general_error,
|
R.string.general_error));
|
||||||
null));
|
|
||||||
activity.finish();
|
activity.finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ import androidx.preference.PreferenceManager;
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.error.EnsureExceptionSerializable;
|
|
||||||
import org.schabi.newpipe.error.ErrorInfo;
|
import org.schabi.newpipe.error.ErrorInfo;
|
||||||
import org.schabi.newpipe.error.ErrorUtil;
|
import org.schabi.newpipe.error.ErrorUtil;
|
||||||
import org.schabi.newpipe.error.UserAction;
|
import org.schabi.newpipe.error.UserAction;
|
||||||
|
@ -70,7 +69,7 @@ public class PlayerErrorHandler {
|
||||||
ErrorUtil.createNotification(
|
ErrorUtil.createNotification(
|
||||||
context,
|
context,
|
||||||
new ErrorInfo(
|
new ErrorInfo(
|
||||||
EnsureExceptionSerializable.ensureSerializable(exception),
|
exception,
|
||||||
UserAction.PLAY_STREAM,
|
UserAction.PLAY_STREAM,
|
||||||
"Player error[type=" + exception.type + "] occurred while playing: "
|
"Player error[type=" + exception.type + "] occurred while playing: "
|
||||||
+ info.getUrl(),
|
+ info.getUrl(),
|
||||||
|
|
|
@ -583,7 +583,7 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
|
||||||
|
|
||||||
ErrorUtil.createNotification(mContext,
|
ErrorUtil.createNotification(mContext,
|
||||||
new ErrorInfo(ErrorInfo.Companion.throwableToStringList(mission.errObject), action,
|
new ErrorInfo(ErrorInfo.Companion.throwableToStringList(mission.errObject), action,
|
||||||
service, request.toString(), reason, null));
|
service, request.toString(), reason));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearFinishedDownloads(boolean delete) {
|
public void clearFinishedDownloads(boolean delete) {
|
||||||
|
|
Loading…
Reference in New Issue