refactor(Spotify): Add extensions debug logging (#5110)
This commit is contained in:
@ -6,7 +6,7 @@ dependencies {
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = 24
|
minSdk = 21
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
@ -2,6 +2,7 @@ package app.revanced.extension.spotify.layout.hide.createbutton;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import app.revanced.extension.shared.Logger;
|
||||||
import app.revanced.extension.shared.Utils;
|
import app.revanced.extension.shared.Utils;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@ -31,10 +32,21 @@ public final class HideCreateButtonPatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String stringifiedNavigationBarItem = navigationBarItem.toString();
|
String stringifiedNavigationBarItem = navigationBarItem.toString();
|
||||||
boolean isCreateButton = CREATE_BUTTON_TITLE_RES_ID_LIST.stream()
|
|
||||||
.anyMatch(stringifiedNavigationBarItem::contains);
|
boolean isCreateButton = false;
|
||||||
|
String matchedTitleResId = null;
|
||||||
|
|
||||||
|
for (String titleResId : CREATE_BUTTON_TITLE_RES_ID_LIST) {
|
||||||
|
if (stringifiedNavigationBarItem.contains(titleResId)) {
|
||||||
|
isCreateButton = true;
|
||||||
|
matchedTitleResId = titleResId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isCreateButton) {
|
if (isCreateButton) {
|
||||||
|
String finalMatchedTitleResId = matchedTitleResId;
|
||||||
|
Logger.printInfo(() -> "Hiding Create button because the navigation bar item " + navigationBarItem +
|
||||||
|
" matched the title resource id " + finalMatchedTitleResId);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +58,14 @@ public final class HideCreateButtonPatch {
|
|||||||
* Create button.
|
* Create button.
|
||||||
*/
|
*/
|
||||||
public static boolean isOldCreateButton(int oldNavigationBarItemTitleResId) {
|
public static boolean isOldCreateButton(int oldNavigationBarItemTitleResId) {
|
||||||
return oldNavigationBarItemTitleResId == OLD_CREATE_BUTTON_TITLE_RES_ID;
|
boolean isCreateButton = oldNavigationBarItemTitleResId == OLD_CREATE_BUTTON_TITLE_RES_ID;
|
||||||
|
|
||||||
|
if (isCreateButton) {
|
||||||
|
Logger.printInfo(() -> "Hiding old Create button because the navigation bar item title resource id" +
|
||||||
|
" matched " + OLD_CREATE_BUTTON_TITLE_RES_ID);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import static java.lang.Boolean.TRUE;
|
|||||||
|
|
||||||
import com.spotify.home.evopage.homeapi.proto.Section;
|
import com.spotify.home.evopage.homeapi.proto.Section;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -133,19 +134,35 @@ public final class UnlockPremiumPatch {
|
|||||||
try {
|
try {
|
||||||
for (OverrideAttribute override : PREMIUM_OVERRIDES) {
|
for (OverrideAttribute override : PREMIUM_OVERRIDES) {
|
||||||
Object attribute = attributes.get(override.key);
|
Object attribute = attributes.get(override.key);
|
||||||
|
|
||||||
if (attribute == null) {
|
if (attribute == null) {
|
||||||
if (override.isExpected) {
|
if (override.isExpected) {
|
||||||
Logger.printException(() -> "'" + override.key + "' expected but not found");
|
Logger.printException(() -> "Attribute " + override.key + " expected but not found");
|
||||||
}
|
}
|
||||||
} else {
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Object overrideValue = override.overrideValue;
|
Object overrideValue = override.overrideValue;
|
||||||
|
Object originalValue;
|
||||||
|
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
|
||||||
|
originalValue = ((com.spotify.useraccount.v1.AccountAttribute) attribute).value_;
|
||||||
|
} else {
|
||||||
|
originalValue = ((com.spotify.remoteconfig.internal.AccountAttribute) attribute).value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overrideValue == originalValue) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.printInfo(() -> "Overriding account attribute " + override.key +
|
||||||
|
" from " + originalValue + " to " + overrideValue);
|
||||||
|
|
||||||
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
|
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
|
||||||
((com.spotify.useraccount.v1.AccountAttribute) attribute).value_ = overrideValue;
|
((com.spotify.useraccount.v1.AccountAttribute) attribute).value_ = overrideValue;
|
||||||
} else {
|
} else {
|
||||||
((com.spotify.remoteconfig.internal.AccountAttribute) attribute).value_ = overrideValue;
|
((com.spotify.remoteconfig.internal.AccountAttribute) attribute).value_ = overrideValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "overrideAttributes failure", ex);
|
Logger.printException(() -> "overrideAttributes failure", ex);
|
||||||
}
|
}
|
||||||
@ -155,7 +172,13 @@ public final class UnlockPremiumPatch {
|
|||||||
* Injection point. Remove station data from Google Assistant URI.
|
* Injection point. Remove station data from Google Assistant URI.
|
||||||
*/
|
*/
|
||||||
public static String removeStationString(String spotifyUriOrUrl) {
|
public static String removeStationString(String spotifyUriOrUrl) {
|
||||||
|
try {
|
||||||
|
Logger.printInfo(() -> "Removing station string from " + spotifyUriOrUrl);
|
||||||
return spotifyUriOrUrl.replace("spotify:station:", "spotify:");
|
return spotifyUriOrUrl.replace("spotify:station:", "spotify:");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Logger.printException(() -> "removeStationString failure", ex);
|
||||||
|
return spotifyUriOrUrl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -164,9 +187,17 @@ public final class UnlockPremiumPatch {
|
|||||||
*/
|
*/
|
||||||
public static void removeHomeSections(List<Section> sections) {
|
public static void removeHomeSections(List<Section> sections) {
|
||||||
try {
|
try {
|
||||||
sections.removeIf(section -> REMOVED_HOME_SECTIONS.contains(section.featureTypeCase_));
|
Iterator<Section> iterator = sections.iterator();
|
||||||
|
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Section section = iterator.next();
|
||||||
|
if (REMOVED_HOME_SECTIONS.contains(section.featureTypeCase_)) {
|
||||||
|
Logger.printInfo(() -> "Removing home section with feature type id " + section.featureTypeCase_);
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "Remove home sections failure", ex);
|
Logger.printException(() -> "removeHomeSections failure", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,7 +210,30 @@ public final class UnlockPremiumPatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String stringifiedContextMenuItem = contextMenuItem.toString();
|
String stringifiedContextMenuItem = contextMenuItem.toString();
|
||||||
return FILTERED_CONTEXT_MENU_ITEMS_BY_STRINGS.stream()
|
for (List<String> stringList : FILTERED_CONTEXT_MENU_ITEMS_BY_STRINGS) {
|
||||||
.anyMatch(filters -> filters.stream().allMatch(stringifiedContextMenuItem::contains));
|
boolean allMatch = true;
|
||||||
|
StringBuilder matchedStrings = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < stringList.size(); i++) {
|
||||||
|
String string = stringList.get(i);
|
||||||
|
if (!stringifiedContextMenuItem.contains(string)) {
|
||||||
|
allMatch = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
matchedStrings.append(string);
|
||||||
|
if (i < stringList.size() - 1) {
|
||||||
|
matchedStrings.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allMatch) {
|
||||||
|
Logger.printInfo(() -> "Filtering context menu item " + stringifiedContextMenuItem +
|
||||||
|
" because the following strings matched: " + matchedStrings);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,10 +33,11 @@ public final class SanitizeSharingLinksPatch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.build().toString();
|
String sanitizedUrl = builder.build().toString();
|
||||||
|
Logger.printInfo(() -> "Sanitized url " + url + " to " + sanitizedUrl);
|
||||||
|
return sanitizedUrl;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "sanitizeUrl failure", ex);
|
Logger.printException(() -> "sanitizeUrl failure with " + url, ex);
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ android {
|
|||||||
compileSdk = 34
|
compileSdk = 34
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = 24
|
minSdk = 21
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
@ -72,7 +72,7 @@ val hideCreateButtonPatch = bytecodePatch(
|
|||||||
|
|
||||||
if (oldNavigationBarAddItemMethod != null) {
|
if (oldNavigationBarAddItemMethod != null) {
|
||||||
// In case an older version of the app is being patched, hook the old method which adds navigation bar items.
|
// 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 old Create button title resource id.
|
// Return null early if the navigation bar item title resource id is the old Create button title resource id.
|
||||||
oldNavigationBarAddItemFingerprint.methodOrNull?.apply {
|
oldNavigationBarAddItemFingerprint.methodOrNull?.apply {
|
||||||
val getNavigationBarItemTitleStringIndex = indexOfFirstInstructionOrThrow {
|
val getNavigationBarItemTitleStringIndex = indexOfFirstInstructionOrThrow {
|
||||||
val reference = getReference<MethodReference>()
|
val reference = getReference<MethodReference>()
|
||||||
|
@ -129,7 +129,7 @@ val customThemePatch = resourcePatch(
|
|||||||
val accentColorPressed by stringOption(
|
val accentColorPressed by stringOption(
|
||||||
key = "accentColorPressed",
|
key = "accentColorPressed",
|
||||||
default = "#FF1ABC54",
|
default = "#FF1ABC54",
|
||||||
title = "Pressed dark theme accent color",
|
title = "Pressed accent color",
|
||||||
description = "The color when accented buttons are pressed, by default slightly darker than accent. " +
|
description = "The color when accented buttons are pressed, by default slightly darker than accent. " +
|
||||||
"Can be a hex color or a resource reference.",
|
"Can be a hex color or a resource reference.",
|
||||||
required = true,
|
required = true,
|
||||||
|
@ -38,7 +38,7 @@ val unlockPremiumPatch = bytecodePatch(
|
|||||||
// so for now this is a dependent of this patch.
|
// so for now this is a dependent of this patch.
|
||||||
//
|
//
|
||||||
// FIXME: Modifying string resources (such as adding patch strings)
|
// FIXME: Modifying string resources (such as adding patch strings)
|
||||||
// is currently failing with ReVanced manager.
|
// is currently failing with ReVanced Manager.
|
||||||
// checkEnvironmentPatch,
|
// checkEnvironmentPatch,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ val unlockPremiumPatch = bytecodePatch(
|
|||||||
// Need to allow mutation of the list so the home ads sections can be removed.
|
// Need to allow mutation of the list so the home ads sections can be removed.
|
||||||
// Protobuf array list has an 'isMutable' boolean parameter that sets the mutability.
|
// Protobuf array list has an 'isMutable' boolean parameter that sets the mutability.
|
||||||
// Forcing that always on breaks unrelated code in strange ways.
|
// Forcing that always on breaks unrelated code in strange ways.
|
||||||
// Instead, return early in the method that throws an error if the list is unmutable.
|
// Instead, return early in the method that throws an error if the list is immutable.
|
||||||
abstractProtobufListEnsureIsMutableFingerprint.match(abstractProtobufListClassDef)
|
abstractProtobufListEnsureIsMutableFingerprint.match(abstractProtobufListClassDef)
|
||||||
.method.returnEarly()
|
.method.returnEarly()
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ val fixFacebookLoginPatch = bytecodePatch(
|
|||||||
// The Facebook SDK tries to handle the login using the Facebook app in case it is installed.
|
// The Facebook SDK tries to handle the login using the Facebook app in case it is installed.
|
||||||
// However, the Facebook app does signature checks with the app that is requesting the authentication,
|
// However, the Facebook app does signature checks with the app that is requesting the authentication,
|
||||||
// which ends up making the Facebook server reject with an invalid key hash for the app signature.
|
// which ends up making the Facebook server reject with an invalid key hash for the app signature.
|
||||||
// Override the Faceboook SDK to always handle the login using the web browser, which does not perform
|
// Override the Facebook SDK to always handle the login using the web browser, which does not perform
|
||||||
// signature checks.
|
// signature checks.
|
||||||
|
|
||||||
val katanaProxyLoginMethodHandlerClass = katanaProxyLoginMethodHandlerClassFingerprint.originalClassDef
|
val katanaProxyLoginMethodHandlerClass = katanaProxyLoginMethodHandlerClassFingerprint.originalClassDef
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package app.revanced.patches.spotify.misc.widgets
|
package app.revanced.patches.spotify.misc.widgets
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint
|
import app.revanced.patcher.fingerprint
|
||||||
import app.revanced.util.indexOfFirstInstruction
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
internal val canBindAppWidgetPermissionFingerprint = fingerprint {
|
internal val canBindAppWidgetPermissionFingerprint = fingerprint {
|
||||||
|
Reference in New Issue
Block a user