diff --git a/android/.gitignore b/android/.gitignore index 549d6a11ae..b7d611cfec 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -92,3 +92,6 @@ app/src/main/res/xml/config.xml /app/fdroid/release /app/play/release /app/src/play/java/com/superproductivity/superproductivity/GoogleClientId.java + +############### +.idea/deploymentTargetSelector.xml diff --git a/android/.idea/deploymentTargetSelector.xml b/android/.idea/deploymentTargetSelector.xml deleted file mode 100644 index 86aca96ee5..0000000000 --- a/android/.idea/deploymentTargetSelector.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/android/.idea/misc.xml b/android/.idea/misc.xml deleted file mode 100644 index f988785754..0000000000 --- a/android/.idea/misc.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/java/com/superproductivity/superproductivity/webview/WebViewRequestHandler.kt b/android/app/src/main/java/com/superproductivity/superproductivity/webview/WebViewRequestHandler.kt index 63a74ae238..88e0a1f27a 100644 --- a/android/app/src/main/java/com/superproductivity/superproductivity/webview/WebViewRequestHandler.kt +++ b/android/app/src/main/java/com/superproductivity/superproductivity/webview/WebViewRequestHandler.kt @@ -7,7 +7,6 @@ import android.webkit.WebResourceRequest import android.webkit.WebResourceResponse import android.webkit.WebView import android.util.Log -import com.superproductivity.superproductivity.BuildConfig import okhttp3.OkHttpClient import okhttp3.Request import java.io.ByteArrayInputStream @@ -35,6 +34,7 @@ class WebViewRequestHandler(private val activity: Activity, private val serviceH } } + fun interceptWebRequest(request: WebResourceRequest?): WebResourceResponse? { try { if (request == null || request.isForMainFrame) { @@ -53,10 +53,7 @@ class WebViewRequestHandler(private val activity: Activity, private val serviceH return null } - Log.v( - "TW", - "interceptRequest mf:${request?.isForMainFrame.toString()} ${request.method} ${request?.url}" - ) + Log.v("TW", "interceptRequest mf:${request?.isForMainFrame.toString()} ${request.method} ${request?.url}") // since we currently don't have a way to also post the body, we only handle GET, HEAD and OPTIONS requests // see https://github.com/KonstantinSchubert/request_data_webviewclient for a possible solution @@ -64,70 +61,30 @@ class WebViewRequestHandler(private val activity: Activity, private val serviceH return null } - // remove user agent header in the hopes that we're treated better by the remotes :D - val keysToRemove = - request.requestHeaders.keys.filter { it.equals("User-Agent", ignoreCase = true) } - for (key in keysToRemove) { - request.requestHeaders.remove(key) - } - val client = OkHttpClient() val newRequestBuilder = Request.Builder() .url(request.url.toString()) + .removeHeader("User-Agent") + .removeHeader("Origin") + .removeHeader("Referer") .method(request.method, null) - // Add each header from the original request to the new request for ((key, value) in request.requestHeaders) { newRequestBuilder.addHeader(key, value) } val newRequest = newRequestBuilder.build() - // currently we can't handle POST requests since everything if (request.method.uppercase() == "OPTIONS") { Log.v("TW", "OPTIONS request triggered") client.newCall(newRequest).execute().use { response -> - Log.v( - "TW", - "OPTIONS original response: ${response.code} ${response.message} ${response.body?.string()}" - ) + Log.v("TW", "OPTIONS original response: ${response.code} ${response.message} ${response.body?.string()}") if (response.code != 200) { Log.v("TW", "OPTIONS overwrite") return OptionsAllowResponse.build() } } } - - - // Handle HEAD requests - if (request.method.uppercase() == "HEAD") { - Log.v("TW", "HEAD request triggered") - client.newCall(newRequest).execute().use { response -> - Log.v("TW", "HEAD response ${response.code} ${response.message}") - val responseHeaders = response.headers.names() - .associateWith { response.headers(it)?.joinToString() } - .toMutableMap() - - val keysToRemoveI = responseHeaders.keys.filter { - it.equals("Access-Control-Allow-Origin", ignoreCase = true) - } - for (key in keysToRemoveI) { - responseHeaders.remove(key) - } - responseHeaders["Access-Control-Allow-Origin"] = "*" - - val contentType = response.header("Content-Type", "text/plain") - val contentEncoding = response.header("Content-Encoding", "utf-8") - val reasonPhrase = response.message.ifEmpty { "OK" } - return WebResourceResponse( - contentType, - contentEncoding, - response.code, - reasonPhrase, - responseHeaders, - null - ) - } - } + //------------- Log.v("TW", "exec request ${request.url}") @@ -137,23 +94,16 @@ class WebViewRequestHandler(private val activity: Activity, private val serviceH .associateWith { response.headers(it)?.joinToString() } .toMutableMap() - val keysToRemoveI = - responseHeaders.keys.filter { - it.equals( - "Access-Control-Allow-Origin", - ignoreCase = true - ) - } - for (key in keysToRemoveI) { - responseHeaders.remove(key) - } - responseHeaders["Access-Control-Allow-Origin"] = "*" + upsertKeyValue(responseHeaders, "Access-Control-Allow-Origin", "*") + upsertKeyValue(responseHeaders, "Access-Control-Allow-Methods", "GET, POST, OPTIONS") val contentType = response.header("Content-Type", "text/plain") val contentEncoding = response.header("Content-Encoding", "utf-8") + // TODO check if this needs to be adjusted for HEAD requests val inputStream = ByteArrayInputStream(response.body?.bytes()) val reasonPhrase = response.message.ifEmpty { "OK" } // provide a default value if the message is null or empty + return WebResourceResponse( contentType, contentEncoding, @@ -168,4 +118,18 @@ class WebViewRequestHandler(private val activity: Activity, private val serviceH return null } } + + fun upsertKeyValue(responseHeaders: MutableMap, keyToChange: String, value: String): MutableMap { + val keyToChangeLower = keyToChange.lowercase() + for (key in responseHeaders.keys) { + if (key.lowercase() == keyToChangeLower) { + // Reassign old key + responseHeaders[key] = value + // Done + return responseHeaders + } + } + responseHeaders[keyToChange] = value + return responseHeaders + } } diff --git a/src/app/features/issue/providers/jira/jira-api.service.ts b/src/app/features/issue/providers/jira/jira-api.service.ts index 7e2acbab9f..32cffa4ee0 100644 --- a/src/app/features/issue/providers/jira/jira-api.service.ts +++ b/src/app/features/issue/providers/jira/jira-api.service.ts @@ -52,6 +52,7 @@ import { SS } from '../../../../core/persistence/storage-keys.const'; import { MatDialog } from '@angular/material/dialog'; import { DialogPromptComponent } from '../../../../ui/dialog-prompt/dialog-prompt.component'; import { stripTrailing } from '../../../../util/strip-trailing'; +import { IS_ANDROID_WEB_VIEW } from '../../../../util/is-android-web-view'; const BLOCK_ACCESS_KEY = 'SUP_BLOCK_JIRA_ACCESS'; const API_VERSION = 'latest'; @@ -85,13 +86,14 @@ export class JiraApiService { private _requestsLog: { [key: string]: JiraRequestLogItem } = {}; private _isBlockAccess: boolean = !!sessionStorage.getItem(BLOCK_ACCESS_KEY); private _isExtension: boolean = false; - private _isInterfacesReadyIfNeeded$: Observable = IS_ELECTRON - ? of(true).pipe() - : this._chromeExtensionInterfaceService.onReady$.pipe( - mapTo(true), - shareReplay(1), - timeoutWith(500, throwError('Jira: Extension not installed or not ready')), - ); + private _isInterfacesReadyIfNeeded$: Observable = + IS_ELECTRON || IS_ANDROID_WEB_VIEW + ? of(true).pipe() + : this._chromeExtensionInterfaceService.onReady$.pipe( + mapTo(true), + shareReplay(1), + timeoutWith(500, throwError('Jira: Extension not installed or not ready')), + ); constructor( private _chromeExtensionInterfaceService: ChromeExtensionInterfaceService, @@ -371,7 +373,7 @@ export class JiraApiService { settings.host && settings.userName && settings.password && - (IS_ELECTRON || this._isExtension) + (IS_ELECTRON || this._isExtension || IS_ANDROID_WEB_VIEW) ); } @@ -408,7 +410,7 @@ export class JiraApiService { this._snackService.open({ type: 'ERROR', msg: - !IS_ELECTRON && !this._isExtension + !IS_ELECTRON && !this._isExtension && !IS_ANDROID_WEB_VIEW ? T.F.JIRA.S.EXTENSION_NOT_LOADED : T.F.JIRA.S.INSUFFICIENT_SETTINGS, });