From 6d88cb49ec739700866290babcba5fb3032dbced Mon Sep 17 00:00:00 2001
From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
Date: Fri, 8 Mar 2024 09:09:15 +0400
Subject: [PATCH] fix(YouTube - Downloads): Use new task context (#2841)
---
api/revanced-patches.api | 1 +
.../integrations/BaseIntegrationsPatch.kt | 4 +-
.../interaction/downloads/DownloadsPatch.kt | 71 +++++++++++++------
.../downloads/DownloadsResourcePatch.kt | 2 +-
...ownloadActionCommandResolverFingerprint.kt | 14 ++++
...dActionCommandResolverParentFingerprint.kt | 17 +++++
.../DownloadButtonActionFingerprint.kt | 7 --
...egacyDownloadCommandResolverFingerprint.kt | 24 +++++++
.../ReturnYouTubeDislikePatch.kt | 3 +-
.../thumbnails/AlternativeThumbnailsPatch.kt | 9 +--
.../playeroverlay/PlayerOverlaysHookPatch.kt | 29 ++++----
...layerOverlaysOnFinishInflateFingerprint.kt | 10 ++-
.../kotlin/app/revanced/util/BytecodeUtils.kt | 3 +
.../resources/addresources/values/strings.xml | 6 +-
14 files changed, 142 insertions(+), 58 deletions(-)
create mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/DownloadActionCommandResolverFingerprint.kt
create mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/DownloadActionCommandResolverParentFingerprint.kt
delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/DownloadButtonActionFingerprint.kt
create mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/LegacyDownloadCommandResolverFingerprint.kt
diff --git a/api/revanced-patches.api b/api/revanced-patches.api
index 9de9da57..4e1ad810 100644
--- a/api/revanced-patches.api
+++ b/api/revanced-patches.api
@@ -1748,6 +1748,7 @@ public final class app/revanced/util/BytecodeUtilsKt {
public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)I
public static final fun indexOfFirstWideLiteralInstructionValue (Lcom/android/tools/smali/dexlib2/iface/Method;J)I
public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V
+ public static final fun resultOrThrow (Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lapp/revanced/patcher/fingerprint/MethodFingerprintResult;
public static final fun returnEarly (Ljava/util/List;Z)V
public static synthetic fun returnEarly$default (Ljava/util/List;ZILjava/lang/Object;)V
public static final fun transformMethods (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V
diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch.kt
index eb7f7e87..058a05a6 100644
--- a/src/main/kotlin/app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch.kt
@@ -64,8 +64,8 @@ abstract class BaseIntegrationsPatch(
method.addInstruction(
0,
- "sput-object v$contextRegister, " +
- "$integrationsDescriptor->context:Landroid/content/Context;",
+ "invoke-static/range { v$contextRegister .. v$contextRegister }, " +
+ "$integrationsDescriptor->setContext(Landroid/content/Context;)V",
)
} ?: throw PatchException("Could not find hook target fingerprint.")
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt
index 82e46f5d..71f81777 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt
@@ -1,16 +1,18 @@
package app.revanced.patches.youtube.interaction.downloads
import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
-import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
-import app.revanced.patcher.util.smali.ExternalLabel
-import app.revanced.patches.youtube.interaction.downloads.fingerprints.DownloadButtonActionFingerprint
+import app.revanced.patches.youtube.interaction.downloads.fingerprints.DownloadActionCommandResolverFingerprint
+import app.revanced.patches.youtube.interaction.downloads.fingerprints.DownloadActionCommandResolverParentFingerprint
+import app.revanced.patches.youtube.interaction.downloads.fingerprints.LegacyDownloadCommandResolverFingerprint
import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsBytecodePatch
+import app.revanced.patches.youtube.shared.fingerprints.MainActivityFingerprint
import app.revanced.patches.youtube.video.information.VideoInformationPatch
-import app.revanced.util.exception
+import app.revanced.util.resultOrThrow
@Patch(
name = "Downloads",
@@ -39,8 +41,10 @@ import app.revanced.util.exception
@Suppress("unused")
object DownloadsPatch : BytecodePatch(
setOf(
- DownloadButtonActionFingerprint,
- ),
+ DownloadActionCommandResolverParentFingerprint,
+ LegacyDownloadCommandResolverFingerprint,
+ MainActivityFingerprint
+ )
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/DownloadsPatch;"
private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/youtube/videoplayer/ExternalDownloadButton;"
@@ -49,19 +53,46 @@ object DownloadsPatch : BytecodePatch(
PlayerControlsBytecodePatch.initializeControl("$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V")
PlayerControlsBytecodePatch.injectVisibilityCheckCall("$BUTTON_DESCRIPTOR->changeVisibility(Z)V")
- DownloadButtonActionFingerprint.result?.let {
- it.mutableMethod.apply {
- addInstructionsWithLabels(
- 2,
- """
- invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppDownloadButtonOnClick()Z
- move-result v0
- if-eqz v0, :show_dialog
- return-void
- """,
- ExternalLabel("show_dialog", getInstruction(2)),
- )
- }
- } ?: throw DownloadButtonActionFingerprint.exception
+ // Main activity is used to launch downloader intent.
+ MainActivityFingerprint.resultOrThrow().mutableMethod.apply {
+ addInstruction(
+ implementation!!.instructions.lastIndex,
+ "invoke-static { p0 }, $INTEGRATIONS_CLASS_DESCRIPTOR->activityCreated(Landroid/app/Activity;)V"
+ )
+ }
+
+ val commonInstructions = """
+ move-result v0
+ if-eqz v0, :show_native_downloader
+ return-void
+ :show_native_downloader
+ nop
+ """
+
+ DownloadActionCommandResolverFingerprint.resolve(context,
+ DownloadActionCommandResolverParentFingerprint.resultOrThrow().classDef)
+ DownloadActionCommandResolverFingerprint.resultOrThrow().mutableMethod.apply {
+ addInstructionsWithLabels(
+ 0,
+ """
+ invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppDownloadButtonOnClick()Z
+ $commonInstructions
+ """
+ )
+ }
+
+ // Legacy fingerprint is used for old spoofed versions,
+ // or if download playlist is pressed on any version.
+ // Downloading playlists is not yet supported,
+ // as the code this hooks does not easily expost the playlist id.
+ LegacyDownloadCommandResolverFingerprint.resultOrThrow().mutableMethod.apply {
+ addInstructionsWithLabels(
+ 0,
+ """
+ invoke-static/range {p1 .. p1}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppDownloadPlaylistLegacyOnClick(Ljava/lang/String;)Z
+ $commonInstructions
+ """
+ )
+ }
}
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsResourcePatch.kt
index bef29f94..24285e53 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsResourcePatch.kt
@@ -31,8 +31,8 @@ internal object DownloadsResourcePatch : ResourcePatch() {
sorting = Sorting.UNSORTED,
preferences = setOf(
SwitchPreference("revanced_external_downloader"),
+ SwitchPreference("revanced_external_downloader_action_button"),
TextPreference("revanced_external_downloader_name", inputType = InputType.TEXT),
- SwitchPreference("revanced_use_in_app_download_button"),
),
),
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/DownloadActionCommandResolverFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/DownloadActionCommandResolverFingerprint.kt
new file mode 100644
index 00000000..2c74eec1
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/DownloadActionCommandResolverFingerprint.kt
@@ -0,0 +1,14 @@
+package app.revanced.patches.youtube.interaction.downloads.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.MethodFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
+
+/**
+ * Resolves to the class found in [DownloadActionCommandResolverParentFingerprint].
+ */
+internal object DownloadActionCommandResolverFingerprint : MethodFingerprint(
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ returnType = "V",
+ parameters = listOf("L", "Ljava/util/Map;")
+)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/DownloadActionCommandResolverParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/DownloadActionCommandResolverParentFingerprint.kt
new file mode 100644
index 00000000..8af33d1e
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/DownloadActionCommandResolverParentFingerprint.kt
@@ -0,0 +1,17 @@
+package app.revanced.patches.youtube.interaction.downloads.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.util.patch.LiteralValueFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
+
+internal object DownloadActionCommandResolverParentFingerprint : LiteralValueFingerprint(
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ returnType = "V",
+ parameters = listOf("L", "L"),
+ strings = listOf(
+ // Strings are not unique and found in other methods.
+ "com.google.android.libraries.youtube.logging.interaction_logger",
+ "Unknown command"
+ ),
+ literalSupplier = { 16 }
+)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/DownloadButtonActionFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/DownloadButtonActionFingerprint.kt
deleted file mode 100644
index 4246f4b8..00000000
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/DownloadButtonActionFingerprint.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package app.revanced.patches.youtube.interaction.downloads.fingerprints
-
-import app.revanced.patcher.fingerprint.MethodFingerprint
-
-internal object DownloadButtonActionFingerprint : MethodFingerprint(
- strings = listOf("offline/get_download_action"),
-)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/LegacyDownloadCommandResolverFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/LegacyDownloadCommandResolverFingerprint.kt
new file mode 100644
index 00000000..36796010
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/LegacyDownloadCommandResolverFingerprint.kt
@@ -0,0 +1,24 @@
+package app.revanced.patches.youtube.interaction.downloads.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.MethodFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
+import com.android.tools.smali.dexlib2.Opcode
+
+/**
+ * For spoofing to older versions. Also called if download playlist is pressed for any version.
+ */
+internal object LegacyDownloadCommandResolverFingerprint : MethodFingerprint(
+ accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
+ returnType = "V",
+ parameters = listOf("Ljava/lang/String;", "Ljava/lang/String;", "L", "L"),
+ strings = listOf(""),
+ opcodes = listOf(
+ Opcode.MOVE_OBJECT_FROM16,
+ Opcode.MOVE_OBJECT_FROM16,
+ Opcode.NEW_INSTANCE,
+ Opcode.INVOKE_DIRECT,
+ Opcode.IGET_OBJECT,
+ Opcode.IF_NEZ,
+ )
+)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt
index 93b9cc0c..c911da3a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt
@@ -32,6 +32,7 @@ import app.revanced.patches.youtube.video.videoid.VideoIdPatch
import app.revanced.util.exception
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
+import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@@ -88,8 +89,6 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
private const val FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/components/ReturnYouTubeDislikeFilterPatch;"
- private fun MethodFingerprint.resultOrThrow() = result ?: throw exception
-
override fun execute(context: BytecodeContext) {
// region Inject newVideoLoaded event handler to update dislikes when a new video is loaded.
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/AlternativeThumbnailsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/AlternativeThumbnailsPatch.kt
index 4c642c7b..bf9162e5 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/AlternativeThumbnailsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/AlternativeThumbnailsPatch.kt
@@ -23,7 +23,7 @@ import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.reques
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnSucceededFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
-import app.revanced.util.exception
+import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
@@ -144,11 +144,8 @@ object AlternativeThumbnailsPatch : BytecodePatch(
NonInteractivePreference("revanced_alt_thumbnail_stills_about"),
)
- fun MethodFingerprint.getResultOrThrow() =
- result ?: throw exception
-
fun MethodFingerprint.alsoResolve(fingerprint: MethodFingerprint) =
- also { resolve(context, fingerprint.getResultOrThrow().classDef) }.getResultOrThrow()
+ also { resolve(context, fingerprint.resultOrThrow().classDef) }.resultOrThrow()
fun MethodFingerprint.resolveAndLetMutableMethod(
fingerprint: MethodFingerprint,
@@ -172,7 +169,7 @@ object AlternativeThumbnailsPatch : BytecodePatch(
// The URL is required for the failure callback hook, but the URL field is obfuscated.
// Add a helper get method that returns the URL field.
- RequestFingerprint.getResultOrThrow().apply {
+ RequestFingerprint.resultOrThrow().apply {
// The url is the only string field that is set inside the constructor.
val urlFieldInstruction = mutableMethod.getInstructions().first {
if (it.opcode != Opcode.IPUT_OBJECT) return@first false
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/PlayerOverlaysHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/PlayerOverlaysHookPatch.kt
index a48cc48c..c94ac05d 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/PlayerOverlaysHookPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/PlayerOverlaysHookPatch.kt
@@ -3,30 +3,31 @@ package app.revanced.patches.youtube.misc.playeroverlay
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.playeroverlay.fingerprint.PlayerOverlaysOnFinishInflateFingerprint
+import app.revanced.util.exception
@Patch(
- description = "Hook for adding custom overlays to the video player.",
+ description = "Hook for the video player overlay",
dependencies = [IntegrationsPatch::class],
- compatiblePackages = [
- CompatiblePackage("com.google.android.youtube", [
- "18.32.39"
- ])
- ]
)
+
+/**
+ * Edit: This patch is not in use and may not work.
+ */
@Suppress("unused")
-object PlayerOverlaysHookPatch : BytecodePatch( // TODO: delete this unused outdated patch and its integration code.
+object PlayerOverlaysHookPatch : BytecodePatch(
setOf(PlayerOverlaysOnFinishInflateFingerprint)
) {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/PlayerOverlaysHookPatch;"
+
override fun execute(context: BytecodeContext) {
- // hook YouTubePlayerOverlaysLayout.onFinishInflate()
- val method = PlayerOverlaysOnFinishInflateFingerprint.result!!.mutableMethod
- method.addInstruction(
- method.implementation!!.instructions.size - 2,
- "invoke-static { p0 }, Lapp/revanced/integrations/youtube/patches/PlayerOverlaysHookPatch;->YouTubePlayerOverlaysLayout_onFinishInflateHook(Ljava/lang/Object;)V"
- )
+ PlayerOverlaysOnFinishInflateFingerprint.result?.mutableMethod?.apply {
+ addInstruction(
+ implementation!!.instructions.lastIndex,
+ "invoke-static { p0 }, $INTEGRATIONS_CLASS_DESCRIPTOR->playerOverlayInflated(Landroid/view/ViewGroup;)V"
+ )
+ } ?: throw PlayerOverlaysOnFinishInflateFingerprint.exception
}
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/fingerprint/PlayerOverlaysOnFinishInflateFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/fingerprint/PlayerOverlaysOnFinishInflateFingerprint.kt
index 1d40fc36..11658c95 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/fingerprint/PlayerOverlaysOnFinishInflateFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/fingerprint/PlayerOverlaysOnFinishInflateFingerprint.kt
@@ -1,10 +1,14 @@
package app.revanced.patches.youtube.misc.playeroverlay.fingerprint
-
+import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
+import com.android.tools.smali.dexlib2.AccessFlags
internal object PlayerOverlaysOnFinishInflateFingerprint : MethodFingerprint(
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ returnType = "V",
customFingerprint = { methodDef, _ ->
- methodDef.definingClass.endsWith("YouTubePlayerOverlaysLayout;") && methodDef.name == "onFinishInflate"
- }
+ methodDef.definingClass.endsWith("/YouTubePlayerOverlaysLayout;")
+ && methodDef.name == "onFinishInflate"
+ },
)
diff --git a/src/main/kotlin/app/revanced/util/BytecodeUtils.kt b/src/main/kotlin/app/revanced/util/BytecodeUtils.kt
index f47ae90d..8daf7770 100644
--- a/src/main/kotlin/app/revanced/util/BytecodeUtils.kt
+++ b/src/main/kotlin/app/revanced/util/BytecodeUtils.kt
@@ -15,6 +15,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
import com.android.tools.smali.dexlib2.iface.reference.Reference
import com.android.tools.smali.dexlib2.util.MethodUtil
+
+fun MethodFingerprint.resultOrThrow() = result ?: throw exception
+
/**
* The [PatchException] of failing to resolve a [MethodFingerprint].
*
diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml
index 4801f8e9..c4731436 100644
--- a/src/main/resources/addresources/values/strings.xml
+++ b/src/main/resources/addresources/values/strings.xml
@@ -232,12 +232,12 @@
Show external download button
Download button shown in player
Download button not shown in player
+ Override download action button
+ Download button opens your external downloader
+ Download button opens the native in-app downloader
Downloader package name
Package name of your installed external downloader app, such as NewPipe or Seal
%s is not installed. Please install it.
- Use in-app download button
- Button will launch the external downloader
- Button will launch the native in-app downloader
Disable precise seeking gesture