Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,23 @@ import android.os.Build
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.view.WindowInsets
import android.view.WindowManager
import android.util.Log
import android.widget.Toast
import androidx.core.net.toUri
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.webkit.WebViewCompat
import com.owncloud.android.R
import com.owncloud.android.datamodel.ReceiverFlag

private const val TAG = "ContextExtensions"

@Suppress("TooGenericExceptionCaught")
fun Context.isWebViewAvailable(): Boolean = try {
WebViewCompat.getCurrentWebViewPackage(this) != null
} catch (e: Exception) {
Log.w(TAG, "WebView provider cannot be resolved: ${e.message}")
false
}

fun Context.hourPlural(hour: Int): String = resources.getQuantityString(R.plurals.hours, hour, hour)

fun Context.minPlural(min: Int): String = resources.getQuantityString(R.plurals.minutes, min, min)
Expand All @@ -40,25 +48,6 @@ fun Context.registerBroadcastReceiver(receiver: BroadcastReceiver?, filter: Inte
registerReceiver(receiver, filter)
}

fun Context.statusBarHeight(): Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val windowInsets = (getSystemService(Context.WINDOW_SERVICE) as WindowManager)
.currentWindowMetrics
.windowInsets
val insets = windowInsets.getInsets(WindowInsets.Type.statusBars())
insets.top
} else {
@Suppress("DEPRECATION")
val decorView = (getSystemService(Context.WINDOW_SERVICE) as WindowManager)
.defaultDisplay
.let { display ->
val decorView = android.view.View(this)
display.getRealMetrics(android.util.DisplayMetrics())
decorView
}
val windowInsetsCompat = ViewCompat.getRootWindowInsets(decorView)
windowInsetsCompat?.getInsets(WindowInsetsCompat.Type.statusBars())?.top ?: 0
}

fun Context.showToast(message: String) {
Handler(Looper.getMainLooper()).post {
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,10 @@
import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.OnSslUntrustedCertListener;
import com.owncloud.android.utils.ErrorMessageAdapter;
import com.owncloud.android.utils.PermissionUtil;
import com.owncloud.android.utils.WebViewUtil;
import com.owncloud.android.utils.ProxyUtil;
import com.owncloud.android.utils.theme.ViewThemeUtils;

import java.lang.ref.WeakReference;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -949,7 +950,6 @@ protected void onNewIntent(Intent intent) {
private void initSimpleSignupLogin() {
viewThemeUtils.platform.colorCircularProgressBar(accountSetupWebviewBinding.loginWebviewProgressBar, ColorRole.ON_PRIMARY_CONTAINER);
accountSetupWebviewBinding.loginWebview.setVisibility(View.GONE);
new WebViewUtil().setProxyKKPlus(accountSetupWebviewBinding.loginWebview);

accountSetupWebviewBinding.loginWebview.getSettings().setAllowFileAccess(false);
accountSetupWebviewBinding.loginWebview.getSettings().setJavaScriptEnabled(true);
Expand All @@ -962,9 +962,8 @@ private void initSimpleSignupLogin() {
Map<String, String> headers = new HashMap<>();
headers.put(RemoteOperation.OCS_API_HEADER, RemoteOperation.OCS_API_HEADER_VALUE);

new WebViewUtil().setProxyKKPlus(accountSetupWebviewBinding.loginWebview);

accountSetupWebviewBinding.loginWebview.loadUrl(getString(R.string.provider_registration_server), headers);
new ProxyUtil(new WeakReference<>(this)).applyProxy(() ->
accountSetupWebviewBinding.loginWebview.loadUrl(getString(R.string.provider_registration_server), headers));
accountSetupWebviewBinding.loginFlowV2.loginFlowInfoV2.setVisibility(View.GONE);

setClient();
Expand Down
25 changes: 14 additions & 11 deletions app/src/main/java/com/owncloud/android/ui/activity/EditorWebView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import androidx.lifecycle.lifecycleScope
import com.google.android.material.snackbar.Snackbar
import com.nextcloud.android.common.ui.theme.utils.ColorRole
import com.nextcloud.client.account.User
import com.nextcloud.utils.AppConstants.ONE_SECOND
import com.nextcloud.utils.SnackbarUtil
import com.nextcloud.utils.extensions.getParcelableArgument
import com.nextcloud.utils.extensions.getSmallThumbnail
Expand All @@ -33,14 +34,13 @@ import com.owncloud.android.R
import com.owncloud.android.databinding.RichdocumentsWebviewBinding
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.datamodel.SyncedFolderObserver
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory
import com.owncloud.android.ui.asynctasks.TextEditorLoadUrlTask
import com.owncloud.android.utils.MimeTypeUtil
import com.owncloud.android.utils.RichDocumentDownloader
import com.owncloud.android.utils.WebViewUtil
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlin.time.Duration.Companion.seconds
import com.nextcloud.utils.AppConstants.ONE_SECOND

abstract class EditorWebView : ExternalSiteWebView() {
private lateinit var binding: RichdocumentsWebviewBinding
Expand Down Expand Up @@ -83,17 +83,20 @@ abstract class EditorWebView : ExternalSiteWebView() {
return
}

lifecycleScope.launch {
WebViewUtil().setProxyKKPlus(webView)
delay(ONE_SECOND)
proxyUtil?.applyProxy {
lifecycleScope.launch {
if (OwnCloudClientManagerFactory.getProxyHost().isNotEmpty()) {
delay(ONE_SECOND)
}

if (loadedUrl != webView.url) {
webView.loadUrl(loadedUrl)
}
if (loadedUrl != webView.url) {
webView.loadUrl(loadedUrl)
}

delay(LOADING_TIMEOUT)
if (!webView.isVisible) {
showLoadingTimeoutSnackbar()
delay(LOADING_TIMEOUT)
if (!webView.isVisible) {
showLoadingTimeoutSnackbar()
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ import androidx.drawerlayout.widget.DrawerLayout
import com.nextcloud.client.utils.IntentUtil
import com.nextcloud.utils.RawResourceReader
import com.nextcloud.utils.SnackbarUtil
import com.nextcloud.utils.extensions.isWebViewAvailable
import com.owncloud.android.MainApp
import com.owncloud.android.R
import com.owncloud.android.databinding.ExternalsiteWebviewBinding
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.ui.NextcloudWebViewClient
import com.owncloud.android.utils.WebViewUtil
import com.owncloud.android.utils.ProxyUtil
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
import java.lang.ref.WeakReference

/**
* This activity shows an URL as a web view
Expand All @@ -40,20 +42,23 @@ open class ExternalSiteWebView : FileActivity() {
private var showToolbar = true
private var showSidebar = false
protected var url: String? = null
protected var proxyUtil: ProxyUtil? = null

private val isDebuggable: Boolean
get() = applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0

final override fun onCreate(savedInstanceState: Bundle?) {
Log_OC.v(TAG, "onCreate() start")

if (!WebViewUtil.available(this)) {
if (!this.isWebViewAvailable()) {
super.onCreate(savedInstanceState)
SnackbarUtil.show(this, R.string.webview_not_available)
finish()
return
}

proxyUtil = ProxyUtil(WeakReference(this))

bindView()
readIntentExtras()
window?.requestFeature(Window.FEATURE_PROGRESS)
Expand Down Expand Up @@ -87,8 +92,9 @@ open class ExternalSiteWebView : FileActivity() {
setupWebSettings(webView.settings)
webView.webViewClient = createWebViewClient()

WebViewUtil().setProxyKKPlus(webView)
url?.let { webView.loadUrl(it) }
proxyUtil?.applyProxy {
url?.let { webView.loadUrl(it) }
}
}

private fun setupToolbarAndDrawer() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
import com.nextcloud.utils.e2ee.E2EEActionResolver;
import com.nextcloud.utils.e2ee.E2EEDialogPresenter;
import com.nextcloud.utils.extensions.BundleExtensionsKt;
import com.nextcloud.utils.extensions.ContextExtensionsKt;
import com.nextcloud.utils.extensions.FileExtensionsKt;
import com.nextcloud.utils.extensions.FragmentExtensionsKt;
import com.nextcloud.utils.extensions.IntentExtensionsKt;
Expand Down Expand Up @@ -118,7 +119,6 @@
import com.owncloud.android.utils.FileSortOrder;
import com.owncloud.android.utils.FileStorageUtils;
import com.owncloud.android.utils.PermissionUtil;
import com.owncloud.android.utils.WebViewUtil;
import com.owncloud.android.utils.theme.ThemeUtils;

import org.greenrobot.eventbus.EventBus;
Expand Down Expand Up @@ -1262,7 +1262,7 @@ private void handlePendingDownloadFile(OCFile file) {
return;
}

boolean webViewAvailable = WebViewUtil.available(context);
boolean webViewAvailable = ContextExtensionsKt.isWebViewAvailable(context);

if (!file.isEncrypted() && mContainerActivity instanceof FileDisplayActivity fda && fda.canPreviewInAudioPlayer(file)) {
setFabVisible(false);
Expand Down
53 changes: 53 additions & 0 deletions app/src/main/java/com/owncloud/android/utils/ProxyUtil.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.owncloud.android.utils

import android.annotation.SuppressLint
import android.content.Context
import androidx.core.content.ContextCompat
import androidx.webkit.ProxyConfig
import androidx.webkit.ProxyController
import androidx.webkit.WebViewFeature
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory
import com.owncloud.android.lib.common.utils.Log_OC
import java.lang.ref.WeakReference

class ProxyUtil(private val context: WeakReference<Context>) {
companion object {
private const val TAG = "ProxyUtil"
}

@SuppressLint("RequiresFeature")
@Suppress("ReturnCount")
fun applyProxy(onApplied: Runnable) {
val context = context.get() ?: return
val proxyHost = OwnCloudClientManagerFactory.getProxyHost()
val proxyPort = OwnCloudClientManagerFactory.getProxyPort()

if (proxyHost.isNullOrEmpty() || proxyPort <= 0) {
onApplied.run()
return
}

if (!WebViewFeature.isFeatureSupported(WebViewFeature.PROXY_OVERRIDE)) {
Log_OC.w(TAG, "WebView does not support proxy override")
onApplied.run()
return
}

val proxyConfig = ProxyConfig.Builder()
.addProxyRule("$proxyHost:$proxyPort")
.build()

ProxyController.getInstance().setProxyOverride(
proxyConfig,
ContextCompat.getMainExecutor(context),
onApplied
)
}
}
99 changes: 0 additions & 99 deletions app/src/main/java/com/owncloud/android/utils/WebViewUtil.kt

This file was deleted.

Loading