Skip to content

Commit 08e8ead

Browse files
authored
feat(Instagram): Add Open links externally patch (#6012)
1 parent d238a42 commit 08e8ead

File tree

12 files changed

+153
-24
lines changed

12 files changed

+153
-24
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package app.revanced.extension.instagram.misc.links;
2+
3+
import android.net.Uri;
4+
5+
import app.revanced.extension.shared.Logger;
6+
import app.revanced.extension.shared.Utils;
7+
8+
@SuppressWarnings("unused")
9+
public final class OpenLinksExternallyPatch {
10+
11+
/**
12+
* Injection point.
13+
*/
14+
public static boolean openExternally(String url) {
15+
try {
16+
// The "url" parameter to this function will be of the form.
17+
// https://l.instagram.com/?u=<actual url>&e=<tracking id>
18+
String actualUrl = Uri.parse(url).getQueryParameter("u");
19+
if (actualUrl != null) {
20+
Utils.openLink(actualUrl);
21+
return true;
22+
}
23+
24+
} catch (Exception ex) {
25+
Logger.printException(() -> "openExternally failure", ex);
26+
}
27+
28+
return false;
29+
}
30+
}

extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import android.content.res.Resources;
1616
import android.graphics.Color;
1717
import android.net.ConnectivityManager;
18+
import android.net.Uri;
1819
import android.os.Build;
1920
import android.os.Bundle;
2021
import android.os.Handler;
@@ -696,6 +697,18 @@ public static void verifyOffMainThread() throws IllegalStateException {
696697
}
697698
}
698699

700+
public static void openLink(String url) {
701+
try {
702+
Intent intent = new Intent("android.intent.action.VIEW", Uri.parse(url));
703+
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
704+
705+
Logger.printInfo(() -> "Opening link with external browser: " + intent);
706+
getContext().startActivity(intent);
707+
} catch (Exception ex) {
708+
Logger.printException(() -> "openLink failure", ex);
709+
}
710+
}
711+
699712
public enum NetworkType {
700713
NONE,
701714
MOBILE,
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
// Do not remove. Necessary for the extension plugin to be applied to the project.
1+
dependencies {
2+
compileOnly(project(":extensions:shared:library"))
3+
}

extensions/twitter/src/main/java/app/revanced/twitter/patches/links/ChangeLinkSharingDomainPatch.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
package app.revanced.twitter.patches.links;
22

3+
@SuppressWarnings("unused")
34
public final class ChangeLinkSharingDomainPatch {
45
private static final String DOMAIN_NAME = "https://fxtwitter.com";
56
private static final String LINK_FORMAT = "%s/%s/status/%s";
67

8+
/**
9+
* Injection point.
10+
*/
711
public static String formatResourceLink(Object... formatArgs) {
812
String username = (String) formatArgs[0];
913
String tweetId = (String) formatArgs[1];
1014
return String.format(LINK_FORMAT, DOMAIN_NAME, username, tweetId);
1115
}
1216

17+
/**
18+
* Injection point.
19+
*/
1320
public static String formatLink(long tweetId, String username) {
1421
return String.format(LINK_FORMAT, DOMAIN_NAME, username, tweetId);
1522
}

extensions/twitter/src/main/java/app/revanced/twitter/patches/links/OpenLinksWithAppChooserPatch.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@
22

33
import android.content.Context;
44
import android.content.Intent;
5-
import android.util.Log;
65

6+
import app.revanced.extension.shared.Logger;
7+
8+
@SuppressWarnings("unused")
79
@Deprecated(forRemoval = true)
810
public final class OpenLinksWithAppChooserPatch {
11+
12+
/**
13+
* Injection point.
14+
*/
915
public static void openWithChooser(final Context context, final Intent intent) {
10-
Log.d("ReVanced", "Opening intent with chooser: " + intent);
16+
Logger.printInfo(() -> "Opening intent with chooser: " + intent);
1117

1218
intent.setAction("android.intent.action.VIEW");
1319

patches/api/patches.api

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,10 @@ public final class app/revanced/patches/instagram/misc/extension/SharedExtension
284284
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
285285
}
286286

287+
public final class app/revanced/patches/instagram/misc/links/OpenLinksExternallyPatchKt {
288+
public static final fun getOpenLinksExternallyPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
289+
}
290+
287291
public final class app/revanced/patches/instagram/misc/signature/SignatureCheckPatchKt {
288292
public static final fun getSignatureCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
289293
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package app.revanced.patches.instagram.misc.links
2+
import app.revanced.patcher.fingerprint
3+
4+
internal const val TARGET_STRING = "Tracking.ARG_CLICK_SOURCE"
5+
6+
internal val inAppBrowserFunctionFingerprint = fingerprint {
7+
returns("Z")
8+
strings("TrackingInfo.ARG_MODULE_NAME", TARGET_STRING)
9+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package app.revanced.patches.instagram.misc.links
2+
3+
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
4+
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
5+
import app.revanced.patcher.patch.bytecodePatch
6+
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
7+
import app.revanced.util.indexOfFirstInstructionOrThrow
8+
import com.android.tools.smali.dexlib2.Opcode
9+
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
10+
11+
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/instagram/misc/links/OpenLinksExternallyPatch;"
12+
13+
@Suppress("unused")
14+
val openLinksExternallyPatch = bytecodePatch(
15+
name = "Open links externally",
16+
description = "Changes links to always open in your external browser, instead of the in-app browser.",
17+
use = false,
18+
) {
19+
20+
dependsOn(sharedExtensionPatch)
21+
22+
compatibleWith("com.instagram.android")
23+
24+
execute {
25+
inAppBrowserFunctionFingerprint.let {
26+
val stringMatchIndex = it.stringMatches?.first { match -> match.string == TARGET_STRING }!!.index
27+
28+
it.method.apply {
29+
val urlResultObjIndex = indexOfFirstInstructionOrThrow(
30+
stringMatchIndex, Opcode.MOVE_OBJECT_FROM16
31+
)
32+
33+
// Register that contains the url after moving from a higher register.
34+
val urlRegister = getInstruction<TwoRegisterInstruction>(urlResultObjIndex).registerA
35+
36+
addInstructions(
37+
urlResultObjIndex + 1,
38+
"""
39+
invoke-static { v$urlRegister }, $EXTENSION_CLASS_DESCRIPTOR->openExternally(Ljava/lang/String;)Z
40+
move-result v$urlRegister
41+
return v$urlRegister
42+
"""
43+
)
44+
}
45+
}
46+
}
47+
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package app.revanced.patches.twitter.misc.extension
22

33
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
4+
import app.revanced.patches.twitter.misc.extension.hooks.applicationInitHook
45

5-
val sharedExtensionPatch = sharedExtensionPatch("twitter")
6+
val sharedExtensionPatch = sharedExtensionPatch("twitter", applicationInitHook)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package app.revanced.patches.twitter.misc.extension.hooks
2+
3+
import app.revanced.patches.shared.misc.extension.extensionHook
4+
5+
internal val applicationInitHook =
6+
extensionHook {
7+
custom { method, classDef ->
8+
classDef.type == "Lcom/twitter/app/TwitterApplication;" && method.name == "onCreate"
9+
}
10+
}

0 commit comments

Comments
 (0)