mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-07 01:51:27 +01:00
feat(Instagram): Add Open links externally patch (#6012)
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
package app.revanced.extension.instagram.misc.links;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class OpenLinksExternallyPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean openExternally(String url) {
|
||||
try {
|
||||
// The "url" parameter to this function will be of the form.
|
||||
// https://l.instagram.com/?u=<actual url>&e=<tracking id>
|
||||
String actualUrl = Uri.parse(url).getQueryParameter("u");
|
||||
if (actualUrl != null) {
|
||||
Utils.openLink(actualUrl);
|
||||
return true;
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "openExternally failure", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@@ -696,6 +697,18 @@ public class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void openLink(String url) {
|
||||
try {
|
||||
Intent intent = new Intent("android.intent.action.VIEW", Uri.parse(url));
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
Logger.printInfo(() -> "Opening link with external browser: " + intent);
|
||||
getContext().startActivity(intent);
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "openLink failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public enum NetworkType {
|
||||
NONE,
|
||||
MOBILE,
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
// Do not remove. Necessary for the extension plugin to be applied to the project.
|
||||
dependencies {
|
||||
compileOnly(project(":extensions:shared:library"))
|
||||
}
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
package app.revanced.twitter.patches.links;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class ChangeLinkSharingDomainPatch {
|
||||
private static final String DOMAIN_NAME = "https://fxtwitter.com";
|
||||
private static final String LINK_FORMAT = "%s/%s/status/%s";
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static String formatResourceLink(Object... formatArgs) {
|
||||
String username = (String) formatArgs[0];
|
||||
String tweetId = (String) formatArgs[1];
|
||||
return String.format(LINK_FORMAT, DOMAIN_NAME, username, tweetId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static String formatLink(long tweetId, String username) {
|
||||
return String.format(LINK_FORMAT, DOMAIN_NAME, username, tweetId);
|
||||
}
|
||||
|
||||
@@ -2,12 +2,18 @@ package app.revanced.twitter.patches.links;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Deprecated(forRemoval = true)
|
||||
public final class OpenLinksWithAppChooserPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void openWithChooser(final Context context, final Intent intent) {
|
||||
Log.d("ReVanced", "Opening intent with chooser: " + intent);
|
||||
Logger.printInfo(() -> "Opening intent with chooser: " + intent);
|
||||
|
||||
intent.setAction("android.intent.action.VIEW");
|
||||
|
||||
|
||||
@@ -284,6 +284,10 @@ public final class app/revanced/patches/instagram/misc/extension/SharedExtension
|
||||
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/instagram/misc/links/OpenLinksExternallyPatchKt {
|
||||
public static final fun getOpenLinksExternallyPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/instagram/misc/signature/SignatureCheckPatchKt {
|
||||
public static final fun getSignatureCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.instagram.misc.links
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal const val TARGET_STRING = "Tracking.ARG_CLICK_SOURCE"
|
||||
|
||||
internal val inAppBrowserFunctionFingerprint = fingerprint {
|
||||
returns("Z")
|
||||
strings("TrackingInfo.ARG_MODULE_NAME", TARGET_STRING)
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package app.revanced.patches.instagram.misc.links
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/instagram/misc/links/OpenLinksExternallyPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val openLinksExternallyPatch = bytecodePatch(
|
||||
name = "Open links externally",
|
||||
description = "Changes links to always open in your external browser, instead of the in-app browser.",
|
||||
use = false,
|
||||
) {
|
||||
|
||||
dependsOn(sharedExtensionPatch)
|
||||
|
||||
compatibleWith("com.instagram.android")
|
||||
|
||||
execute {
|
||||
inAppBrowserFunctionFingerprint.let {
|
||||
val stringMatchIndex = it.stringMatches?.first { match -> match.string == TARGET_STRING }!!.index
|
||||
|
||||
it.method.apply {
|
||||
val urlResultObjIndex = indexOfFirstInstructionOrThrow(
|
||||
stringMatchIndex, Opcode.MOVE_OBJECT_FROM16
|
||||
)
|
||||
|
||||
// Register that contains the url after moving from a higher register.
|
||||
val urlRegister = getInstruction<TwoRegisterInstruction>(urlResultObjIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
urlResultObjIndex + 1,
|
||||
"""
|
||||
invoke-static { v$urlRegister }, $EXTENSION_CLASS_DESCRIPTOR->openExternally(Ljava/lang/String;)Z
|
||||
move-result v$urlRegister
|
||||
return v$urlRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.patches.twitter.misc.extension
|
||||
|
||||
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.twitter.misc.extension.hooks.applicationInitHook
|
||||
|
||||
val sharedExtensionPatch = sharedExtensionPatch("twitter")
|
||||
val sharedExtensionPatch = sharedExtensionPatch("twitter", applicationInitHook)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.patches.twitter.misc.extension.hooks
|
||||
|
||||
import app.revanced.patches.shared.misc.extension.extensionHook
|
||||
|
||||
internal val applicationInitHook =
|
||||
extensionHook {
|
||||
custom { method, classDef ->
|
||||
classDef.type == "Lcom/twitter/app/TwitterApplication;" && method.name == "onCreate"
|
||||
}
|
||||
}
|
||||
@@ -53,28 +53,28 @@ val changeLinkSharingDomainPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
execute {
|
||||
val replacementIndex =
|
||||
linkSharingDomainFingerprint.stringMatches!!.first().index
|
||||
val domainRegister =
|
||||
linkSharingDomainFingerprint.method.getInstruction<OneRegisterInstruction>(replacementIndex).registerA
|
||||
linkSharingDomainFingerprint.let {
|
||||
val replacementIndex = it.stringMatches!!.first().index
|
||||
val domainRegister = it.method.getInstruction<OneRegisterInstruction>(
|
||||
replacementIndex
|
||||
).registerA
|
||||
|
||||
linkSharingDomainFingerprint.method.replaceInstruction(
|
||||
replacementIndex,
|
||||
"const-string v$domainRegister, \"https://$domainName\"",
|
||||
)
|
||||
|
||||
// Replace the domain name when copying a link with "Copy link" button.
|
||||
linkBuilderFingerprint.method.apply {
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { p0, p1, p2 }, $EXTENSION_CLASS_DESCRIPTOR->formatLink(JLjava/lang/String;)Ljava/lang/String;
|
||||
move-result-object p0
|
||||
return-object p0
|
||||
""",
|
||||
it.method.replaceInstruction(
|
||||
replacementIndex,
|
||||
"const-string v$domainRegister, \"https://$domainName\"",
|
||||
)
|
||||
}
|
||||
|
||||
// Replace the domain name when copying a link with "Copy link" button.
|
||||
linkBuilderFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { p0, p1, p2 }, $EXTENSION_CLASS_DESCRIPTOR->formatLink(JLjava/lang/String;)Ljava/lang/String;
|
||||
move-result-object p0
|
||||
return-object p0
|
||||
"""
|
||||
)
|
||||
|
||||
// Used in the Share via... dialog.
|
||||
linkResourceGetterFingerprint.method.apply {
|
||||
val templateIdConstIndex = indexOfFirstLiteralInstructionOrThrow(tweetShareLinkTemplateId)
|
||||
|
||||
@@ -9,7 +9,7 @@ import app.revanced.patches.twitter.misc.extension.sharedExtensionPatch
|
||||
@Suppress("unused")
|
||||
val openLinksWithAppChooserPatch = bytecodePatch(
|
||||
description = "Instead of opening links directly, open them with an app chooser. " +
|
||||
"As a result you can select a browser to open the link with.",
|
||||
"As a result you can select a browser to open the link with.",
|
||||
) {
|
||||
dependsOn(sharedExtensionPatch)
|
||||
|
||||
@@ -18,7 +18,7 @@ val openLinksWithAppChooserPatch = bytecodePatch(
|
||||
execute {
|
||||
val methodReference =
|
||||
"Lapp/revanced/extension/twitter/patches/links/OpenLinksWithAppChooserPatch;->" +
|
||||
"openWithChooser(Landroid/content/Context;Landroid/content/Intent;)V"
|
||||
"openWithChooser(Landroid/content/Context;Landroid/content/Intent;)V"
|
||||
|
||||
openLinkFingerprint.method.addInstructions(
|
||||
0,
|
||||
|
||||
Reference in New Issue
Block a user