Ladybird: Add new template Kotlin Android application without Qt
This template app from Android Studio should hopefully be more fun to work on than the Qt wrapped application we were using before. :^) It currently builds the native code using gradle rules, and has a stub WebViewImplementationNative class that will wrap a c++ class of the same name that inhertis from WebView::ViewImplementation. Spawning helper processes and creating proper views in Kotlin is next on the list.
Author: https://github.com/ADKaster Commit: https://github.com/SerenityOS/serenity/commit/7bc009d80f Pull-request: https://github.com/SerenityOS/serenity/pull/20915 Reviewed-by: https://github.com/bugaevc Reviewed-by: https://github.com/trflynn89
7
.gitignore
vendored
|
@ -30,6 +30,13 @@ sync-local.sh
|
||||||
.exrc
|
.exrc
|
||||||
.helix/
|
.helix/
|
||||||
|
|
||||||
|
# Gradle/AndroidStudio
|
||||||
|
.gradle/
|
||||||
|
.cxx/
|
||||||
|
local.properties
|
||||||
|
# We can't build from cmd.exe anyway
|
||||||
|
gradlew.bat
|
||||||
|
|
||||||
Userland/Libraries/LibWasm/Tests/Fixtures/SpecTests
|
Userland/Libraries/LibWasm/Tests/Fixtures/SpecTests
|
||||||
Userland/Libraries/LibWasm/Tests/Spec
|
Userland/Libraries/LibWasm/Tests/Spec
|
||||||
|
|
||||||
|
|
6
Ladybird/.gitignore
vendored
|
@ -1,12 +1,8 @@
|
||||||
.qmake.stash
|
.qmake.stash
|
||||||
Makefile
|
Makefile
|
||||||
ladybird
|
|
||||||
*.o
|
*.o
|
||||||
moc_*
|
moc_*
|
||||||
Build
|
Build
|
||||||
build
|
build
|
||||||
CMakeLists.txt.user
|
CMakeLists.txt.user
|
||||||
android/gradle
|
Android/src/main/assets/
|
||||||
android/gradlew*
|
|
||||||
android/assets/
|
|
||||||
|
|
||||||
|
|
78
Ladybird/Android/build.gradle.kts
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
import com.android.build.gradle.internal.tasks.factory.dependsOn
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("com.android.application")
|
||||||
|
id("org.jetbrains.kotlin.android")
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Move this somewhere nicer, with better behavior (like controlling host compiler)
|
||||||
|
task<Exec>("buildLagomTools") {
|
||||||
|
commandLine = listOf("sh", "-c", "cmake -S ../../Meta/Lagom -B $buildDir/lagom-tools " +
|
||||||
|
" -Dpackage=LagomTools -DCMAKE_INSTALL_PREFIX=$buildDir/lagom-tools-install -GNinja" +
|
||||||
|
" -DSERENITY_CACHE_DIR=$buildDir/caches;" +
|
||||||
|
" ninja -C $buildDir/lagom-tools install")
|
||||||
|
}
|
||||||
|
tasks.named("preBuild").dependsOn("buildLagomTools")
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "org.serenityos.ladybird"
|
||||||
|
compileSdk = 33
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId = "org.serenityos.ladybird"
|
||||||
|
minSdk = 30
|
||||||
|
targetSdk = 33
|
||||||
|
versionCode = 1
|
||||||
|
versionName = "1.0"
|
||||||
|
|
||||||
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
externalNativeBuild {
|
||||||
|
cmake {
|
||||||
|
cppFlags += "-std=c++20"
|
||||||
|
arguments += listOf(
|
||||||
|
"-DLagomTools_DIR=$buildDir/lagom-tools-install/share/LagomTools",
|
||||||
|
"-DSERENITY_CACHE_DIR=$buildDir/caches"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ndk {
|
||||||
|
// Specifies the ABI configurations of your native
|
||||||
|
// libraries Gradle should build and package with your app.
|
||||||
|
abiFilters += listOf("x86_64", "arm64-v8a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
isMinifyEnabled = false
|
||||||
|
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
externalNativeBuild {
|
||||||
|
cmake {
|
||||||
|
path = file("../CMakeLists.txt")
|
||||||
|
version = "3.27.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
viewBinding = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("androidx.core:core-ktx:1.10.1")
|
||||||
|
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||||
|
implementation("com.google.android.material:material:1.9.0")
|
||||||
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
|
testImplementation("junit:junit:4.13.2")
|
||||||
|
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||||
|
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||||
|
}
|
21
Ladybird/Android/proguard-rules.pro
vendored
Normal file
|
@ -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
|
41
Ladybird/Android/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:installLocation="auto"
|
||||||
|
android:versionCode="001"
|
||||||
|
android:versionName="head">
|
||||||
|
<supports-screens android:anyDensity="true"
|
||||||
|
android:largeScreens="true"
|
||||||
|
android:normalScreens="true"
|
||||||
|
android:smallScreens="true"/>
|
||||||
|
<application
|
||||||
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/Theme.Ladybird"
|
||||||
|
tools:targetApi="33"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:requestLegacyExternalStorage="true"
|
||||||
|
android:allowNativeHeapPointerTagging="false"
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:fullBackupOnly="false"
|
||||||
|
android:enableOnBackInvokedCallback="true">
|
||||||
|
<activity
|
||||||
|
android:name=".LadybirdActivity"
|
||||||
|
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:screenOrientation="unspecified"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data android:name="android.app.extract_android_style" android:value="minimal"/>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
<uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/>
|
||||||
|
</manifest>
|
18
Ladybird/Android/src/main/cpp/LadybirdActivity.cpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Ladybird/Utilities.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Java_org_serenityos_ladybird_LadybirdActivity_initNativeCode(JNIEnv* env, jobject /* thiz */, jstring resource_dir)
|
||||||
|
{
|
||||||
|
char const* raw_resource_dir = env->GetStringUTFChars(resource_dir, nullptr);
|
||||||
|
s_serenity_resource_root = raw_resource_dir;
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "Ladybird", "Serenity resource dir is %s", s_serenity_resource_root.characters());
|
||||||
|
env->ReleaseStringUTFChars(resource_dir, raw_resource_dir);
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibWebView/ViewImplementation.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
using namespace WebView;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class WebViewImplementationNative : public WebView::ViewImplementation {
|
||||||
|
public:
|
||||||
|
virtual Gfx::IntRect viewport_rect() const override { return {}; }
|
||||||
|
virtual Gfx::IntPoint to_content_position(Gfx::IntPoint) const override { return {}; }
|
||||||
|
virtual Gfx::IntPoint to_widget_position(Gfx::IntPoint) const override { return {}; }
|
||||||
|
virtual void update_zoom() override { }
|
||||||
|
|
||||||
|
static jclass global_class_reference;
|
||||||
|
static jfieldID instance_pointer_field;
|
||||||
|
};
|
||||||
|
jclass WebViewImplementationNative::global_class_reference;
|
||||||
|
jfieldID WebViewImplementationNative::instance_pointer_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Java_org_serenityos_ladybird_WebViewImplementationNative_00024Companion_nativeClassInit(JNIEnv* env, jobject /* thiz */)
|
||||||
|
{
|
||||||
|
auto local_class = env->FindClass("org/serenityos/ladybird/WebViewImplementationNative");
|
||||||
|
if (!local_class)
|
||||||
|
TODO();
|
||||||
|
WebViewImplementationNative::global_class_reference = reinterpret_cast<jclass>(env->NewGlobalRef(local_class));
|
||||||
|
|
||||||
|
auto field = env->GetFieldID(WebViewImplementationNative::global_class_reference, "nativeInstance", "J");
|
||||||
|
if (!field)
|
||||||
|
TODO();
|
||||||
|
WebViewImplementationNative::instance_pointer_field = field;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
|
Java_org_serenityos_ladybird_WebViewImplementationNative_nativeObjectInit(JNIEnv*, jobject /* thiz */)
|
||||||
|
{
|
||||||
|
auto instance = reinterpret_cast<jlong>(new WebViewImplementationNative);
|
||||||
|
__android_log_print(ANDROID_LOG_DEBUG, "Ladybird", "New WebViewImplementationNative at %p", reinterpret_cast<void*>(instance));
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Java_org_serenityos_ladybird_WebViewImplementationNative_nativeObjectDispose(JNIEnv*, jobject /* thiz */, jlong instance)
|
||||||
|
{
|
||||||
|
delete reinterpret_cast<WebViewImplementationNative*>(instance);
|
||||||
|
__android_log_print(ANDROID_LOG_DEBUG, "Ladybird", "Destroyed WebViewImplementationNative at %p", reinterpret_cast<void*>(instance));
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.serenityos.ladybird
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.TextView
|
||||||
|
import org.serenityos.ladybird.databinding.ActivityMainBinding
|
||||||
|
import org.serenityos.ladybird.TransferAssets
|
||||||
|
|
||||||
|
class LadybirdActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private lateinit var binding: ActivityMainBinding
|
||||||
|
private lateinit var resourceDir: String
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
resourceDir = TransferAssets.transferAssets(this)
|
||||||
|
initNativeCode(resourceDir)
|
||||||
|
view = WebViewImplementationNative()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
view.dispose()
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var view: WebViewImplementationNative
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A native method that is implemented by the 'ladybird' native library,
|
||||||
|
* which is packaged with this application.
|
||||||
|
*/
|
||||||
|
private external fun initNativeCode(resourceDir: String)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// Used to load the 'ladybird' library on application startup.
|
||||||
|
init {
|
||||||
|
System.loadLibrary("ladybird")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
|
||||||
|
* <p>
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.serenityos.ladybird;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.AssetManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import java.lang.String;
|
||||||
|
|
||||||
|
public class TransferAssets {
|
||||||
|
/**
|
||||||
|
@return new ladybird resource root
|
||||||
|
*/
|
||||||
|
static public String transferAssets(Context context) {
|
||||||
|
Log.d("Ladybird", "Hello from java");
|
||||||
|
Context applicationContext = context.getApplicationContext();
|
||||||
|
File assetDir = applicationContext.getFilesDir();
|
||||||
|
AssetManager assetManager = applicationContext.getAssets();
|
||||||
|
if (!copyAsset(assetManager, "ladybird-assets.tar", assetDir.getAbsolutePath() + "/ladybird-assets.tar")) {
|
||||||
|
Log.e("Ladybird", "Unable to copy assets");
|
||||||
|
return "Invalid Assets, this won't work";
|
||||||
|
}
|
||||||
|
Log.d("Ladybird", "Copied ladybird-assets.tar to app-specific storage path");
|
||||||
|
return assetDir.getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ty to https://stackoverflow.com/a/22903693 for the sauce
|
||||||
|
private static boolean copyAsset(AssetManager assetManager,
|
||||||
|
String fromAssetPath, String toPath) {
|
||||||
|
try {
|
||||||
|
InputStream in = assetManager.open(fromAssetPath);
|
||||||
|
new File(toPath).createNewFile();
|
||||||
|
OutputStream out = new FileOutputStream(toPath);
|
||||||
|
copyFile(in, out);
|
||||||
|
in.close();
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void copyFile(InputStream in, OutputStream out) throws IOException {
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int read;
|
||||||
|
while ((read = in.read(buffer)) != -1) {
|
||||||
|
out.write(buffer, 0, read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.serenityos.ladybird
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around WebView::ViewImplementation for use by Kotlin
|
||||||
|
*/
|
||||||
|
class WebViewImplementationNative {
|
||||||
|
// Instance Pointer to native object, very unsafe :)
|
||||||
|
private var nativeInstance = nativeObjectInit()
|
||||||
|
|
||||||
|
init {
|
||||||
|
Log.d(
|
||||||
|
"Ladybird",
|
||||||
|
"New WebViewImplementationNative (Kotlin) with nativeInstance ${this.nativeInstance}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dispose() {
|
||||||
|
nativeObjectDispose(nativeInstance)
|
||||||
|
nativeInstance = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private external fun nativeObjectInit(): Long
|
||||||
|
private external fun nativeObjectDispose(instance: Long)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/*
|
||||||
|
* We use a static class initializer to allow the native code to cache some
|
||||||
|
* field offsets. This native function looks up and caches interesting
|
||||||
|
* class/field/method IDs. Throws on failure.
|
||||||
|
*/
|
||||||
|
private external fun nativeClassInit()
|
||||||
|
|
||||||
|
init {
|
||||||
|
nativeClassInit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,170 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<path
|
||||||
|
android:fillColor="#3DDC84"
|
||||||
|
android:pathData="M0,0h108v108h-108z" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M9,0L9,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,0L19,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,0L29,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,0L39,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,0L49,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,0L59,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,0L69,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,0L79,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M89,0L89,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M99,0L99,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,9L108,9"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,19L108,19"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,29L108,29"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,39L108,39"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,49L108,49"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,59L108,59"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,69L108,69"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,79L108,79"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,89L108,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,99L108,99"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,29L89,29"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,39L89,39"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,49L89,49"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,59L89,59"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,69L89,69"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,79L89,79"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,19L29,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,19L39,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,19L49,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,19L59,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,19L69,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,19L79,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
</vector>
|
|
@ -0,0 +1,30 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:endX="85.84757"
|
||||||
|
android:endY="92.4963"
|
||||||
|
android:startX="42.9492"
|
||||||
|
android:startY="49.59793"
|
||||||
|
android:type="linear">
|
||||||
|
<item
|
||||||
|
android:color="#44000000"
|
||||||
|
android:offset="0.0" />
|
||||||
|
<item
|
||||||
|
android:color="#00000000"
|
||||||
|
android:offset="1.0" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||||
|
android:strokeWidth="1"
|
||||||
|
android:strokeColor="#00000000" />
|
||||||
|
</vector>
|
19
Ladybird/Android/src/main/res/layout/activity_main.xml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sample_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Hello World!"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background" />
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
|
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
|
</adaptive-icon>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background" />
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
|
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
|
</adaptive-icon>
|
BIN
Ladybird/Android/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
Ladybird/Android/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
Ladybird/Android/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 982 B |
BIN
Ladybird/Android/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
Ladybird/Android/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.8 KiB |
BIN
Ladybird/Android/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
BIN
Ladybird/Android/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 7.6 KiB |
16
Ladybird/Android/src/main/res/values-night/themes.xml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="Theme.Ladybird" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
|
<!-- Primary brand color. -->
|
||||||
|
<item name="colorPrimary">@color/purple_200</item>
|
||||||
|
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||||
|
<item name="colorOnPrimary">@color/black</item>
|
||||||
|
<!-- Secondary brand color. -->
|
||||||
|
<item name="colorSecondary">@color/teal_200</item>
|
||||||
|
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||||
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
|
<!-- Status bar color. -->
|
||||||
|
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
</style>
|
||||||
|
</resources>
|
10
Ladybird/Android/src/main/res/values/colors.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="purple_200">#FFBB86FC</color>
|
||||||
|
<color name="purple_500">#FF6200EE</color>
|
||||||
|
<color name="purple_700">#FF3700B3</color>
|
||||||
|
<color name="teal_200">#FF03DAC5</color>
|
||||||
|
<color name="teal_700">#FF018786</color>
|
||||||
|
<color name="black">#FF000000</color>
|
||||||
|
<color name="white">#FFFFFFFF</color>
|
||||||
|
</resources>
|
3
Ladybird/Android/src/main/res/values/strings.xml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">Ladybird</string>
|
||||||
|
</resources>
|
16
Ladybird/Android/src/main/res/values/themes.xml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="Theme.Ladybird" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
|
<!-- Primary brand color. -->
|
||||||
|
<item name="colorPrimary">@color/purple_500</item>
|
||||||
|
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||||
|
<item name="colorOnPrimary">@color/white</item>
|
||||||
|
<!-- Secondary brand color. -->
|
||||||
|
<item name="colorSecondary">@color/teal_200</item>
|
||||||
|
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||||
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
|
<!-- Status bar color. -->
|
||||||
|
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
</style>
|
||||||
|
</resources>
|
13
Ladybird/Android/src/main/res/xml/backup_rules.xml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Sample backup rules file; uncomment and customize as necessary.
|
||||||
|
See https://developer.android.com/guide/topics/data/autobackup
|
||||||
|
for details.
|
||||||
|
Note: This file is ignored for devices older that API 31
|
||||||
|
See https://developer.android.com/about/versions/12/backup-restore
|
||||||
|
-->
|
||||||
|
<full-backup-content>
|
||||||
|
<!--
|
||||||
|
<include domain="sharedpref" path="."/>
|
||||||
|
<exclude domain="sharedpref" path="device.xml"/>
|
||||||
|
-->
|
||||||
|
</full-backup-content>
|
19
Ladybird/Android/src/main/res/xml/data_extraction_rules.xml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Sample data extraction rules file; uncomment and customize as necessary.
|
||||||
|
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||||
|
for details.
|
||||||
|
-->
|
||||||
|
<data-extraction-rules>
|
||||||
|
<cloud-backup>
|
||||||
|
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
||||||
|
<include .../>
|
||||||
|
<exclude .../>
|
||||||
|
-->
|
||||||
|
</cloud-backup>
|
||||||
|
<!--
|
||||||
|
<device-transfer>
|
||||||
|
<include .../>
|
||||||
|
<exclude .../>
|
||||||
|
</device-transfer>
|
||||||
|
-->
|
||||||
|
</data-extraction-rules>
|
|
@ -75,6 +75,10 @@ add_compile_options(-Wno-expansion-to-defined)
|
||||||
add_compile_options(-Wno-user-defined-literals)
|
add_compile_options(-Wno-user-defined-literals)
|
||||||
|
|
||||||
serenity_option(ENABLE_QT ON CACHE BOOL "Build ladybird application using Qt GUI")
|
serenity_option(ENABLE_QT ON CACHE BOOL "Build ladybird application using Qt GUI")
|
||||||
|
if (ANDROID AND ENABLE_QT)
|
||||||
|
message(STATUS "Disabling Qt for Android")
|
||||||
|
set(ENABLE_QT OFF CACHE BOOL "" FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (ENABLE_QT)
|
if (ENABLE_QT)
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
@ -140,6 +144,13 @@ elseif (APPLE)
|
||||||
-fobjc-arc
|
-fobjc-arc
|
||||||
-Wno-deprecated-anon-enum-enum-conversion # Required for CGImageCreate
|
-Wno-deprecated-anon-enum-enum-conversion # Required for CGImageCreate
|
||||||
)
|
)
|
||||||
|
elseif(ANDROID)
|
||||||
|
add_library(ladybird SHARED
|
||||||
|
${SOURCES}
|
||||||
|
Android/src/main/cpp/LadybirdActivity.cpp
|
||||||
|
Android/src/main/cpp/WebViewImplementationNative.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries(ladybird PRIVATE log)
|
||||||
else()
|
else()
|
||||||
# TODO: Check for other GUI frameworks here when we move them in-tree
|
# TODO: Check for other GUI frameworks here when we move them in-tree
|
||||||
# For now, we can export a static library of common files for chromes to link to
|
# For now, we can export a static library of common files for chromes to link to
|
||||||
|
@ -168,7 +179,6 @@ target_link_libraries(headless-browser PRIVATE LibWeb LibWebView LibWebSocket Li
|
||||||
|
|
||||||
if (ANDROID)
|
if (ANDROID)
|
||||||
include(cmake/AndroidExtras.cmake)
|
include(cmake/AndroidExtras.cmake)
|
||||||
link_android_libs(headless-browser)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_target(run${LADYBIRD_CUSTOM_TARGET_SUFFIX}
|
add_custom_target(run${LADYBIRD_CUSTOM_TARGET_SUFFIX}
|
||||||
|
|
|
@ -1,198 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <AK/DeprecatedString.h>
|
|
||||||
#include <AK/LexicalPath.h>
|
|
||||||
#include <AK/Platform.h>
|
|
||||||
#include <AK/ScopeGuard.h>
|
|
||||||
#include <LibArchive/Tar.h>
|
|
||||||
#include <LibArchive/TarStream.h>
|
|
||||||
#include <LibCompress/Gzip.h>
|
|
||||||
#include <LibCore/Directory.h>
|
|
||||||
#include <LibCore/System.h>
|
|
||||||
#include <LibFileSystem/FileSystem.h>
|
|
||||||
#include <LibMain/Main.h>
|
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QJniObject>
|
|
||||||
#include <QSslSocket>
|
|
||||||
|
|
||||||
#ifndef AK_OS_ANDROID
|
|
||||||
# error This file is for Android only, check CMake config!
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// HACK ALERT, we need to include LibMain manually here because the Qt build system doesn't include LibMain.a in the actual executable,
|
|
||||||
// nor include it in libladybird_<arch>.so
|
|
||||||
#include <LibMain/Main.cpp> // NOLINT(bugprone-suspicious-include)
|
|
||||||
|
|
||||||
extern DeprecatedString s_serenity_resource_root;
|
|
||||||
|
|
||||||
void android_platform_init();
|
|
||||||
static void extract_ladybird_resources();
|
|
||||||
static ErrorOr<void> extract_tar_archive(String archive_file, DeprecatedString output_directory);
|
|
||||||
|
|
||||||
void android_platform_init()
|
|
||||||
{
|
|
||||||
qDebug() << "Device supports OpenSSL: " << QSslSocket::supportsSsl();
|
|
||||||
|
|
||||||
QJniObject res = QJniObject::callStaticMethod<jstring>("org/serenityos/ladybird/TransferAssets",
|
|
||||||
"transferAssets",
|
|
||||||
"(Landroid/content/Context;)Ljava/lang/String;",
|
|
||||||
QNativeInterface::QAndroidApplication::context());
|
|
||||||
s_serenity_resource_root = res.toString().toUtf8().data();
|
|
||||||
|
|
||||||
extract_ladybird_resources();
|
|
||||||
}
|
|
||||||
|
|
||||||
void extract_ladybird_resources()
|
|
||||||
{
|
|
||||||
qDebug() << "serenity resource root is " << s_serenity_resource_root.characters();
|
|
||||||
auto file_or_error = Core::System::open(DeprecatedString::formatted("{}/res/icons/16x16/app-browser.png", s_serenity_resource_root), O_RDONLY);
|
|
||||||
if (file_or_error.is_error()) {
|
|
||||||
qDebug() << "Unable to open test file file as expected, extracting asssets...";
|
|
||||||
|
|
||||||
MUST(extract_tar_archive(MUST(String::formatted("{}/ladybird-assets.tar", s_serenity_resource_root)), s_serenity_resource_root));
|
|
||||||
} else {
|
|
||||||
qDebug() << "Opened app-browser.png test file, good to go!";
|
|
||||||
qDebug() << "Hopefully no developer changed the asset files and expected them to be re-extracted!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorOr<void> extract_tar_archive(String archive_file, DeprecatedString output_directory)
|
|
||||||
{
|
|
||||||
constexpr size_t buffer_size = 4096;
|
|
||||||
|
|
||||||
auto file = TRY(Core::InputBufferedFile::create(TRY(Core::File::open(archive_file, Core::File::OpenMode::Read))));
|
|
||||||
|
|
||||||
DeprecatedString old_pwd = TRY(Core::System::getcwd());
|
|
||||||
|
|
||||||
TRY(Core::System::chdir(output_directory));
|
|
||||||
ScopeGuard go_back = [&old_pwd] { MUST(Core::System::chdir(old_pwd)); };
|
|
||||||
|
|
||||||
auto tar_stream = TRY(Archive::TarInputStream::construct(make<Compress::GzipCompressor>(move(file))));
|
|
||||||
|
|
||||||
HashMap<DeprecatedString, DeprecatedString> global_overrides;
|
|
||||||
HashMap<DeprecatedString, DeprecatedString> local_overrides;
|
|
||||||
|
|
||||||
auto get_override = [&](StringView key) -> Optional<DeprecatedString> {
|
|
||||||
Optional<DeprecatedString> maybe_local = local_overrides.get(key);
|
|
||||||
|
|
||||||
if (maybe_local.has_value())
|
|
||||||
return maybe_local;
|
|
||||||
|
|
||||||
Optional<DeprecatedString> maybe_global = global_overrides.get(key);
|
|
||||||
|
|
||||||
if (maybe_global.has_value())
|
|
||||||
return maybe_global;
|
|
||||||
|
|
||||||
return {};
|
|
||||||
};
|
|
||||||
|
|
||||||
while (!tar_stream->finished()) {
|
|
||||||
Archive::TarFileHeader const& header = tar_stream->header();
|
|
||||||
|
|
||||||
// Handle meta-entries earlier to avoid consuming the file content stream.
|
|
||||||
if (header.content_is_like_extended_header()) {
|
|
||||||
switch (header.type_flag()) {
|
|
||||||
case Archive::TarFileType::GlobalExtendedHeader: {
|
|
||||||
TRY(tar_stream->for_each_extended_header([&](StringView key, StringView value) {
|
|
||||||
if (value.length() == 0)
|
|
||||||
global_overrides.remove(key);
|
|
||||||
else
|
|
||||||
global_overrides.set(key, value);
|
|
||||||
}));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Archive::TarFileType::ExtendedHeader: {
|
|
||||||
TRY(tar_stream->for_each_extended_header([&](StringView key, StringView value) {
|
|
||||||
local_overrides.set(key, value);
|
|
||||||
}));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
warnln("Unknown extended header type '{}' of {}", (char)header.type_flag(), header.filename());
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
TRY(tar_stream->advance());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Archive::TarFileStream file_stream = tar_stream->file_contents();
|
|
||||||
|
|
||||||
// Handle other header types that don't just have an effect on extraction.
|
|
||||||
switch (header.type_flag()) {
|
|
||||||
case Archive::TarFileType::LongName: {
|
|
||||||
StringBuilder long_name;
|
|
||||||
|
|
||||||
Array<u8, buffer_size> buffer;
|
|
||||||
|
|
||||||
while (!file_stream.is_eof()) {
|
|
||||||
auto slice = TRY(file_stream.read_some(buffer));
|
|
||||||
long_name.append(reinterpret_cast<char*>(slice.data()), slice.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
local_overrides.set("path", long_name.to_deprecated_string());
|
|
||||||
TRY(tar_stream->advance());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// None of the relevant headers, so continue as normal.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
LexicalPath path = LexicalPath(header.filename());
|
|
||||||
if (!header.prefix().is_empty())
|
|
||||||
path = path.prepend(header.prefix());
|
|
||||||
DeprecatedString filename = get_override("path"sv).value_or(path.string());
|
|
||||||
|
|
||||||
DeprecatedString absolute_path = TRY(FileSystem::absolute_path(filename)).to_deprecated_string();
|
|
||||||
auto parent_path = LexicalPath(absolute_path).parent();
|
|
||||||
auto header_mode = TRY(header.mode());
|
|
||||||
|
|
||||||
switch (header.type_flag()) {
|
|
||||||
case Archive::TarFileType::NormalFile:
|
|
||||||
case Archive::TarFileType::AlternateNormalFile: {
|
|
||||||
MUST(Core::Directory::create(parent_path, Core::Directory::CreateDirectories::Yes));
|
|
||||||
|
|
||||||
int fd = TRY(Core::System::open(absolute_path, O_CREAT | O_WRONLY, header_mode));
|
|
||||||
|
|
||||||
Array<u8, buffer_size> buffer;
|
|
||||||
while (!file_stream.is_eof()) {
|
|
||||||
auto slice = TRY(file_stream.read_some(buffer));
|
|
||||||
TRY(Core::System::write(fd, slice));
|
|
||||||
}
|
|
||||||
|
|
||||||
TRY(Core::System::close(fd));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Archive::TarFileType::SymLink: {
|
|
||||||
MUST(Core::Directory::create(parent_path, Core::Directory::CreateDirectories::Yes));
|
|
||||||
|
|
||||||
TRY(Core::System::symlink(header.link_name(), absolute_path));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Archive::TarFileType::Directory: {
|
|
||||||
MUST(Core::Directory::create(parent_path, Core::Directory::CreateDirectories::Yes));
|
|
||||||
|
|
||||||
auto result_or_error = Core::System::mkdir(absolute_path, header_mode);
|
|
||||||
if (result_or_error.is_error() && result_or_error.error().code() != EEXIST)
|
|
||||||
return result_or_error.release_error();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// FIXME: Implement other file types
|
|
||||||
warnln("file type '{}' of {} is not yet supported", (char)header.type_flag(), header.filename());
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Non-global headers should be cleared after every file.
|
|
||||||
local_overrides.clear();
|
|
||||||
|
|
||||||
TRY(tar_stream->advance());
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
|
@ -19,9 +19,6 @@ add_executable(RequestServer ${REQUESTSERVER_SOURCES})
|
||||||
target_include_directories(RequestServer PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/)
|
target_include_directories(RequestServer PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/)
|
||||||
target_include_directories(RequestServer PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..)
|
target_include_directories(RequestServer PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..)
|
||||||
target_link_libraries(RequestServer PRIVATE LibCore LibMain LibCrypto LibFileSystem LibGemini LibHTTP LibIPC LibMain LibTLS LibWebView)
|
target_link_libraries(RequestServer PRIVATE LibCore LibMain LibCrypto LibFileSystem LibGemini LibHTTP LibIPC LibMain LibTLS LibWebView)
|
||||||
if (ANDROID)
|
|
||||||
link_android_libs(RequestServer)
|
|
||||||
endif()
|
|
||||||
if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||||
# Solaris has socket and networking related functions in two extra libraries
|
# Solaris has socket and networking related functions in two extra libraries
|
||||||
target_link_libraries(RequestServer PRIVATE nsl socket)
|
target_link_libraries(RequestServer PRIVATE nsl socket)
|
||||||
|
|
|
@ -22,10 +22,6 @@ ErrorOr<String> application_directory()
|
||||||
|
|
||||||
void platform_init()
|
void platform_init()
|
||||||
{
|
{
|
||||||
#ifdef AK_OS_ANDROID
|
|
||||||
extern void android_platform_init();
|
|
||||||
android_platform_init();
|
|
||||||
#else
|
|
||||||
s_serenity_resource_root = [] {
|
s_serenity_resource_root = [] {
|
||||||
auto const* source_dir = getenv("SERENITY_SOURCE_DIR");
|
auto const* source_dir = getenv("SERENITY_SOURCE_DIR");
|
||||||
if (source_dir) {
|
if (source_dir) {
|
||||||
|
@ -37,13 +33,12 @@ void platform_init()
|
||||||
if (FileSystem::is_directory(home_lagom))
|
if (FileSystem::is_directory(home_lagom))
|
||||||
return home_lagom;
|
return home_lagom;
|
||||||
auto app_dir = application_directory().release_value_but_fixme_should_propagate_errors().to_deprecated_string();
|
auto app_dir = application_directory().release_value_but_fixme_should_propagate_errors().to_deprecated_string();
|
||||||
# ifdef AK_OS_MACOS
|
#ifdef AK_OS_MACOS
|
||||||
return LexicalPath(app_dir).parent().append("Resources"sv).string();
|
return LexicalPath(app_dir).parent().append("Resources"sv).string();
|
||||||
# else
|
#else
|
||||||
return LexicalPath(app_dir).parent().append("share"sv).string();
|
return LexicalPath(app_dir).parent().append("share"sv).string();
|
||||||
# endif
|
|
||||||
}();
|
|
||||||
#endif
|
#endif
|
||||||
|
}();
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<Vector<String>> get_paths_for_helper_process(StringView process_name)
|
ErrorOr<Vector<String>> get_paths_for_helper_process(StringView process_name)
|
||||||
|
|
|
@ -56,9 +56,6 @@ endif()
|
||||||
target_include_directories(WebContent PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/)
|
target_include_directories(WebContent PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/)
|
||||||
target_include_directories(WebContent PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..)
|
target_include_directories(WebContent PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..)
|
||||||
target_link_libraries(WebContent PRIVATE LibAudio LibCore LibFileSystem LibGfx LibIPC LibJS LibMain LibWeb LibWebSocket LibProtocol LibWebView)
|
target_link_libraries(WebContent PRIVATE LibAudio LibCore LibFileSystem LibGfx LibIPC LibJS LibMain LibWeb LibWebSocket LibProtocol LibWebView)
|
||||||
if (ANDROID)
|
|
||||||
link_android_libs(WebContent)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (HAVE_PULSEAUDIO)
|
if (HAVE_PULSEAUDIO)
|
||||||
target_compile_definitions(WebContent PRIVATE HAVE_PULSEAUDIO=1)
|
target_compile_definitions(WebContent PRIVATE HAVE_PULSEAUDIO=1)
|
||||||
|
|
|
@ -16,6 +16,3 @@ target_include_directories(WebDriver PRIVATE ${SERENITY_SOURCE_DIR}/Userland)
|
||||||
target_include_directories(WebDriver PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services)
|
target_include_directories(WebDriver PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services)
|
||||||
target_link_libraries(WebDriver PRIVATE LibCore LibFileSystem LibGfx LibIPC LibJS LibMain LibWeb LibWebSocket)
|
target_link_libraries(WebDriver PRIVATE LibCore LibFileSystem LibGfx LibIPC LibJS LibMain LibWeb LibWebSocket)
|
||||||
add_dependencies(WebDriver headless-browser)
|
add_dependencies(WebDriver headless-browser)
|
||||||
if (ANDROID)
|
|
||||||
link_android_libs(WebDriver)
|
|
||||||
endif()
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.serenityos.ladybird" android:installLocation="auto" android:versionCode="001" android:versionName="head">
|
|
||||||
<!-- %%INSERT_PERMISSIONS -->
|
|
||||||
<!-- %%INSERT_FEATURES -->
|
|
||||||
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true"/>
|
|
||||||
<application android:name="org.qtproject.qt.android.bindings.QtApplication" android:hardwareAccelerated="true" android:label="ladybird" android:requestLegacyExternalStorage="true" android:allowNativeHeapPointerTagging="false" android:allowBackup="true" android:fullBackupOnly="false" android:enableOnBackInvokedCallback="true">
|
|
||||||
<activity android:name="org.qtproject.qt.android.bindings.QtActivity" android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:label="ladybird" android:launchMode="singleTop" android:screenOrientation="unspecified" android:exported="true">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
|
||||||
</intent-filter>
|
|
||||||
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
|
|
||||||
<meta-data android:name="android.app.arguments" android:value="-- %%INSERT_APP_ARGUMENTS%% --"/>
|
|
||||||
<meta-data android:name="android.app.extract_android_style" android:value="minimal"/>
|
|
||||||
</activity>
|
|
||||||
</application>
|
|
||||||
<uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/>
|
|
||||||
</manifest>
|
|
|
@ -1,21 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8'?>
|
|
||||||
<resources>
|
|
||||||
<!-- DO NOT EDIT THIS: This file is populated automatically by the deployment tool. -->
|
|
||||||
|
|
||||||
<array name="bundled_libs">
|
|
||||||
<!-- %%INSERT_EXTRA_LIBS%% -->
|
|
||||||
</array>
|
|
||||||
|
|
||||||
<array name="qt_libs">
|
|
||||||
<!-- %%INSERT_QT_LIBS%% -->
|
|
||||||
</array>
|
|
||||||
|
|
||||||
<array name="load_local_libs">
|
|
||||||
<!-- %%INSERT_LOCAL_LIBS%% -->
|
|
||||||
</array>
|
|
||||||
|
|
||||||
<string name="static_init_classes"><!-- %%INSERT_INIT_CLASSES%% --></string>
|
|
||||||
<string name="use_local_qt_libs"><!-- %%USE_LOCAL_QT_LIBS%% --></string>
|
|
||||||
<string name="bundle_local_qt_libs"><!-- %%BUNDLE_LOCAL_QT_LIBS%% --></string>
|
|
||||||
<string name="system_libs_prefix"><!-- %%SYSTEM_LIBS_PREFIX%% --></string>
|
|
||||||
</resources>
|
|
|
@ -1,69 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.serenityos.ladybird;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.AssetManager;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
import java.lang.String;
|
|
||||||
|
|
||||||
public class TransferAssets
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
@returns new ladybird resource root
|
|
||||||
*/
|
|
||||||
static public String transferAssets(Context context)
|
|
||||||
{
|
|
||||||
Log.d("Ladybird", "Hello from java");
|
|
||||||
Context applicationContext = context.getApplicationContext();
|
|
||||||
File assetDir = applicationContext.getFilesDir();
|
|
||||||
AssetManager assetManager = applicationContext.getAssets();
|
|
||||||
if (!copyAsset(assetManager, "ladybird-assets.tar", assetDir.getAbsolutePath() + "/ladybird-assets.tar")) {
|
|
||||||
Log.e("Ladybird", "Unable to copy assets");
|
|
||||||
return "Invalid Assets, this won't work";
|
|
||||||
}
|
|
||||||
Log.d("Ladybird", "Copied ladybird-assets.tar to app-specific storage path");
|
|
||||||
return assetDir.getAbsolutePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ty to https://stackoverflow.com/a/22903693 for the sauce
|
|
||||||
private static boolean copyAsset(AssetManager assetManager,
|
|
||||||
String fromAssetPath, String toPath) {
|
|
||||||
InputStream in = null;
|
|
||||||
OutputStream out = null;
|
|
||||||
try {
|
|
||||||
in = assetManager.open(fromAssetPath);
|
|
||||||
new File(toPath).createNewFile();
|
|
||||||
out = new FileOutputStream(toPath);
|
|
||||||
copyFile(in, out);
|
|
||||||
in.close();
|
|
||||||
in = null;
|
|
||||||
out.flush();
|
|
||||||
out.close();
|
|
||||||
out = null;
|
|
||||||
return true;
|
|
||||||
} catch(Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void copyFile(InputStream in, OutputStream out) throws IOException {
|
|
||||||
byte[] buffer = new byte[4096];
|
|
||||||
int read;
|
|
||||||
while((read = in.read(buffer)) != -1){
|
|
||||||
out.write(buffer, 0, read);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -3,42 +3,6 @@
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
#
|
#
|
||||||
|
|
||||||
#
|
|
||||||
# Source directory for androiddeployqt to use when bundling the application
|
|
||||||
#
|
|
||||||
set_property(TARGET ladybird APPEND PROPERTY
|
|
||||||
QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android
|
|
||||||
)
|
|
||||||
|
|
||||||
#
|
|
||||||
# Android-specific sources and libs
|
|
||||||
#
|
|
||||||
add_library(android_init STATIC AndroidPlatform.cpp)
|
|
||||||
target_link_libraries(android_init PUBLIC Qt::Core Qt::Gui Qt::Network LibCompress LibArchive LibFileSystem)
|
|
||||||
|
|
||||||
macro(link_android_libs target)
|
|
||||||
target_link_libraries(${target} PRIVATE android_init)
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
#
|
|
||||||
# NDK and Qt don't ship OpenSSL for Android
|
|
||||||
# Download the prebuilt binaries from KDAB for inclusion as recommended in Qt docs.
|
|
||||||
#
|
|
||||||
include(FetchContent)
|
|
||||||
FetchContent_Declare(android_openssl
|
|
||||||
GIT_REPOSITORY https://github.com/KDAB/android_openssl
|
|
||||||
GIT_TAG origin/master
|
|
||||||
GIT_SHALLOW TRUE
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(android_openssl)
|
|
||||||
link_android_libs(ladybird)
|
|
||||||
target_link_libraries(ladybird PRIVATE Qt::Network)
|
|
||||||
set_property(TARGET ladybird APPEND PROPERTY QT_ANDROID_EXTRA_LIBS ${ANDROID_EXTRA_LIBS}
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/WebContent/libWebContent_${ANDROID_ABI}.so"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/SQLServer/libSQLServer_${ANDROID_ABI}.so"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/WebDriver/libWebDriver_${ANDROID_ABI}.so"
|
|
||||||
)
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copy resources into tarball for inclusion in /assets of APK
|
# Copy resources into tarball for inclusion in /assets of APK
|
||||||
#
|
#
|
||||||
|
@ -70,6 +34,6 @@ add_custom_target(copy-content-filters
|
||||||
"asset-bundle/res/ladybird/BrowserContentFilters.txt"
|
"asset-bundle/res/ladybird/BrowserContentFilters.txt"
|
||||||
)
|
)
|
||||||
add_dependencies(archive-assets copy-autoplay-allowlist copy-content-filters)
|
add_dependencies(archive-assets copy-autoplay-allowlist copy-content-filters)
|
||||||
add_custom_target(copy-assets COMMAND ${CMAKE_COMMAND} -E copy_if_different ladybird-assets.tar.gz "${CMAKE_SOURCE_DIR}/android/assets/")
|
add_custom_target(copy-assets COMMAND ${CMAKE_COMMAND} -E copy_if_different ladybird-assets.tar.gz "${CMAKE_SOURCE_DIR}/Android/src/main/assets/")
|
||||||
add_dependencies(copy-assets archive-assets)
|
add_dependencies(copy-assets archive-assets)
|
||||||
add_dependencies(ladybird copy-assets)
|
add_dependencies(ladybird copy-assets)
|
||||||
|
|
|
@ -7,10 +7,6 @@ set(package ladybird)
|
||||||
set(ladybird_applications ladybird SQLServer WebContent WebDriver WebSocketServer RequestServer headless-browser)
|
set(ladybird_applications ladybird SQLServer WebContent WebDriver WebSocketServer RequestServer headless-browser)
|
||||||
|
|
||||||
set(app_install_targets ${ladybird_applications})
|
set(app_install_targets ${ladybird_applications})
|
||||||
if (ANDROID)
|
|
||||||
# androiddeployqt will get confused with duplicate resources if we install every app
|
|
||||||
set(app_install_targets ladybird)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
install(TARGETS ${app_install_targets}
|
install(TARGETS ${app_install_targets}
|
||||||
EXPORT ladybirdTargets
|
EXPORT ladybirdTargets
|
||||||
|
@ -37,6 +33,9 @@ foreach (application IN LISTS ladybird_applications)
|
||||||
endforeach()
|
endforeach()
|
||||||
list(REMOVE_DUPLICATES all_required_lagom_libraries)
|
list(REMOVE_DUPLICATES all_required_lagom_libraries)
|
||||||
|
|
||||||
|
# Remove ladybird shlib if it exists
|
||||||
|
list(REMOVE_ITEM all_required_lagom_libraries ladybird)
|
||||||
|
|
||||||
# Install webcontent impl library if it exists
|
# Install webcontent impl library if it exists
|
||||||
if (TARGET webcontent)
|
if (TARGET webcontent)
|
||||||
list(APPEND all_required_lagom_libraries webcontent)
|
list(APPEND all_required_lagom_libraries webcontent)
|
||||||
|
|
|
@ -254,3 +254,5 @@ set(XML_PARSER_DEBUG ON)
|
||||||
# set(ELF_DEBUG ON)
|
# set(ELF_DEBUG ON)
|
||||||
# False positive: A32_DEBUG_INTERFACE is the name of a CPU feature, not a debug flag.
|
# False positive: A32_DEBUG_INTERFACE is the name of a CPU feature, not a debug flag.
|
||||||
# set(IA32_DEBUG_INTERFACE ON)
|
# set(IA32_DEBUG_INTERFACE ON)
|
||||||
|
# False positive: ANDROID_LOG_DEBUG is a log level, not a debug flag
|
||||||
|
# set(ANDROID_LOG_DEBUG ON)
|
||||||
|
|
5
build.gradle.kts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
plugins {
|
||||||
|
id("com.android.application") version "8.1.1" apply false
|
||||||
|
id("org.jetbrains.kotlin.android") version "1.9.0" apply false
|
||||||
|
}
|
23
gradle.properties
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# Project-wide Gradle settings.
|
||||||
|
# IDE (e.g. Android Studio) users:
|
||||||
|
# Gradle settings configured through the IDE *will override*
|
||||||
|
# any settings specified in this file.
|
||||||
|
# For more details on how to configure your build environment visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
|
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||||
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
# org.gradle.parallel=true
|
||||||
|
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||||
|
# Android operating system, and which are packaged with your app's APK
|
||||||
|
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||||
|
android.useAndroidX=true
|
||||||
|
# Kotlin code style for this project: "official" or "obsolete":
|
||||||
|
kotlin.code.style=official
|
||||||
|
# Enables namespacing of each library's R class so that its R class includes only the
|
||||||
|
# resources declared in the library itself and none from the library's dependencies,
|
||||||
|
# thereby reducing the size of the R class for that library
|
||||||
|
android.nonTransitiveRClass=true
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#Fri Sep 01 12:36:55 CEST 2023
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
185
gradlew
vendored
Executable file
|
@ -0,0 +1,185 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2015 the original author or authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=`expr $i + 1`
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
0) set -- ;;
|
||||||
|
1) set -- "$args0" ;;
|
||||||
|
2) set -- "$args0" "$args1" ;;
|
||||||
|
3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=`save "$@"`
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
18
settings.gradle.kts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.name = "Ladybird"
|
||||||
|
include("Ladybird")
|
||||||
|
project(":Ladybird").projectDir = file("Ladybird/Android")
|