mirror of https://codeberg.org/tom79/Fedilab
parent
403fb1aba7
commit
95beb7f3c1
@ -1,252 +0,0 @@
|
||||
package app.fedilab.android.activities;
|
||||
/* Copyright 2021 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.databinding.ActivityWebviewBinding;
|
||||
import app.fedilab.android.helper.CountDrawable;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.webview.CustomWebview;
|
||||
import app.fedilab.android.webview.FedilabWebChromeClient;
|
||||
import app.fedilab.android.webview.FedilabWebViewClient;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
|
||||
|
||||
public class WebviewActivity extends BaseActivity {
|
||||
|
||||
|
||||
private String url;
|
||||
private boolean peertubeLink;
|
||||
private CustomWebview webView;
|
||||
private FedilabWebViewClient FedilabWebViewClient;
|
||||
private ActivityWebviewBinding binding;
|
||||
private Menu defaultMenu;
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
binding = ActivityWebviewBinding.inflate(getLayoutInflater());
|
||||
View view = binding.getRoot();
|
||||
setContentView(view);
|
||||
setSupportActionBar(binding.toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayShowTitleEnabled(false);
|
||||
}
|
||||
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
Bundle b = getIntent().getExtras();
|
||||
if (b != null) {
|
||||
url = b.getString("url", null);
|
||||
peertubeLink = b.getBoolean("peertubeLink", false);
|
||||
}
|
||||
if (url == null)
|
||||
finish();
|
||||
if (getSupportActionBar() != null)
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
webView = Helper.initializeWebview(WebviewActivity.this, R.id.webview, null);
|
||||
setTitle("");
|
||||
|
||||
webView.getSettings().setJavaScriptEnabled(true);
|
||||
|
||||
|
||||
FedilabWebChromeClient FedilabWebChromeClient = new FedilabWebChromeClient(WebviewActivity.this, webView, binding.webviewContainer, binding.videoLayout);
|
||||
FedilabWebChromeClient.setOnToggledFullscreen(fullscreen -> {
|
||||
|
||||
if (fullscreen) {
|
||||
binding.videoLayout.setVisibility(View.VISIBLE);
|
||||
WindowManager.LayoutParams attrs = getWindow().getAttributes();
|
||||
attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
||||
attrs.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
|
||||
getWindow().setAttributes(attrs);
|
||||
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
|
||||
} else {
|
||||
WindowManager.LayoutParams attrs = getWindow().getAttributes();
|
||||
attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
||||
attrs.flags &= ~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
|
||||
getWindow().setAttributes(attrs);
|
||||
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
||||
binding.videoLayout.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
webView.setWebChromeClient(FedilabWebChromeClient);
|
||||
FedilabWebViewClient = new FedilabWebViewClient(WebviewActivity.this);
|
||||
webView.setWebViewClient(FedilabWebViewClient);
|
||||
webView.setDownloadListener((url, userAgent, contentDisposition, mimetype, contentLength) -> {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
if (ContextCompat.checkSelfPermission(WebviewActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(WebviewActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(WebviewActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE);
|
||||
} else {
|
||||
Helper.manageDownloads(WebviewActivity.this, url);
|
||||
}
|
||||
} else {
|
||||
Helper.manageDownloads(WebviewActivity.this, url);
|
||||
}
|
||||
});
|
||||
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://"))
|
||||
url = "http://" + url;
|
||||
webView.loadUrl(url);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void setCount(Context context, String count) {
|
||||
if (defaultMenu != null && !peertubeLink) {
|
||||
MenuItem menuItem = defaultMenu.findItem(R.id.action_block);
|
||||
LayerDrawable icon = (LayerDrawable) menuItem.getIcon();
|
||||
|
||||
CountDrawable badge;
|
||||
|
||||
// Reuse drawable if possible
|
||||
Drawable reuse = icon.findDrawableByLayerId(R.id.ic_block_count);
|
||||
if (reuse instanceof CountDrawable) {
|
||||
badge = (CountDrawable) reuse;
|
||||
} else {
|
||||
badge = new CountDrawable(context);
|
||||
}
|
||||
|
||||
badge.setCount(count);
|
||||
icon.mutate();
|
||||
icon.setDrawableByLayerId(R.id.ic_block_count, badge);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
if (!peertubeLink)
|
||||
setCount(WebviewActivity.this, "0");
|
||||
defaultMenu = menu;
|
||||
return super.onPrepareOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(@NotNull Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.main_webview, menu);
|
||||
defaultMenu = menu;
|
||||
if (peertubeLink) {
|
||||
menu.findItem(R.id.action_go).setVisible(false);
|
||||
menu.findItem(R.id.action_block).setVisible(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int itemId = item.getItemId();
|
||||
if (itemId == android.R.id.home) {
|
||||
finish();
|
||||
return true;
|
||||
} else if (itemId == R.id.action_block) {
|
||||
|
||||
|
||||
List<String> domains = FedilabWebViewClient.getDomains();
|
||||
|
||||
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(WebviewActivity.this, R.layout.domains_blocked);
|
||||
arrayAdapter.addAll(domains);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(WebviewActivity.this, Helper.dialogStyle());
|
||||
builder.setTitle(R.string.list_of_blocked_domains);
|
||||
|
||||
builder.setNegativeButton(R.string.close, (dialog, which) -> dialog.dismiss());
|
||||
|
||||
builder.setAdapter(arrayAdapter, (dialog, which) -> {
|
||||
String strName = arrayAdapter.getItem(which);
|
||||
assert strName != null;
|
||||
Toasty.info(WebviewActivity.this, strName, Toast.LENGTH_LONG).show();
|
||||
});
|
||||
builder.show();
|
||||
|
||||
return true;
|
||||
} else if (itemId == R.id.action_go) {
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||
try {
|
||||
startActivity(browserIntent);
|
||||
} catch (Exception e) {
|
||||
Toasty.error(WebviewActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
public void setUrl(String newUrl) {
|
||||
this.url = newUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (webView != null)
|
||||
webView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (webView != null)
|
||||
webView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (webView.canGoBack()) {
|
||||
webView.goBack();
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (webView != null)
|
||||
webView.destroy();
|
||||
}
|
||||
|
||||
}
|
@ -1,325 +0,0 @@
|
||||
/* Copyright 2021 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package app.fedilab.android.activities;
|
||||
|
||||
|
||||
import static app.fedilab.android.activities.LoginActivity.apiLogin;
|
||||
import static app.fedilab.android.activities.LoginActivity.client_idLogin;
|
||||
import static app.fedilab.android.activities.LoginActivity.client_secretLogin;
|
||||
import static app.fedilab.android.activities.LoginActivity.currentInstanceLogin;
|
||||
import static app.fedilab.android.activities.LoginActivity.requestedAdmin;
|
||||
import static app.fedilab.android.activities.LoginActivity.softwareLogin;
|
||||
import static app.fedilab.android.helper.Helper.PREF_USER_TOKEN;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.View;
|
||||
import android.webkit.CookieManager;
|
||||
import android.webkit.CookieSyncManager;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import app.fedilab.android.BaseMainActivity;
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.client.entities.app.Account;
|
||||
import app.fedilab.android.databinding.ActivityWebviewConnectBinding;
|
||||
import app.fedilab.android.exception.DBException;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.viewmodel.mastodon.AccountsVM;
|
||||
import app.fedilab.android.viewmodel.mastodon.AdminVM;
|
||||
import app.fedilab.android.viewmodel.mastodon.OauthVM;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
|
||||
|
||||
public class WebviewConnectActivity extends BaseActivity {
|
||||
|
||||
|
||||
private ActivityWebviewConnectBinding binding;
|
||||
private AlertDialog alert;
|
||||
private String login_url;
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void clearCookies(Context context) {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||
CookieManager.getInstance().removeAllCookies(null);
|
||||
CookieManager.getInstance().flush();
|
||||
} else {
|
||||
CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(context);
|
||||
cookieSyncMngr.startSync();
|
||||
CookieManager cookieManager = CookieManager.getInstance();
|
||||
cookieManager.removeAllCookie();
|
||||
cookieManager.removeSessionCookie();
|
||||
cookieSyncMngr.stopSync();
|
||||
cookieSyncMngr.sync();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ApplySharedPref")
|
||||
public static void proceedLogin(Activity activity, Account account) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
//update the database
|
||||
new Account(activity).insertOrUpdate(account);
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
BaseMainActivity.currentToken = account.token;
|
||||
BaseMainActivity.currentUserID = account.user_id;
|
||||
BaseMainActivity.api = Account.API.MASTODON;
|
||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||
editor.putString(PREF_USER_TOKEN, account.token);
|
||||
editor.commit();
|
||||
//The user is now authenticated, it will be redirected to MainActivity
|
||||
Runnable myRunnable = () -> {
|
||||
Intent mainActivity = new Intent(activity, MainActivity.class);
|
||||
activity.startActivity(mainActivity);
|
||||
activity.finish();
|
||||
};
|
||||
mainHandler.post(myRunnable);
|
||||
} catch (DBException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(WebviewConnectActivity.this);
|
||||
|
||||
binding = ActivityWebviewConnectBinding.inflate(getLayoutInflater());
|
||||
View rootView = binding.getRoot();
|
||||
setContentView(rootView);
|
||||
|
||||
Bundle b = getIntent().getExtras();
|
||||
if (b != null) {
|
||||
login_url = b.getString("login_url");
|
||||
requestedAdmin = b.getBoolean("requestedAdmin", false);
|
||||
}
|
||||
if (login_url == null)
|
||||
finish();
|
||||
|
||||
clearCookies(WebviewConnectActivity.this);
|
||||
binding.webviewConnect.getSettings().setJavaScriptEnabled(true);
|
||||
// String user_agent = sharedpreferences.getString(getString(R.string.SET_CUSTOM_USER_AGENT), Helper.USER_AGENT);
|
||||
// binding.webviewConnect.getSettings().setUserAgentString(user_agent);
|
||||
binding.webviewConnect.getSettings().setDomStorageEnabled(true);
|
||||
CookieManager.getInstance().setAcceptThirdPartyCookies(binding.webviewConnect, true);
|
||||
|
||||
|
||||
final ProgressBar pbar = findViewById(R.id.progress_bar);
|
||||
binding.webviewConnect.setWebChromeClient(new WebChromeClient() {
|
||||
@Override
|
||||
public void onProgressChanged(WebView view, int progress) {
|
||||
if (progress < 100 && pbar.getVisibility() == ProgressBar.GONE) {
|
||||
pbar.setVisibility(ProgressBar.VISIBLE);
|
||||
}
|
||||
pbar.setProgress(progress);
|
||||
if (progress == 100) {
|
||||
pbar.setVisibility(ProgressBar.GONE);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
binding.webviewConnect.setWebViewClient(new WebViewClient() {
|
||||
|
||||
/* @Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
||||
String x_xsrf_token = null;
|
||||
String x_csrf_token = null;
|
||||
if (request.getUrl().toString().contains("accounts/verify_credentials")) {
|
||||
|
||||
String cookies = CookieManager.getInstance().getCookie(request.getUrl().toString());
|
||||
|
||||
Map<String, String> requestHeaders = request.getRequestHeaders();
|
||||
Iterator<Map.Entry<String, String>> it = requestHeaders.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<String, String> pair = it.next();
|
||||
if (pair.getKey().compareTo("X-XSRF-TOKEN") == 0) {
|
||||
x_xsrf_token = pair.getValue();
|
||||
}
|
||||
if (pair.getKey().compareTo("X-CSRF-TOKEN") == 0) {
|
||||
x_csrf_token = pair.getValue();
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
if (x_xsrf_token != null && x_csrf_token != null) {
|
||||
String finalX_xsrf_token = x_xsrf_token;
|
||||
String finalX_csrf_token = x_csrf_token;
|
||||
new Handler(Looper.getMainLooper()).post(() -> {
|
||||
view.stopLoading();
|
||||
SharedPreferences sharedpreferences1 = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sharedpreferences1.edit();
|
||||
String token = "X-XSRF-TOKEN= " + finalX_xsrf_token + ";X-CSRF-TOKEN= " + finalX_csrf_token + "|" + cookies;
|
||||
editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, token);
|
||||
editor.commit();
|
||||
view.setVisibility(View.GONE);
|
||||
//Update the account with the token;
|
||||
new UpdateAccountInfoAsyncTask(WebviewConnectActivity.this, token, clientId, clientSecret, null, instance, social);
|
||||
});
|
||||
}
|
||||
}
|
||||
return super.shouldInterceptRequest(view, request);
|
||||
}*/
|
||||
|
||||
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
||||
if (request.getUrl().toString().contains(currentInstanceLogin + "/api/v1")) {
|
||||
request.getRequestHeaders();
|
||||
Map<String, String> requestHeaders = request.getRequestHeaders();
|
||||
Iterator<Map.Entry<String, String>> it = requestHeaders.entrySet().iterator();
|
||||
String token = null;
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<String, String> pair = it.next();
|
||||
if (pair.getKey().equals("Authorization")) {
|
||||
token = pair.getValue();
|
||||
break;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
if (token != null) {
|
||||
AccountsVM accountsVM = new ViewModelProvider(WebviewConnectActivity.this).get(AccountsVM.class);
|
||||
String finalToken = token;
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = () -> {
|
||||
accountsVM.getConnectedAccount(currentInstanceLogin, finalToken).observe(WebviewConnectActivity.this, mastodonAccount -> {
|
||||
if (mastodonAccount != null) {
|
||||
Account account = new Account();
|
||||
account.client_id = client_idLogin;
|
||||
account.client_secret = client_secretLogin;
|
||||
account.token = finalToken;
|
||||
account.api = apiLogin;
|
||||
account.software = softwareLogin;
|
||||
account.instance = currentInstanceLogin;
|
||||
account.mastodon_account = mastodonAccount;
|
||||
account.user_id = mastodonAccount.id;
|
||||
//We check if user have really moderator rights
|
||||
if (requestedAdmin) {
|
||||
AdminVM adminVM = new ViewModelProvider(WebviewConnectActivity.this).get(AdminVM.class);
|
||||
adminVM.getAccount(account.instance, account.token, account.user_id).observe(WebviewConnectActivity.this, adminAccount -> {
|
||||
account.admin = adminAccount != null;
|
||||
proceedLogin(WebviewConnectActivity.this, account);
|
||||
});
|
||||
} else {
|
||||
proceedLogin(WebviewConnectActivity.this, account);
|
||||
}
|
||||
} else {
|
||||
Toasty.error(WebviewConnectActivity.this, getString(R.string.toast_error), Toasty.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
};
|
||||
mainHandler.post(myRunnable);
|
||||
}
|
||||
}
|
||||
return super.shouldInterceptRequest(view, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
super.shouldOverrideUrlLoading(view, url);
|
||||
if (url.contains(Helper.REDIRECT_CONTENT_WEB)) {
|
||||
Matcher matcher = Helper.codePattern.matcher(url);
|
||||
if (!matcher.find()) {
|
||||
return false;
|
||||
}
|
||||
String code = matcher.group(1);
|
||||
OauthVM oauthVM = new ViewModelProvider(WebviewConnectActivity.this).get(OauthVM.class);
|
||||
//API call to get the user token
|
||||
String scope = requestedAdmin ? Helper.OAUTH_SCOPES_ADMIN : Helper.OAUTH_SCOPES;
|
||||
oauthVM.createToken(currentInstanceLogin, "authorization_code", client_idLogin, client_secretLogin, Helper.REDIRECT_CONTENT_WEB, scope, code)
|
||||
.observe(WebviewConnectActivity.this, tokenObj -> {
|
||||
if (tokenObj != null) {
|
||||
Account account = new Account();
|
||||
account.client_id = client_idLogin;
|
||||
account.client_secret = client_secretLogin;
|
||||
account.token = tokenObj.token_type + " " + tokenObj.access_token;
|
||||
account.api = apiLogin;
|
||||
account.software = softwareLogin;
|
||||
account.instance = currentInstanceLogin;
|
||||
//API call to retrieve account information for the new token
|
||||
AccountsVM accountsVM = new ViewModelProvider(WebviewConnectActivity.this).get(AccountsVM.class);
|
||||
accountsVM.getConnectedAccount(currentInstanceLogin, account.token).observe(WebviewConnectActivity.this, mastodonAccount -> {
|
||||
if (mastodonAccount != null) {
|
||||
account.mastodon_account = mastodonAccount;
|
||||
account.user_id = mastodonAccount.id;
|
||||
//We check if user have really moderator rights
|
||||
if (requestedAdmin) {
|
||||
AdminVM adminVM = new ViewModelProvider(WebviewConnectActivity.this).get(AdminVM.class);
|
||||
adminVM.getAccount(account.instance, account.token, account.user_id).observe(WebviewConnectActivity.this, adminAccount -> {
|
||||
account.admin = adminAccount != null;
|
||||
proceedLogin(WebviewConnectActivity.this, account);
|
||||
});
|
||||
} else {
|
||||
proceedLogin(WebviewConnectActivity.this, account);
|
||||
}
|
||||
} else {
|
||||
Toasty.error(WebviewConnectActivity.this, getString(R.string.toast_error), Toasty.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Toasty.error(WebviewConnectActivity.this, getString(R.string.toast_token), Toasty.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
binding.webviewConnect.loadUrl(login_url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (binding.webviewConnect.canGoBack()) {
|
||||
binding.webviewConnect.goBack();
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (alert != null) {
|
||||
alert.dismiss();
|
||||
alert = null;
|
||||
}
|
||||
binding.webviewConnect.destroy();
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
package app.fedilab.android.webview;
|
||||
/* Copyright 2021 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.webkit.WebView;
|
||||
|
||||
public class CustomWebview extends WebView {
|
||||
|
||||
|
||||
public CustomWebview(Context context) {
|
||||
super(getFixedContext(context));
|
||||
}
|
||||
|
||||
public CustomWebview(Context context, AttributeSet attrs) {
|
||||
super(getFixedContext(context), attrs);
|
||||
}
|
||||
|
||||
public CustomWebview(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(getFixedContext(context), attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public CustomWebview(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public CustomWebview(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
|
||||
super(getFixedContext(context), attrs, defStyleAttr, privateBrowsing);
|
||||
}
|
||||
|
||||
public static Context getFixedContext(Context context) {
|
||||
return context.createConfigurationContext(new Configuration());
|
||||
}
|
||||
}
|
@ -1,228 +0,0 @@
|
||||
package app.fedilab.android.webview;
|
||||
/* Copyright 2021 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Bitmap;
|
||||
import android.media.MediaPlayer;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import app.fedilab.android.R;
|
||||
|
||||
|
||||
public class FedilabWebChromeClient extends WebChromeClient implements MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {
|
||||
|
||||
private final CustomWebview webView;
|
||||
private final View activityNonVideoView;
|
||||
private final ViewGroup activityVideoView;
|
||||
private final ProgressBar pbar;
|
||||
private final Activity activity;
|
||||
private FrameLayout videoViewContainer;
|
||||
private CustomViewCallback videoViewCallback;
|
||||
private ToggledFullscreenCallback toggledFullscreenCallback;
|
||||
private boolean isVideoFullscreen;
|
||||
|
||||
|
||||
public FedilabWebChromeClient(Activity activity, CustomWebview webView, FrameLayout activityNonVideoView, ViewGroup activityVideoView) {
|
||||
this.activity = activity;
|
||||
this.isVideoFullscreen = false;
|
||||
this.webView = webView;
|
||||
this.pbar = activity.findViewById(R.id.progress_bar);
|
||||
this.activityNonVideoView = activityNonVideoView;
|
||||
this.activityVideoView = activityVideoView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(WebView view, int progress) {
|
||||
if (pbar != null) {
|
||||
if (progress < 100 && pbar.getVisibility() == ProgressBar.GONE) {
|
||||
pbar.setVisibility(ProgressBar.VISIBLE);
|
||||
}
|
||||
pbar.setProgress(progress);
|
||||
if (progress == 100) {
|
||||
pbar.setVisibility(ProgressBar.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitmap getDefaultVideoPoster() {
|
||||
return Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedIcon(WebView view, Bitmap icon) {
|
||||
super.onReceivedIcon(view, icon);
|
||||
LayoutInflater mInflater = LayoutInflater.from(activity);
|
||||
ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
View webview_actionbar = mInflater.inflate(R.layout.webview_actionbar, new LinearLayout(activity), false);
|
||||
TextView webview_title = webview_actionbar.findViewById(R.id.webview_title);
|
||||
webview_title.setText(view.getTitle());
|
||||
ImageView webview_favicon = webview_actionbar.findViewById(R.id.webview_favicon);
|
||||
if (icon != null)
|
||||
webview_favicon.setImageBitmap(icon);
|
||||
actionBar.setCustomView(webview_actionbar);
|
||||
actionBar.setDisplayShowCustomEnabled(true);
|
||||
} else {
|
||||
activity.setTitle(view.getTitle());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback that will be fired when the video starts or finishes displaying using a custom view (typically full-screen)
|
||||
*
|
||||
* @param callback A VideoEnabledWebChromeClient.ToggledFullscreenCallback callback
|
||||
*/
|
||||
public void setOnToggledFullscreen(ToggledFullscreenCallback callback) {
|
||||
this.toggledFullscreenCallback = callback;
|
||||
}
|
||||
|
||||
//FULLSCREEN VIDEO
|
||||
//Code from https://stackoverflow.com/a/16179544/3197259
|
||||
|
||||
@Override
|
||||
public void onShowCustomView(View view, CustomViewCallback callback) {
|
||||
if (view instanceof FrameLayout) {
|
||||
if (((AppCompatActivity) activity).getSupportActionBar() != null)
|
||||
//noinspection ConstantConditions
|
||||
((AppCompatActivity) activity).getSupportActionBar().hide();
|
||||
// A video wants to be shown
|
||||
FrameLayout frameLayout = (FrameLayout) view;
|
||||
View focusedChild = frameLayout.getFocusedChild();
|
||||
|
||||
// Save video related variables
|
||||
isVideoFullscreen = true;
|
||||
this.videoViewContainer = frameLayout;
|
||||
this.videoViewCallback = callback;
|
||||
|
||||
// Hide the non-video view, add the video view, and show it
|
||||
activityNonVideoView.setVisibility(View.INVISIBLE);
|
||||
activityVideoView.addView(videoViewContainer, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
activityVideoView.setVisibility(View.VISIBLE);
|
||||
if (focusedChild instanceof android.widget.VideoView) {
|
||||
// android.widget.VideoView (typically API level <11)
|
||||
android.widget.VideoView videoView = (android.widget.VideoView) focusedChild;
|
||||
// Handle all the required events
|
||||
videoView.setOnCompletionListener(this);
|
||||
videoView.setOnErrorListener(this);
|
||||
} else {
|
||||
// Other classes, including:
|
||||
// - android.webkit.HTML5VideoFullScreen$VideoSurfaceView, which inherits from android.view.SurfaceView (typically API level 11-18)
|
||||
// - android.webkit.HTML5VideoFullScreen$VideoTextureView, which inherits from android.view.TextureView (typically API level 11-18)
|
||||
// - com.android.org.chromium.content.browser.ContentVideoView$VideoSurfaceView, which inherits from android.view.SurfaceView (typically API level 19+)
|
||||
|
||||
// Handle HTML5 video ended event only if the class is a SurfaceView
|
||||
// Test case: TextureView of Sony Xperia T API level 16 doesn't work fullscreen when loading the javascript below
|
||||
if (webView != null && webView.getSettings().getJavaScriptEnabled() && focusedChild instanceof SurfaceView) {
|
||||
// Run javascript code that detects the video end and notifies the Javascript interface
|
||||
String js = "javascript:";
|
||||
js += "var _ytrp_html5_video_last;";
|
||||
js += "var _ytrp_html5_video = document.getElementsByTagName('video')[0];";
|
||||
js += "if (_ytrp_html5_video != undefined && _ytrp_html5_video != _ytrp_html5_video_last) {";
|
||||
{
|
||||
js += "_ytrp_html5_video_last = _ytrp_html5_video;";
|
||||
js += "function _ytrp_html5_video_ended() {";
|
||||
{
|
||||
js += "_VideoEnabledWebView.notifyVideoEnd();"; // Must match Javascript interface name and method of VideoEnableWebView
|
||||
}
|
||||
js += "}";
|
||||
js += "_ytrp_html5_video.addEventListener('ended', _ytrp_html5_video_ended);";
|
||||
}
|
||||
js += "}";
|
||||
webView.loadUrl(js);
|
||||
}
|
||||
}
|
||||
// Notify full-screen change
|
||||
if (toggledFullscreenCallback != null) {
|
||||
toggledFullscreenCallback.toggledFullscreen(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Available in API level 14+, deprecated in API level 18+
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) {
|
||||
onShowCustomView(view, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHideCustomView() {
|
||||
if (((AppCompatActivity) activity).getSupportActionBar() != null)
|
||||
//noinspection ConstantConditions
|
||||
((AppCompatActivity) activity).getSupportActionBar().show();
|
||||
// This method should be manually called on video end in all cases because it's not always called automatically.
|
||||
// This method must be manually called on back key press (from this class' onBackPressed() method).
|
||||
if (isVideoFullscreen) {
|
||||
// Hide the video view, remove it, and show the non-video view
|
||||
activityVideoView.setVisibility(View.INVISIBLE);
|
||||
activityVideoView.removeView(videoViewContainer);
|
||||
activityNonVideoView.setVisibility(View.VISIBLE);
|
||||
// Call back (only in API level <19, because in API level 19+ with chromium webview it crashes)
|
||||
if (videoViewCallback != null && !videoViewCallback.getClass().getName().contains(".chromium.")) {
|
||||
videoViewCallback.onCustomViewHidden();
|
||||
}
|
||||
|
||||
// Reset video related variables
|
||||
isVideoFullscreen = false;
|
||||
videoViewContainer = null;
|
||||
videoViewCallback = null;
|
||||
|
||||
// Notify full-screen change
|
||||
if (toggledFullscreenCallback != null) {
|
||||
toggledFullscreenCallback.toggledFullscreen(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Video will start loading
|
||||
@Override
|
||||
public View getVideoLoadingProgressView() {
|
||||
return super.getVideoLoadingProgressView();
|
||||
}
|
||||
|
||||
// Video finished playing, only called in the case of android.widget.VideoView (typically API level <11)
|
||||
@Override
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
onHideCustomView();
|
||||
}
|
||||
|
||||
// Error while playing video, only called in the case of android.widget.VideoView (typically API level <11)
|
||||
@Override
|
||||
public boolean onError(MediaPlayer mp, int what, int extra) {
|
||||
return false; // By returning false, onCompletion() will be called
|
||||
}
|
||||
|
||||
public interface ToggledFullscreenCallback {
|
||||
void toggledFullscreen(boolean fullscreen);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,163 +0,0 @@
|
||||
package app.fedilab.android.webview;
|
||||
/* Copyright 2021 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
|
||||
import static app.fedilab.android.client.entities.app.DomainsBlock.trackingDomains;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.http.SslError;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.webkit.SslErrorHandler;
|
||||
import android.webkit.URLUtil;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import app.fedilab.android.BuildConfig;
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.activities.WebviewActivity;
|
||||
|
||||
|
||||
public class FedilabWebViewClient extends WebViewClient {
|
||||
|
||||
private final Activity activity;
|
||||
public List<String> domains = new ArrayList<>();
|
||||
private int count = 0;
|
||||
|
||||
public FedilabWebViewClient(Activity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
super.onPageFinished(view, url);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(final WebView view, String url) {
|
||||
if (trackingDomains != null) {
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(url);
|
||||
String domain = uri.getHost();
|
||||
if (domain != null) {
|
||||
domain = domain.startsWith("www.") ? domain.substring(4) : domain;
|
||||
}
|
||||
if (domain != null && trackingDomains.contains(domain)) {
|
||||
if (activity instanceof WebviewActivity) {
|
||||
count++;
|
||||
domains.add(url);
|
||||
((WebviewActivity) activity).setCount(activity, String.valueOf(count));
|
||||
}
|
||||
ByteArrayInputStream nothing = new ByteArrayInputStream("".getBytes());
|
||||
return new WebResourceResponse("text/plain", "utf-8", nothing);
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
try {
|
||||
if (url.length() > 50) {
|
||||
url = url.substring(0, 50);
|
||||
}
|
||||
uri = new URI(url);
|
||||
String domain = uri.getHost();
|
||||
if (domain != null) {
|
||||
domain = domain.startsWith("www.") ? domain.substring(4) : domain;
|
||||
}
|
||||
if (domain != null && trackingDomains.contains(domain)) {
|
||||
if (activity instanceof WebviewActivity) {
|
||||
count++;
|
||||
domains.add(url);
|
||||
((WebviewActivity) activity).setCount(activity, String.valueOf(count));
|
||||
}
|
||||
ByteArrayInputStream nothing = new ByteArrayInputStream("".getBytes());
|
||||
return new WebResourceResponse("text/plain", "utf-8", nothing);
|
||||
|
||||
}
|
||||
} catch (URISyntaxException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.shouldInterceptRequest(view, url);
|
||||
}
|
||||
|
||||
public List<String> getDomains() {
|
||||
return this.domains;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
|
||||
if (BuildConfig.DONATIONS) {
|
||||
if (view.getUrl() != null && view.getUrl().endsWith(".onion")) {
|
||||
handler.proceed();
|
||||
} else {
|
||||
super.onReceivedSslError(view, handler, error);
|
||||
}
|
||||
} else {
|
||||
super.onReceivedSslError(view, handler, error);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
if (URLUtil.isNetworkUrl(url)) {
|
||||
return false;
|
||||
} else {
|
||||
view.stopLoading();
|
||||
view.goBack();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
||||
super.onPageStarted(view, url, favicon);
|
||||
count = 0;
|
||||
domains = new ArrayList<>();
|
||||
domains.clear();
|
||||
ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar();
|
||||
LayoutInflater mInflater = LayoutInflater.from(activity);
|
||||
if (actionBar != null) {
|
||||
View webview_actionbar = mInflater.inflate(R.layout.webview_actionbar, new LinearLayout(activity), false);
|
||||
TextView webview_title = webview_actionbar.findViewById(R.id.webview_title);
|
||||
webview_title.setText(url);
|
||||
actionBar.setCustomView(webview_actionbar);
|
||||
actionBar.setDisplayShowCustomEnabled(true);
|
||||
} else {
|
||||
activity.setTitle(url);
|
||||
}
|
||||
//Changes the url in webview activity so that it can be opened with an external app
|
||||
try {
|
||||
if (activity instanceof WebviewActivity)
|
||||
((WebviewActivity) activity).setUrl(url);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,166 +0,0 @@
|
||||
package app.fedilab.android.webview;
|
||||
/* Copyright 2021 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Proxy;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ProxyHelper {
|
||||
|
||||
|
||||
public static void setProxy(Context context, CustomWebview webview, String host, int port, String applicationClassName) {
|
||||
|
||||
setProxyKKPlus(context, webview, host, port, applicationClassName);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("all")
|
||||
private static boolean setProxyICS(CustomWebview webview, String host, int port) {
|
||||
try {
|
||||
Class jwcjb = Class.forName("android.webkit.JWebCoreJavaBridge");
|
||||
Class params[] = new Class[1];
|
||||
params[0] = Class.forName("android.net.ProxyProperties");
|
||||
Method updateProxyInstance = jwcjb.getDeclaredMethod("updateProxy", params);
|
||||
|
||||
Class wv = Class.forName("android.webkit.WebView");
|
||||
Field mWebViewCoreField = wv.getDeclaredField("mWebViewCore");
|
||||
Object mWebViewCoreFieldInstance = getFieldValueSafely(mWebViewCoreField, webview);
|
||||
|
||||
Class wvc = Class.forName("android.webkit.WebViewCore");
|
||||
Field mBrowserFrameField = wvc.getDeclaredField("mBrowserFrame");
|
||||
Object mBrowserFrame = getFieldValueSafely(mBrowserFrameField, mWebViewCoreFieldInstance);
|
||||
|
||||
Class bf = Class.forName("android.webkit.BrowserFrame");
|
||||
Field sJavaBridgeField = bf.getDeclaredField("sJavaBridge");
|
||||
Object sJavaBridge = getFieldValueSafely(sJavaBridgeField, mBrowserFrame);
|
||||
|
||||
Class ppclass = Class.forName("android.net.ProxyProperties");
|
||||
Class pparams[] = new Class[3];
|
||||
pparams[0] = String.class;
|
||||
pparams[1] = int.class;
|
||||
pparams[2] = String.class;
|
||||
Constructor ppcont = ppclass.getConstructor(pparams);
|
||||
|
||||
updateProxyInstance.invoke(sJavaBridge, ppcont.newInstance(host, port, null));
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Proxy for Android 4.1 - 4.3.
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
private static boolean setProxyJB(CustomWebview webview, String host, int port) {
|
||||
|
||||
try {
|
||||
Class wvcClass = Class.forName("android.webkit.WebViewClassic");
|
||||
Class wvParams[] = new Class[1];
|
||||
wvParams[0] = Class.forName("android.webkit.WebView");
|
||||
Method fromWebView = wvcClass.getDeclaredMethod("fromWebView", wvParams);
|
||||
Object webViewClassic = fromWebView.invoke(null, webview);
|
||||
|
||||
Class wv = Class.forName("android.webkit.WebViewClassic");
|
||||
Field mWebViewCoreField = wv.getDeclaredField("mWebViewCore");
|
||||
Object mWebViewCoreFieldInstance = getFieldValueSafely(mWebViewCoreField, webViewClassic);
|
||||
|
||||
Class wvc = Class.forName("android.webkit.WebViewCore");
|
||||
Field mBrowserFrameField = wvc.getDeclaredField("mBrowserFrame");
|
||||
Object mBrowserFrame = getFieldValueSafely(mBrowserFrameField, mWebViewCoreFieldInstance);
|
||||
|
||||
Class bf = Class.forName("android.webkit.BrowserFrame");
|
||||
Field sJavaBridgeField = bf.getDeclaredField("sJavaBridge");
|
||||
Object sJavaBridge = getFieldValueSafely(sJavaBridgeField, mBrowserFrame);
|
||||
|
||||
Class ppclass = Class.forName("android.net.ProxyProperties");
|
||||
Class pparams[] = new Class[3];
|
||||
pparams[0] = String.class;
|
||||
pparams[1] = int.class;
|
||||
pparams[2] = String.class;
|
||||
Constructor ppcont = ppclass.getConstructor(pparams);
|
||||
|
||||
Class jwcjb = Class.forName("android.webkit.JWebCoreJavaBridge");
|
||||
Class params[] = new Class[1];
|
||||
params[0] = Class.forName("android.net.ProxyProperties");
|
||||
Method updateProxyInstance = jwcjb.getDeclaredMethod("updateProxy", params);
|
||||
|
||||
updateProxyInstance.invoke(sJavaBridge, ppcont.newInstance(host, port, null));
|
||||
} catch (Exception ex) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// from https://stackoverflow.com/questions/19979578/android-webview-set-proxy-programatically-kitkat
|
||||
@SuppressLint("NewApi")
|
||||
@SuppressWarnings("all")
|
||||
private static void setProxyKKPlus(Context appContext, CustomWebview webView, String host, int port, String applicationClassName) {
|
||||
|
||||
System.setProperty("http.proxyHost", host);
|
||||
System.setProperty("http.proxyPort", port + "");
|
||||
System.setProperty("https.proxyHost", host);
|
||||
System.setProperty("https.proxyPort", port + "");
|
||||
try {
|
||||
Class applictionCls = Class.forName("android.app.Application");
|
||||
Field loadedApkField = applictionCls.getDeclaredField("mLoadedApk");
|
||||
loadedApkField.setAccessible(true);
|
||||
Object loadedApk = loadedApkField.get(appContext);
|
||||
Class loadedApkCls = Class.forName("android.app.LoadedApk");
|
||||
Field receiversField = loadedApkCls.getDeclaredField("mReceivers");
|
||||
receiversField.setAccessible(true);
|
||||
ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
|
||||
for (Object receiverMap : receivers.values()) {
|
||||
for (Object rec : ((ArrayMap) receiverMap).keySet()) {
|
||||
Class clazz = rec.getClass();
|
||||
if (clazz.getName().contains("ProxyChangeListener")) {
|
||||
Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class, Intent.class);
|
||||
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
|
||||
|
||||
onReceiveMethod.invoke(rec, appContext, intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static Object getFieldValueSafely(Field field, Object classInstance) throws IllegalArgumentException, IllegalAccessException {
|
||||
boolean oldAccessibleValue = field.isAccessible();
|
||||
field.setAccessible(true);
|
||||
Object result = field.get(classInstance);
|
||||
field.setAccessible(oldAccessibleValue);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Copyright 2021 Thomas Schneider
|
||||
|
||||
This file is a part of Fedilab
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
see <http://www.gnu.org/licenses>
|
||||
-->
|
||||
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:openDrawer="start">
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".activities.WebviewActivity">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:fitsSystemWindows="true"
|
||||
app:layout_scrollFlags="scroll|enterAlways">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/favicon"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:contentDescription="@string/favicon" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/toolbar_title"
|
||||
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp" />
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="?attr/actionBarSize"
|
||||
android:orientation="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="10dp"
|
||||
android:padding="1dp" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/webview_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<app.fedilab.android.webview.CustomWebview
|
||||
android:id="@+id/webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white" />
|
||||
</FrameLayout>
|
||||
<!-- View where the video will be shown when video goes fullscreen -->
|
||||
<RelativeLayout
|
||||
android:id="@+id/videoLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</androidx.drawerlayout.widget.DrawerLayout>
|
@ -1,40 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Copyright 2022 Thomas Schneider
|
||||
|
||||
This file is a part of Fedilab
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
see <http://www.gnu.org/licenses>
|
||||
-->
|
||||
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="10dp"
|
||||
android:padding="2dp" />
|
||||
|
||||
<app.fedilab.android.webview.CustomWebview
|
||||
android:id="@+id/webviewConnect"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
</LinearLayout>
|
||||
</androidx.drawerlayout.widget.DrawerLayout>
|
Loading…
Reference in new issue