diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
new file mode 100644
index 00000000..774c5408
--- /dev/null
+++ b/.idea/deploymentTargetDropDown.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.safedk/hashes.safedk b/.safedk/hashes.safedk
index b5af034b..a2e7dbdc 100644
--- a/.safedk/hashes.safedk
+++ b/.safedk/hashes.safedk
@@ -1,3 +1,3 @@
-#Sat Feb 04 14:33:30 PKT 2023
+#Thu Feb 09 03:08:42 PKT 2023
\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000=
-json=2027486056
+json=-1378969876
diff --git a/.safedk/plugin.properties b/.safedk/plugin.properties
index e48dbea2..adb42cee 100644
--- a/.safedk/plugin.properties
+++ b/.safedk/plugin.properties
@@ -1,5 +1,5 @@
#
-#Sat Feb 04 14:33:30 PKT 2023
+#Thu Feb 09 03:08:42 PKT 2023
\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000=
sdk_analysis_plugin_version=4.8.3
set_multidex=true
diff --git a/app/build.gradle b/app/build.gradle
index 2ca55109..074843d7 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -3,15 +3,14 @@ import com.android.build.OutputFile
plugins {
id "com.jetbrains.python.envs" version "0.0.26"
}
-
apply plugin: 'com.android.application'
apply from: 'variables.gradle'
apply plugin: 'kotlin-android'
apply plugin: 'applovin-quality-service'
-applovin {
- apiKey "pCPe4EeU2ZQVwQPeHLgseRqHBX1V5pvo9Piuu4J809dRhadEgukXa1A8po_UeXu5hmPOTaP1v4QPaMKIEOhh50"
-}
+applovin {
+ apiKey project.ext.applovin_key
+}
android {
@@ -30,7 +29,7 @@ android {
}
}
kotlinOptions {
- jvmTarget = "1.8"
+ jvmTarget = project.ext.jvmTarget
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
@@ -76,7 +75,7 @@ android {
orionRelease.root = project.ext.releaseRoot
}
- namespace 'com.example.myapplication'
+ namespace project.ext.application_id
}
dependencies {
@@ -105,7 +104,7 @@ dependencies {
/* Ads Manager */
implementation 'com.applovin:applovin-sdk:11.7.0'
- implementation 'com.facebook.android:audience-network-sdk:6.10.0'
+ implementation 'com.facebook.android:audience-network-sdk:6.12.0'
implementation 'com.applovin.mediation:facebook-adapter:6.12.0.1'
/* Orbot Service */
diff --git a/app/fabric.properties b/app/fabric.properties
index 48555c31..d3f5a12f 100755
--- a/app/fabric.properties
+++ b/app/fabric.properties
@@ -1,3 +1 @@
-#Contains API Secret used to validate your application. Commit to internal source control; avoid making secret public.
-#Wed May 01 00:42:45 PKT 2019
-apiSecret=042501af0b2390b9f064ff9a0823e52a2dd04b2280c9b675925cebbb9620ecbf
+
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 193375a0..8ba938dc 100755
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -1,35 +1,32 @@
-keep,includedescriptorclasses class net.sqlcipher.** { *; }
-keep,includedescriptorclasses interface net.sqlcipher.** { *; }
+-keep class org.mozilla.** {*;}
+-keep class com.flurry.** { *; }
+-keep class okhttp3.** { *; }
+-keep interface okhttp3.** { *; }
+-keepattributes Signature
+-keepattributes Annotation
+-keepattributes *Annotation*,EnclosingMethod,Signature
+-keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet, int); }
+
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable
-dontwarn javax.annotation.**
-dontwarn org.codehaus.mojo.animal_sniffer.*
--dontwarn okhttp3.internal.platform.ConscryptPlatform
--dontwarn org.conscrypt.ConscryptHostnameVerifier
-dontwarn okhttp3.*
-dontwarn org.chromium.net.*
-
--keep class org.mozilla.** {*;}
--keep class com.flurry.** { *; }
-dontwarn com.flurry.**
--keepattributes *Annotation*,EnclosingMethod,Signature
--keepclasseswithmembers class * {
- public (android.content.Context, android.util.AttributeSet, int);
- }
-
--dontobfuscate
-# https://stackoverflow.com/questions/9651703/using-proguard-with-android-without-obfuscation
--optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable
-
--keep class org.orbotproject.android.service.vpn.Tun2Socks {
- void logTun2Socks(java.lang.String, java.lang.String, java.lang.String);
-}
-
--keepattributes Signature
--keepattributes Annotation
--keep class okhttp3.** { *; }
--keep interface okhttp3.** { *; }
-dontwarn okhttp3.**
-dontwarn okio.**
+-dontobfuscate
-dontoptimize
-dontpreverify
+
+# -dontwarn okhttp3.internal.platform.ConscryptPlatform
+# -dontwarn org.conscrypt.ConscryptHostnameVerifier
+# -keep class org.orbotproject.android.service.vpn.Tun2Socks {
+# void logTun2Socks(java.lang.String, java.lang.String, java.lang.String);
+# }
+
+
diff --git a/app/src/main/java/com/hiddenservices/onionservices/appManager/activityContextManager.java b/app/src/main/java/com/hiddenservices/onionservices/appManager/activityContextManager.java
index c1eae870..f491e8bf 100644
--- a/app/src/main/java/com/hiddenservices/onionservices/appManager/activityContextManager.java
+++ b/app/src/main/java/com/hiddenservices/onionservices/appManager/activityContextManager.java
@@ -4,7 +4,7 @@ import static com.hiddenservices.onionservices.constants.constants.CONST_PACKAGE
import android.content.Context;
import androidx.appcompat.app.AppCompatActivity;
-import com.example.myapplication.R;
+import com.hiddenservices.onionservices.R;
import com.hiddenservices.onionservices.appManager.bookmarkManager.bookmarkHome.bookmarkController;
import com.hiddenservices.onionservices.appManager.bridgeManager.bridgeController;
import com.hiddenservices.onionservices.appManager.historyManager.historyController;
diff --git a/app/src/main/java/com/hiddenservices/onionservices/appManager/advertManager/advertController.java b/app/src/main/java/com/hiddenservices/onionservices/appManager/advertManager/advertController.java
index c287bb08..98c7a828 100644
--- a/app/src/main/java/com/hiddenservices/onionservices/appManager/advertManager/advertController.java
+++ b/app/src/main/java/com/hiddenservices/onionservices/appManager/advertManager/advertController.java
@@ -8,7 +8,7 @@ import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.ProgressBar;
-import com.example.myapplication.R;
+import com.hiddenservices.onionservices.R;
import com.hiddenservices.onionservices.eventObserver;
import java.util.Collections;
diff --git a/app/src/main/java/com/hiddenservices/onionservices/appManager/advertManager/advertViewController.java b/app/src/main/java/com/hiddenservices/onionservices/appManager/advertManager/advertViewController.java
index 62ef46b1..ce5d8dd9 100644
--- a/app/src/main/java/com/hiddenservices/onionservices/appManager/advertManager/advertViewController.java
+++ b/app/src/main/java/com/hiddenservices/onionservices/appManager/advertManager/advertViewController.java
@@ -6,7 +6,7 @@ import android.widget.ProgressBar;
import androidx.appcompat.app.AppCompatActivity;
-import com.example.myapplication.R;
+import com.hiddenservices.onionservices.R;
import com.hiddenservices.onionservices.eventObserver;
import com.hiddenservices.onionservices.helperManager.sharedUIMethod;
diff --git a/app/src/main/java/com/hiddenservices/onionservices/appManager/bookmarkManager/bookmarkHome/bookmarkAdapter.java b/app/src/main/java/com/hiddenservices/onionservices/appManager/bookmarkManager/bookmarkHome/bookmarkAdapter.java
index fa16302a..e4bb5cef 100644
--- a/app/src/main/java/com/hiddenservices/onionservices/appManager/bookmarkManager/bookmarkHome/bookmarkAdapter.java
+++ b/app/src/main/java/com/hiddenservices/onionservices/appManager/bookmarkManager/bookmarkHome/bookmarkAdapter.java
@@ -15,11 +15,12 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import com.hiddenservices.onionservices.constants.enums;
+import com.hiddenservices.onionservices.constants.status;
import com.hiddenservices.onionservices.constants.strings;
import com.hiddenservices.onionservices.dataManager.models.bookmarkRowModel;
import com.hiddenservices.onionservices.eventObserver;
import com.hiddenservices.onionservices.helperManager.helperMethod;
-import com.example.myapplication.R;
+import com.hiddenservices.onionservices.R;
import java.util.ArrayList;
import java.util.Arrays;
@@ -446,10 +447,12 @@ public class bookmarkAdapter extends RecyclerView.Adapter= android.os.Build.VERSION_CODES.O) {
+ manager = mGeckoView.getContext().getSystemService(AutofillManager.class);
+ if (manager == null) {
+ return;
+ }
+ manager.notifyViewEntered(mGeckoView, data.getId(),displayRectForId(session, node));
+ }
+ }
+
+ @Override
+ public void onNodeFocus(@NonNull final GeckoSession session, @NonNull final Autofill.Node node, @NonNull final Autofill.NodeData data) {
+ final AutofillManager manager;
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
+ manager = mGeckoView.getContext().getSystemService(AutofillManager.class);
+ if (manager == null) {
+ return;
+ }
+ manager.notifyViewEntered(mGeckoView, data.getId(),displayRectForId(session, node));
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/contentDelegate.java b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/contentDelegate.java
new file mode 100644
index 00000000..1ddd58ec
--- /dev/null
+++ b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/contentDelegate.java
@@ -0,0 +1,218 @@
+package com.hiddenservices.onionservices.appManager.homeManager.geckoManager.delegateModel;
+
+
+import static com.hiddenservices.onionservices.constants.constants.CONST_GENESIS_HELP_URL_CACHE;
+import static com.hiddenservices.onionservices.constants.constants.CONST_GENESIS_HELP_URL_CACHE_DARK;
+import static com.hiddenservices.onionservices.constants.constants.CONST_GENESIS_URL_CACHED;
+import static com.hiddenservices.onionservices.constants.constants.CONST_GENESIS_URL_CACHED_DARK;
+import static com.hiddenservices.onionservices.pluginManager.pluginEnums.eMessageManager.M_LONG_PRESS_URL;
+import static com.hiddenservices.onionservices.pluginManager.pluginEnums.eMessageManager.M_LONG_PRESS_WITH_LINK;
+import android.content.ActivityNotFoundException;
+import android.os.Handler;
+import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+import androidx.appcompat.app.AppCompatActivity;
+import com.hiddenservices.onionservices.appManager.homeManager.geckoManager.dataModel.geckoDataModel;
+import com.hiddenservices.onionservices.appManager.homeManager.geckoManager.geckoDownloadManager;
+import com.hiddenservices.onionservices.appManager.homeManager.geckoManager.geckoSession;
+import com.hiddenservices.onionservices.constants.enums;
+import com.hiddenservices.onionservices.constants.status;
+import com.hiddenservices.onionservices.constants.strings;
+import com.hiddenservices.onionservices.eventObserver;
+import com.hiddenservices.onionservices.helperManager.helperMethod;
+import org.json.JSONObject;
+import org.mozilla.geckoview.GeckoSession;
+import org.mozilla.geckoview.WebResponse;
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+
+public class contentDelegate implements GeckoSession.ContentDelegate {
+
+ /*Private Variables*/
+
+ private WeakReference mContext;
+ private eventObserver.eventListener mEvent;
+ private geckoDataModel mGeckoDataModel;
+ private geckoSession mGeckoSession;
+
+ private geckoDownloadManager mDownloadManager;
+ private int mCrashCount = 0;
+
+ /*Initializations*/
+
+ public contentDelegate(WeakReference pContext, eventObserver.eventListener pEvent, geckoDataModel pGeckoDataModel, geckoSession pGeckoSession) {
+ this.mContext = pContext;
+ this.mEvent = pEvent;
+ this.mGeckoDataModel = pGeckoDataModel;
+ this.mGeckoSession = pGeckoSession;
+
+ mDownloadManager = new geckoDownloadManager();
+ }
+
+ /*Local Listeners*/
+
+ @UiThread
+ public void onTitleChange(@NonNull GeckoSession var1, @Nullable String var2) {
+ if (var2 != null && !var2.equals(strings.GENERIC_EMPTY_STR) && var2.length() > 2 && !var2.equals("about:blank")) {
+ mGeckoDataModel.mCurrentTitle = var2;
+ }
+ }
+
+ @Override
+ public void onFullScreen(@NonNull GeckoSession var1, boolean var2) {
+ mGeckoDataModel.mFullScreenStatus = var2;
+ mEvent.invokeObserver(Arrays.asList(var2, mGeckoDataModel.mSessionID), enums.etype.ON_FULL_SCREEN);
+ }
+
+ @UiThread
+ @Override
+ public void onContextMenu(@NonNull GeckoSession var1, int var2, int var3, @NonNull GeckoSession.ContentDelegate.ContextElement var4) {
+
+ String title = strings.GENERIC_EMPTY_STR;
+ if (var4.title != null) {
+ title = var4.title;
+ }
+ if (var4.type != 0 && var4.srcUri != null) {
+ if (var4.linkUri != null) {
+ mEvent.invokeObserver(Arrays.asList(var4.linkUri, mGeckoDataModel.mSessionID, var4.srcUri, title, mGeckoDataModel.mTheme, var4.altText, mGeckoSession, mContext.get()), M_LONG_PRESS_WITH_LINK);
+ } else {
+ try {
+ String mTitle = var4.title;
+ if (mTitle == null || mTitle.length() <= 0) {
+ mTitle = helperMethod.getDomainName(mGeckoDataModel.mCurrentURL) + "\n" + var4.srcUri;
+ }
+ mEvent.invokeObserver(Arrays.asList(var4.srcUri, mGeckoDataModel.mSessionID, mTitle, mGeckoDataModel.mTheme, mGeckoSession, mContext.get()), enums.etype.on_long_press);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ Log.i("", "");
+ }
+ }
+ } else if (var4.linkUri != null) {
+ mEvent.invokeObserver(Arrays.asList(var4.linkUri, mGeckoDataModel.mSessionID, title, mGeckoDataModel.mTheme, mGeckoSession, mContext.get()), M_LONG_PRESS_URL);
+ }
+ }
+
+ @UiThread
+ @Override
+ public void onExternalResponse(@NonNull GeckoSession session, @NonNull WebResponse response) {
+ try {
+ if (response.headers.containsKey("Content-Disposition")) {
+ mDownloadManager.downloadFile(response, mGeckoSession, mContext.get(), mEvent);
+ } else if (response.headers.containsKey("Content-Type")) {
+ mDownloadManager.downloadFile(response, mGeckoSession, mContext.get(), mEvent);
+ }
+ } catch (ActivityNotFoundException e) {
+ mEvent.invokeObserver(Arrays.asList(response, mGeckoDataModel.mSessionID), enums.etype.on_handle_external_intent);
+ mGeckoSession.stop();
+ }
+ }
+
+ @UiThread
+ public void onFirstContentfulPaint(@NonNull GeckoSession var1) {
+ if (mGeckoDataModel.mCurrentURL.contains("167.86.99.31") || mGeckoDataModel.mCurrentURL.startsWith(CONST_GENESIS_URL_CACHED) || mGeckoDataModel.mCurrentURL.startsWith(CONST_GENESIS_URL_CACHED_DARK) || mGeckoDataModel.mCurrentURL.startsWith(CONST_GENESIS_HELP_URL_CACHE) || mGeckoDataModel.mCurrentURL.startsWith(CONST_GENESIS_HELP_URL_CACHE_DARK)) {
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, false), enums.etype.M_ON_BANNER_UPDATE);
+ } else {
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, true), enums.etype.M_ON_BANNER_UPDATE);
+ }
+
+ if (!mGeckoDataModel.mCurrentURL.equals("about:blank")) {
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mCurrentURL_ID, mGeckoDataModel.mTheme), enums.etype.ON_FIRST_PAINT);
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mCurrentURL_ID, mGeckoDataModel.mTheme), enums.etype.ON_LOAD_REQUEST);
+ }
+
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mTheme), enums.etype.ON_EXPAND_TOP_BAR);
+ }
+
+ @UiThread
+ public void onWebAppManifest(@NonNull GeckoSession var1, @NonNull JSONObject var2) {
+ try {
+ mGeckoDataModel.mThemeChanged = true;
+ mGeckoDataModel.mTheme = var2.getString("theme_color");
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mTheme), enums.etype.ON_UPDATE_THEME);
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL,mGeckoDataModel.mSessionID,mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mCurrentURL_ID, mGeckoDataModel.mTheme), enums.etype.M_INDEX_WEBSITE);
+ } catch (Exception ex) {
+ mGeckoDataModel.mTheme = null;
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mTheme), enums.etype.ON_UPDATE_THEME);
+ ex.printStackTrace();
+ }
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mCurrentURL_ID, mGeckoDataModel.mTheme), enums.etype.ON_UPDATE_TAB_TITLE);
+ }
+
+ @UiThread
+ public void onCrash(@NonNull GeckoSession session) {
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mCurrentURL_ID, mGeckoDataModel.mTheme, mGeckoSession), enums.etype.ON_DESTROY_MEDIA);
+
+ if (!mGeckoSession.isClosed() && status.sSettingIsAppStarted) {
+ if (mEvent == null) {
+ return;
+ }
+ Object mSessionObject = mEvent.invokeObserver(null, enums.etype.SESSION_ID);
+ if (mSessionObject == null || mGeckoDataModel.mSessionID == null) {
+ return;
+ }
+ String mSessionID = (String) mSessionObject;
+ if (mSessionID.equals(mGeckoDataModel.mSessionID)) {
+ if (mCrashCount <= 5) {
+ final Handler handler = new Handler();
+ handler.postDelayed(() -> {
+ try {
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mCurrentURL_ID, mGeckoDataModel.mTheme, this), enums.etype.M_OPEN_SESSION);
+ } catch (Exception ignored) {
+ }
+ }, mCrashCount * 500L);
+ }
+ mCrashCount += 1;
+ }
+ }
+ }
+
+ @UiThread
+ public void onKill(@NonNull GeckoSession session) {
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mCurrentURL_ID, mGeckoDataModel.mTheme, mGeckoSession), enums.etype.ON_DESTROY_MEDIA);
+
+ if (!mGeckoSession.isClosed() && status.sSettingIsAppStarted) {
+ if (mEvent == null) {
+ return;
+ }
+ Object mSessionObject = mEvent.invokeObserver(null, enums.etype.SESSION_ID);
+ if (mSessionObject == null || mGeckoDataModel.mSessionID == null) {
+ return;
+ }
+ String mSessionID = (String) mSessionObject;
+
+
+ if (mSessionID.equals(mGeckoDataModel.mSessionID)) {
+ if (mCrashCount <= 5) {
+ final Handler handler = new Handler();
+ handler.postDelayed(() -> {
+ if (status.sSettingIsAppStarted && !session.isOpen()) {
+ try {
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mCurrentURL_ID, mGeckoDataModel.mTheme, this), enums.etype.M_OPEN_SESSION);
+ } catch (Exception ignored) {
+ }
+ }
+ }, mCrashCount * 500L);
+ }
+ mCrashCount += 1;
+ }
+ }
+ }
+
+ /*Local Triggers*/
+
+ public boolean getFullScreenStatus() {
+ return !mGeckoDataModel.mFullScreenStatus;
+ }
+
+ public void resetCrash() {
+ mCrashCount = 0;
+ }
+
+ public geckoDownloadManager getDownloadManager(){
+ return this.mDownloadManager;
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/historyDelegate.java b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/historyDelegate.java
new file mode 100644
index 00000000..106f147e
--- /dev/null
+++ b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/historyDelegate.java
@@ -0,0 +1,76 @@
+package com.hiddenservices.onionservices.appManager.homeManager.geckoManager.delegateModel;
+
+
+import androidx.annotation.NonNull;
+import androidx.annotation.UiThread;
+import androidx.appcompat.app.AppCompatActivity;
+import com.hiddenservices.onionservices.appManager.homeManager.geckoManager.dataModel.geckoDataModel;
+import com.hiddenservices.onionservices.appManager.homeManager.geckoManager.geckoSession;
+import com.hiddenservices.onionservices.appManager.homeManager.geckoManager.helperClasses.intentHandler;
+import com.hiddenservices.onionservices.constants.enums;
+import com.hiddenservices.onionservices.eventObserver;
+import com.hiddenservices.onionservices.helperManager.helperMethod;
+import org.mozilla.geckoview.GeckoSession;
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+
+public class historyDelegate implements GeckoSession.HistoryDelegate {
+
+ /*Private Variables*/
+
+ private WeakReference mContext;
+ private GeckoSession.HistoryDelegate.HistoryList mHistory = null;
+ private eventObserver.eventListener mEvent;
+ private geckoDataModel mGeckoDataModel;
+ private geckoSession mGeckoSession;
+ private int mCurrentIndex = 0;
+
+ /*Initializations*/
+
+ public historyDelegate(WeakReference pContext, eventObserver.eventListener pEvent, geckoDataModel pGeckoDataModel, geckoSession pGeckoSession) {
+ this.mContext = pContext;
+ this.mEvent = pEvent;
+ this.mGeckoDataModel = pGeckoDataModel;
+ this.mGeckoSession = pGeckoSession;
+ }
+
+ @UiThread
+ public void onHistoryStateChange(@NonNull GeckoSession var1, @NonNull GeckoSession.HistoryDelegate.HistoryList var2) {
+ mHistory = var2;
+ if(mHistory !=null){
+ setURL(mHistory.get(mHistory.getCurrentIndex()).getUri());
+ mEvent.invokeObserver(Arrays.asList(mHistory, mGeckoDataModel.mSessionID), enums.etype.on_url_load);
+ if(mCurrentIndex != var2.getCurrentIndex()){
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mHistory.get(mHistory.getCurrentIndex()).getTitle(), mGeckoDataModel.mCurrentURL_ID, mGeckoDataModel.mTheme, mGeckoSession), enums.etype.ON_UPDATE_SEARCH_BAR);
+ }
+
+ Object mID = mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mHistory.get(mHistory.getCurrentIndex()).getTitle(), -1, mGeckoDataModel.mTheme, mGeckoSession, false), enums.etype.ON_UPDATE_HISTORY);
+ if (mID != null) {
+ mGeckoDataModel.mCurrentURL_ID = (int) mID;
+ }
+ }
+ mCurrentIndex = var2.getCurrentIndex();
+ }
+
+ /*Local Triggers*/
+
+ public void setURL(String pURL) {
+ if (helperMethod.getHost(pURL).endsWith(".onion")) {
+ pURL = pURL.replace("www.", "");
+ }
+
+ this.mGeckoDataModel.mCurrentURL = pURL;
+ if(pURL.startsWith("tel:")){
+ intentHandler.actionDial(pURL, mContext);
+ }
+ }
+
+ public boolean isHistoryEmpty(){
+ if(mHistory!=null && mHistory.size()>0){
+ return false;
+ }else {
+ return true;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/mediaDelegate.java b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/mediaDelegate.java
similarity index 73%
rename from app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/mediaDelegate.java
rename to app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/mediaDelegate.java
index 58d94f68..7e5f7cd0 100644
--- a/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/mediaDelegate.java
+++ b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/mediaDelegate.java
@@ -1,126 +1,136 @@
-package com.hiddenservices.onionservices.appManager.homeManager.geckoManager;
-
-
-import static android.content.Context.NOTIFICATION_SERVICE;
-import android.app.Activity;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.os.Build;
-import android.widget.RemoteViews;
-import androidx.core.app.NotificationCompat;
-import androidx.core.app.NotificationManagerCompat;
-import com.example.myapplication.R;
-import com.hiddenservices.onionservices.constants.status;
-import com.hiddenservices.onionservices.helperManager.helperMethod;
-import com.hiddenservices.onionservices.pluginManager.pluginReciever.mediaNotificationReciever;
-import org.mozilla.geckoview.GeckoSession;
-
-public class mediaDelegate implements GeckoSession.MediaDelegate {
- private Context mContext;
-
- public mediaDelegate(Activity activity, Context pContext) {
- mContext = pContext;
- }
-
- public void onHideDefaultNotification(){
- NotificationManagerCompat.from(mContext).cancel(1030);
- }
-
- public void showNotification(Context context, String title, String url, Bitmap mediaImage, boolean not_status) {
- NotificationManager mNotificationManager = (NotificationManager) mContext.getSystemService( NOTIFICATION_SERVICE ) ;
- if(title.length()<=0 || !status.sBackgroundMusic){
- return;
- }
- RemoteViews contentView;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ) {
- contentView = new RemoteViews(context.getPackageName() , R.layout. media_notification_no_background ) ;
- }else if (android.os.Build.VERSION. SDK_INT > Build.VERSION_CODES.N_MR1){
- contentView = new RemoteViews(context.getPackageName() , R.layout. media_notification_layout ) ;
- }else {
- contentView = new RemoteViews(context.getPackageName() , R.layout. media_notification_layout_small ) ;
- }
-
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S ) {
- contentView.setInt(R.id.layout,"setBackgroundResource", R.color.c_tab_background);
- }
- contentView.setTextViewText(R.id.header, title);
- contentView.setTextViewText(R.id.body, "☍ " + url);
-
- try {
- contentView.setImageViewBitmap(R.id.logo, mediaImage);
- } catch (Throwable e) {
- e.printStackTrace();
- }
-
- if (not_status){
- PendingIntent pIntent = helperMethod.onCreateActionIntent(context, mediaNotificationReciever.class, 1030, "media_play", 0);
- contentView.setOnClickPendingIntent(R.id.trigger, pIntent);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ) {
- contentView.setImageViewResource(R.id.trigger, R.drawable.ic_baseline_play_arrow_no_tint);
- }else {
- contentView.setImageViewResource(R.id.trigger, R.drawable.ic_baseline_play_arrow);
- }
- }else {
- PendingIntent pIntent = helperMethod.onCreateActionIntent(context, mediaNotificationReciever.class, 1030, "media_pause", 1);
- contentView.setOnClickPendingIntent(R.id.trigger, pIntent);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ) {
- contentView.setImageViewResource(R.id.trigger, R.drawable.ic_baseline_pause_no_tint);
- }else {
- contentView.setImageViewResource(R.id.trigger, R.drawable.ic_baseline_pause);
- }
- }
-
- PendingIntent pIntentPrev = helperMethod.onCreateActionIntent(context, mediaNotificationReciever.class, 1030, "media_next", 2);
- contentView.setOnClickPendingIntent(R.id.next, pIntentPrev);
-
- if(android.os.Build.VERSION. SDK_INT > Build.VERSION_CODES.N){
- PendingIntent pIntentNext = helperMethod.onCreateActionIntent(context, mediaNotificationReciever.class, 1030, "media_back", 3);
- contentView.setOnClickPendingIntent(R.id.back, pIntentNext);
- }
-
- NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mContext, "1030" ) ;
-
- mBuilder.setPriority(Notification.PRIORITY_LOW);
- mBuilder.setAutoCancel(true);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
- mBuilder.setCustomBigContentView(contentView);
- mBuilder.setStyle(new NotificationCompat.DecoratedCustomViewStyle());
- }else {
- mBuilder.setContent(contentView);
- }
-
- mBuilder.setSmallIcon(R.drawable.ic_baseline_media) ;
- mBuilder.setAutoCancel( true ) ;
- if (android.os.Build.VERSION. SDK_INT >= android.os.Build.VERSION_CODES. O ) {
- int importance = NotificationManager.IMPORTANCE_LOW ;
- NotificationChannel notificationChannel = new NotificationChannel( "1030" , "NOTIFICATION_CHANNEL_NAME" , importance) ;
- notificationChannel.setSound(null, null);
- mBuilder.setChannelId("1030") ;
- assert mNotificationManager != null;
- mNotificationManager.createNotificationChannel(notificationChannel) ;
- }
- Notification notification = mBuilder.build();
-
- mBuilder.setContentIntent(PendingIntent.getActivity(context, 1030, new Intent(context, mediaDelegate.class), PendingIntent.FLAG_IMMUTABLE));
- PendingIntent dummyIntent = null;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- PendingIntent.getActivity(context, 1030, new Intent(), PendingIntent.FLAG_IMMUTABLE);
- }else {
- PendingIntent.getActivity(context, 1030, new Intent(), 0);
- }
- notification.fullScreenIntent = dummyIntent;
-
- if(!not_status){
- notification.flags |= Notification.FLAG_NO_CLEAR;
- }
-
- notification.defaults = 0;
- mNotificationManager.notify(1030 , notification) ;
-
- }
+package com.hiddenservices.onionservices.appManager.homeManager.geckoManager.delegateModel;
+
+
+import static android.content.Context.NOTIFICATION_SERVICE;
+
+import android.annotation.SuppressLint;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.os.Build;
+import android.widget.RemoteViews;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
+import com.hiddenservices.onionservices.R;
+import com.hiddenservices.onionservices.constants.status;
+import com.hiddenservices.onionservices.helperManager.helperMethod;
+import com.hiddenservices.onionservices.pluginManager.pluginReciever.mediaNotificationReciever;
+import org.mozilla.geckoview.GeckoSession;
+
+import java.lang.ref.WeakReference;
+
+public class mediaDelegate implements GeckoSession.MediaDelegate {
+
+ /*Private Variables*/
+
+ private WeakReference mContext;
+ private static int S_NOTIFICATION_ID = 1030;
+ private static String S_NOTIFICATION_CHANNEL_ID = "1030";
+ private static String S_NOTIFICATION_CHANNEL_NAME = "MEDIA_NOTIFICATION";
+
+ /*Initializations*/
+
+ public mediaDelegate(WeakReference pContext) {
+ mContext = pContext;
+ }
+
+ public void onHideDefaultNotification(){
+ NotificationManagerCompat.from(mContext.get()).cancel(S_NOTIFICATION_ID);
+ }
+
+ /*Triggers*/
+
+ @SuppressLint("InlinedApi")
+ public void showNotification(Context context, String title, String url, Bitmap mediaImage, boolean media_status) {
+ NotificationManager mNotificationManager = (NotificationManager) mContext.get().getSystemService( NOTIFICATION_SERVICE ) ;
+ if(title.length()<=0 || !status.sBackgroundMusic){
+ return;
+ }
+ RemoteViews contentView;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ) {
+ contentView = new RemoteViews(context.getPackageName() , R.layout. media_notification_no_background ) ;
+ }else if (android.os.Build.VERSION. SDK_INT > Build.VERSION_CODES.N_MR1){
+ contentView = new RemoteViews(context.getPackageName() , R.layout. media_notification_layout ) ;
+ }else {
+ contentView = new RemoteViews(context.getPackageName() , R.layout. media_notification_layout_small ) ;
+ }
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S ) {
+ contentView.setInt(R.id.layout,"setBackgroundResource", R.color.c_tab_background);
+ }
+ contentView.setTextViewText(R.id.header, title);
+ contentView.setTextViewText(R.id.body, "☍ " + url);
+
+ try {
+ contentView.setImageViewBitmap(R.id.logo, mediaImage);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+
+ if (!media_status){
+ PendingIntent pIntent = helperMethod.onCreateActionIntent(context, mediaNotificationReciever.class, S_NOTIFICATION_ID, "media_play", 0);
+ contentView.setOnClickPendingIntent(R.id.trigger, pIntent);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ) {
+ contentView.setImageViewResource(R.id.trigger, R.drawable.ic_baseline_play_arrow_no_tint);
+ }else {
+ contentView.setImageViewResource(R.id.trigger, R.drawable.ic_baseline_play_arrow);
+ }
+ }else {
+ PendingIntent pIntent = helperMethod.onCreateActionIntent(context, mediaNotificationReciever.class, S_NOTIFICATION_ID, "media_pause", 1);
+ contentView.setOnClickPendingIntent(R.id.trigger, pIntent);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ) {
+ contentView.setImageViewResource(R.id.trigger, R.drawable.ic_baseline_pause_no_tint);
+ }else {
+ contentView.setImageViewResource(R.id.trigger, R.drawable.ic_baseline_pause);
+ }
+ }
+
+ PendingIntent pIntentPrev = helperMethod.onCreateActionIntent(context, mediaNotificationReciever.class, S_NOTIFICATION_ID, "media_next", 2);
+ contentView.setOnClickPendingIntent(R.id.next, pIntentPrev);
+
+ if(android.os.Build.VERSION. SDK_INT > Build.VERSION_CODES.N){
+ PendingIntent pIntentNext = helperMethod.onCreateActionIntent(context, mediaNotificationReciever.class, S_NOTIFICATION_ID, "media_back", 3);
+ contentView.setOnClickPendingIntent(R.id.back, pIntentNext);
+ }
+
+ NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mContext.get(), S_NOTIFICATION_CHANNEL_ID ) ;
+
+ mBuilder.setPriority(Notification.PRIORITY_LOW);
+ mBuilder.setAutoCancel(true);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
+ mBuilder.setCustomBigContentView(contentView);
+ mBuilder.setStyle(new NotificationCompat.DecoratedCustomViewStyle());
+ }else {
+ mBuilder.setContent(contentView);
+ }
+
+ mBuilder.setSmallIcon(R.drawable.ic_baseline_media) ;
+ mBuilder.setAutoCancel( true ) ;
+ if (android.os.Build.VERSION. SDK_INT >= android.os.Build.VERSION_CODES. O ) {
+ int importance = NotificationManager.IMPORTANCE_LOW ;
+ NotificationChannel notificationChannel = new NotificationChannel( S_NOTIFICATION_CHANNEL_ID , S_NOTIFICATION_CHANNEL_NAME , importance) ;
+ notificationChannel.setSound(null, null);
+ mBuilder.setChannelId(S_NOTIFICATION_CHANNEL_ID) ;
+ assert mNotificationManager != null;
+ mNotificationManager.createNotificationChannel(notificationChannel) ;
+ }
+ Notification notification = mBuilder.build();
+
+ mBuilder.setContentIntent(PendingIntent.getActivity(context, S_NOTIFICATION_ID, new Intent(context, mediaDelegate.class), PendingIntent.FLAG_IMMUTABLE));
+ notification.fullScreenIntent = null;
+
+ if(media_status){
+ notification.flags |= Notification.FLAG_NO_CLEAR;
+ }
+
+ notification.defaults = 0;
+ mNotificationManager.notify(S_NOTIFICATION_ID , notification) ;
+
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/mediaSessionDelegate.java b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/mediaSessionDelegate.java
new file mode 100644
index 00000000..c819b353
--- /dev/null
+++ b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/mediaSessionDelegate.java
@@ -0,0 +1,124 @@
+package com.hiddenservices.onionservices.appManager.homeManager.geckoManager.delegateModel;
+
+import static com.hiddenservices.onionservices.constants.strings.GENERIC_EMPTY_STR;
+
+import android.graphics.Bitmap;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import com.hiddenservices.onionservices.appManager.homeManager.geckoManager.dataModel.geckoDataModel;
+import com.hiddenservices.onionservices.constants.enums;
+import com.hiddenservices.onionservices.helperManager.helperMethod;
+import org.mozilla.geckoview.GeckoSession;
+import org.mozilla.geckoview.MediaSession;
+import java.lang.ref.WeakReference;
+
+public class mediaSessionDelegate implements MediaSession.Delegate{
+
+ /*Private Variables*/
+
+ private MediaSession mMediaSession = null;
+ private mediaDelegate mMediaDelegate;
+ private WeakReference mContext;
+ private geckoDataModel mGeckoDataModel;
+
+ private Bitmap mMediaImage;
+ private String mMediaTitle = GENERIC_EMPTY_STR;
+
+ /*Initializations*/
+
+ public mediaSessionDelegate(WeakReference pContext, geckoDataModel pGeckoDataModel, mediaDelegate pMediaDelegate){
+ this.mContext = pContext;
+ this.mMediaDelegate = pMediaDelegate;
+ this.mGeckoDataModel = pGeckoDataModel;
+ }
+
+ /*Local Listeners*/
+
+ @Override
+ public void onActivated(@NonNull GeckoSession session, @NonNull MediaSession mediaSession) {
+ MediaSession.Delegate.super.onActivated(session, mediaSession);
+ mMediaSession = mediaSession;
+ }
+
+ @Override
+ public void onDeactivated(@NonNull GeckoSession session, @NonNull MediaSession mediaSession) {
+ MediaSession.Delegate.super.onPause(session, mediaSession);
+ mMediaDelegate.onHideDefaultNotification();
+ }
+
+ @Override
+ public void onMetadata(@NonNull GeckoSession session, @NonNull MediaSession mediaSession, @NonNull MediaSession.Metadata meta) {
+
+ try {
+ mMediaTitle = meta.title;
+ mMediaImage = meta.artwork.getBitmap(250).poll(2500);
+ mMediaDelegate.showNotification(mContext.get(), mMediaTitle, helperMethod.getHost(mGeckoDataModel.mCurrentURL), mMediaImage, true);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+
+ MediaSession.Delegate.super.onMetadata(session, mediaSession, meta);
+ }
+
+ @Override
+ public void onFeatures(@NonNull GeckoSession session, @NonNull MediaSession mediaSession, long features) {
+ MediaSession.Delegate.super.onFeatures(session, mediaSession, features);
+ }
+
+ @Override
+ public void onPlay(@NonNull GeckoSession session, @NonNull MediaSession mediaSession) {
+ MediaSession.Delegate.super.onPlay(session, mediaSession);
+ mMediaDelegate.showNotification(this.mContext.get(), mMediaTitle, helperMethod.getHost(mGeckoDataModel.mCurrentURL), mMediaImage, true);
+ }
+
+ @Override
+ public void onPause(@NonNull GeckoSession session, @NonNull MediaSession mediaSession) {
+ MediaSession.Delegate.super.onPause(session, mediaSession);
+ mMediaDelegate.showNotification(this.mContext.get(), mMediaTitle, helperMethod.getHost(mGeckoDataModel.mCurrentURL), mMediaImage, false);
+ }
+
+ @Override
+ public void onStop(@NonNull GeckoSession session, @NonNull MediaSession mediaSession) {
+ MediaSession.Delegate.super.onStop(session, mediaSession);
+ mMediaDelegate.showNotification(this.mContext.get(), mMediaTitle, helperMethod.getHost(mGeckoDataModel.mCurrentURL), mMediaImage, false);
+ }
+
+ @Override
+ public void onPositionState(@NonNull GeckoSession session, @NonNull MediaSession mediaSession, @NonNull MediaSession.PositionState state) {
+ MediaSession.Delegate.super.onPositionState(session, mediaSession, state);
+ }
+
+ @Override
+ public void onFullscreen(@NonNull GeckoSession session, @NonNull MediaSession mediaSession, boolean enabled, @Nullable @org.jetbrains.annotations.Nullable MediaSession.ElementMetadata meta) {
+ MediaSession.Delegate.super.onFullscreen(session, mediaSession, enabled, meta);
+ }
+
+ /*Triggers*/
+
+ public void onTrigger(enums.MediaController pCommands){
+ if(mMediaSession!=null){
+ if(pCommands.equals(enums.MediaController.PLAY)){
+ mMediaDelegate.showNotification(this.mContext.get(), mMediaTitle, helperMethod.getHost(mGeckoDataModel.mCurrentURL), mMediaImage, true);
+ mMediaSession.play();
+ }
+ else if(pCommands.equals(enums.MediaController.PAUSE)){
+ mMediaDelegate.showNotification(this.mContext.get(), mMediaTitle, helperMethod.getHost(mGeckoDataModel.mCurrentURL), mMediaImage, false);
+ mMediaSession.pause();
+ }
+ else if(pCommands.equals(enums.MediaController.STOP)){
+ mMediaSession.stop();
+ }
+ else if(pCommands.equals(enums.MediaController.DESTROY)){
+ mMediaSession.stop();
+ mMediaDelegate.onHideDefaultNotification();
+ }
+ else if(pCommands.equals(enums.MediaController.SKIP_BACKWARD)){
+ mMediaSession.previousTrack();
+ }
+ else if(pCommands.equals(enums.MediaController.SKIP_FORWARD)){
+ mMediaSession.nextTrack();
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/geckoPromptView.java b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/promptDelegate.java
similarity index 73%
rename from app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/geckoPromptView.java
rename to app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/promptDelegate.java
index d743724a..59ce4f2a 100644
--- a/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/geckoPromptView.java
+++ b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/promptDelegate.java
@@ -1,1103 +1,1035 @@
-package com.hiddenservices.onionservices.appManager.homeManager.geckoManager;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.ActivityNotFoundException;
-import android.content.ClipData;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.res.TypedArray;
-import android.graphics.Color;
-import android.graphics.PorterDuff;
-import android.net.Uri;
-import android.os.Build;
-import android.text.InputType;
-import android.text.format.DateFormat;
-import android.util.Log;
-import android.view.InflateException;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.webkit.MimeTypeMap;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.CheckedTextView;
-import android.widget.DatePicker;
-import android.widget.EditText;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.ScrollView;
-import android.widget.Spinner;
-import android.widget.TextView;
-import android.widget.TimePicker;
-
-import androidx.annotation.Nullable;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.core.app.ShareCompat;
-
-import com.hiddenservices.onionservices.appManager.activityContextManager;
-import com.hiddenservices.onionservices.helperManager.helperMethod;
-
-import java.io.File;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Locale;
-
-import org.mozilla.geckoview.AllowOrDeny;
-import org.mozilla.geckoview.GeckoResult;
-import org.mozilla.geckoview.GeckoSession;
-import org.mozilla.geckoview.SlowScriptResponse;
-
-final class geckoPromptView implements GeckoSession.PromptDelegate {
- protected static final String LOGTAG = "BasicGeckoViewPrompt";
-
- private final AppCompatActivity mActivity;
- public int filePickerRequestCode = 1;
- private int mFileType;
- private GeckoResult mFileResponse;
- private FilePrompt mFilePrompt;
-
- public geckoPromptView(final AppCompatActivity activity) {
- mActivity = activity;
- }
-
- public void stopMedia(){
- try {
- activityContextManager.getInstance().getHomeController().onKillMedia();
- }catch (Exception ex){}
- }
-
- @Override
- public GeckoResult onAlertPrompt(final GeckoSession session,
- final AlertPrompt prompt) {
- stopMedia();
- final Activity activity = mActivity;
- if (activity == null) {
- return GeckoResult.fromValue(prompt.dismiss());
- }
- final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
- .setTitle(prompt.title)
- .setMessage(prompt.message)
- .setPositiveButton(android.R.string.ok, /* onClickListener */ null);
- GeckoResult res = new GeckoResult();
- createStandardDialog(builder, prompt, res).show();
- return res;
- }
-
- @Override
- public GeckoResult onButtonPrompt(final GeckoSession session,
- final ButtonPrompt prompt) {
- stopMedia();
- final Activity activity = mActivity;
- if (activity == null) {
- return GeckoResult.fromValue(prompt.dismiss());
- }
- final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
- .setTitle(prompt.title)
- .setMessage(prompt.message);
-
- GeckoResult res = new GeckoResult();
-
- final DialogInterface.OnClickListener listener =
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- res.complete(prompt.confirm(ButtonPrompt.Type.POSITIVE));
- } else if (which == DialogInterface.BUTTON_NEGATIVE) {
- res.complete(prompt.confirm(ButtonPrompt.Type.NEGATIVE));
- } else {
- res.complete(prompt.dismiss());
- }
- }
- };
-
- builder.setPositiveButton(android.R.string.ok, listener);
- builder.setNegativeButton(android.R.string.cancel, listener);
-
- createStandardDialog(builder, prompt, res).show();
- return res;
- }
-
- public static String getMimeType(Context context, Uri uri) {
- String extension;
-
- //Check uri format to avoid null
- if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
- //If scheme is a content
- final MimeTypeMap mime = MimeTypeMap.getSingleton();
- extension = mime.getExtensionFromMimeType(context.getContentResolver().getType(uri));
- } else {
- //If scheme is a File
- //This will replace white spaces with %20 and also other special characters. This will avoid returning null values on file name with spaces and special characters.
- extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(new File(uri.getPath())).toString());
-
- }
-
- return extension;
- }
-
- static boolean mPopupOpened = false;
- @Override
- public GeckoResult onSharePrompt(final GeckoSession session,
- final SharePrompt prompt) {
- stopMedia();
- new Thread(){
- public void run(){
- try {
- sleep(4000);
- mPopupOpened = false;
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }.start();
- if(!mPopupOpened){
- mPopupOpened = true;
- }else {
- return GeckoResult.fromValue(prompt.confirm(SharePrompt.Result.ABORT));
- }
- try {
- String m_data = prompt.uri;
- if(prompt.text!=null){
- m_data += " : " + prompt.text;
- }
-
- ShareCompat.IntentBuilder.from(mActivity)
- .setType("text/x-uri")
- .setChooserTitle(prompt.title)
- .setText(m_data)
- .startChooser();
- }catch (Exception ex){}
-
- return GeckoResult.fromValue(prompt.confirm(SharePrompt.Result.SUCCESS));
-
- }
-
- @Nullable
- @Override
- public GeckoResult onRepostConfirmPrompt(final GeckoSession session,
- final RepostConfirmPrompt prompt) {
- stopMedia();
- final Activity activity = mActivity;
- if (activity == null) {
- return GeckoResult.fromValue(prompt.dismiss());
- }
- final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
- .setTitle("Are you sure?")
- .setMessage("To display this page, GeckoViewExample must send information that will repeat any action (such as a search or order confirmation) that was performed earlier.");
-
- GeckoResult res = new GeckoResult<>();
-
- final DialogInterface.OnClickListener listener = (dialog, which) -> {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- res.complete(prompt.confirm(AllowOrDeny.ALLOW));
- } else if (which == DialogInterface.BUTTON_NEGATIVE) {
- res.complete(prompt.confirm(AllowOrDeny.DENY));
- } else {
- res.complete(prompt.dismiss());
- }
- };
-
- builder.setPositiveButton("Resend", listener);
- builder.setNegativeButton("Cancel", listener);
-
- try {
- if(mActivity!=null && !mActivity.isFinishing())
- {
- createStandardDialog(builder, prompt, res).show();
- }
- }catch (Exception ex){}
- return res;
- }
-
- @Nullable
- @Override
- public GeckoResult onBeforeUnloadPrompt(final GeckoSession session,
- final BeforeUnloadPrompt prompt) {
- stopMedia();
- final Activity activity = mActivity;
- if (activity == null) {
- return GeckoResult.fromValue(prompt.dismiss());
- }
- final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
- .setTitle("Are you sure?")
- .setMessage("This page is asking you to confirm that you want to leave - data you have entered may not be saved");
-
- GeckoResult res = new GeckoResult<>();
-
- final DialogInterface.OnClickListener listener = (dialog, which) -> {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- res.complete(prompt.confirm(AllowOrDeny.ALLOW));
- } else if (which == DialogInterface.BUTTON_NEGATIVE) {
- res.complete(prompt.confirm(AllowOrDeny.DENY));
- } else {
- res.complete(prompt.dismiss());
- }
- };
-
- builder.setPositiveButton("Leave Page", listener);
- builder.setNegativeButton("Stay on Page", listener);
-
- createStandardDialog(builder, prompt, res).show();
- return res;
- }
-
- private int getViewPadding(final AlertDialog.Builder builder) {
- stopMedia();
- final TypedArray attr = builder.getContext().obtainStyledAttributes(
- new int[]{android.R.attr.listPreferredItemPaddingLeft});
- final int padding = attr.getDimensionPixelSize(0, 1);
- attr.recycle();
- return padding;
- }
-
- private LinearLayout addStandardLayout(final AlertDialog.Builder builder,
- final String title, final String msg) {
- stopMedia();
- final ScrollView scrollView = new ScrollView(builder.getContext());
- final LinearLayout container = new LinearLayout(builder.getContext());
- final int horizontalPadding = getViewPadding(builder);
- final int verticalPadding = (msg == null || msg.isEmpty()) ? horizontalPadding : 0;
- container.setOrientation(LinearLayout.VERTICAL);
- container.setPadding(/* left */ horizontalPadding, /* top */ verticalPadding,
- /* right */ horizontalPadding, /* bottom */ verticalPadding);
- scrollView.addView(container);
- builder.setTitle(title)
- .setMessage(msg)
- .setView(scrollView);
- return container;
- }
-
- private AlertDialog createStandardDialog(final AlertDialog.Builder builder,
- final BasePrompt prompt,
- final GeckoResult response) {
- final AlertDialog dialog = builder.create();
- stopMedia();
- dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
- @Override
- public void onDismiss(final DialogInterface dialog) {
- if (!prompt.isComplete()) {
- response.complete(prompt.dismiss());
- }
- }
- });
- return dialog;
- }
-
- @Override
- public GeckoResult onTextPrompt(final GeckoSession session,
- final TextPrompt prompt) {
- final Activity activity = mActivity;
- stopMedia();
- if (activity == null) {
- return GeckoResult.fromValue(prompt.dismiss());
- }
- final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- final LinearLayout container = addStandardLayout(builder, prompt.title, prompt.message);
- final EditText editText = new EditText(builder.getContext());
- editText.setText(prompt.defaultValue);
- container.addView(editText);
-
- GeckoResult res = new GeckoResult();
-
- builder.setNegativeButton(android.R.string.cancel, /* listener */ null)
- .setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- res.complete(prompt.confirm(editText.getText().toString()));
- }
- });
-
- createStandardDialog(builder, prompt, res).show();
- return res;
- }
-
- @Override
- public GeckoResult onAuthPrompt(final GeckoSession session,
- final AuthPrompt prompt) {
- final Activity activity = mActivity;
- stopMedia();
- if (activity == null) {
- return GeckoResult.fromValue(prompt.dismiss());
- }
- final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- final LinearLayout container = addStandardLayout(builder, prompt.title, prompt.message);
-
- final int flags = prompt.authOptions.flags;
- final int level = prompt.authOptions.level;
- final EditText username;
- if ((flags & AuthPrompt.AuthOptions.Flags.ONLY_PASSWORD) == 0) {
- username = new EditText(builder.getContext());
- username.setHint("Username");
- username.setText(prompt.authOptions.username);
- container.addView(username);
- } else {
- username = null;
- }
-
- final EditText password = new EditText(builder.getContext());
- password.setHint("Password");
- password.setText(prompt.authOptions.password);
- password.setInputType(InputType.TYPE_CLASS_TEXT |
- InputType.TYPE_TEXT_VARIATION_PASSWORD);
- container.addView(password);
-
- if (level != AuthPrompt.AuthOptions.Level.NONE) {
- final ImageView secure = new ImageView(builder.getContext());
- secure.setImageResource(android.R.drawable.ic_lock_lock);
- container.addView(secure);
- }
-
- GeckoResult res = new GeckoResult();
-
- builder.setNegativeButton(android.R.string.cancel, /* listener */ null)
- .setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- if ((flags & AuthPrompt.AuthOptions.Flags.ONLY_PASSWORD) == 0) {
- res.complete(prompt.confirm(username.getText().toString(),
- password.getText().toString()));
-
- } else {
- res.complete(prompt.confirm(password.getText().toString()));
- }
- }
- });
- createStandardDialog(builder, prompt, res).show();
-
- return res;
- }
-
- private static class ModifiableChoice {
- public boolean modifiableSelected;
- public String modifiableLabel;
- public final ChoicePrompt.Choice choice;
-
- public ModifiableChoice(ChoicePrompt.Choice c) {
- choice = c;
- modifiableSelected = choice.selected;
- modifiableLabel = choice.label;
- }
- }
-
- private void addChoiceItems(final int type, final ArrayAdapter list,
- final ChoicePrompt.Choice[] items, final String indent) {
- stopMedia();
- if (type == ChoicePrompt.Type.MENU) {
- for (final ChoicePrompt.Choice item : items) {
- list.add(new ModifiableChoice(item));
- }
- return;
- }
-
- for (final ChoicePrompt.Choice item : items) {
- final ModifiableChoice modItem = new ModifiableChoice(item);
-
- final ChoicePrompt.Choice[] children = item.items;
-
- if (indent != null && children == null) {
- modItem.modifiableLabel = indent + modItem.modifiableLabel;
- }
- list.add(modItem);
-
- if (children != null) {
- final String newIndent;
- if (type == ChoicePrompt.Type.SINGLE || type == ChoicePrompt.Type.MULTIPLE) {
- newIndent = (indent != null) ? indent + '\t' : "\t";
- } else {
- newIndent = null;
- }
- addChoiceItems(type, list, children, newIndent);
- }
- }
- }
-
- private void onChoicePromptImpl(final GeckoSession session, final String title,
- final String message, final int type,
- final ChoicePrompt.Choice[] choices, final ChoicePrompt prompt,
- final GeckoResult res) {
- stopMedia();
- final Activity activity = mActivity;
- if (activity == null) {
- res.complete(prompt.dismiss());
- return;
- }
- final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- addStandardLayout(builder, title, message);
-
- final ListView list = new ListView(builder.getContext());
- if (type == ChoicePrompt.Type.MULTIPLE) {
- list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
- }
-
- final ArrayAdapter adapter = new ArrayAdapter(
- builder.getContext(), android.R.layout.simple_list_item_1) {
- private static final int TYPE_MENU_ITEM = 0;
- private static final int TYPE_MENU_CHECK = 1;
- private static final int TYPE_SEPARATOR = 2;
- private static final int TYPE_GROUP = 3;
- private static final int TYPE_SINGLE = 4;
- private static final int TYPE_MULTIPLE = 5;
- private static final int TYPE_COUNT = 6;
-
- private LayoutInflater mInflater;
- private View mSeparator;
-
- @Override
- public int getViewTypeCount() {
- return TYPE_COUNT;
- }
-
- @Override
- public int getItemViewType(final int position) {
- final ModifiableChoice item = getItem(position);
- if (item.choice.separator) {
- return TYPE_SEPARATOR;
- } else if (type == ChoicePrompt.Type.MENU) {
- return item.modifiableSelected ? TYPE_MENU_CHECK : TYPE_MENU_ITEM;
- } else if (item.choice.items != null) {
- return TYPE_GROUP;
- } else if (type == ChoicePrompt.Type.SINGLE) {
- return TYPE_SINGLE;
- } else if (type == ChoicePrompt.Type.MULTIPLE) {
- return TYPE_MULTIPLE;
- } else {
- throw new UnsupportedOperationException();
- }
- }
-
- @Override
- public boolean isEnabled(final int position) {
- final ModifiableChoice item = getItem(position);
- return !item.choice.separator && !item.choice.disabled &&
- ((type != ChoicePrompt.Type.SINGLE &&
- type != ChoicePrompt.Type.MULTIPLE) ||
- item.choice.items == null);
- }
-
- @Override
- public View getView(final int position, View view,
- final ViewGroup parent) {
- final int itemType = getItemViewType(position);
- final int layoutId;
- if (itemType == TYPE_SEPARATOR) {
- if (mSeparator == null) {
- mSeparator = new View(getContext());
- mSeparator.setLayoutParams(new ListView.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, 2, itemType));
- final TypedArray attr = getContext().obtainStyledAttributes(
- new int[]{android.R.attr.listDivider});
- mSeparator.setBackgroundResource(attr.getResourceId(0, 0));
- attr.recycle();
- }
- return mSeparator;
- } else if (itemType == TYPE_MENU_ITEM) {
- layoutId = android.R.layout.simple_list_item_1;
- } else if (itemType == TYPE_MENU_CHECK) {
- layoutId = android.R.layout.simple_list_item_checked;
- } else if (itemType == TYPE_GROUP) {
- layoutId = android.R.layout.preference_category;
- } else if (itemType == TYPE_SINGLE) {
- layoutId = android.R.layout.simple_list_item_single_choice;
- } else if (itemType == TYPE_MULTIPLE) {
- layoutId = android.R.layout.simple_list_item_multiple_choice;
- } else {
- throw new UnsupportedOperationException();
- }
-
- if (view == null) {
- if (mInflater == null) {
- mInflater = LayoutInflater.from(builder.getContext());
- }
- view = mInflater.inflate(layoutId, parent, false);
- }
-
- final ModifiableChoice item = getItem(position);
- final TextView text = (TextView) view;
- text.setEnabled(!item.choice.disabled);
- text.setText(item.modifiableLabel);
- if (view instanceof CheckedTextView) {
- final boolean selected = item.modifiableSelected;
- if (itemType == TYPE_MULTIPLE) {
- list.setItemChecked(position, selected);
- } else {
- ((CheckedTextView) view).setChecked(selected);
- }
- }
- return view;
- }
- };
- addChoiceItems(type, adapter, choices, /* indent */ null);
-
- list.setAdapter(adapter);
- builder.setView(list);
-
- final AlertDialog dialog;
- if (type == ChoicePrompt.Type.SINGLE || type == ChoicePrompt.Type.MENU) {
- dialog = createStandardDialog(builder, prompt, res);
- list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(final AdapterView> parent, final View v,
- final int position, final long id) {
- final ModifiableChoice item = adapter.getItem(position);
- if (type == ChoicePrompt.Type.MENU) {
- final ChoicePrompt.Choice[] children = item.choice.items;
- if (children != null) {
- // Show sub-menu.
- dialog.setOnDismissListener(null);
- dialog.dismiss();
- onChoicePromptImpl(session, item.modifiableLabel, /* msg */ null,
- type, children, prompt, res);
- return;
- }
- }
- res.complete(prompt.confirm(item.choice));
- dialog.dismiss();
- }
- });
- } else if (type == ChoicePrompt.Type.MULTIPLE) {
- list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(final AdapterView> parent, final View v,
- final int position, final long id) {
- final ModifiableChoice item = adapter.getItem(position);
- item.modifiableSelected = ((CheckedTextView) v).isChecked();
- }
- });
- builder.setNegativeButton(android.R.string.cancel, /* listener */ null)
- .setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog,
- final int which) {
- final int len = adapter.getCount();
- ArrayList items = new ArrayList<>(len);
- for (int i = 0; i < len; i++) {
- final ModifiableChoice item = adapter.getItem(i);
- if (item.modifiableSelected) {
- items.add(item.choice.id);
- }
- }
- res.complete(prompt.confirm(items.toArray(new String[items.size()])));
- }
- });
- dialog = createStandardDialog(builder, prompt, res);
- } else {
- throw new UnsupportedOperationException();
- }
- try {
- if(mActivity!=null && !mActivity.isFinishing())
- {
- dialog.show();
- }
- }catch (Exception ex){}
- }
-
- @Override
- public GeckoResult onChoicePrompt(final GeckoSession session,
- final ChoicePrompt prompt) {
- stopMedia();
- final GeckoResult res = new GeckoResult();
- onChoicePromptImpl(session, prompt.title, prompt.message, prompt.type, prompt.choices,
- prompt, res);
- return res;
- }
-
- private static int parseColor(final String value, final int def) {
- try {
- return Color.parseColor(value);
- } catch (final IllegalArgumentException e) {
- return def;
- }
- }
-
- @Override
- public GeckoResult onColorPrompt(final GeckoSession session,
- final ColorPrompt prompt) {
- stopMedia();
- final Activity activity = mActivity;
- if (activity == null) {
- return GeckoResult.fromValue(prompt.dismiss());
- }
- final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- addStandardLayout(builder, prompt.title, /* msg */ null);
-
- final int initial = parseColor(prompt.defaultValue, /* def */ 0);
- final ArrayAdapter adapter = new ArrayAdapter(
- builder.getContext(), android.R.layout.simple_list_item_1) {
- private LayoutInflater mInflater;
-
- @Override
- public int getViewTypeCount() {
- return 2;
- }
-
- @Override
- public int getItemViewType(final int position) {
- return (getItem(position) == initial) ? 1 : 0;
- }
-
- @Override
- public View getView(final int position, View view,
- final ViewGroup parent) {
- if (mInflater == null) {
- mInflater = LayoutInflater.from(builder.getContext());
- }
- final int color = getItem(position);
- if (view == null) {
- view = mInflater.inflate((color == initial) ?
- android.R.layout.simple_list_item_checked :
- android.R.layout.simple_list_item_1, parent, false);
- }
- view.setBackgroundResource(android.R.drawable.editbox_background);
- view.getBackground().setColorFilter(color, PorterDuff.Mode.MULTIPLY);
- return view;
- }
- };
-
- adapter.addAll(0xffff4444 /* holo_red_light */,
- 0xffcc0000 /* holo_red_dark */,
- 0xffffbb33 /* holo_orange_light */,
- 0xffff8800 /* holo_orange_dark */,
- 0xff99cc00 /* holo_green_light */,
- 0xff669900 /* holo_green_dark */,
- 0xff33b5e5 /* holo_blue_light */,
- 0xff0099cc /* holo_blue_dark */,
- 0xffaa66cc /* holo_purple */,
- 0xffffffff /* white */,
- 0xffaaaaaa /* lighter_gray */,
- 0xff555555 /* darker_gray */,
- 0xff000000 /* black */);
-
- final ListView list = new ListView(builder.getContext());
- list.setAdapter(adapter);
- builder.setView(list);
-
- GeckoResult res = new GeckoResult();
-
- final AlertDialog dialog = createStandardDialog(builder, prompt, res);
- list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(final AdapterView> parent, final View v,
- final int position, final long id) {
- res.complete(prompt.confirm(String.format("#%06x", 0xffffff & adapter.getItem(position))));
- dialog.dismiss();
- }
- });
- dialog.show();
-
- return res;
- }
-
- private static Date parseDate(final SimpleDateFormat formatter,
- final String value,
- final boolean defaultToNow) {
- try {
- if (value != null && !value.isEmpty()) {
- return formatter.parse(value);
- }
- } catch (final ParseException e) {
- }
- return defaultToNow ? new Date() : null;
- }
-
- @SuppressWarnings("deprecation")
- private static void setTimePickerTime(final TimePicker picker, final Calendar cal) {
- if (Build.VERSION.SDK_INT >= 23) {
- picker.setHour(cal.get(Calendar.HOUR_OF_DAY));
- picker.setMinute(cal.get(Calendar.MINUTE));
- } else {
- picker.setCurrentHour(cal.get(Calendar.HOUR_OF_DAY));
- picker.setCurrentMinute(cal.get(Calendar.MINUTE));
- }
- }
-
- @SuppressWarnings("deprecation")
- private static void setCalendarTime(final Calendar cal, final TimePicker picker) {
- if (Build.VERSION.SDK_INT >= 23) {
- cal.set(Calendar.HOUR_OF_DAY, picker.getHour());
- cal.set(Calendar.MINUTE, picker.getMinute());
- } else {
- cal.set(Calendar.HOUR_OF_DAY, picker.getCurrentHour());
- cal.set(Calendar.MINUTE, picker.getCurrentMinute());
- }
- }
-
- @Override
- public GeckoResult onDateTimePrompt(final GeckoSession session,
- final DateTimePrompt prompt) {
- stopMedia();
- final Activity activity = mActivity;
- if (activity == null) {
- return GeckoResult.fromValue(prompt.dismiss());
- }
- final String format;
- if (prompt.type == DateTimePrompt.Type.DATE) {
- format = "yyyy-MM-dd";
- } else if (prompt.type == DateTimePrompt.Type.MONTH) {
- format = "yyyy-MM";
- } else if (prompt.type == DateTimePrompt.Type.WEEK) {
- format = "yyyy-'W'ww";
- } else if (prompt.type == DateTimePrompt.Type.TIME) {
- format = "HH:mm";
- } else if (prompt.type == DateTimePrompt.Type.DATETIME_LOCAL) {
- format = "yyyy-MM-dd'T'HH:mm";
- } else {
- throw new UnsupportedOperationException();
- }
-
- final SimpleDateFormat formatter = new SimpleDateFormat(format, Locale.ROOT);
- final Date minDate = parseDate(formatter, prompt.minValue, /* defaultToNow */ false);
- final Date maxDate = parseDate(formatter, prompt.maxValue, /* defaultToNow */ false);
- final Date date = parseDate(formatter, prompt.defaultValue, /* defaultToNow */ true);
- final Calendar cal = formatter.getCalendar();
- cal.setTime(date);
-
- final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- final LayoutInflater inflater = LayoutInflater.from(builder.getContext());
- final DatePicker datePicker;
- if (prompt.type == DateTimePrompt.Type.DATE || prompt.type == DateTimePrompt.Type.MONTH ||
- prompt.type == DateTimePrompt.Type.WEEK || prompt.type == DateTimePrompt.Type.DATETIME_LOCAL) {
- final int resId = builder.getContext().getResources().getIdentifier(
- "date_picker_dialog", "layout", "android");
- DatePicker picker = null;
- if (resId != 0) {
- try {
- picker = (DatePicker) inflater.inflate(resId, /* root */ null);
- } catch (final ClassCastException | InflateException e) {
- }
- }
- if (picker == null) {
- picker = new DatePicker(builder.getContext());
- }
- picker.init(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH),
- cal.get(Calendar.DAY_OF_MONTH), /* listener */ null);
- if (minDate != null) {
- picker.setMinDate(minDate.getTime());
- }
- if (maxDate != null) {
- picker.setMaxDate(maxDate.getTime());
- }
- datePicker = picker;
- } else {
- datePicker = null;
- }
-
- final TimePicker timePicker;
- if (prompt.type == DateTimePrompt.Type.TIME || prompt.type == DateTimePrompt.Type.DATETIME_LOCAL) {
- final int resId = builder.getContext().getResources().getIdentifier(
- "time_picker_dialog", "layout", "android");
- TimePicker picker = null;
- if (resId != 0) {
- try {
- picker = (TimePicker) inflater.inflate(resId, /* root */ null);
- } catch (final ClassCastException | InflateException e) {
- }
- }
- if (picker == null) {
- picker = new TimePicker(builder.getContext());
- }
- setTimePickerTime(picker, cal);
- picker.setIs24HourView(DateFormat.is24HourFormat(builder.getContext()));
- timePicker = picker;
- } else {
- timePicker = null;
- }
-
- final LinearLayout container = addStandardLayout(builder, prompt.title, /* msg */ null);
- container.setPadding(/* left */ 0, /* top */ 0, /* right */ 0, /* bottom */ 0);
- if (datePicker != null) {
- container.addView(datePicker);
- }
- if (timePicker != null) {
- container.addView(timePicker);
- }
-
- GeckoResult res = new GeckoResult();
-
- final DialogInterface.OnClickListener listener =
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- if (which == DialogInterface.BUTTON_NEUTRAL) {
- // Clear
- res.complete(prompt.confirm(""));
- return;
- }
- if (datePicker != null) {
- cal.set(datePicker.getYear(), datePicker.getMonth(),
- datePicker.getDayOfMonth());
- }
- if (timePicker != null) {
- setCalendarTime(cal, timePicker);
- }
- res.complete(prompt.confirm(formatter.format(cal.getTime())));
- }
- };
- builder.setNegativeButton(android.R.string.cancel, /* listener */ null)
- .setNeutralButton("Clear", listener)
- .setPositiveButton(android.R.string.ok, listener);
- createStandardDialog(builder, prompt, res).show();
-
- return res;
- }
-
- @Override
- @TargetApi(19)
- public GeckoResult onFilePrompt(GeckoSession session, FilePrompt prompt) {
- stopMedia();
- final Activity activity = mActivity;
- if (activity == null) {
- return GeckoResult.fromValue(prompt.dismiss());
- }
-
- // Merge all given MIME types into one, using wildcard if needed.
- String mimeType = null;
- String mimeSubtype = null;
- if (prompt.mimeTypes != null) {
- for (final String rawType : prompt.mimeTypes) {
- final String normalizedType = rawType.trim().toLowerCase(Locale.ROOT);
- final int len = normalizedType.length();
- int slash = normalizedType.indexOf('/');
- if (slash < 0) {
- slash = len;
- }
- final String newType = normalizedType.substring(0, slash);
- final String newSubtype = normalizedType.substring(Math.min(slash + 1, len));
- if (mimeType == null) {
- mimeType = newType;
- } else if (!mimeType.equals(newType)) {
- mimeType = "*";
- }
- if (mimeSubtype == null) {
- mimeSubtype = newSubtype;
- } else if (!mimeSubtype.equals(newSubtype)) {
- mimeSubtype = "*";
- }
- }
- }
-
- final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
- intent.setType((mimeType != null ? mimeType : "*") + '/' +
- (mimeSubtype != null ? mimeSubtype : "*"));
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
- if (Build.VERSION.SDK_INT >= 18 && prompt.type == FilePrompt.Type.MULTIPLE) {
- intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
- }
- if (Build.VERSION.SDK_INT >= 19 && prompt.mimeTypes.length > 0) {
- intent.putExtra(Intent.EXTRA_MIME_TYPES, prompt.mimeTypes);
- }
-
- GeckoResult res = new GeckoResult();
-
- try {
- mFileResponse = res;
- mFilePrompt = prompt;
- activity.startActivityForResult(intent, filePickerRequestCode);
- } catch (final ActivityNotFoundException e) {
- Log.e(LOGTAG, "Cannot launch activity", e);
- return GeckoResult.fromValue(prompt.dismiss());
- }
-
- return res;
- }
-
- public void onFileCallbackResult(final int resultCode, final Intent data) {
- stopMedia();
- if (mFileResponse == null) {
- return;
- }
-
- final GeckoResult res = mFileResponse;
- mFileResponse = null;
-
- final FilePrompt prompt = mFilePrompt;
- mFilePrompt = null;
-
- if (resultCode != Activity.RESULT_OK || data == null) {
- res.complete(prompt.dismiss());
- return;
- }
-
- final Uri uri = data.getData();
- final ClipData clip = data.getClipData();
-
- if (prompt.type == FilePrompt.Type.SINGLE ||
- (prompt.type == FilePrompt.Type.MULTIPLE && clip == null)) {
- res.complete(prompt.confirm(mActivity, uri));
- } else if (prompt.type == FilePrompt.Type.MULTIPLE) {
- if (clip == null) {
- Log.w(LOGTAG, "No selected file");
- res.complete(prompt.dismiss());
- return;
- }
- final int count = clip.getItemCount();
- final ArrayList uris = new ArrayList<>(count);
- for (int i = 0; i < count; i++) {
- uris.add(clip.getItemAt(i).getUri());
- }
- res.complete(prompt.confirm(mActivity, uris.toArray(new Uri[uris.size()])));
- }
- }
-
- public void onPermissionPrompt(final GeckoSession session, final String title,
- final GeckoSession.PermissionDelegate.Callback callback) {
- stopMedia();
- final Activity activity = mActivity;
- if (activity == null) {
- callback.reject();
- return;
- }
- final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setTitle(title)
- .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- callback.reject();
- }
- })
- .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- callback.grant();
- }
- });
-
- final AlertDialog dialog = builder.create();
- dialog.show();
- }
-
- public void onSlowScriptPrompt(GeckoSession geckoSession, String title, GeckoResult reportAction) {
- stopMedia();
- final Activity activity = mActivity;
- if (activity == null) {
- return;
- }
- final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setTitle(title)
- .setNegativeButton("Wait", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- reportAction.complete(SlowScriptResponse.CONTINUE);
- }
- })
- .setPositiveButton("Stop", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- reportAction.complete(SlowScriptResponse.STOP);
- }
- });
-
- final AlertDialog dialog = builder.create();
- dialog.show();
- }
-
- private Spinner addMediaSpinner(final Context context, final ViewGroup container,
- final GeckoSession.PermissionDelegate.MediaSource[] sources, final String[] sourceNames) {
- final ArrayAdapter adapter = new ArrayAdapter(
- context, android.R.layout.simple_spinner_item) {
- private View convertView(final int position, final View view) {
- if (view != null) {
- final GeckoSession.PermissionDelegate.MediaSource item = getItem(position);
- ((TextView) view).setText(sourceNames != null ? sourceNames[position] : "media");
- }
- return view;
- }
-
- @Override
- public View getView(final int position, View view,
- final ViewGroup parent) {
- return convertView(position, super.getView(position, view, parent));
- }
-
- @Override
- public View getDropDownView(final int position, final View view,
- final ViewGroup parent) {
- return convertView(position, super.getDropDownView(position, view, parent));
- }
- };
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- adapter.addAll(sources);
-
- final Spinner spinner = new Spinner(context);
- spinner.setAdapter(adapter);
- spinner.setSelection(0);
- container.addView(spinner);
- return spinner;
- }
-
- public void onMediaPrompt(final GeckoSession session, final String title,
- final GeckoSession.PermissionDelegate.MediaSource[] video, final GeckoSession.PermissionDelegate.MediaSource[] audio,
- final String[] videoNames, final String[] audioNames,
- final GeckoSession.PermissionDelegate.MediaCallback callback) {
- final Activity activity = mActivity;
- stopMedia();
- if (activity == null || (video == null && audio == null)) {
- callback.reject();
- return;
- }
- final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- final LinearLayout container = addStandardLayout(builder, title, /* msg */ null);
-
- final Spinner videoSpinner;
- if (video != null) {
- videoSpinner = addMediaSpinner(builder.getContext(), container, video, videoNames);
- } else {
- videoSpinner = null;
- }
-
- final Spinner audioSpinner;
- if (audio != null) {
- audioSpinner = addMediaSpinner(builder.getContext(), container, audio, audioNames);
- } else {
- audioSpinner = null;
- }
-
- builder.setNegativeButton(android.R.string.cancel, /* listener */ null)
- .setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- final GeckoSession.PermissionDelegate.MediaSource video = (videoSpinner != null)
- ? (GeckoSession.PermissionDelegate.MediaSource) videoSpinner.getSelectedItem() : null;
- final GeckoSession.PermissionDelegate.MediaSource audio = (audioSpinner != null)
- ? (GeckoSession.PermissionDelegate.MediaSource) audioSpinner.getSelectedItem() : null;
- callback.grant(video, audio);
- }
- });
-
- final AlertDialog dialog = builder.create();
- dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
- @Override
- public void onDismiss(final DialogInterface dialog) {
- callback.reject();
- }
- });
- dialog.show();
- }
-
- public void onMediaPrompt(final GeckoSession session, final String title,
- final GeckoSession.PermissionDelegate.MediaSource[] video, final GeckoSession.PermissionDelegate.MediaSource[] audio,
- final GeckoSession.PermissionDelegate.MediaCallback callback) {
- stopMedia();
- onMediaPrompt(session, title, video, audio, null, null, callback);
- }
-
- @Override
- public GeckoResult onPopupPrompt(final GeckoSession session,
- final PopupPrompt prompt) {
- stopMedia();
- return GeckoResult.fromValue(prompt.confirm(AllowOrDeny.ALLOW));
- }
+package com.hiddenservices.onionservices.appManager.homeManager.geckoManager.delegateModel;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.ActivityNotFoundException;
+import android.content.ClipData;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.net.Uri;
+import android.os.Build;
+import android.text.InputType;
+import android.text.format.DateFormat;
+import android.util.Log;
+import android.view.InflateException;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.MimeTypeMap;
+import android.widget.ArrayAdapter;
+import android.widget.CheckedTextView;
+import android.widget.DatePicker;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.ScrollView;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.TimePicker;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ShareCompat;
+import com.hiddenservices.onionservices.appManager.activityContextManager;
+import java.io.File;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import org.mozilla.geckoview.AllowOrDeny;
+import org.mozilla.geckoview.GeckoResult;
+import org.mozilla.geckoview.GeckoSession;
+import org.mozilla.geckoview.SlowScriptResponse;
+
+public final class promptDelegate implements GeckoSession.PromptDelegate {
+
+ private final AppCompatActivity mActivity;
+ private GeckoResult mFileResponse;
+ private FilePrompt mFilePrompt;
+
+ static final String LOGTAG = "BasicGeckoViewPrompt";
+ public int filePickerRequestCode = 1;
+
+ public promptDelegate(final AppCompatActivity activity) {
+ mActivity = activity;
+ }
+
+ public void stopMedia(){
+ try {
+ activityContextManager.getInstance().getHomeController().onKillMedia();
+ }catch (Exception ex){}
+ }
+
+ @Override
+ public GeckoResult onAlertPrompt(@NonNull final GeckoSession session,
+ @NonNull final AlertPrompt prompt) {
+ stopMedia();
+ final Activity activity = mActivity;
+ if (activity == null) {
+ return GeckoResult.fromValue(prompt.dismiss());
+ }
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
+ .setTitle(prompt.title)
+ .setMessage(prompt.message)
+ .setPositiveButton(android.R.string.ok, null);
+ GeckoResult res = new GeckoResult<>();
+ createStandardDialog(builder, prompt, res).show();
+ return res;
+ }
+
+ @Override
+ public GeckoResult onButtonPrompt(@NonNull final GeckoSession session,
+ @NonNull final ButtonPrompt prompt) {
+ stopMedia();
+ final Activity activity = mActivity;
+ if (activity == null) {
+ return GeckoResult.fromValue(prompt.dismiss());
+ }
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
+ .setTitle(prompt.title)
+ .setMessage(prompt.message);
+
+ GeckoResult res = new GeckoResult<>();
+
+ final DialogInterface.OnClickListener listener =
+ (dialog, which) -> {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ res.complete(prompt.confirm(ButtonPrompt.Type.POSITIVE));
+ } else if (which == DialogInterface.BUTTON_NEGATIVE) {
+ res.complete(prompt.confirm(ButtonPrompt.Type.NEGATIVE));
+ } else {
+ res.complete(prompt.dismiss());
+ }
+ };
+
+ builder.setPositiveButton(android.R.string.ok, listener);
+ builder.setNegativeButton(android.R.string.cancel, listener);
+
+ createStandardDialog(builder, prompt, res).show();
+ return res;
+ }
+
+ public static String getMimeType(Context context, Uri uri) {
+ String extension;
+
+ //Check uri format to avoid null
+ if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
+ //If scheme is a content
+ final MimeTypeMap mime = MimeTypeMap.getSingleton();
+ extension = mime.getExtensionFromMimeType(context.getContentResolver().getType(uri));
+ } else {
+ //If scheme is a File
+ //This will replace white spaces with %20 and also other special characters. This will avoid returning null values on file name with spaces and special characters.
+ extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(new File(uri.getPath())).toString());
+
+ }
+
+ return extension;
+ }
+
+ static boolean mPopupOpened = false;
+ @Override
+ public GeckoResult onSharePrompt(@NonNull final GeckoSession session,
+ @NonNull final SharePrompt prompt) {
+ stopMedia();
+ new Thread(){
+ public void run(){
+ try {
+ sleep(4000);
+ mPopupOpened = false;
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }.start();
+ if(!mPopupOpened){
+ mPopupOpened = true;
+ }else {
+ return GeckoResult.fromValue(prompt.confirm(SharePrompt.Result.ABORT));
+ }
+ try {
+ String m_data = prompt.uri;
+ if(prompt.text!=null){
+ m_data += " : " + prompt.text;
+ }
+
+ ShareCompat.IntentBuilder.from(mActivity)
+ .setType("text/x-uri")
+ .setChooserTitle(prompt.title)
+ .setText(m_data)
+ .startChooser();
+ }catch (Exception ex){}
+
+ return GeckoResult.fromValue(prompt.confirm(SharePrompt.Result.SUCCESS));
+
+ }
+
+ @Nullable
+ @Override
+ public GeckoResult onRepostConfirmPrompt(@NonNull final GeckoSession session,
+ @NonNull final RepostConfirmPrompt prompt) {
+ stopMedia();
+ final Activity activity = mActivity;
+ if (activity == null) {
+ return GeckoResult.fromValue(prompt.dismiss());
+ }
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
+ .setTitle("Are you sure?")
+ .setMessage("To display this page, GeckoViewExample must send information that will repeat any action (such as a search or order confirmation) that was performed earlier.");
+
+ GeckoResult res = new GeckoResult<>();
+
+ final DialogInterface.OnClickListener listener = (dialog, which) -> {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ res.complete(prompt.confirm(AllowOrDeny.ALLOW));
+ } else if (which == DialogInterface.BUTTON_NEGATIVE) {
+ res.complete(prompt.confirm(AllowOrDeny.DENY));
+ } else {
+ res.complete(prompt.dismiss());
+ }
+ };
+
+ builder.setPositiveButton("Resend", listener);
+ builder.setNegativeButton("Cancel", listener);
+
+ try {
+ if(mActivity!=null && !mActivity.isFinishing())
+ {
+ createStandardDialog(builder, prompt, res).show();
+ }
+ }catch (Exception ex){}
+ return res;
+ }
+
+ @Nullable
+ @Override
+ public GeckoResult onBeforeUnloadPrompt(@NonNull final GeckoSession session,
+ @NonNull final BeforeUnloadPrompt prompt) {
+ stopMedia();
+ final Activity activity = mActivity;
+ if (activity == null) {
+ return GeckoResult.fromValue(prompt.dismiss());
+ }
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
+ .setTitle("Are you sure?")
+ .setMessage("This page is asking you to confirm that you want to leave - data you have entered may not be saved");
+
+ GeckoResult res = new GeckoResult<>();
+
+ final DialogInterface.OnClickListener listener = (dialog, which) -> {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ res.complete(prompt.confirm(AllowOrDeny.ALLOW));
+ } else if (which == DialogInterface.BUTTON_NEGATIVE) {
+ res.complete(prompt.confirm(AllowOrDeny.DENY));
+ } else {
+ res.complete(prompt.dismiss());
+ }
+ };
+
+ builder.setPositiveButton("Leave Page", listener);
+ builder.setNegativeButton("Stay on Page", listener);
+
+ createStandardDialog(builder, prompt, res).show();
+ return res;
+ }
+
+ private int getViewPadding(final AlertDialog.Builder builder) {
+ stopMedia();
+ final TypedArray attr = builder.getContext().obtainStyledAttributes(
+ new int[]{android.R.attr.listPreferredItemPaddingLeft});
+ final int padding = attr.getDimensionPixelSize(0, 1);
+ attr.recycle();
+ return padding;
+ }
+
+ private LinearLayout addStandardLayout(final AlertDialog.Builder builder,
+ final String title, final String msg) {
+ stopMedia();
+ final ScrollView scrollView = new ScrollView(builder.getContext());
+ final LinearLayout container = new LinearLayout(builder.getContext());
+ final int horizontalPadding = getViewPadding(builder);
+ final int verticalPadding = (msg == null || msg.isEmpty()) ? horizontalPadding : 0;
+ container.setOrientation(LinearLayout.VERTICAL);
+ container.setPadding(/* left */ horizontalPadding, /* top */ verticalPadding,
+ /* right */ horizontalPadding, /* bottom */ verticalPadding);
+ scrollView.addView(container);
+ builder.setTitle(title)
+ .setMessage(msg)
+ .setView(scrollView);
+ return container;
+ }
+
+ private AlertDialog createStandardDialog(final AlertDialog.Builder builder,
+ final BasePrompt prompt,
+ final GeckoResult response) {
+ final AlertDialog dialog = builder.create();
+ stopMedia();
+ dialog.setOnDismissListener(dialog1 -> {
+ if (!prompt.isComplete()) {
+ response.complete(prompt.dismiss());
+ }
+ });
+ return dialog;
+ }
+
+ @Override
+ public GeckoResult onTextPrompt(@NonNull final GeckoSession session,
+ @NonNull final TextPrompt prompt) {
+ final Activity activity = mActivity;
+ stopMedia();
+ if (activity == null) {
+ return GeckoResult.fromValue(prompt.dismiss());
+ }
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ final LinearLayout container = addStandardLayout(builder, prompt.title, prompt.message);
+ final EditText editText = new EditText(builder.getContext());
+ editText.setText(prompt.defaultValue);
+ container.addView(editText);
+
+ GeckoResult res = new GeckoResult<>();
+
+ builder.setNegativeButton(android.R.string.cancel, /* listener */ null)
+ .setPositiveButton(android.R.string.ok,
+ (dialog, which) -> res.complete(prompt.confirm(editText.getText().toString())));
+
+ createStandardDialog(builder, prompt, res).show();
+ return res;
+ }
+
+ @Override
+ public GeckoResult onAuthPrompt(@NonNull final GeckoSession session,
+ @NonNull final AuthPrompt prompt) {
+ final Activity activity = mActivity;
+ stopMedia();
+ if (activity == null) {
+ return GeckoResult.fromValue(prompt.dismiss());
+ }
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ final LinearLayout container = addStandardLayout(builder, prompt.title, prompt.message);
+
+ final int flags = prompt.authOptions.flags;
+ final int level = prompt.authOptions.level;
+ final EditText username;
+ if ((flags & AuthPrompt.AuthOptions.Flags.ONLY_PASSWORD) == 0) {
+ username = new EditText(builder.getContext());
+ username.setHint("Username");
+ username.setText(prompt.authOptions.username);
+ container.addView(username);
+ } else {
+ username = null;
+ }
+
+ final EditText password = new EditText(builder.getContext());
+ password.setHint("Password");
+ password.setText(prompt.authOptions.password);
+ password.setInputType(InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ container.addView(password);
+
+ if (level != AuthPrompt.AuthOptions.Level.NONE) {
+ final ImageView secure = new ImageView(builder.getContext());
+ secure.setImageResource(android.R.drawable.ic_lock_lock);
+ container.addView(secure);
+ }
+
+ GeckoResult res = new GeckoResult<>();
+
+ builder.setNegativeButton(android.R.string.cancel, /* listener */ null)
+ .setPositiveButton(android.R.string.ok,
+ (dialog, which) -> {
+ if ((flags & AuthPrompt.AuthOptions.Flags.ONLY_PASSWORD) == 0) {
+ res.complete(prompt.confirm(username.getText().toString(),
+ password.getText().toString()));
+
+ } else {
+ res.complete(prompt.confirm(password.getText().toString()));
+ }
+ });
+ createStandardDialog(builder, prompt, res).show();
+
+ return res;
+ }
+
+ private static class ModifiableChoice {
+ public boolean modifiableSelected;
+ public String modifiableLabel;
+ public final ChoicePrompt.Choice choice;
+
+ public ModifiableChoice(ChoicePrompt.Choice c) {
+ choice = c;
+ modifiableSelected = choice.selected;
+ modifiableLabel = choice.label;
+ }
+ }
+
+ private void addChoiceItems(final int type, final ArrayAdapter list,
+ final ChoicePrompt.Choice[] items, final String indent) {
+ stopMedia();
+ if (type == ChoicePrompt.Type.MENU) {
+ for (final ChoicePrompt.Choice item : items) {
+ list.add(new ModifiableChoice(item));
+ }
+ return;
+ }
+
+ for (final ChoicePrompt.Choice item : items) {
+ final ModifiableChoice modItem = new ModifiableChoice(item);
+
+ final ChoicePrompt.Choice[] children = item.items;
+
+ if (indent != null && children == null) {
+ modItem.modifiableLabel = indent + modItem.modifiableLabel;
+ }
+ list.add(modItem);
+
+ if (children != null) {
+ final String newIndent;
+ if (type == ChoicePrompt.Type.SINGLE || type == ChoicePrompt.Type.MULTIPLE) {
+ newIndent = (indent != null) ? indent + '\t' : "\t";
+ } else {
+ newIndent = null;
+ }
+ addChoiceItems(type, list, children, newIndent);
+ }
+ }
+ }
+
+ private void onChoicePromptImpl(final String title,
+ final String message, final int type,
+ final ChoicePrompt.Choice[] choices, final ChoicePrompt prompt,
+ final GeckoResult res) {
+ stopMedia();
+ final Activity activity = mActivity;
+ if (activity == null) {
+ res.complete(prompt.dismiss());
+ return;
+ }
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ addStandardLayout(builder, title, message);
+
+ final ListView list = new ListView(builder.getContext());
+ if (type == ChoicePrompt.Type.MULTIPLE) {
+ list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+ }
+
+ final ArrayAdapter adapter = new ArrayAdapter(
+ builder.getContext(), android.R.layout.simple_list_item_1) {
+ private static final int TYPE_MENU_ITEM = 0;
+ private static final int TYPE_MENU_CHECK = 1;
+ private static final int TYPE_SEPARATOR = 2;
+ private static final int TYPE_GROUP = 3;
+ private static final int TYPE_SINGLE = 4;
+ private static final int TYPE_MULTIPLE = 5;
+ private static final int TYPE_COUNT = 6;
+
+ private LayoutInflater mInflater;
+ private View mSeparator;
+
+ @Override
+ public int getViewTypeCount() {
+ return TYPE_COUNT;
+ }
+
+ @Override
+ public int getItemViewType(final int position) {
+ final ModifiableChoice item = getItem(position);
+ if (item.choice.separator) {
+ return TYPE_SEPARATOR;
+ } else if (type == ChoicePrompt.Type.MENU) {
+ return item.modifiableSelected ? TYPE_MENU_CHECK : TYPE_MENU_ITEM;
+ } else if (item.choice.items != null) {
+ return TYPE_GROUP;
+ } else if (type == ChoicePrompt.Type.SINGLE) {
+ return TYPE_SINGLE;
+ } else if (type == ChoicePrompt.Type.MULTIPLE) {
+ return TYPE_MULTIPLE;
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ @Override
+ public boolean isEnabled(final int position) {
+ final ModifiableChoice item = getItem(position);
+ return !item.choice.separator && !item.choice.disabled &&
+ ((type != ChoicePrompt.Type.SINGLE &&
+ type != ChoicePrompt.Type.MULTIPLE) ||
+ item.choice.items == null);
+ }
+
+ @Override
+ public View getView(final int position, View view,
+ final ViewGroup parent) {
+ final int itemType = getItemViewType(position);
+ final int layoutId;
+ if (itemType == TYPE_SEPARATOR) {
+ if (mSeparator == null) {
+ mSeparator = new View(getContext());
+ mSeparator.setLayoutParams(new ListView.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, 2, itemType));
+ final TypedArray attr = getContext().obtainStyledAttributes(
+ new int[]{android.R.attr.listDivider});
+ mSeparator.setBackgroundResource(attr.getResourceId(0, 0));
+ attr.recycle();
+ }
+ return mSeparator;
+ } else if (itemType == TYPE_MENU_ITEM) {
+ layoutId = android.R.layout.simple_list_item_1;
+ } else if (itemType == TYPE_MENU_CHECK) {
+ layoutId = android.R.layout.simple_list_item_checked;
+ } else if (itemType == TYPE_GROUP) {
+ layoutId = android.R.layout.preference_category;
+ } else if (itemType == TYPE_SINGLE) {
+ layoutId = android.R.layout.simple_list_item_single_choice;
+ } else if (itemType == TYPE_MULTIPLE) {
+ layoutId = android.R.layout.simple_list_item_multiple_choice;
+ } else {
+ throw new UnsupportedOperationException();
+ }
+
+ if (view == null) {
+ if (mInflater == null) {
+ mInflater = LayoutInflater.from(builder.getContext());
+ }
+ view = mInflater.inflate(layoutId, parent, false);
+ }
+
+ final ModifiableChoice item = getItem(position);
+ final TextView text = (TextView) view;
+ text.setEnabled(!item.choice.disabled);
+ text.setText(item.modifiableLabel);
+ if (view instanceof CheckedTextView) {
+ final boolean selected = item.modifiableSelected;
+ if (itemType == TYPE_MULTIPLE) {
+ list.setItemChecked(position, selected);
+ } else {
+ ((CheckedTextView) view).setChecked(selected);
+ }
+ }
+ return view;
+ }
+ };
+ addChoiceItems(type, adapter, choices, /* indent */ null);
+
+ list.setAdapter(adapter);
+ builder.setView(list);
+
+ final AlertDialog dialog;
+ if (type == ChoicePrompt.Type.SINGLE || type == ChoicePrompt.Type.MENU) {
+ dialog = createStandardDialog(builder, prompt, res);
+ list.setOnItemClickListener((parent, v, position, id) -> {
+ final ModifiableChoice item = adapter.getItem(position);
+ if (type == ChoicePrompt.Type.MENU) {
+ final ChoicePrompt.Choice[] children = item.choice.items;
+ if (children != null) {
+ // Show sub-menu.
+ dialog.setOnDismissListener(null);
+ dialog.dismiss();
+ onChoicePromptImpl(item.modifiableLabel, /* msg */ null,
+ type, children, prompt, res);
+ return;
+ }
+ }
+ res.complete(prompt.confirm(item.choice));
+ dialog.dismiss();
+ });
+ } else if (type == ChoicePrompt.Type.MULTIPLE) {
+ list.setOnItemClickListener((parent, v, position, id) -> {
+ final ModifiableChoice item = adapter.getItem(position);
+ item.modifiableSelected = ((CheckedTextView) v).isChecked();
+ });
+ builder.setNegativeButton(android.R.string.cancel, /* listener */ null)
+ .setPositiveButton(android.R.string.ok,
+ (dialog1, which) -> {
+ final int len = adapter.getCount();
+ ArrayList items = new ArrayList<>(len);
+ for (int i = 0; i < len; i++) {
+ final ModifiableChoice item = adapter.getItem(i);
+ if (item.modifiableSelected) {
+ items.add(item.choice.id);
+ }
+ }
+ res.complete(prompt.confirm(items.toArray(new String[0])));
+ });
+ dialog = createStandardDialog(builder, prompt, res);
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ if(mActivity!=null && !mActivity.isFinishing())
+ {
+ dialog.show();
+ }
+ }catch (Exception ex){}
+ }
+
+ @Override
+ public GeckoResult onChoicePrompt(@NonNull final GeckoSession session,
+ @NonNull final ChoicePrompt prompt) {
+ stopMedia();
+ final GeckoResult res = new GeckoResult<>();
+ onChoicePromptImpl(prompt.title, prompt.message, prompt.type, prompt.choices,
+ prompt, res);
+ return res;
+ }
+
+ private static int parseColor(final String value, final int def) {
+ try {
+ return Color.parseColor(value);
+ } catch (final IllegalArgumentException e) {
+ return def;
+ }
+ }
+
+ @Override
+ public GeckoResult onColorPrompt(@NonNull final GeckoSession session,
+ @NonNull final ColorPrompt prompt) {
+ stopMedia();
+ final Activity activity = mActivity;
+ if (activity == null) {
+ return GeckoResult.fromValue(prompt.dismiss());
+ }
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ addStandardLayout(builder, prompt.title, /* msg */ null);
+
+ final int initial = parseColor(prompt.defaultValue, /* def */ 0);
+ final ArrayAdapter adapter = new ArrayAdapter(
+ builder.getContext(), android.R.layout.simple_list_item_1) {
+ private LayoutInflater mInflater;
+
+ @Override
+ public int getViewTypeCount() {
+ return 2;
+ }
+
+ @Override
+ public int getItemViewType(final int position) {
+ return (getItem(position) == initial) ? 1 : 0;
+ }
+
+ @Override
+ public View getView(final int position, View view,
+ final ViewGroup parent) {
+ if (mInflater == null) {
+ mInflater = LayoutInflater.from(builder.getContext());
+ }
+ final int color = getItem(position);
+ if (view == null) {
+ view = mInflater.inflate((color == initial) ?
+ android.R.layout.simple_list_item_checked :
+ android.R.layout.simple_list_item_1, parent, false);
+ }
+ view.setBackgroundResource(android.R.drawable.editbox_background);
+ view.getBackground().setColorFilter(color, PorterDuff.Mode.MULTIPLY);
+ return view;
+ }
+ };
+
+ adapter.addAll(0xffff4444 /* holo_red_light */,
+ 0xffcc0000 /* holo_red_dark */,
+ 0xffffbb33 /* holo_orange_light */,
+ 0xffff8800 /* holo_orange_dark */,
+ 0xff99cc00 /* holo_green_light */,
+ 0xff669900 /* holo_green_dark */,
+ 0xff33b5e5 /* holo_blue_light */,
+ 0xff0099cc /* holo_blue_dark */,
+ 0xffaa66cc /* holo_purple */,
+ 0xffffffff /* white */,
+ 0xffaaaaaa /* lighter_gray */,
+ 0xff555555 /* darker_gray */,
+ 0xff000000 /* black */);
+
+ final ListView list = new ListView(builder.getContext());
+ list.setAdapter(adapter);
+ builder.setView(list);
+
+ GeckoResult res = new GeckoResult<>();
+
+ final AlertDialog dialog = createStandardDialog(builder, prompt, res);
+ list.setOnItemClickListener((parent, v, position, id) -> {
+ res.complete(prompt.confirm(String.format("#%06x", 0xffffff & adapter.getItem(position))));
+ dialog.dismiss();
+ });
+ dialog.show();
+
+ return res;
+ }
+
+ private static Date parseDate(final SimpleDateFormat formatter,
+ final String value,
+ final boolean defaultToNow) {
+ try {
+ if (value != null && !value.isEmpty()) {
+ return formatter.parse(value);
+ }
+ } catch (final ParseException e) {
+ }
+ return defaultToNow ? new Date() : null;
+ }
+
+ @SuppressWarnings("deprecation")
+ private static void setTimePickerTime(final TimePicker picker, final Calendar cal) {
+ if (Build.VERSION.SDK_INT >= 23) {
+ picker.setHour(cal.get(Calendar.HOUR_OF_DAY));
+ picker.setMinute(cal.get(Calendar.MINUTE));
+ } else {
+ picker.setCurrentHour(cal.get(Calendar.HOUR_OF_DAY));
+ picker.setCurrentMinute(cal.get(Calendar.MINUTE));
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private static void setCalendarTime(final Calendar cal, final TimePicker picker) {
+ if (Build.VERSION.SDK_INT >= 23) {
+ cal.set(Calendar.HOUR_OF_DAY, picker.getHour());
+ cal.set(Calendar.MINUTE, picker.getMinute());
+ } else {
+ cal.set(Calendar.HOUR_OF_DAY, picker.getCurrentHour());
+ cal.set(Calendar.MINUTE, picker.getCurrentMinute());
+ }
+ }
+
+ @Override
+ public GeckoResult onDateTimePrompt(@NonNull final GeckoSession session,
+ @NonNull final DateTimePrompt prompt) {
+ stopMedia();
+ final Activity activity = mActivity;
+ if (activity == null) {
+ return GeckoResult.fromValue(prompt.dismiss());
+ }
+ final String format;
+ if (prompt.type == DateTimePrompt.Type.DATE) {
+ format = "yyyy-MM-dd";
+ } else if (prompt.type == DateTimePrompt.Type.MONTH) {
+ format = "yyyy-MM";
+ } else if (prompt.type == DateTimePrompt.Type.WEEK) {
+ format = "yyyy-'W'ww";
+ } else if (prompt.type == DateTimePrompt.Type.TIME) {
+ format = "HH:mm";
+ } else if (prompt.type == DateTimePrompt.Type.DATETIME_LOCAL) {
+ format = "yyyy-MM-dd'T'HH:mm";
+ } else {
+ throw new UnsupportedOperationException();
+ }
+
+ final SimpleDateFormat formatter = new SimpleDateFormat(format, Locale.ROOT);
+ final Date minDate = parseDate(formatter, prompt.minValue, /* defaultToNow */ false);
+ final Date maxDate = parseDate(formatter, prompt.maxValue, /* defaultToNow */ false);
+ final Date date = parseDate(formatter, prompt.defaultValue, /* defaultToNow */ true);
+ final Calendar cal = formatter.getCalendar();
+ cal.setTime(date);
+
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ final LayoutInflater inflater = LayoutInflater.from(builder.getContext());
+ final DatePicker datePicker;
+ if (prompt.type == DateTimePrompt.Type.DATE || prompt.type == DateTimePrompt.Type.MONTH ||
+ prompt.type == DateTimePrompt.Type.WEEK || prompt.type == DateTimePrompt.Type.DATETIME_LOCAL) {
+ @SuppressLint("DiscouragedApi") final int resId = builder.getContext().getResources().getIdentifier(
+ "date_picker_dialog", "layout", "android");
+ DatePicker picker = null;
+ if (resId != 0) {
+ try {
+ picker = (DatePicker) inflater.inflate(resId, /* root */ null);
+ } catch (final ClassCastException | InflateException e) {
+ }
+ }
+ if (picker == null) {
+ picker = new DatePicker(builder.getContext());
+ }
+ picker.init(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH),
+ cal.get(Calendar.DAY_OF_MONTH), /* listener */ null);
+ if (minDate != null) {
+ picker.setMinDate(minDate.getTime());
+ }
+ if (maxDate != null) {
+ picker.setMaxDate(maxDate.getTime());
+ }
+ datePicker = picker;
+ } else {
+ datePicker = null;
+ }
+
+ final TimePicker timePicker;
+ if (prompt.type == DateTimePrompt.Type.TIME || prompt.type == DateTimePrompt.Type.DATETIME_LOCAL) {
+ @SuppressLint("DiscouragedApi") final int resId = builder.getContext().getResources().getIdentifier(
+ "time_picker_dialog", "layout", "android");
+ TimePicker picker = null;
+ if (resId != 0) {
+ try {
+ picker = (TimePicker) inflater.inflate(resId, /* root */ null);
+ } catch (final ClassCastException | InflateException e) {
+ }
+ }
+ if (picker == null) {
+ picker = new TimePicker(builder.getContext());
+ }
+ setTimePickerTime(picker, cal);
+ picker.setIs24HourView(DateFormat.is24HourFormat(builder.getContext()));
+ timePicker = picker;
+ } else {
+ timePicker = null;
+ }
+
+ final LinearLayout container = addStandardLayout(builder, prompt.title, /* msg */ null);
+ container.setPadding(/* left */ 0, /* top */ 0, /* right */ 0, /* bottom */ 0);
+ if (datePicker != null) {
+ container.addView(datePicker);
+ }
+ if (timePicker != null) {
+ container.addView(timePicker);
+ }
+
+ GeckoResult res = new GeckoResult<>();
+
+ final DialogInterface.OnClickListener listener =
+ (dialog, which) -> {
+ if (which == DialogInterface.BUTTON_NEUTRAL) {
+ // Clear
+ res.complete(prompt.confirm(""));
+ return;
+ }
+ if (datePicker != null) {
+ cal.set(datePicker.getYear(), datePicker.getMonth(),
+ datePicker.getDayOfMonth());
+ }
+ if (timePicker != null) {
+ setCalendarTime(cal, timePicker);
+ }
+ res.complete(prompt.confirm(formatter.format(cal.getTime())));
+ };
+ builder.setNegativeButton(android.R.string.cancel, /* listener */ null)
+ .setNeutralButton("Clear", listener)
+ .setPositiveButton(android.R.string.ok, listener);
+ createStandardDialog(builder, prompt, res).show();
+
+ return res;
+ }
+
+ @Override
+ public GeckoResult onFilePrompt(@NonNull GeckoSession session, @NonNull FilePrompt prompt) {
+ stopMedia();
+ final Activity activity = mActivity;
+ if (activity == null) {
+ return GeckoResult.fromValue(prompt.dismiss());
+ }
+
+ // Merge all given MIME types into one, using wildcard if needed.
+ String mimeType = null;
+ String mimeSubtype = null;
+ if (prompt.mimeTypes != null) {
+ for (final String rawType : prompt.mimeTypes) {
+ final String normalizedType = rawType.trim().toLowerCase(Locale.ROOT);
+ final int len = normalizedType.length();
+ int slash = normalizedType.indexOf('/');
+ if (slash < 0) {
+ slash = len;
+ }
+ final String newType = normalizedType.substring(0, slash);
+ final String newSubtype = normalizedType.substring(Math.min(slash + 1, len));
+ if (mimeType == null) {
+ mimeType = newType;
+ } else if (!mimeType.equals(newType)) {
+ mimeType = "*";
+ }
+ if (mimeSubtype == null) {
+ mimeSubtype = newSubtype;
+ } else if (!mimeSubtype.equals(newSubtype)) {
+ mimeSubtype = "*";
+ }
+ }
+ }
+
+ final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.setType((mimeType != null ? mimeType : "*") + '/' +
+ (mimeSubtype != null ? mimeSubtype : "*"));
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
+ if (prompt.type == FilePrompt.Type.MULTIPLE) {
+ intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
+ }
+ if (prompt.mimeTypes.length > 0) {
+ intent.putExtra(Intent.EXTRA_MIME_TYPES, prompt.mimeTypes);
+ }
+
+ GeckoResult res = new GeckoResult<>();
+
+ try {
+ mFileResponse = res;
+ mFilePrompt = prompt;
+ activity.startActivityForResult(intent, filePickerRequestCode);
+ } catch (final ActivityNotFoundException e) {
+ Log.e(LOGTAG, "Cannot launch activity", e);
+ return GeckoResult.fromValue(prompt.dismiss());
+ }
+
+ return res;
+ }
+
+ public void onFileCallbackResult(final int resultCode, final Intent data) {
+ stopMedia();
+ if (mFileResponse == null) {
+ return;
+ }
+
+ final GeckoResult res = mFileResponse;
+ mFileResponse = null;
+
+ final FilePrompt prompt = mFilePrompt;
+ mFilePrompt = null;
+
+ if (resultCode != Activity.RESULT_OK || data == null) {
+ res.complete(prompt.dismiss());
+ return;
+ }
+
+ final Uri uri = data.getData();
+ final ClipData clip = data.getClipData();
+
+ if (prompt.type == FilePrompt.Type.SINGLE ||
+ (prompt.type == FilePrompt.Type.MULTIPLE && clip == null)) {
+ res.complete(prompt.confirm(mActivity, uri));
+ } else if (prompt.type == FilePrompt.Type.MULTIPLE) {
+ if (clip == null) {
+ Log.w(LOGTAG, "No selected file");
+ res.complete(prompt.dismiss());
+ return;
+ }
+ final int count = clip.getItemCount();
+ final ArrayList uris = new ArrayList<>(count);
+ for (int i = 0; i < count; i++) {
+ uris.add(clip.getItemAt(i).getUri());
+ }
+ res.complete(prompt.confirm(mActivity, uris.toArray(new Uri[0])));
+ }
+ }
+
+ public void onPermissionPrompt(final String title,
+ final GeckoSession.PermissionDelegate.Callback callback) {
+ stopMedia();
+ final Activity activity = mActivity;
+ if (activity == null) {
+ callback.reject();
+ return;
+ }
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ builder.setTitle(title)
+ .setNegativeButton(android.R.string.cancel, (dialog, which) -> callback.reject())
+ .setPositiveButton(android.R.string.ok, (dialog, which) -> callback.grant());
+
+ final AlertDialog dialog = builder.create();
+ dialog.show();
+ }
+
+ public void onSlowScriptPrompt(String title, GeckoResult reportAction) {
+ stopMedia();
+ final Activity activity = mActivity;
+ if (activity == null) {
+ return;
+ }
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ builder.setTitle(title)
+ .setNegativeButton("Wait", (dialog, which) -> reportAction.complete(SlowScriptResponse.CONTINUE))
+ .setPositiveButton("Stop", (dialog, which) -> reportAction.complete(SlowScriptResponse.STOP));
+
+ final AlertDialog dialog = builder.create();
+ dialog.show();
+ }
+
+ private Spinner addMediaSpinner(final Context context, final ViewGroup container,
+ final GeckoSession.PermissionDelegate.MediaSource[] sources, final String[] sourceNames) {
+ final ArrayAdapter adapter = new ArrayAdapter(
+ context, android.R.layout.simple_spinner_item) {
+ private View convertView(final int position, final View view) {
+ if (view != null) {
+ ((TextView) view).setText(sourceNames != null ? sourceNames[position] : "media");
+ }
+ return view;
+ }
+
+ @Override
+ public View getView(final int position, View view,
+ final ViewGroup parent) {
+ return convertView(position, super.getView(position, view, parent));
+ }
+
+ @Override
+ public View getDropDownView(final int position, final View view,
+ @NonNull final ViewGroup parent) {
+ return convertView(position, super.getDropDownView(position, view, parent));
+ }
+ };
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ adapter.addAll(sources);
+
+ final Spinner spinner = new Spinner(context);
+ spinner.setAdapter(adapter);
+ spinner.setSelection(0);
+ container.addView(spinner);
+ return spinner;
+ }
+
+ public void onMediaPrompt(final String title,
+ final GeckoSession.PermissionDelegate.MediaSource[] video, final GeckoSession.PermissionDelegate.MediaSource[] audio,
+ final String[] videoNames, final String[] audioNames,
+ final GeckoSession.PermissionDelegate.MediaCallback callback) {
+ final Activity activity = mActivity;
+ stopMedia();
+ if (activity == null || (video == null && audio == null)) {
+ callback.reject();
+ return;
+ }
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ final LinearLayout container = addStandardLayout(builder, title, null);
+
+ final Spinner videoSpinner;
+ if (video != null) {
+ videoSpinner = addMediaSpinner(builder.getContext(), container, video, videoNames);
+ } else {
+ videoSpinner = null;
+ }
+
+ final Spinner audioSpinner;
+ if (audio != null) {
+ audioSpinner = addMediaSpinner(builder.getContext(), container, audio, audioNames);
+ } else {
+ audioSpinner = null;
+ }
+
+ builder.setNegativeButton(android.R.string.cancel, null)
+ .setPositiveButton(android.R.string.ok,
+ (dialog, which) -> {
+ final GeckoSession.PermissionDelegate.MediaSource video1 = (videoSpinner != null)
+ ? (GeckoSession.PermissionDelegate.MediaSource) videoSpinner.getSelectedItem() : null;
+ final GeckoSession.PermissionDelegate.MediaSource audio1 = (audioSpinner != null)
+ ? (GeckoSession.PermissionDelegate.MediaSource) audioSpinner.getSelectedItem() : null;
+ callback.grant(video1, audio1);
+ });
+
+ final AlertDialog dialog = builder.create();
+ dialog.setOnDismissListener(dialog1 -> callback.reject());
+ dialog.show();
+ }
+
+ public void onMediaPrompt(final String title,
+ final GeckoSession.PermissionDelegate.MediaSource[] video, final GeckoSession.PermissionDelegate.MediaSource[] audio,
+ final GeckoSession.PermissionDelegate.MediaCallback callback) {
+ stopMedia();
+ onMediaPrompt(title, video, audio, null, null, callback);
+ }
+
+ @Override
+ public GeckoResult onPopupPrompt(@NonNull final GeckoSession session,
+ final PopupPrompt prompt) {
+ stopMedia();
+ return GeckoResult.fromValue(prompt.confirm(AllowOrDeny.ALLOW));
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/scrollDelegate.java b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/scrollDelegate.java
new file mode 100644
index 00000000..333a9930
--- /dev/null
+++ b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/scrollDelegate.java
@@ -0,0 +1,51 @@
+package com.hiddenservices.onionservices.appManager.homeManager.geckoManager.delegateModel;
+
+
+import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.UiThread;
+import com.hiddenservices.onionservices.appManager.homeManager.geckoManager.dataModel.geckoDataModel;
+import com.hiddenservices.onionservices.appManager.homeManager.geckoManager.geckoSession;
+import com.hiddenservices.onionservices.constants.enums;
+import com.hiddenservices.onionservices.eventObserver;
+import com.hiddenservices.onionservices.helperManager.helperMethod;
+import org.mozilla.geckoview.GeckoSession;
+import java.util.Arrays;
+
+public class scrollDelegate implements GeckoSession.ScrollDelegate {
+
+ /*Private Variables*/
+
+ private eventObserver.eventListener mEvent;
+ private geckoDataModel mGeckoDataModel;
+
+ private int mScollOffset = 0;
+
+ /*Initializations*/
+
+ public scrollDelegate(eventObserver.eventListener pEvent, geckoDataModel pGeckoDataModel) {
+ this.mEvent = pEvent;
+ this.mGeckoDataModel = pGeckoDataModel;
+ }
+
+ /*Scroll Delegate*/
+ @UiThread
+ public void onScrollChanged(@NonNull GeckoSession session, int scrollX, int scrollY) {
+ Log.i("fucker111 : ", scrollY + "");
+ mScollOffset = scrollY;
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mCurrentURL_ID, mGeckoDataModel.mTheme), enums.etype.M_UPDATE_PIXEL_BACKGROUND);
+ if (scrollY <= 3) {
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mCurrentURL_ID, mGeckoDataModel.mTheme), enums.etype.M_ON_SCROLL_TOP_BOUNDARIES);
+ } else if (scrollY <= helperMethod.pxFromDp(30)) {
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mCurrentURL_ID, mGeckoDataModel.mTheme), enums.etype.M_ON_SCROLL_BOUNDARIES);
+ } else {
+ mEvent.invokeObserver(Arrays.asList(mGeckoDataModel.mCurrentURL, mGeckoDataModel.mSessionID, mGeckoDataModel.mCurrentTitle, mGeckoDataModel.mCurrentURL_ID, mGeckoDataModel.mTheme), enums.etype.M_ON_SCROLL_NO_BOUNDARIES);
+ }
+
+ }
+
+ public int getScrollOffset() {
+ return mScollOffset;
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/selectionActionDelegate.java b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/selectionDelegate.java
similarity index 89%
rename from app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/selectionActionDelegate.java
rename to app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/selectionDelegate.java
index fa9937df..3e4ea8cf 100644
--- a/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/selectionActionDelegate.java
+++ b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/delegateModel/selectionDelegate.java
@@ -1,473 +1,478 @@
-package com.hiddenservices.onionservices.appManager.homeManager.geckoManager;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.content.ActivityNotFoundException;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.graphics.Matrix;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.os.Build;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.UiThread;
-
-import android.util.Log;
-import android.view.ActionMode;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-
-import com.hiddenservices.onionservices.appManager.activityContextManager;
-
-import org.mozilla.gecko.util.ThreadUtils;
-import org.mozilla.geckoview.GeckoSession;
-
-/**
- * Class that implements a basic SelectionActionDelegate. This class is used by GeckoView by
- * default if the consumer does not explicitly set a SelectionActionDelegate.
- *
- * To provide custom actions, extend this class and override the following methods,
- *
- * 1) Override {@link #getAllActions} to include custom action IDs in the returned array. This
- * array must include all actions, available or not, and must not change over the class lifetime.
- *
- * 2) Override {@link #isActionAvailable} to return whether a custom action is currently available.
- *
- * 3) Override {@link #prepareAction} to set custom title and/or icon for a custom action.
- *
- * 4) Override {@link #performAction} to perform a custom action when used.
- */
-@UiThread
-public class selectionActionDelegate implements ActionMode.Callback,
- GeckoSession.SelectionActionDelegate {
- private static final String LOGTAG = "BasicSelectionAction";
-
- protected static final String ACTION_PROCESS_TEXT = Intent.ACTION_PROCESS_TEXT;
-
- private static final String[] FLOATING_TOOLBAR_ACTIONS = new String[]{
- ACTION_CUT, ACTION_COPY, ACTION_PASTE, ACTION_SELECT_ALL, "SEARCH"
- };
- private static final String[] FIXED_TOOLBAR_ACTIONS = new String[]{
- ACTION_SELECT_ALL, ACTION_CUT, ACTION_COPY, ACTION_PASTE, "SEARCH"
- };
-
- protected final @NonNull
- Activity mActivity;
- protected final boolean mUseFloatingToolbar;
- protected final @NonNull
- Matrix mTempMatrix = new Matrix();
- protected final @NonNull
- RectF mTempRect = new RectF();
- private boolean mFullScreen = false;
-
- private boolean mExternalActionsEnabled;
-
- protected @Nullable
- ActionMode mActionMode;
- protected @Nullable
- GeckoSession mSession;
- protected @Nullable
- Selection mSelection;
- protected boolean mRepopulatedMenu;
-
- public void setFullScreen(boolean pFullScreen) {
- mFullScreen = pFullScreen;
- }
-
- @TargetApi(Build.VERSION_CODES.M)
- private class Callback2Wrapper extends ActionMode.Callback2 {
- @Override
- public boolean onCreateActionMode(final ActionMode actionMode, final Menu menu) {
- return selectionActionDelegate.this.onCreateActionMode(actionMode, menu);
- }
-
- @Override
- public boolean onPrepareActionMode(final ActionMode actionMode, final Menu menu) {
- return selectionActionDelegate.this.onPrepareActionMode(actionMode, menu);
- }
-
- @Override
- public boolean onActionItemClicked(final ActionMode actionMode, final MenuItem menuItem) {
- return selectionActionDelegate.this.onActionItemClicked(actionMode, menuItem);
- }
-
- @Override
- public void onDestroyActionMode(final ActionMode actionMode) {
- selectionActionDelegate.this.onDestroyActionMode(actionMode);
- }
-
- @Override
- public void onGetContentRect(final ActionMode mode, final View view, final Rect outRect) {
- super.onGetContentRect(mode, view, outRect);
- selectionActionDelegate.this.onGetContentRect(mode, view, outRect);
- }
- }
-
- @SuppressWarnings("checkstyle:javadocmethod")
- public selectionActionDelegate(final @NonNull Activity activity) {
- this(activity, Build.VERSION.SDK_INT >= 23);
- }
-
- @SuppressWarnings("checkstyle:javadocmethod")
- public selectionActionDelegate(final @NonNull Activity activity,
- final boolean useFloatingToolbar) {
- mActivity = activity;
- mUseFloatingToolbar = useFloatingToolbar;
- mExternalActionsEnabled = true;
- }
-
- /**
- * Set whether to include text actions from other apps in the floating toolbar.
- *
- * @param enable True if external actions should be enabled.
- */
- public void enableExternalActions(final boolean enable) {
- ThreadUtils.assertOnUiThread();
- mExternalActionsEnabled = enable;
-
- if (mActionMode != null) {
- mActionMode.invalidate();
- }
- }
-
- /**
- * Get whether text actions from other apps are enabled.
- *
- * @return True if external actions are enabled.
- */
- public boolean areExternalActionsEnabled() {
- return mExternalActionsEnabled;
- }
-
- /**
- * Return list of all actions in proper order, regardless of their availability at present.
- * Override to add to or remove from the default set.
- *
- * @return Array of action IDs in proper order.
- */
- protected @NonNull
- String[] getAllActions() {
- return mUseFloatingToolbar ? FLOATING_TOOLBAR_ACTIONS
- : FIXED_TOOLBAR_ACTIONS;
- }
-
- /**
- * Return whether an action is presently available. Override to indicate
- * availability for custom actions.
- *
- * @param id Action ID.
- * @return True if the action is presently available.
- */
- protected boolean isActionAvailable(final @NonNull String id) {
- if (mSelection == null || mSelection.text.length() < 1 || mSelection.text.getBytes().length >= 500000) {
- return false;
- }
-
- if (mExternalActionsEnabled && !mSelection.text.isEmpty() &&
- ACTION_PROCESS_TEXT.equals(id)) {
- final PackageManager pm = mActivity.getPackageManager();
- return pm.resolveActivity(getProcessTextIntent(), PackageManager.MATCH_DEFAULT_ONLY) != null;
- }
- if (id.equals("SEARCH") && !mSelection.text.isEmpty() && mExternalActionsEnabled) {
- return true;
- }
-
- return mSelection.isActionAvailable(id);
- }
-
- /**
- * Provides access to whether there are text selection actions available. Override to indicate
- * availability for custom actions.
- *
- * @return True if there are text selection actions available.
- */
- public boolean isActionAvailable() {
- if (mSelection == null) {
- return false;
- }
-
- return isActionAvailable(ACTION_PROCESS_TEXT) ||
- !mSelection.availableActions.isEmpty();
- }
-
- /**
- * Prepare a menu item corresponding to a certain action. Override to prepare
- * menu item for custom action.
- *
- * @param id Action ID.
- * @param item New menu item to prepare.
- */
- protected void prepareAction(final @NonNull String id, final @NonNull MenuItem item) {
-
- if (mFullScreen) {
- return;
- }
- switch (id) {
- case ACTION_CUT:
- item.setTitle(android.R.string.cut);
- break;
- case ACTION_COPY:
- item.setTitle(android.R.string.copy);
- break;
- case "SEARCH":
- item.setTitle("Search");
- break;
- case ACTION_PASTE:
- item.setTitle(android.R.string.paste);
- break;
- case ACTION_SELECT_ALL:
- item.setTitle(android.R.string.selectAll);
- break;
- case ACTION_PROCESS_TEXT:
- throw new IllegalStateException("Unexpected action");
- }
- }
-
- /**
- * Perform the specified action. Override to perform custom actions.
- *
- * @param id Action ID.
- * @param item Nenu item for the action.
- * @return True if the action was performed.
- */
- protected boolean performAction(final @NonNull String id, final @NonNull MenuItem item) {
- if (ACTION_PROCESS_TEXT.equals(id)) {
- try {
- mActivity.startActivity(item.getIntent());
- } catch (final ActivityNotFoundException e) {
- Log.e(LOGTAG, "Cannot perform action", e);
- return false;
- }
- return true;
- }
-
- if (mSelection == null) {
- return false;
- }
- if (id.equals("SEARCH")) {
- if (activityContextManager.getInstance() != null && activityContextManager.getInstance().getHomeController() != null) {
- activityContextManager.getInstance().getHomeController().onSearchString(mSelection.text);
- }
- clearSelection();
- mActionMode.finish();
- return false;
- }
- mSelection.execute(id);
-
- if (ACTION_COPY.equals(id)) {
- if (mUseFloatingToolbar) {
- clearSelection();
- } else {
- mActionMode.finish();
- }
- }
- return true;
- }
-
- /**
- * Get the current selection object. This object should not be stored as it does not update
- * when the selection becomes invalid. Stale actions are ignored.
- *
- * @return The {@link GeckoSession.SelectionActionDelegate.Selection} attached to the current
- * action menu. null if no action menu is active.
- */
- public @Nullable
- Selection getSelection() {
- return mSelection;
- }
-
- /**
- * Clear the current selection, if possible.
- */
- public void clearSelection() {
- if (mSelection == null) {
- return;
- }
-
- if (isActionAvailable(ACTION_COLLAPSE_TO_END)) {
- mSelection.collapseToEnd();
- } else if (isActionAvailable(ACTION_UNSELECT)) {
- mSelection.unselect();
- } else {
- mSelection.hide();
- }
- }
-
- private Intent getProcessTextIntent() {
- final Intent intent = new Intent(Intent.ACTION_PROCESS_TEXT);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.setType("text/plain");
- intent.putExtra(Intent.EXTRA_PROCESS_TEXT, mSelection.text);
- // TODO: implement ability to replace text in Gecko for editable selection (bug 1453137).
- intent.putExtra(Intent.EXTRA_PROCESS_TEXT_READONLY, true);
- return intent;
- }
-
- @Override
- public boolean onCreateActionMode(final ActionMode actionMode, final Menu menu) {
- ThreadUtils.assertOnUiThread();
- final String[] allActions = getAllActions();
- for (final String actionId : allActions) {
- if (isActionAvailable(actionId)) {
- if (!mUseFloatingToolbar && (
- Build.VERSION.SDK_INT == 22 || Build.VERSION.SDK_INT == 23)) {
- // Android bug where onPrepareActionMode is not called initially.
- onPrepareActionMode(actionMode, menu);
- }
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean onPrepareActionMode(final ActionMode actionMode, final Menu menu) {
- ThreadUtils.assertOnUiThread();
- final String[] allActions = getAllActions();
- boolean changed = false;
-
- // Whether we are repopulating an existing menu.
- mRepopulatedMenu = menu.size() != 0;
-
- // For each action, see if it's available at present, and if necessary,
- // add to or remove from menu.
- for (int i = 0; i < allActions.length; i++) {
- final String actionId = allActions[i];
- final int menuId = i + Menu.FIRST;
-
- if (ACTION_PROCESS_TEXT.equals(actionId)) {
- if (mExternalActionsEnabled && !mSelection.text.isEmpty()) {
- menu.addIntentOptions(menuId, menuId, menuId,
- mActivity.getComponentName(),
- /* specifiec */ null, getProcessTextIntent(),
- /* flags */ 0, /* items */ null);
- changed = true;
- } else if (menu.findItem(menuId) != null) {
- menu.removeGroup(menuId);
- changed = true;
- }
- continue;
- }
-
- if (isActionAvailable(actionId)) {
- if (menu.findItem(menuId) == null) {
- prepareAction(actionId, menu.add(/* group */ Menu.NONE, menuId,
- menuId, /* title */ ""));
- changed = true;
- }
- } else if (menu.findItem(menuId) != null) {
- menu.removeItem(menuId);
- changed = true;
- }
- }
- return changed;
- }
-
- @Override
- public boolean onActionItemClicked(final ActionMode actionMode, final MenuItem menuItem) {
- ThreadUtils.assertOnUiThread();
- MenuItem realMenuItem = null;
- if (mRepopulatedMenu) {
- // When we repopulate an existing menu, Android can sometimes give us an old,
- // deleted MenuItem. Find the current MenuItem that corresponds to the old one.
- final Menu menu = actionMode.getMenu();
- final int size = menu.size();
- for (int i = 0; i < size; i++) {
- final MenuItem item = menu.getItem(i);
- if (item == menuItem || (item.getItemId() == menuItem.getItemId() &&
- item.getTitle().equals(menuItem.getTitle()))) {
- realMenuItem = item;
- break;
- }
- }
- } else {
- realMenuItem = menuItem;
- }
-
- if (realMenuItem == null) {
- return false;
- }
- final String[] allActions = getAllActions();
- return performAction(allActions[realMenuItem.getItemId() - Menu.FIRST], realMenuItem);
- }
-
- @Override
- public void onDestroyActionMode(final ActionMode actionMode) {
- ThreadUtils.assertOnUiThread();
- if (!mUseFloatingToolbar) {
- clearSelection();
- }
- mSession = null;
- mSelection = null;
- mActionMode = null;
- }
-
- @SuppressWarnings("checkstyle:javadocmethod")
- public void onGetContentRect(final @Nullable ActionMode mode, final @Nullable View view,
- final @NonNull Rect outRect) {
- ThreadUtils.assertOnUiThread();
- if (mSelection == null || mSelection.clientRect == null) {
- return;
- }
- mSession.getClientToScreenMatrix(mTempMatrix);
- mTempMatrix.mapRect(mTempRect, mSelection.clientRect);
- mTempRect.roundOut(outRect);
- }
-
- @TargetApi(Build.VERSION_CODES.M)
- @Override
- public void onShowActionRequest(final GeckoSession session, final Selection selection) {
- ThreadUtils.assertOnUiThread();
- mSession = session;
- mSelection = selection;
-
-
- try {
- if (mActionMode != null) {
- if (isActionAvailable()) {
- mActionMode.invalidate();
- } else {
- mActionMode.finish();
- }
- return;
- }
- if (mUseFloatingToolbar) {
- String strManufacturer = android.os.Build.MANUFACTURER;
- if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1 || (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1 && (strManufacturer.toLowerCase().contains("samsung") || android.os.Build.MODEL.toLowerCase().contains("samsung") || Build.PRODUCT.toLowerCase().contains("samsung")))) {
- mActionMode = mActivity.startActionMode(this);
- } else {
- mActionMode = mActivity.startActionMode(new Callback2Wrapper(), ActionMode.TYPE_FLOATING);
- }
- } else {
- mActionMode = mActivity.startActionMode(this);
- }
- } catch (Exception ignored) {
- }
- }
-
- @Override
- public void onHideAction(final GeckoSession session, final int reason) {
- ThreadUtils.assertOnUiThread();
- if (mActionMode == null) {
- return;
- }
-
- switch (reason) {
- case HIDE_REASON_ACTIVE_SCROLL:
- case HIDE_REASON_ACTIVE_SELECTION:
- case HIDE_REASON_INVISIBLE_SELECTION:
- if (mUseFloatingToolbar) {
- // Hide the floating toolbar when scrolling/selecting.
- mActionMode.finish();
- }
- break;
-
- case HIDE_REASON_NO_SELECTION:
- mActionMode.finish();
- break;
- }
- }
+package com.hiddenservices.onionservices.appManager.homeManager.geckoManager.delegateModel;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.UiThread;
+
+import android.util.Log;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+
+import com.hiddenservices.onionservices.appManager.activityContextManager;
+
+import org.mozilla.gecko.util.ThreadUtils;
+import org.mozilla.geckoview.GeckoSession;
+
+/**
+ * Class that implements a basic SelectionActionDelegate. This class is used by GeckoView by
+ * default if the consumer does not explicitly set a SelectionActionDelegate.
+ *
+ * To provide custom actions, extend this class and override the following methods,
+ *
+ * 1) Override {@link #getAllActions} to include custom action IDs in the returned array. This
+ * array must include all actions, available or not, and must not change over the class lifetime.
+ *
+ * 2) Override {@link #isActionAvailable} to return whether a custom action is currently available.
+ *
+ * 3) Override {@link #prepareAction} to set custom title and/or icon for a custom action.
+ *
+ * 4) Override {@link #performAction} to perform a custom action when used.
+ */
+@UiThread
+public class selectionDelegate implements ActionMode.Callback,
+ GeckoSession.SelectionActionDelegate {
+ private static final String LOGTAG = "BasicSelectionAction";
+
+ protected static final String ACTION_PROCESS_TEXT = "android.intent.action.PROCESS_TEXT";
+
+ private static final String[] FLOATING_TOOLBAR_ACTIONS = new String[]{
+ ACTION_CUT, ACTION_COPY, ACTION_PASTE, ACTION_SELECT_ALL, "SEARCH"
+ };
+ private static final String[] FIXED_TOOLBAR_ACTIONS = new String[]{
+ ACTION_SELECT_ALL, ACTION_CUT, ACTION_COPY, ACTION_PASTE, "SEARCH"
+ };
+
+ protected final @NonNull
+ Activity mActivity;
+ protected final boolean mUseFloatingToolbar;
+ protected final @NonNull
+ Matrix mTempMatrix = new Matrix();
+ protected final @NonNull
+ RectF mTempRect = new RectF();
+ private boolean mFullScreen = false;
+
+ private boolean mExternalActionsEnabled;
+
+ protected @Nullable
+ ActionMode mActionMode;
+ protected @Nullable
+ GeckoSession mSession;
+ protected @Nullable
+ Selection mSelection;
+ protected boolean mRepopulatedMenu;
+
+ public void setFullScreen(boolean pFullScreen) {
+ mFullScreen = pFullScreen;
+ }
+
+ @TargetApi(Build.VERSION_CODES.M)
+ private class Callback2Wrapper extends ActionMode.Callback2 {
+ @Override
+ public boolean onCreateActionMode(final ActionMode actionMode, final Menu menu) {
+ return selectionDelegate.this.onCreateActionMode(actionMode, menu);
+ }
+
+ @Override
+ public boolean onPrepareActionMode(final ActionMode actionMode, final Menu menu) {
+ return selectionDelegate.this.onPrepareActionMode(actionMode, menu);
+ }
+
+ @Override
+ public boolean onActionItemClicked(final ActionMode actionMode, final MenuItem menuItem) {
+ return selectionDelegate.this.onActionItemClicked(actionMode, menuItem);
+ }
+
+ @Override
+ public void onDestroyActionMode(final ActionMode actionMode) {
+ selectionDelegate.this.onDestroyActionMode(actionMode);
+ }
+
+ @Override
+ public void onGetContentRect(final ActionMode mode, final View view, final Rect outRect) {
+ super.onGetContentRect(mode, view, outRect);
+ selectionDelegate.this.onGetContentRect(mode, view, outRect);
+ }
+ }
+
+ @SuppressWarnings("checkstyle:javadocmethod")
+ public selectionDelegate(final @NonNull Activity activity) {
+ this(activity, Build.VERSION.SDK_INT >= 23);
+ }
+
+ @SuppressWarnings("checkstyle:javadocmethod")
+ public selectionDelegate(final @NonNull Activity activity,
+ final boolean useFloatingToolbar) {
+ mActivity = activity;
+ mUseFloatingToolbar = useFloatingToolbar;
+ mExternalActionsEnabled = true;
+ }
+
+ /**
+ * Set whether to include text actions from other apps in the floating toolbar.
+ *
+ * @param enable True if external actions should be enabled.
+ */
+ public void enableExternalActions(final boolean enable) {
+ ThreadUtils.assertOnUiThread();
+ mExternalActionsEnabled = enable;
+
+ if (mActionMode != null) {
+ mActionMode.invalidate();
+ }
+ }
+
+ /**
+ * Get whether text actions from other apps are enabled.
+ *
+ * @return True if external actions are enabled.
+ */
+ public boolean areExternalActionsEnabled() {
+ return mExternalActionsEnabled;
+ }
+
+ /**
+ * Return list of all actions in proper order, regardless of their availability at present.
+ * Override to add to or remove from the default set.
+ *
+ * @return Array of action IDs in proper order.
+ */
+ protected @NonNull
+ String[] getAllActions() {
+ return mUseFloatingToolbar ? FLOATING_TOOLBAR_ACTIONS
+ : FIXED_TOOLBAR_ACTIONS;
+ }
+
+ /**
+ * Return whether an action is presently available. Override to indicate
+ * availability for custom actions.
+ *
+ * @param id Action ID.
+ * @return True if the action is presently available.
+ */
+ protected boolean isActionAvailable(final @NonNull String id) {
+ if (mSelection == null || mSelection.text.length() < 1 || mSelection.text.getBytes().length >= 500000) {
+ return false;
+ }
+
+ if (mExternalActionsEnabled && !mSelection.text.isEmpty() &&
+ ACTION_PROCESS_TEXT.equals(id)) {
+ final PackageManager pm = mActivity.getPackageManager();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ return pm.resolveActivity(getProcessTextIntent(), PackageManager.MATCH_DEFAULT_ONLY) != null;
+ }
+ }
+ if (id.equals("SEARCH") && !mSelection.text.isEmpty() && mExternalActionsEnabled) {
+ return true;
+ }
+
+ return mSelection.isActionAvailable(id);
+ }
+
+ /**
+ * Provides access to whether there are text selection actions available. Override to indicate
+ * availability for custom actions.
+ *
+ * @return True if there are text selection actions available.
+ */
+ public boolean isActionAvailable() {
+ if (mSelection == null) {
+ return false;
+ }
+
+ return isActionAvailable(ACTION_PROCESS_TEXT) ||
+ !mSelection.availableActions.isEmpty();
+ }
+
+ /**
+ * Prepare a menu item corresponding to a certain action. Override to prepare
+ * menu item for custom action.
+ *
+ * @param id Action ID.
+ * @param item New menu item to prepare.
+ */
+ protected void prepareAction(final @NonNull String id, final @NonNull MenuItem item) {
+
+ if (mFullScreen) {
+ return;
+ }
+ switch (id) {
+ case ACTION_CUT:
+ item.setTitle(android.R.string.cut);
+ break;
+ case ACTION_COPY:
+ item.setTitle(android.R.string.copy);
+ break;
+ case "SEARCH":
+ item.setTitle("Search");
+ break;
+ case ACTION_PASTE:
+ item.setTitle(android.R.string.paste);
+ break;
+ case ACTION_SELECT_ALL:
+ item.setTitle(android.R.string.selectAll);
+ break;
+ case ACTION_PROCESS_TEXT:
+ throw new IllegalStateException("Unexpected action");
+ }
+ }
+
+ /**
+ * Perform the specified action. Override to perform custom actions.
+ *
+ * @param id Action ID.
+ * @param item Nenu item for the action.
+ * @return True if the action was performed.
+ */
+ protected boolean performAction(final @NonNull String id, final @NonNull MenuItem item) {
+ if (ACTION_PROCESS_TEXT.equals(id)) {
+ try {
+ mActivity.startActivity(item.getIntent());
+ } catch (final ActivityNotFoundException e) {
+ Log.e(LOGTAG, "Cannot perform action", e);
+ return false;
+ }
+ return true;
+ }
+
+ if (mSelection == null) {
+ return false;
+ }
+ if (id.equals("SEARCH")) {
+ if (activityContextManager.getInstance() != null && activityContextManager.getInstance().getHomeController() != null) {
+ activityContextManager.getInstance().getHomeController().onSearchString(mSelection.text);
+ }
+ clearSelection();
+ mActionMode.finish();
+ return false;
+ }
+ mSelection.execute(id);
+
+ if (ACTION_COPY.equals(id)) {
+ if (mUseFloatingToolbar) {
+ clearSelection();
+ } else {
+ mActionMode.finish();
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Get the current selection object. This object should not be stored as it does not update
+ * when the selection becomes invalid. Stale actions are ignored.
+ *
+ * @return The {@link GeckoSession.SelectionActionDelegate.Selection} attached to the current
+ * action menu. null if no action menu is active.
+ */
+ public @Nullable
+ Selection getSelection() {
+ return mSelection;
+ }
+
+ /**
+ * Clear the current selection, if possible.
+ */
+ public void clearSelection() {
+ if (mSelection == null) {
+ return;
+ }
+
+ if (isActionAvailable(ACTION_COLLAPSE_TO_END)) {
+ mSelection.collapseToEnd();
+ } else if (isActionAvailable(ACTION_UNSELECT)) {
+ mSelection.unselect();
+ } else {
+ mSelection.hide();
+ }
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.M)
+ private Intent getProcessTextIntent() {
+ final Intent intent = new Intent(Intent.ACTION_PROCESS_TEXT);
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ intent.setType("text/plain");
+ intent.putExtra(Intent.EXTRA_PROCESS_TEXT, mSelection.text);
+ intent.putExtra(Intent.EXTRA_PROCESS_TEXT_READONLY, true);
+ return intent;
+ }
+
+ @Override
+ public boolean onCreateActionMode(final ActionMode actionMode, final Menu menu) {
+ ThreadUtils.assertOnUiThread();
+ final String[] allActions = getAllActions();
+ for (final String actionId : allActions) {
+ if (isActionAvailable(actionId)) {
+ if (!mUseFloatingToolbar && (
+ Build.VERSION.SDK_INT == 22 || Build.VERSION.SDK_INT == 23)) {
+ // Android bug where onPrepareActionMode is not called initially.
+ onPrepareActionMode(actionMode, menu);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(final ActionMode actionMode, final Menu menu) {
+ ThreadUtils.assertOnUiThread();
+ final String[] allActions = getAllActions();
+ boolean changed = false;
+
+ // Whether we are repopulating an existing menu.
+ mRepopulatedMenu = menu.size() != 0;
+
+ // For each action, see if it's available at present, and if necessary,
+ // add to or remove from menu.
+ for (int i = 0; i < allActions.length; i++) {
+ final String actionId = allActions[i];
+ final int menuId = i + Menu.FIRST;
+
+ if (ACTION_PROCESS_TEXT.equals(actionId)) {
+ if (mExternalActionsEnabled && !mSelection.text.isEmpty()) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ menu.addIntentOptions(menuId, menuId, menuId,
+ mActivity.getComponentName(),
+ /* specifiec */ null, getProcessTextIntent(),
+ /* flags */ 0, /* items */ null);
+ }
+ changed = true;
+ } else if (menu.findItem(menuId) != null) {
+ menu.removeGroup(menuId);
+ changed = true;
+ }
+ continue;
+ }
+
+ if (isActionAvailable(actionId)) {
+ if (menu.findItem(menuId) == null) {
+ prepareAction(actionId, menu.add(/* group */ Menu.NONE, menuId,
+ menuId, /* title */ ""));
+ changed = true;
+ }
+ } else if (menu.findItem(menuId) != null) {
+ menu.removeItem(menuId);
+ changed = true;
+ }
+ }
+ return changed;
+ }
+
+ @Override
+ public boolean onActionItemClicked(final ActionMode actionMode, final MenuItem menuItem) {
+ ThreadUtils.assertOnUiThread();
+ MenuItem realMenuItem = null;
+ if (mRepopulatedMenu) {
+ // When we repopulate an existing menu, Android can sometimes give us an old,
+ // deleted MenuItem. Find the current MenuItem that corresponds to the old one.
+ final Menu menu = actionMode.getMenu();
+ final int size = menu.size();
+ for (int i = 0; i < size; i++) {
+ final MenuItem item = menu.getItem(i);
+ if (item == menuItem || (item.getItemId() == menuItem.getItemId() &&
+ item.getTitle().equals(menuItem.getTitle()))) {
+ realMenuItem = item;
+ break;
+ }
+ }
+ } else {
+ realMenuItem = menuItem;
+ }
+
+ if (realMenuItem == null) {
+ return false;
+ }
+ final String[] allActions = getAllActions();
+ return performAction(allActions[realMenuItem.getItemId() - Menu.FIRST], realMenuItem);
+ }
+
+ @Override
+ public void onDestroyActionMode(final ActionMode actionMode) {
+ ThreadUtils.assertOnUiThread();
+ if (!mUseFloatingToolbar) {
+ clearSelection();
+ }
+ mSession = null;
+ mSelection = null;
+ mActionMode = null;
+ }
+
+ @SuppressWarnings("checkstyle:javadocmethod")
+ public void onGetContentRect(final @Nullable ActionMode mode, final @Nullable View view,
+ final @NonNull Rect outRect) {
+ ThreadUtils.assertOnUiThread();
+ if (mSelection == null || mSelection.clientRect == null) {
+ return;
+ }
+ mSession.getClientToScreenMatrix(mTempMatrix);
+ mTempMatrix.mapRect(mTempRect, mSelection.clientRect);
+ mTempRect.roundOut(outRect);
+ }
+
+ @TargetApi(Build.VERSION_CODES.M)
+ @Override
+ public void onShowActionRequest(@NonNull final GeckoSession session, @NonNull final Selection selection) {
+ ThreadUtils.assertOnUiThread();
+ mSession = session;
+ mSelection = selection;
+
+
+ try {
+ if (mActionMode != null) {
+ if (isActionAvailable()) {
+ mActionMode.invalidate();
+ } else {
+ mActionMode.finish();
+ }
+ return;
+ }
+ if (mUseFloatingToolbar) {
+ String strManufacturer = android.os.Build.MANUFACTURER;
+ if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1 || (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1 && (strManufacturer.toLowerCase().contains("samsung") || android.os.Build.MODEL.toLowerCase().contains("samsung") || Build.PRODUCT.toLowerCase().contains("samsung")))) {
+ mActionMode = mActivity.startActionMode(this);
+ } else {
+ mActionMode = mActivity.startActionMode(new Callback2Wrapper(), ActionMode.TYPE_FLOATING);
+ }
+ } else {
+ mActionMode = mActivity.startActionMode(this);
+ }
+ } catch (Exception ignored) {
+ }
+ }
+
+ @Override
+ public void onHideAction(@NonNull final GeckoSession session, final int reason) {
+ ThreadUtils.assertOnUiThread();
+ if (mActionMode == null) {
+ return;
+ }
+
+ switch (reason) {
+ case HIDE_REASON_ACTIVE_SCROLL:
+ case HIDE_REASON_ACTIVE_SELECTION:
+ case HIDE_REASON_INVISIBLE_SELECTION:
+ if (mUseFloatingToolbar) {
+ // Hide the floating toolbar when scrolling/selecting.
+ mActionMode.finish();
+ }
+ break;
+
+ case HIDE_REASON_NO_SELECTION:
+ mActionMode.finish();
+ break;
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/geckoClients.java b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/geckoClients.java
index c00cc1a7..26057b98 100644
--- a/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/geckoClients.java
+++ b/app/src/main/java/com/hiddenservices/onionservices/appManager/homeManager/geckoManager/geckoClients.java
@@ -7,13 +7,8 @@ import android.net.Uri;
import android.os.Handler;
import android.util.Log;
import android.widget.ImageView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
-
import com.hiddenservices.onionservices.appManager.activityContextManager;
-import com.hiddenservices.onionservices.appManager.homeManager.homeController.homeController;
import com.hiddenservices.onionservices.appManager.kotlinHelperLibraries.BrowserIconManager;
import com.hiddenservices.onionservices.constants.*;
import com.hiddenservices.onionservices.dataManager.dataController;
@@ -25,14 +20,12 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.util.Arrays;
import java.util.List;
import static com.hiddenservices.onionservices.constants.constants.CONST_GENESIS_URL_CACHED;
import static com.hiddenservices.onionservices.constants.constants.CONST_GENESIS_URL_CACHED_DARK;
import static com.hiddenservices.onionservices.constants.constants.CONST_PRIVACY_POLICY_URL_NON_TOR;
import static com.hiddenservices.onionservices.constants.constants.CONST_REPORT_URL;
-import static com.hiddenservices.onionservices.constants.enums.etype.M_INDEX_WEBSITE;
import static com.hiddenservices.onionservices.constants.enums.etype.on_handle_external_intent;
import static org.mozilla.geckoview.GeckoSessionSettings.USER_AGENT_MODE_MOBILE;
import static org.mozilla.geckoview.StorageController.ClearFlags.AUTH_SESSIONS;
@@ -44,15 +37,10 @@ import static org.mozilla.geckoview.StorageController.ClearFlags.PERMISSIONS;
import static org.mozilla.geckoview.StorageController.ClearFlags.SITE_DATA;
import static org.mozilla.geckoview.StorageController.ClearFlags.SITE_SETTINGS;
-import org.json.JSONObject;
-import org.mozilla.gecko.EventDispatcher;
-import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.geckoview.ContentBlocking;
-import org.mozilla.geckoview.GeckoResult;
import org.mozilla.geckoview.GeckoRuntime;
import org.mozilla.geckoview.GeckoRuntimeSettings;
import org.mozilla.geckoview.GeckoView;
-import org.mozilla.geckoview.WebExtension;
import org.mozilla.geckoview.WebResponse;
import org.torproject.android.service.wrapper.orbotLocalConstants;
@@ -211,126 +199,6 @@ public class geckoClients {
return cacheFile.getAbsolutePath();
}
-/*
- @SuppressLint("WrongThread")
- public void installExtension() {
-
- mRuntime.getWebExtensionController()
- .ensureBuiltIn("resource://android/assets/parser/", "messaging@example.com")
- .accept(
- extension -> {
- Log.i("MessageDelegate", "Extension installed: " + extension);
- extension.setMessageDelegate(mMessagingDelegate, "browser");
- },
- e -> {
- Log.e("MessageDelegate", "Error registering WebExtension", e);
- }
- );
-
- mRuntime.getWebExtensionController()
- .ensureBuiltIn("resource://android/assets/adblock/", "messaging@example.com")
- .accept(
- extension -> {
- Log.i("MessageDelegate", "Extension installed: " + extension);
- extension.setMessageDelegate(mMessagingDelegate, "browser");
- },
- e -> {
- Log.e("MessageDelegate", "Error registering WebExtension", e);
- }
- );
- }
-
- private final WebExtension.MessageDelegate mMessagingDelegate = new WebExtension.MessageDelegate() {
-
- @Override
- public void onConnect(@NonNull WebExtension.Port port) {
- Log.e("MessageDelegate", "onConnect");
- mPort = port;
- mPort.setDelegate(mPortDelegate);
- }
-
- @Override
- public GeckoResult