diff --git a/UI/Android/BuildLagomTools.sh b/UI/Android/BuildLagomTools.sh index 92bb8bf6950..2331f73b430 100755 --- a/UI/Android/BuildLagomTools.sh +++ b/UI/Android/BuildLagomTools.sh @@ -35,6 +35,7 @@ cmake -S "${LADYBIRD_SOURCE_DIR}/Meta/Lagom" -B "$BUILD_DIR/lagom-tools" \ -DCMAKE_C_COMPILER="$CC" \ -DCMAKE_CXX_COMPILER="$CXX" \ -DLADYBIRD_CACHE_DIR="$CACHE_DIR" \ + -DBUILD_SHARED_LIBS=OFF \ -DLAGOM_TOOLS_ONLY=ON \ -DINSTALL_LAGOM_TOOLS=ON \ -DCMAKE_TOOLCHAIN_FILE="$LADYBIRD_SOURCE_DIR/Build/vcpkg/scripts/buildsystems/vcpkg.cmake" \ diff --git a/UI/Android/build.gradle.kts b/UI/Android/build.gradle.kts index 28753fc9bc0..fc66c9d3dae 100644 --- a/UI/Android/build.gradle.kts +++ b/UI/Android/build.gradle.kts @@ -1,8 +1,8 @@ import com.android.build.gradle.internal.tasks.factory.dependsOn plugins { - id("com.android.application") version "8.4.0" - id("org.jetbrains.kotlin.android") version "1.9.0" + id("com.android.application") version "8.11.0" + id("org.jetbrains.kotlin.android") version "2.1.20" } var buildDir = layout.buildDirectory.get() @@ -22,20 +22,21 @@ tasks.named("prepareKotlinBuildScriptModel").dependsOn("buildLagomTools") android { namespace = "org.serenityos.ladybird" - compileSdk = 34 + compileSdk = 35 + // FIXME: Replace the NDK version to a stable one (this is r29 beta 2) + ndkVersion = "29.0.13599879" defaultConfig { applicationId = "org.serenityos.ladybird" minSdk = 30 - targetSdk = 34 + targetSdk = 35 versionCode = 1 versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { - // FIXME: Use -std=c++23 once the Android NDK's clang supports that. - cppFlags += "-std=c++2b" + cppFlags += "-std=c++23" arguments += listOf( "-DLagomTools_DIR=$buildDir/lagom-tools-install/share/LagomTools", "-DANDROID_STL=c++_shared", @@ -91,5 +92,5 @@ dependencies { androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.ext:junit-ktx:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") - implementation("com.google.oboe:oboe:1.9.0") + implementation("com.google.oboe:oboe:1.9.3") } diff --git a/UI/Android/gradle/wrapper/gradle-wrapper.properties b/UI/Android/gradle/wrapper/gradle-wrapper.properties index 9f5931daee4..103ad6520b1 100644 --- a/UI/Android/gradle/wrapper/gradle-wrapper.properties +++ b/UI/Android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +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.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/UI/Android/src/main/assets/.gitkeep b/UI/Android/src/main/assets/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/UI/Android/src/main/cpp/ALooperEventLoopImplementation.h b/UI/Android/src/main/cpp/ALooperEventLoopImplementation.h index 658a8a17bdd..efa927510f0 100644 --- a/UI/Android/src/main/cpp/ALooperEventLoopImplementation.h +++ b/UI/Android/src/main/cpp/ALooperEventLoopImplementation.h @@ -72,10 +72,7 @@ public: virtual void wake() override; virtual void post_event(Core::EventReceiver& receiver, NonnullOwnPtr&&) override; - // FIXME: These APIs only exist for obscure use-cases inside SerenityOS. Try to get rid of them. - virtual void unquit() override { } virtual bool was_exit_requested() const override { return false; } - virtual void notify_forked_and_in_child() override { } EventLoopThreadData& thread_data(); diff --git a/UI/Android/src/main/cpp/ImageDecoderService.cpp b/UI/Android/src/main/cpp/ImageDecoderService.cpp index 0bddbd8c7eb..6abc08d2798 100644 --- a/UI/Android/src/main/cpp/ImageDecoderService.cpp +++ b/UI/Android/src/main/cpp/ImageDecoderService.cpp @@ -16,7 +16,7 @@ ErrorOr service_main(int ipc_socket) Core::EventLoop event_loop; auto socket = TRY(Core::LocalSocket::adopt_fd(ipc_socket)); - auto client = TRY(ImageDecoder::ConnectionFromClient::try_create(move(socket))); + auto client = TRY(ImageDecoder::ConnectionFromClient::try_create(make(move(socket)))); return event_loop.exec(); } diff --git a/UI/Android/src/main/cpp/JNIHelpers.cpp b/UI/Android/src/main/cpp/JNIHelpers.cpp index b06223d47fb..dc90215a411 100644 --- a/UI/Android/src/main/cpp/JNIHelpers.cpp +++ b/UI/Android/src/main/cpp/JNIHelpers.cpp @@ -12,7 +12,7 @@ namespace Ladybird { jstring JavaEnvironment::jstring_from_ak_string(String const& str) { auto as_utf16 = MUST(AK::utf8_to_utf16(str.code_points())); - return m_env->NewString(as_utf16.data(), as_utf16.size()); + return m_env->NewString(reinterpret_cast(as_utf16.data.data()), as_utf16.data.size()); } } diff --git a/UI/Android/src/main/cpp/LadybirdActivity.cpp b/UI/Android/src/main/cpp/LadybirdActivity.cpp index 62690ef503b..2f79c068a54 100644 --- a/UI/Android/src/main/cpp/LadybirdActivity.cpp +++ b/UI/Android/src/main/cpp/LadybirdActivity.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -19,47 +18,52 @@ #include #include #include -#include +#include #include -static ErrorOr extract_tar_archive(String archive_file, ByteString output_directory); - JavaVM* global_vm; static OwnPtr s_application; static OwnPtr s_main_event_loop; static jobject s_java_instance; static jmethodID s_schedule_event_loop_method; -struct Application : public WebView::Application { +class Application : public WebView::Application { WEB_VIEW_APPLICATION(Application); + +public: + explicit Application(); }; -Application::Application(Badge, Main::Arguments&) -{ -} +Application::Application() = default; extern "C" JNIEXPORT void JNICALL -Java_org_serenityos_ladybird_LadybirdActivity_initNativeCode(JNIEnv*, jobject, jstring, jstring, jobject); +Java_org_serenityos_ladybird_LadybirdActivity_initNativeCode(JNIEnv*, jobject, jstring, jstring, jobject, jstring); extern "C" JNIEXPORT void JNICALL -Java_org_serenityos_ladybird_LadybirdActivity_initNativeCode(JNIEnv* env, jobject thiz, jstring resource_dir, jstring tag_name, jobject timer_service) +Java_org_serenityos_ladybird_LadybirdActivity_initNativeCode(JNIEnv* env, jobject thiz, jstring resource_dir, jstring tag_name, jobject timer_service, jstring user_dir) { char const* raw_resource_dir = env->GetStringUTFChars(resource_dir, nullptr); - s_ladybird_resource_root = raw_resource_dir; + WebView::s_ladybird_resource_root = raw_resource_dir; env->ReleaseStringUTFChars(resource_dir, raw_resource_dir); + // While setting XDG environment variables in order to store user data may seem silly + // but in our case it seems to be the most rational idea. + char const* raw_user_dir = env->GetStringUTFChars(user_dir, nullptr); + setenv("XDG_CONFIG_HOME", ByteString::formatted("{}/config", raw_user_dir).characters(), 1); + setenv("XDG_DATA_HOME", ByteString::formatted("{}/userdata", raw_user_dir).characters(), 1); + env->ReleaseStringUTFChars(user_dir, raw_user_dir); + char const* raw_tag_name = env->GetStringUTFChars(tag_name, nullptr); AK::set_log_tag_name(raw_tag_name); env->ReleaseStringUTFChars(tag_name, raw_tag_name); - dbgln("Set resource dir to {}", s_ladybird_resource_root); + dbgln("Set resource dir to {}", WebView::s_ladybird_resource_root); - auto file_or_error = Core::System::open(MUST(String::formatted("{}/res/icons/48x48/app-browser.png", s_ladybird_resource_root)), O_RDONLY); + auto file_or_error = Core::System::open(MUST(String::formatted("{}/res/icons/48x48/app-browser.png", WebView::s_ladybird_resource_root)), O_RDONLY); if (file_or_error.is_error()) { - dbgln("No resource files, extracting assets..."); - MUST(extract_tar_archive(MUST(String::formatted("{}/ladybird-assets.tar", s_ladybird_resource_root)), s_ladybird_resource_root)); + dbgln("No resource files, perhaps extracting went wrong?"); } else { - dbgln("Found app-browser.png, not re-extracting assets."); + dbgln("Found app-browser.png"); dbgln("Hopefully no developer changed the asset files and expected them to be re-extracted!"); } @@ -93,7 +97,7 @@ Java_org_serenityos_ladybird_LadybirdActivity_initNativeCode(JNIEnv* env, jobjec // FIXME: We are not making use of this Application object to track our processes. // So, right now, the Application's ProcessManager is constantly empty. // (However, LibWebView depends on an Application object existing, so we do have to actually create one.) - s_application = Application::create(arguments, "about:newtab"sv); + s_application = Application::create(arguments).release_value_but_fixme_should_propagate_errors(); } extern "C" JNIEXPORT void JNICALL @@ -120,139 +124,3 @@ Java_org_serenityos_ladybird_LadybirdActivity_disposeNativeCode(JNIEnv* env, job delete &Core::EventLoopManager::the(); } - -ErrorOr extract_tar_archive(String archive_file, ByteString output_directory) -{ - constexpr size_t buffer_size = 4096; - - auto file = TRY(Core::InputBufferedFile::create(TRY(Core::File::open(archive_file, Core::File::OpenMode::Read)))); - - ByteString 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(move(file))); - - HashMap global_overrides; - HashMap local_overrides; - - auto get_override = [&](StringView key) -> Optional { - Optional maybe_local = local_overrides.get(key); - - if (maybe_local.has_value()) - return maybe_local; - - Optional 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 buffer; - - while (!file_stream.is_eof()) { - auto slice = TRY(file_stream.read_some(buffer)); - long_name.append(reinterpret_cast(slice.data()), slice.size()); - } - - local_overrides.set("path", long_name.to_byte_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()); - ByteString filename = get_override("path"sv).value_or(path.string()); - - ByteString absolute_path = TRY(FileSystem::absolute_path(filename)); - 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 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 {}; -} diff --git a/UI/Android/src/main/cpp/LadybirdServiceBaseJNI.cpp b/UI/Android/src/main/cpp/LadybirdServiceBaseJNI.cpp index 00b423c5901..190bb389360 100644 --- a/UI/Android/src/main/cpp/LadybirdServiceBaseJNI.cpp +++ b/UI/Android/src/main/cpp/LadybirdServiceBaseJNI.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include JavaVM* global_vm; @@ -42,10 +42,11 @@ Java_org_serenityos_ladybird_LadybirdServiceBase_initNativeCode(JNIEnv* env, job env->GetJavaVM(&global_vm); char const* raw_resource_dir = env->GetStringUTFChars(resource_dir, nullptr); - s_ladybird_resource_root = raw_resource_dir; + // FIXME: Don't set s_ladybird_resource_root on every service in order not to link with LibWebView. + WebView::s_ladybird_resource_root = raw_resource_dir; env->ReleaseStringUTFChars(resource_dir, raw_resource_dir); // FIXME: Use a custom Android version that uses AssetManager to load files. - Core::ResourceImplementation::install(make(MUST(String::formatted("{}/res", s_ladybird_resource_root)))); + Core::ResourceImplementation::install(make(MUST(String::formatted("{}/res", WebView::s_ladybird_resource_root)))); char const* raw_tag_name = env->GetStringUTFChars(tag_name, nullptr); AK::set_log_tag_name(raw_tag_name); diff --git a/UI/Android/src/main/cpp/RequestServerService.cpp b/UI/Android/src/main/cpp/RequestServerService.cpp index 5fefe5da4a6..ed036ad07ac 100644 --- a/UI/Android/src/main/cpp/RequestServerService.cpp +++ b/UI/Android/src/main/cpp/RequestServerService.cpp @@ -15,20 +15,24 @@ #include #include #include +#include #include -#include -#include -#include + +namespace RequestServer { + +extern ByteString g_default_certificate_path; + +} ErrorOr service_main(int ipc_socket) { + + RequestServer::g_default_certificate_path = ByteString::formatted("{}/res/ladybird/cacert.pem", WebView::s_ladybird_resource_root); + Core::EventLoop event_loop; - RequestServer::HttpProtocol::install(); - RequestServer::HttpsProtocol::install(); - auto socket = TRY(Core::LocalSocket::adopt_fd(ipc_socket)); - auto client = TRY(RequestServer::ConnectionFromClient::try_create(move(socket))); + auto client = TRY(RequestServer::ConnectionFromClient::try_create(make(move(socket)))); return event_loop.exec(); } diff --git a/UI/Android/src/main/cpp/WebContentService.cpp b/UI/Android/src/main/cpp/WebContentService.cpp index b1aafad72ca..f90b4349dc4 100644 --- a/UI/Android/src/main/cpp/WebContentService.cpp +++ b/UI/Android/src/main/cpp/WebContentService.cpp @@ -24,11 +24,11 @@ #include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include @@ -53,21 +53,26 @@ ErrorOr service_main(int ipc_socket) Web::Platform::EventLoopPlugin::install(*new Web::Platform::EventLoopPluginSerenity); auto image_decoder_client = TRY(bind_image_decoder_service()); - Web::Platform::ImageCodecPlugin::install(*new Ladybird::ImageCodecPlugin(move(image_decoder_client))); + Web::Platform::ImageCodecPlugin::install(*new WebView::ImageCodecPlugin(move(image_decoder_client))); Web::Platform::AudioCodecPlugin::install_creation_hook([](auto loader) { return Web::Platform::AudioCodecPluginAgnostic::create(move(loader)); }); + Web::Bindings::initialize_main_thread_vm(Web::Bindings::AgentType::SimilarOriginWindow); + auto request_server_client = TRY(bind_request_server_service()); - Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create(move(request_server_client)))); + Web::ResourceLoader::initialize(Web::Bindings::main_thread_vm().heap(), move(request_server_client)); bool is_layout_test_mode = false; Web::HTML::Window::set_internals_object_exposed(is_layout_test_mode); - Web::Platform::FontPlugin::install(*new Ladybird::FontPlugin(is_layout_test_mode)); + Web::Platform::FontPlugin::install(*new WebView::FontPlugin(is_layout_test_mode)); - TRY(Web::Bindings::initialize_main_thread_vm(Web::HTML::EventLoop::Type::Window)); + // Currently site isolation doesn't work on Android since everything is running + // in the same process. It would require an entire redesign of this port + // in order to make it work. For now, it's better to just disable it. + WebView::disable_site_isolation(); auto maybe_content_filter_error = load_content_filters(); if (maybe_content_filter_error.is_error()) @@ -78,7 +83,7 @@ ErrorOr service_main(int ipc_socket) dbgln("Failed to load autoplay allowlist: {}", maybe_autoplay_allowlist_error.error()); auto webcontent_socket = TRY(Core::LocalSocket::adopt_fd(ipc_socket)); - auto webcontent_client = TRY(WebContent::ConnectionFromClient::try_create(move(webcontent_socket))); + auto webcontent_client = TRY(WebContent::ConnectionFromClient::try_create(make(move(webcontent_socket)))); return event_loop.exec(); } @@ -98,14 +103,14 @@ ErrorOr> bind_service(void (*bind_method)(int)) auto socket = TRY(Core::LocalSocket::adopt_fd(ui_fd)); TRY(socket->set_blocking(true)); - auto new_client = TRY(try_make_ref_counted(move(socket))); + auto new_client = TRY(try_make_ref_counted(make(move(socket)))); return new_client; } static ErrorOr load_content_filters() { - auto file_or_error = Core::File::open(ByteString::formatted("{}/res/ladybird/default-config/BrowserContentFilters.txt", s_ladybird_resource_root), Core::File::OpenMode::Read); + auto file_or_error = Core::File::open(ByteString::formatted("{}/res/ladybird/default-config/BrowserContentFilters.txt", WebView::s_ladybird_resource_root), Core::File::OpenMode::Read); if (file_or_error.is_error()) return file_or_error.release_error(); @@ -132,7 +137,7 @@ static ErrorOr load_content_filters() static ErrorOr load_autoplay_allowlist() { - auto file_or_error = Core::File::open(TRY(String::formatted("{}/res/ladybird/default-config/BrowserAutoplayAllowlist.txt", s_ladybird_resource_root)), Core::File::OpenMode::Read); + auto file_or_error = Core::File::open(TRY(String::formatted("{}/res/ladybird/default-config/BrowserAutoplayAllowlist.txt", WebView::s_ladybird_resource_root)), Core::File::OpenMode::Read); if (file_or_error.is_error()) return file_or_error.release_error(); @@ -152,7 +157,7 @@ static ErrorOr load_autoplay_allowlist() } auto& autoplay_allowlist = Web::PermissionsPolicy::AutoplayAllowlist::the(); - TRY(autoplay_allowlist.enable_for_origins(origins)); + autoplay_allowlist.enable_for_origins(origins); return {}; } diff --git a/UI/Android/src/main/cpp/WebViewImplementationNative.cpp b/UI/Android/src/main/cpp/WebViewImplementationNative.cpp index 5696d45bed3..7f44f1795ca 100644 --- a/UI/Android/src/main/cpp/WebViewImplementationNative.cpp +++ b/UI/Android/src/main/cpp/WebViewImplementationNative.cpp @@ -7,7 +7,8 @@ #include "WebViewImplementationNative.h" #include "JNIHelpers.h" #include -#include +#include +#include #include #include #include @@ -20,7 +21,7 @@ static Gfx::BitmapFormat to_gfx_bitmap_format(i32 f) { switch (f) { case ANDROID_BITMAP_FORMAT_RGBA_8888: - return Gfx::BitmapFormat::BGRA8888; + return Gfx::BitmapFormat::RGBA8888; default: VERIFY_NOT_REACHED(); } @@ -62,6 +63,8 @@ void WebViewImplementationNative::initialize_client(WebView::ViewImplementation: client().async_set_device_pixels_per_css_pixel(0, m_device_pixel_ratio); + set_system_visibility_state(Web::HTML::VisibilityState::Visible); + // FIXME: update_palette, update system fonts } @@ -71,25 +74,11 @@ void WebViewImplementationNative::paint_into_bitmap(void* android_bitmap_raw, An VERIFY((info.flags & ANDROID_BITMAP_FLAGS_IS_HARDWARE) == 0); auto android_bitmap = MUST(Gfx::Bitmap::create_wrapper(to_gfx_bitmap_format(info.format), Gfx::AlphaType::Premultiplied, { info.width, info.height }, info.stride, android_bitmap_raw)); - Gfx::DeprecatedPainter painter(android_bitmap); + auto painter = Gfx::Painter::create(android_bitmap); if (auto* bitmap = m_client_state.has_usable_bitmap ? m_client_state.front_bitmap.bitmap.ptr() : m_backup_bitmap.ptr()) - painter.blit({ 0, 0 }, *bitmap, bitmap->rect()); + painter->draw_bitmap(android_bitmap->rect().to_type(), Gfx::ImmutableBitmap::create(MUST(bitmap->clone())), bitmap->rect(), Gfx::ScalingMode::NearestNeighbor, {}, 1.0f, Gfx::CompositingAndBlendingOperator::Copy); else - painter.clear_rect(painter.clip_rect(), Gfx::Color::Magenta); - - // Convert our internal BGRA into RGBA. This will be slowwwwwww - // FIXME: Don't do a color format swap here. - for (auto y = 0; y < android_bitmap->height(); ++y) { - auto* scanline = android_bitmap->scanline(y); - for (auto x = 0; x < android_bitmap->width(); ++x) { - auto current_pixel = scanline[x]; - u32 alpha = (current_pixel & 0xFF000000U) >> 24; - u32 red = (current_pixel & 0x00FF0000U) >> 16; - u32 green = (current_pixel & 0x0000FF00U) >> 8; - u32 blue = (current_pixel & 0x000000FFU); - scanline[x] = (alpha << 24U) | (blue << 16U) | (green << 8U) | red; - } - } + painter->fill_rect(android_bitmap->rect().to_type(), Gfx::Color::Magenta); } void WebViewImplementationNative::set_viewport_geometry(int w, int h) @@ -139,7 +128,7 @@ NonnullRefPtr WebViewImplementationNative::bind_web_c auto socket = MUST(Core::LocalSocket::adopt_fd(ui_fd)); MUST(socket->set_blocking(true)); - auto new_client = make_ref_counted(move(socket), *this); + auto new_client = make_ref_counted(make(move(socket)), *this); return new_client; } diff --git a/UI/Android/src/main/cpp/WebViewImplementationNativeJNI.cpp b/UI/Android/src/main/cpp/WebViewImplementationNativeJNI.cpp index b720398e6b9..b4ab29e6349 100644 --- a/UI/Android/src/main/cpp/WebViewImplementationNativeJNI.cpp +++ b/UI/Android/src/main/cpp/WebViewImplementationNativeJNI.cpp @@ -102,7 +102,7 @@ Java_org_serenityos_ladybird_WebViewImplementation_nativeLoadURL(JNIEnv* env, jo char const* raw_url = env->GetStringUTFChars(url, nullptr); auto ak_url = URL::create_with_url_or_path(StringView { raw_url, strlen(raw_url) }); env->ReleaseStringUTFChars(url, raw_url); - impl->load(ak_url); + impl->load(ak_url.release_value()); } extern "C" JNIEXPORT void JNICALL diff --git a/UI/Android/src/main/java/org/serenityos/ladybird/ImageDecoderService.kt b/UI/Android/src/main/java/org/serenityos/ladybird/ImageDecoderService.kt index 1c5e1cb5229..816484be363 100644 --- a/UI/Android/src/main/java/org/serenityos/ladybird/ImageDecoderService.kt +++ b/UI/Android/src/main/java/org/serenityos/ladybird/ImageDecoderService.kt @@ -15,7 +15,7 @@ class ImageDecoderService : LadybirdServiceBase("ImageDecoderService") { companion object { init { - System.loadLibrary("imagedecoder") + System.loadLibrary("imagedecoderservice") } } } diff --git a/UI/Android/src/main/java/org/serenityos/ladybird/LadybirdActivity.kt b/UI/Android/src/main/java/org/serenityos/ladybird/LadybirdActivity.kt index dc5bd856f85..1286be37a74 100644 --- a/UI/Android/src/main/java/org/serenityos/ladybird/LadybirdActivity.kt +++ b/UI/Android/src/main/java/org/serenityos/ladybird/LadybirdActivity.kt @@ -13,6 +13,11 @@ import android.view.inputmethod.EditorInfo import android.widget.EditText import android.widget.TextView import org.serenityos.ladybird.databinding.ActivityMainBinding +import java.io.BufferedInputStream +import java.io.BufferedOutputStream +import java.io.File +import java.io.FileOutputStream +import java.util.zip.ZipFile class LadybirdActivity : AppCompatActivity() { @@ -26,7 +31,29 @@ class LadybirdActivity : AppCompatActivity() { super.onCreate(savedInstanceState) resourceDir = TransferAssets.transferAssets(this) - initNativeCode(resourceDir, "Ladybird", timerService) + val testFile = File("$resourceDir/res/icons/48x48/app-browser.png") + if (!testFile.exists()) + { + ZipFile("$resourceDir/ladybird-assets.zip").use { zip -> + zip.entries().asSequence().forEach { entry -> + val fileName = entry.name + val file = File("$resourceDir/$fileName") + if (!entry.isDirectory) + { + val parentFolder = File(file.parent!!) + if (!parentFolder.exists()) + parentFolder.mkdirs() + zip.getInputStream(entry).use { input -> + file.outputStream().use { output -> + input.copyTo(output) + } + } + } + } + } + } + val userDir = applicationContext.getExternalFilesDir(null)!!.absolutePath; + initNativeCode(resourceDir, "Ladybird", timerService, userDir) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) @@ -63,7 +90,7 @@ class LadybirdActivity : AppCompatActivity() { } private external fun initNativeCode( - resourceDir: String, tag: String, timerService: TimerExecutorService + resourceDir: String, tag: String, timerService: TimerExecutorService, userDir: String ) private external fun disposeNativeCode() diff --git a/UI/Android/src/main/java/org/serenityos/ladybird/RequestServerService.kt b/UI/Android/src/main/java/org/serenityos/ladybird/RequestServerService.kt index c1941a38b88..fb60abb82e0 100644 --- a/UI/Android/src/main/java/org/serenityos/ladybird/RequestServerService.kt +++ b/UI/Android/src/main/java/org/serenityos/ladybird/RequestServerService.kt @@ -15,7 +15,7 @@ class RequestServerService : LadybirdServiceBase("RequestServerService") { companion object { init { - System.loadLibrary("requestserver") + System.loadLibrary("requestserverservice") } } } diff --git a/UI/Android/src/main/java/org/serenityos/ladybird/TransferAssets.java b/UI/Android/src/main/java/org/serenityos/ladybird/TransferAssets.java index b034188621f..fcba154d842 100644 --- a/UI/Android/src/main/java/org/serenityos/ladybird/TransferAssets.java +++ b/UI/Android/src/main/java/org/serenityos/ladybird/TransferAssets.java @@ -27,11 +27,11 @@ public class TransferAssets { Context applicationContext = context.getApplicationContext(); File assetDir = applicationContext.getFilesDir(); AssetManager assetManager = applicationContext.getAssets(); - if (!copyAsset(assetManager, "ladybird-assets.tar", assetDir.getAbsolutePath() + "/ladybird-assets.tar")) { + if (!copyAsset(assetManager, "ladybird-assets.zip", assetDir.getAbsolutePath() + "/ladybird-assets.zip")) { 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"); + Log.d("Ladybird", "Copied ladybird-assets.zip to app-specific storage path"); return assetDir.getAbsolutePath(); } diff --git a/UI/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt b/UI/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt index 26d665a5bff..fb7e41da2b6 100644 --- a/UI/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt +++ b/UI/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt @@ -54,7 +54,7 @@ class WebContentService : LadybirdServiceBase("WebContentService") { companion object { init { - System.loadLibrary("webcontent") + System.loadLibrary("webcontentservice") } } } diff --git a/UI/cmake/AndroidExtras.cmake b/UI/cmake/AndroidExtras.cmake index f6c95cba982..e79f9dec7cf 100644 --- a/UI/cmake/AndroidExtras.cmake +++ b/UI/cmake/AndroidExtras.cmake @@ -15,13 +15,11 @@ macro(copy_res_folder folder) ) add_dependencies(archive-assets copy-${folder}) endmacro() -add_custom_target(archive-assets COMMAND ${CMAKE_COMMAND} -E chdir asset-bundle tar cf ../ladybird-assets.tar ./ ) +add_custom_target(archive-assets COMMAND ${CMAKE_COMMAND} -E chdir asset-bundle zip -r ../ladybird-assets.zip ./ ) copy_res_folder(ladybird) -copy_res_folder(html) copy_res_folder(fonts) copy_res_folder(icons) -copy_res_folder(emoji) copy_res_folder(themes) -add_custom_target(copy-assets COMMAND ${CMAKE_COMMAND} -E copy_if_different ladybird-assets.tar "${CMAKE_SOURCE_DIR}/UI/Android/src/main/assets/") +add_custom_target(copy-assets COMMAND ${CMAKE_COMMAND} -E copy_if_different ladybird-assets.zip "${CMAKE_SOURCE_DIR}/UI/Android/src/main/assets/") add_dependencies(copy-assets archive-assets) add_dependencies(ladybird copy-assets)