Skip to content

Commit

Permalink
Recreate Base Gecko Activity.
Browse files Browse the repository at this point in the history
  • Loading branch information
GabrielBRDeveloper committed Feb 18, 2023
1 parent 74423de commit 7474489
Show file tree
Hide file tree
Showing 13 changed files with 562 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -1,39 +1,57 @@
package br.com.nullexcept.webappmanager.app;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.pm.ApplicationInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Process;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.Window;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import org.mozilla.gecko.mozglue.GeckoLoader;
import org.mozilla.geckoview.AllowOrDeny;
import org.mozilla.geckoview.GeckoResult;
import org.mozilla.geckoview.GeckoRuntime;
import org.mozilla.geckoview.GeckoRuntimeSettings;
import org.mozilla.geckoview.GeckoSession;
import org.mozilla.geckoview.GeckoView;
import org.mozilla.geckoview.WebExtension;
import org.mozilla.geckoview.WebExtensionController;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.List;

import br.com.nullexcept.webappmanager.R;
import br.com.nullexcept.webappmanager.app.basewebapp.DialogOptions;
import br.com.nullexcept.webappmanager.config.Config;
import br.com.nullexcept.webappmanager.web.WebSession;

public class BaseWebAppActivity extends AppCompatActivity {
Config config;
public static BaseWebAppActivity CURRENT_CONTEXT;
public static Config CURRENT_CONFIG;
public static GeckoSession session;
public static GeckoRuntime runtime;

Expand All @@ -43,6 +61,10 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {

config = new Config(this, getClass().getName());
config.load();
CURRENT_CONFIG = config;
CURRENT_CONTEXT = this;


if (!config.enable){
Toast.makeText(this, R.string.not_exists, Toast.LENGTH_LONG).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Expand All @@ -53,92 +75,88 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
return;
}


setTitle(config.name);
setContentView(R.layout.webapp_acitivity);
GeckoView view = findViewById(R.id.webview);
if (runtime == null){
session = new GeckoSession();

if (session == null){
GeckoRuntimeSettings.Builder settings = new GeckoRuntimeSettings.Builder();
settings = settings.arguments(new String[]{
"--profile", config.getProfileDir().getAbsolutePath()
});

session.getSettings().setUserAgentOverride(config.user_agent);

session = new WebSession(this);
runtime = GeckoRuntime.create(this, settings.build());
session.open(runtime);
view.setSession(session);

session.loadUri(config.url);
}
view.setSession(session);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setTaskDescription(new ActivityManager.TaskDescription(config.name, null, Color.WHITE));

((GeckoView)findViewById(R.id.webview)).setSession(session);
log(session);

findViewById(R.id.options).setOnClickListener(v -> {
new DialogOptions(this).getDialog().show();
});

if (!config.action_bar){
findViewById(R.id.header).setVisibility(View.INVISIBLE);
findViewById(R.id.content).setPadding(0,0,0,0);
}
setTitle(config.name);
checkIcon();
}

private void loadIcon() {
File dir = new File(config.getSaveDir(), "icon.png");
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setTaskDescription(new ActivityManager.TaskDescription(config.name, BitmapFactory.decodeFile(dir.getAbsolutePath()), Color.WHITE));
}
}catch (Exception e){}

public GeckoRuntime getRuntime() {
return runtime;
}

private long oldTime = 0;
public GeckoSession getSession() {
return session;
}

@Override
public void onBackPressed() {
session.goBack();
//Check double back click
if(System.currentTimeMillis() - oldTime < 500){
super.onBackPressed();
public void error(Object... items){
for (Object obj: items){
_log(2, obj);
}
oldTime = System.currentTimeMillis();
}

@Override
protected void onPause() {
super.onPause();
public void log(Object... items){
for (Object obj: items){
_log(1, obj);
}
}

@Override
protected void onDestroy() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//finishAndRemoveTask();
//Process.killProcess(Process.myPid());
private void _log(int level, Object obj){
if (obj instanceof Throwable){
try {
Throwable th = (Throwable) obj;
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream stream = new PrintStream(out);
th.printStackTrace(stream);
stream.flush();
out.close();
obj = out.toString("utf8");
} catch (Exception e){}
}
switch (level){
case 0: Log.i(getClass().getSimpleName(), obj+""); break;
case 1: Log.d(getClass().getSimpleName(), obj+""); break;
case 2: Log.e(getClass().getSimpleName(), obj+""); break;
}
super.onDestroy();
}


private long LAST_BACK = 0;
@Override
public File getCacheDir() {
File file = new File(config.getSaveDir(), "cache");
file.mkdirs();
return file;
public void onBackPressed() {
if (System.currentTimeMillis()-LAST_BACK < 500){
super.onBackPressed();
} else {
if (session != null){
session.goBack();
}
}
LAST_BACK = System.currentTimeMillis();
}

private void checkIcon(){
new Thread(()->{
try {
File dir = new File(config.getSaveDir(), "icon.png");
dir.getParentFile().mkdirs();
if (dir.exists()){
loadIcon();
return;
}

String url = config.url.substring(config.url.indexOf("://")+3);
if (url.contains("/")){
url = url.substring(0, url.indexOf("/"));
}
//@TODO Need add code to get Icon from GeckoSession
}catch (Exception e){e.printStackTrace();}
}).start();
public void loadUrl(String url) {
session.loadUri(url);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package br.com.nullexcept.webappmanager.app.basewebapp;

import android.view.View;

import androidx.appcompat.app.AlertDialog;

import br.com.nullexcept.webappmanager.R;
import br.com.nullexcept.webappmanager.app.BaseWebAppActivity;

public class DialogOptions {
private AlertDialog dialog;
public DialogOptions(BaseWebAppActivity ctx){
ctx.runOnUiThread(()->{
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
View view = ctx.getLayoutInflater().inflate(R.layout.dialog_actions,null, false);

view.findViewById(R.id.opt_addons_store).setOnClickListener(v -> {
dialog.dismiss();
ctx.loadUrl("https://addons.mozilla.org/pt-BR/android/");
});
view.findViewById(R.id.opt_gecko_settings).setOnClickListener(v -> {
dialog.dismiss();
ctx.loadUrl("about:preferences");
});
builder.setView(view);
dialog = builder.create();
});
}

public AlertDialog getDialog() {
return dialog;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package br.com.nullexcept.webappmanager.web;

import org.mozilla.geckoview.GeckoSession;
import org.mozilla.geckoview.MediaSession;

import br.com.nullexcept.webappmanager.app.BaseWebAppActivity;
import br.com.nullexcept.webappmanager.config.Config;
import br.com.nullexcept.webappmanager.web.delegates.ContentListener;
import br.com.nullexcept.webappmanager.web.delegates.NavigationListener;
import br.com.nullexcept.webappmanager.web.delegates.ProcessListener;
import br.com.nullexcept.webappmanager.web.delegates.PromptListener;

public class WebSession extends GeckoSession {
private Class current;
public WebSession(Object current){
this.current = current.getClass();
getSettings().setUserAgentOverride(config().user_agent);
setProgressDelegate(new ProcessListener(this));
setContentDelegate(new ContentListener(this));
setNavigationDelegate(new NavigationListener(this));
setPromptDelegate(new PromptListener(this));
}

public void log(Object... items){
context().log(items);
}

public void error(Object... items){
context().error(items);
}

public Config config(){
try {
return (Config) current.getField("CURRENT_CONFIG").get(null);
} catch (Exception e) {}
return null;
}

public BaseWebAppActivity context(){
try {
return (BaseWebAppActivity) current.getField("CURRENT_CONTEXT").get(null);
} catch (Exception e) {}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package br.com.nullexcept.webappmanager.web.delegates;

import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.mozilla.geckoview.GeckoSession;

import br.com.nullexcept.webappmanager.R;
import br.com.nullexcept.webappmanager.web.WebSession;

public class ContentListener implements GeckoSession.ContentDelegate {
private WebSession session;
public ContentListener(WebSession session){
this.session = session;
}

@Override
public void onTitleChange(@NonNull GeckoSession current, @Nullable String title) {
GeckoSession.ContentDelegate.super.onTitleChange(current, title);
session.context().runOnUiThread(()->{
((TextView)session.context().findViewById(R.id.title)).setText(title);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package br.com.nullexcept.webappmanager.web.delegates;

import android.annotation.SuppressLint;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.mozilla.geckoview.AllowOrDeny;
import org.mozilla.geckoview.GeckoResult;
import org.mozilla.geckoview.GeckoSession;
import org.mozilla.geckoview.WebExtension;
import org.mozilla.geckoview.WebExtensionController;

import java.util.List;

import br.com.nullexcept.webappmanager.R;
import br.com.nullexcept.webappmanager.web.WebSession;

public class NavigationListener implements GeckoSession.NavigationDelegate {
private WebSession session;
public NavigationListener(WebSession session){
this.session = session;
}
@Nullable
@Override
public GeckoResult<GeckoSession> onNewSession(@NonNull GeckoSession current, @NonNull String uri) {
session.loadUri(uri);
session.log("Requested new session!!");
return null;
}

@SuppressLint("WrongThread")
@Nullable
@Override
public GeckoResult<AllowOrDeny> onLoadRequest(@NonNull GeckoSession session, @NonNull LoadRequest request) {
String url = request.uri+"";
if (url.startsWith("https://addons.mozilla.org/") && url.endsWith(".xpi")){
this.session.log("REQUIRES INSTALL NEW PLUGIN");
this.session.context().getRuntime().getWebExtensionController().install(url).accept(webExtension -> {
NavigationListener.this.session.context().getRuntime().getWebExtensionController().enable(webExtension, WebExtensionController.EnableSource.USER);
});
}
return GeckoSession.NavigationDelegate.super.onLoadRequest(session, request);
}

@Override
public void onLocationChange(@NonNull GeckoSession current, @Nullable String url, @NonNull List<GeckoSession.PermissionDelegate.ContentPermission> perms) {
GeckoSession.NavigationDelegate.super.onLocationChange(current, url, perms);
session.context().runOnUiThread(()->{
((TextView)session.context().findViewById(R.id.url)).setText(url);
});
}
}
Loading

0 comments on commit 7474489

Please sign in to comment.