fix(Spotify): Fix Hide Create button
and Sanitize sharing links
for older but supported app targets (#5159)
This commit is contained in:
@ -37,20 +37,24 @@ public final class HideCreateButtonPatch {
|
||||
return null;
|
||||
}
|
||||
|
||||
String stringifiedNavigationBarItem = navigationBarItem.toString();
|
||||
try {
|
||||
String stringifiedNavigationBarItem = navigationBarItem.toString();
|
||||
|
||||
for (ComponentFilter componentFilter : CREATE_BUTTON_COMPONENT_FILTERS) {
|
||||
if (componentFilter.filterUnavailable()) {
|
||||
Logger.printInfo(() -> "returnNullIfIsCreateButton: Filter " +
|
||||
componentFilter.getFilterRepresentation() + " not available, skipping");
|
||||
continue;
|
||||
}
|
||||
for (ComponentFilter componentFilter : CREATE_BUTTON_COMPONENT_FILTERS) {
|
||||
if (componentFilter.filterUnavailable()) {
|
||||
Logger.printInfo(() -> "returnNullIfIsCreateButton: Filter " +
|
||||
componentFilter.getFilterRepresentation() + " not available, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stringifiedNavigationBarItem.contains(componentFilter.getFilterValue())) {
|
||||
Logger.printInfo(() -> "Hiding Create button because the navigation bar item " + navigationBarItem +
|
||||
" matched the filter " + componentFilter.getFilterRepresentation());
|
||||
return null;
|
||||
if (stringifiedNavigationBarItem.contains(componentFilter.getFilterValue())) {
|
||||
Logger.printInfo(() -> "Hiding Create button because the navigation bar item " +
|
||||
navigationBarItem + " matched the filter " + componentFilter.getFilterRepresentation());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "returnNullIfIsCreateButton failure", ex);
|
||||
}
|
||||
|
||||
return navigationBarItem;
|
||||
|
@ -202,37 +202,41 @@ public final class UnlockPremiumPatch {
|
||||
return false;
|
||||
}
|
||||
|
||||
String stringifiedContextMenuItem = contextMenuItem.toString();
|
||||
try {
|
||||
String stringifiedContextMenuItem = contextMenuItem.toString();
|
||||
|
||||
for (List<ComponentFilter> componentFilters : CONTEXT_MENU_ITEMS_COMPONENT_FILTERS) {
|
||||
boolean allMatch = true;
|
||||
StringBuilder matchedFilterRepresentations = new StringBuilder();
|
||||
for (List<ComponentFilter> componentFilters : CONTEXT_MENU_ITEMS_COMPONENT_FILTERS) {
|
||||
boolean allMatch = true;
|
||||
StringBuilder matchedFilterRepresentations = new StringBuilder();
|
||||
|
||||
for (int i = 0, filterSize = componentFilters.size(); i < filterSize; i++) {
|
||||
ComponentFilter componentFilter = componentFilters.get(i);
|
||||
for (int i = 0, filterSize = componentFilters.size(); i < filterSize; i++) {
|
||||
ComponentFilter componentFilter = componentFilters.get(i);
|
||||
|
||||
if (componentFilter.filterUnavailable()) {
|
||||
Logger.printInfo(() -> "isFilteredContextMenuItem: Filter " +
|
||||
componentFilter.getFilterRepresentation() + " not available, skipping");
|
||||
continue;
|
||||
if (componentFilter.filterUnavailable()) {
|
||||
Logger.printInfo(() -> "isFilteredContextMenuItem: Filter " +
|
||||
componentFilter.getFilterRepresentation() + " not available, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!stringifiedContextMenuItem.contains(componentFilter.getFilterValue())) {
|
||||
allMatch = false;
|
||||
break;
|
||||
}
|
||||
|
||||
matchedFilterRepresentations.append(componentFilter.getFilterRepresentation());
|
||||
if (i < filterSize - 1) {
|
||||
matchedFilterRepresentations.append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (!stringifiedContextMenuItem.contains(componentFilter.getFilterValue())) {
|
||||
allMatch = false;
|
||||
break;
|
||||
}
|
||||
|
||||
matchedFilterRepresentations.append(componentFilter.getFilterRepresentation());
|
||||
if (i < filterSize - 1) {
|
||||
matchedFilterRepresentations.append(", ");
|
||||
if (allMatch) {
|
||||
Logger.printInfo(() -> "Filtering context menu item " + stringifiedContextMenuItem +
|
||||
" because the following filters matched: " + matchedFilterRepresentations);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (allMatch) {
|
||||
Logger.printInfo(() -> "Filtering context menu item " + stringifiedContextMenuItem +
|
||||
" because the following filters matched: " + matchedFilterRepresentations);
|
||||
return true;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "isFilteredContextMenuItem failure", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -72,7 +72,7 @@ val hideCreateButtonPatch = bytecodePatch(
|
||||
|
||||
if (oldNavigationBarAddItemMethod != null) {
|
||||
// In case an older version of the app is being patched, hook the old method which adds navigation bar items.
|
||||
// Return null early if the navigation bar item title resource id is the old Create button title resource id.
|
||||
// Return early if the navigation bar item title resource id is the old Create button title resource id.
|
||||
oldNavigationBarAddItemFingerprint.methodOrNull?.apply {
|
||||
val getNavigationBarItemTitleStringIndex = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
@ -89,6 +89,16 @@ val hideCreateButtonPatch = bytecodePatch(
|
||||
val isOldCreateButtonDescriptor =
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->isOldCreateButton(I)Z"
|
||||
|
||||
val returnEarlyInstruction = if (returnType == "V") {
|
||||
// In older implementations the method return value is void.
|
||||
"return-void"
|
||||
} else {
|
||||
// In newer implementations
|
||||
// return null because the method return value is a BottomNavigationItemView.
|
||||
"const/4 v0, 0\n" +
|
||||
"return-object v0"
|
||||
}
|
||||
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
@ -98,9 +108,7 @@ val hideCreateButtonPatch = bytecodePatch(
|
||||
# If this navigation bar item is not the Create button, jump to the normal method logic.
|
||||
if-eqz v0, :normal-method-logic
|
||||
|
||||
# Return null early because this method return value is a BottomNavigationItemView.
|
||||
const/4 v0, 0
|
||||
return-object v0
|
||||
$returnEarlyInstruction
|
||||
""",
|
||||
ExternalLabel("normal-method-logic", firstInstruction)
|
||||
)
|
||||
|
@ -3,6 +3,7 @@ package app.revanced.patches.spotify.misc.privacy
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val shareCopyUrlFingerprint = fingerprint {
|
||||
returns("Ljava/lang/Object;")
|
||||
@ -23,9 +24,15 @@ internal val shareCopyUrlLegacyFingerprint = fingerprint {
|
||||
}
|
||||
|
||||
internal val formatAndroidShareSheetUrlFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("Ljava/lang/String;")
|
||||
parameters("L", "Ljava/lang/String;")
|
||||
opcodes(
|
||||
Opcode.GOTO,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.RETURN_OBJECT
|
||||
)
|
||||
literal {
|
||||
'\n'.code.toLong()
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@ -56,7 +57,15 @@ val sanitizeSharingLinksPatch = bytecodePatch(
|
||||
shareUrlParameter = "p2"
|
||||
} else {
|
||||
shareSheetFingerprint = formatAndroidShareSheetUrlFingerprint
|
||||
shareUrlParameter = "p1"
|
||||
val methodAccessFlags = formatAndroidShareSheetUrlFingerprint.originalMethod.accessFlags
|
||||
shareUrlParameter = if (AccessFlags.STATIC.isSet(methodAccessFlags)) {
|
||||
// In newer implementations the method is static, so p0 is not `this`.
|
||||
"p1"
|
||||
} else {
|
||||
// In older implementations the method is not static, making it so p0 is `this`.
|
||||
// For that reason, add one to the parameter register.
|
||||
"p2"
|
||||
}
|
||||
}
|
||||
|
||||
shareSheetFingerprint.method.addInstructions(
|
||||
|
Reference in New Issue
Block a user