diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:35:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:35:49 +0000 |
commit | d8bbc7858622b6d9c278469aab701ca0b609cddf (patch) | |
tree | eff41dc61d9f714852212739e6b3738b82a2af87 /mobile/android/android-components/components/lib/fetch-okhttp | |
parent | Releasing progress-linux version 125.0.3-1~progress7.99u1. (diff) | |
download | firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip |
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mobile/android/android-components/components/lib/fetch-okhttp')
7 files changed, 270 insertions, 0 deletions
diff --git a/mobile/android/android-components/components/lib/fetch-okhttp/README.md b/mobile/android/android-components/components/lib/fetch-okhttp/README.md new file mode 100644 index 0000000000..d1cd0a3d2f --- /dev/null +++ b/mobile/android/android-components/components/lib/fetch-okhttp/README.md @@ -0,0 +1,25 @@ +# [Android Components](../../../README.md) > Libraries > Fetch-OkHttp + +A [concept-fetch](../../concept/fetch/README.md) implementation using [OkHttp](https://github.com/square/okhttp). + +This implementation of `concept-fetch` uses [OkHttp](https://github.com/square/okhttp) - a third-party library from Square. It is intended for apps that already use OkHttp and want components to use the same client. + +## Usage + +### Setting up the dependency + +Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)): + +```Groovy +implementation "org.mozilla.components:lib-fetch-okhttp:{latest-version}" +``` + +### Performing requests + +See the [concept-fetch documentation](../../concept/fetch/README.md) for generic examples of using the API of components implementing `concept-fetch`. + +## License + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/ diff --git a/mobile/android/android-components/components/lib/fetch-okhttp/build.gradle b/mobile/android/android-components/components/lib/fetch-okhttp/build.gradle new file mode 100644 index 0000000000..c7f1dd9495 --- /dev/null +++ b/mobile/android/android-components/components/lib/fetch-okhttp/build.gradle @@ -0,0 +1,43 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + defaultConfig { + minSdkVersion config.minSdkVersion + compileSdk config.compileSdkVersion + targetSdkVersion config.targetSdkVersion + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + namespace 'mozilla.components.lib.fetch.okhttp' + +} + +dependencies { + implementation ComponentsDependencies.kotlin_coroutines + + implementation ComponentsDependencies.thirdparty_okhttp + implementation ComponentsDependencies.thirdparty_okhttp_urlconnection + + implementation project(':concept-fetch') + + testImplementation project(':support-test') + + testImplementation ComponentsDependencies.androidx_test_junit + testImplementation ComponentsDependencies.testing_robolectric + testImplementation project(':tooling-fetch-tests') +} + +apply from: '../../../android-lint.gradle' +apply from: '../../../publish.gradle' +ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description) diff --git a/mobile/android/android-components/components/lib/fetch-okhttp/proguard-rules.pro b/mobile/android/android-components/components/lib/fetch-okhttp/proguard-rules.pro new file mode 100644 index 0000000000..f1b424510d --- /dev/null +++ b/mobile/android/android-components/components/lib/fetch-okhttp/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/mobile/android/android-components/components/lib/fetch-okhttp/src/main/AndroidManifest.xml b/mobile/android/android-components/components/lib/fetch-okhttp/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..e16cda1d34 --- /dev/null +++ b/mobile/android/android-components/components/lib/fetch-okhttp/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<manifest /> diff --git a/mobile/android/android-components/components/lib/fetch-okhttp/src/main/java/mozilla/components/lib/fetch/okhttp/OkHttpClient.kt b/mobile/android/android-components/components/lib/fetch-okhttp/src/main/java/mozilla/components/lib/fetch/okhttp/OkHttpClient.kt new file mode 100644 index 0000000000..0b885eee44 --- /dev/null +++ b/mobile/android/android-components/components/lib/fetch-okhttp/src/main/java/mozilla/components/lib/fetch/okhttp/OkHttpClient.kt @@ -0,0 +1,149 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package mozilla.components.lib.fetch.okhttp + +import android.content.Context +import mozilla.components.concept.fetch.BuildConfig +import mozilla.components.concept.fetch.Client +import mozilla.components.concept.fetch.Headers +import mozilla.components.concept.fetch.MutableHeaders +import mozilla.components.concept.fetch.Request +import mozilla.components.concept.fetch.Response +import mozilla.components.concept.fetch.isDataUri +import mozilla.components.lib.fetch.okhttp.OkHttpClient.Companion.CACHE_MAX_SIZE +import mozilla.components.lib.fetch.okhttp.OkHttpClient.Companion.getOrCreateCookieManager +import okhttp3.Cache +import okhttp3.CacheControl +import okhttp3.JavaNetCookieJar +import okhttp3.OkHttpClient +import okhttp3.RequestBody.Companion.toRequestBody +import java.net.CookieHandler +import java.net.CookieManager + +typealias RequestBuilder = okhttp3.Request.Builder + +/** + * [Client] implementation using OkHttp. + */ +class OkHttpClient( + private val client: OkHttpClient = OkHttpClient(), + private val context: Context? = null, +) : Client() { + private val defaultHeaders: Headers = MutableHeaders( + "User-Agent" to "MozacFetch/${BuildConfig.LIBRARY_VERSION}", + "Accept-Encoding" to "gzip", + ) + + override fun fetch(request: Request): Response { + if (request.private) { + throw IllegalArgumentException("Client doesn't support private request") + } + + if (request.isDataUri()) { + return fetchDataUri(request) + } + + val requestClient = client.rebuildFor(request, context) + + val requestBuilder = createRequestBuilderWithBody(request) + requestBuilder.addHeadersFrom(request, defaultHeaders = defaultHeaders) + + if (!request.useCaches) { + requestBuilder.cacheControl(CacheControl.FORCE_NETWORK) + } + + val actualResponse = requestClient.newCall( + requestBuilder.build(), + ).execute() + + return actualResponse.toResponse() + } + + companion object { + internal const val CACHE_MAX_SIZE: Long = 10L * 1024L * 1024L + + fun getOrCreateCookieManager(): CookieManager { + if (CookieHandler.getDefault() == null) { + CookieHandler.setDefault(CookieManager()) + } + return CookieHandler.getDefault() as CookieManager + } + } +} + +private fun OkHttpClient.rebuildFor(request: Request, context: Context?): OkHttpClient { + @Suppress("ComplexCondition") + if (request.connectTimeout != null || + request.readTimeout != null || + request.redirect != Request.Redirect.FOLLOW || + request.cookiePolicy != Request.CookiePolicy.OMIT + ) { + val clientBuilder = newBuilder() + + request.connectTimeout?.let { (timeout, unit) -> clientBuilder.connectTimeout(timeout, unit) } + request.readTimeout?.let { (timeout, unit) -> clientBuilder.readTimeout(timeout, unit) } + + if (request.redirect == Request.Redirect.MANUAL) { + clientBuilder.followRedirects(false) + } + + if (request.cookiePolicy == Request.CookiePolicy.INCLUDE) { + clientBuilder.cookieJar(JavaNetCookieJar(getOrCreateCookieManager())) + } + + context?.let { + clientBuilder.cache(Cache(context.cacheDir, CACHE_MAX_SIZE)) + } + + return clientBuilder.build() + } + + return this +} + +private fun okhttp3.Response.toResponse(): Response { + val body = body + val headers = translateHeaders(headers) + + return Response( + url = request.url.toString(), + headers = headers, + status = code, + body = if (body != null) Response.Body(body.byteStream(), headers["Content-Type"]) else Response.Body.empty(), + ) +} + +private fun createRequestBuilderWithBody(request: Request): RequestBuilder { + val requestBody = request.body?.useStream { it.readBytes() }?.let { + it.toRequestBody(null, 0, it.size) + } + + return RequestBuilder() + .url(request.url) + .method(request.method.name, requestBody) +} + +private fun RequestBuilder.addHeadersFrom(request: Request, defaultHeaders: Headers) { + defaultHeaders + .filter { header -> + request.headers?.contains(header.name) != true + }.filter { header -> + header.name != "Accept-Encoding" && header.value != "gzip" + }.forEach { header -> + addHeader(header.name, header.value) + } + + request.headers?.forEach { header -> addHeader(header.name, header.value) } +} + +private fun translateHeaders(actualHeaders: okhttp3.Headers): Headers { + val headers = MutableHeaders() + + for (i in 0 until actualHeaders.size) { + headers.append(actualHeaders.name(i), actualHeaders.value(i)) + } + + return headers +} diff --git a/mobile/android/android-components/components/lib/fetch-okhttp/src/test/java/mozilla/components/lib/fetch/okhttp/OkHttpFetchTestCases.kt b/mobile/android/android-components/components/lib/fetch-okhttp/src/test/java/mozilla/components/lib/fetch/okhttp/OkHttpFetchTestCases.kt new file mode 100644 index 0000000000..50610409c3 --- /dev/null +++ b/mobile/android/android-components/components/lib/fetch-okhttp/src/test/java/mozilla/components/lib/fetch/okhttp/OkHttpFetchTestCases.kt @@ -0,0 +1,27 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package mozilla.components.lib.fetch.okhttp + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import mozilla.components.concept.fetch.Client +import mozilla.components.support.test.robolectric.testContext +import mozilla.components.tooling.fetch.tests.FetchTestCases +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class OkHttpFetchTestCases : FetchTestCases() { + + override fun createNewClient(): Client = OkHttpClient(okhttp3.OkHttpClient(), testContext) + + // Inherits test methods from generic test suite base class + + @Test + fun `Client instance`() { + // We need at least one test case defined here so that this is recognized as test class. + assertTrue(createNewClient() is OkHttpClient) + } +} diff --git a/mobile/android/android-components/components/lib/fetch-okhttp/src/test/resources/robolectric.properties b/mobile/android/android-components/components/lib/fetch-okhttp/src/test/resources/robolectric.properties new file mode 100644 index 0000000000..932b01b9eb --- /dev/null +++ b/mobile/android/android-components/components/lib/fetch-okhttp/src/test/resources/robolectric.properties @@ -0,0 +1 @@ +sdk=28 |