1313import android .webkit .ValueCallback ;
1414import android .webkit .WebChromeClient ;
1515import android .webkit .WebResourceRequest ;
16+ import android .webkit .WebResourceResponse ;
1617import android .webkit .WebSettings ;
1718import android .webkit .WebView ;
1819import android .widget .TextView ;
3839import org .json .JSONException ;
3940import org .json .JSONObject ;
4041
42+ import java .io .ByteArrayInputStream ;
4143import java .io .IOException ;
4244import java .util .HashMap ;
4345
4446/**
4547 * Per Androidacy repo implementation agreement, no request of this WebView shall be modified.
4648 */
47- public class AndroidacyActivity extends FoxActivity {
49+ public final class AndroidacyActivity extends FoxActivity {
4850 private static final String TAG = "AndroidacyActivity" ;
4951
5052 static {
@@ -147,6 +149,19 @@ public boolean shouldOverrideUrlLoading(
147149 return false ;
148150 }
149151
152+ @ Nullable
153+ @ Override
154+ public WebResourceResponse shouldInterceptRequest (
155+ WebView view , WebResourceRequest request ) {
156+ if (AndroidacyActivity .this .megaIntercept (
157+ this .pageUrl , request .getUrl ().toString ())) {
158+ // Block request as Androidacy doesn't allow duplicate requests
159+ return new WebResourceResponse ("text/plain" , "UTF-8" ,
160+ new ByteArrayInputStream (new byte [0 ]));
161+ }
162+ return null ;
163+ }
164+
150165 @ Override
151166 public void onPageStarted (WebView view , String url , Bitmap favicon ) {
152167 this .pageUrl = url ;
@@ -224,18 +239,12 @@ public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
224239 AndroidacyWebAPI androidacyWebAPI = this .androidacyWebAPI ;
225240 if (androidacyWebAPI != null ) {
226241 if (!androidacyWebAPI .downloadMode ) {
242+ // Native module popup may cause download after consumed action
227243 if (androidacyWebAPI .consumedAction )
228- return ; // Native module popup may cause download after consumed action
229- int lenPrefix = 0 ;
230- // Workaround WebView/Chromium bug
231- for (String prefix : new String []{
232- "https://api.androidacy.com/magisk/download/" ,
233- "https://staging-api.androidacy.com/magisk/download/"
234- }) { // Make both staging and non staging act the same
235- if (downloadUrl .startsWith (prefix )) lenPrefix = prefix .length ();
236- }
237- if (lenPrefix != 0 ) {
238- final String moduleId = downloadUrl .substring (lenPrefix );
244+ return ;
245+ // Workaround Androidacy bug
246+ final String moduleId = moduleIdOfUrl (downloadUrl );
247+ if (moduleId != null ) {
239248 webView .evaluateJavascript ("document.querySelector(" +
240249 "\" #download-form input[name=_token]\" ).value" ,
241250 result -> new Thread ("Androidacy popup workaround thread" ) {
@@ -253,6 +262,8 @@ public void run() {
253262 if (downloadUrl .equals (realUrl )) {
254263 Log .e (TAG , "Failed to resolve URL from " +
255264 downloadUrl );
265+ AndroidacyActivity .this .megaIntercept (
266+ webView .getUrl (), downloadUrl );
256267 return ;
257268 }
258269 Log .i (TAG , "Got url: " + realUrl );
@@ -264,7 +275,8 @@ public void run() {
264275 }
265276 }.start ());
266277 return ;
267- }
278+ } else if (this .megaIntercept (webView .getUrl (), downloadUrl ))
279+ return ;
268280 }
269281 androidacyWebAPI .consumedAction = true ;
270282 androidacyWebAPI .downloadMode = false ;
@@ -313,4 +325,44 @@ protected void onResume() {
313325 this .androidacyWebAPI .consumedAction = false ;
314326 }
315327 }
328+
329+ private String moduleIdOfUrl (String url ) {
330+ for (String prefix : new String []{
331+ "https://api.androidacy.com/magisk/download/" ,
332+ "https://staging-api.androidacy.com/magisk/download/" ,
333+ "https://api.androidacy.com/magisk/readme/" ,
334+ "https://staging-api.androidacy.com/magisk/readme/" ,
335+ "https://api.androidacy.com/magisk/info/" ,
336+ "https://staging-api.androidacy.com/magisk/info/"
337+ }) { // Make both staging and non staging act the same
338+ int i = url .indexOf ('?' , prefix .length ()); if (i == -1 ) i = url .length ();
339+ if (url .startsWith (prefix )) return url .substring (prefix .length (), i );
340+ }
341+ return null ;
342+ }
343+
344+ private boolean isFileUrl (String url ) {
345+ for (String prefix : new String []{
346+ "https://api.androidacy.com/magisk/file/" ,
347+ "https://staging-api.androidacy.com/magisk/file/"
348+ }) { // Make both staging and non staging act the same
349+ if (url .startsWith (prefix )) return true ;
350+ }
351+ return false ;
352+ }
353+
354+ private boolean megaIntercept (String pageUrl , String fileUrl ) {
355+ if (pageUrl == null || fileUrl == null ) return false ;
356+ if (this .isFileUrl (fileUrl )) {
357+ Log .d (TAG , "megaIntercept(" +
358+ AndroidacyUtil .hideToken (pageUrl ) + ", " +
359+ AndroidacyUtil .hideToken (fileUrl ) + ")" );
360+ }
361+ final AndroidacyWebAPI androidacyWebAPI = this .androidacyWebAPI ;
362+ final String moduleId = this .moduleIdOfUrl (pageUrl );
363+ if (moduleId == null || !this .isFileUrl (fileUrl )) return false ;
364+ androidacyWebAPI .openNativeModuleDialogRaw (fileUrl ,
365+ moduleId , "" , androidacyWebAPI .canInstall ());
366+ return true ;
367+ }
316368}
0 commit comments