What’s new in Compose Multiplatform WebView 1.5.0:Migrated to CEF Browser & Cookie Management Supported

Kevin Zou
6 min readOct 23, 2023

--

In the previous article, we provide an introduction to the Compose Multiplatform WebView library. It offers a WebView component that allows developers to display web pages in Compose Multiplatform projects. Since its release, many developers have used it and provided valuable suggestions. We promptly responded to these suggestions and have gradually incorporated them into new versions. In this article, I will introduce the new features added since version 1.0.0 and outline our future plans.

CEF Browser

The most important feature is the browser migration for the Desktop target. In our original solution, the WebView display on the Desktop side was implemented through JavaFX. Although it can display web pages normally, there will be lag when browsing complex web pages. This is because it uses its own rendering engine, and all tasks are executed in a single main thread. This greatly limits its performance when displaying web pages. Therefore, we decided to look for a more powerful engine to replace JavaFX, and ultimately we chose CEF Browser.

CEF Browser (Chromium Embedded Framework Browser) is a browser developed based on Chromium embedded framework. It combines the functionality of the browser with the customization of the application, enabling developers to display web pages, including HTML, CSS, and JavaScript, in their own applications. It supports running on multiple platforms, including Windows, Mac, and Linux operating systems.

Through CEF Browser, developers can use powerful web technologies to build complex User Interfaces, achieve online content display, data interaction, multimedia playback, and other functions. It also provides rich APIs and event handling mechanisms, enabling developers to interact with web pages and implement customized behavior and functionality.

Thanks to Jeff’s research and development, we successfully switched to the CEF Browser in version 1.3.0. The new WebView component significantly enhances performance on the Desktop side, allowing even complex web pages to load smoothly.

Before using the new version of WebView, developers must follow certain steps to properly configure CEF. Please refer to the link below for a detailed guide.

Basic Web Capability Support

In addition to switching to CEF Browser, we have been gradually improving support for basic web capabilities in several new versions after version 1.0.0. The main expanded capabilities are as follows:

Custom settings support

Firstly, We provide support for WebView Settings, allowing developers to customize settings for each platform’s WebView. We have extracted general settings for developers to customize, as well as specific settings for each platform that can be set separately.

/**
* Web settings for different platform
*/
class WebSettings {
/**
* Whether the WebView should enable JavaScript execution.
* Default is true.
*/
var isJavaScriptEnabled = true

/**
* WebView's user-agent string.
* Default is null.
*/
var customUserAgentString: String? = null

/**
* Android platform specific settings
*/
val androidWebSettings = PlatformWebSettings.AndroidWebSettings()

/**
* Desktop platform specific settings
*/
val desktopWebSettings = PlatformWebSettings.DesktopWebSettings()

/**
* iOS platform specific settings
*/
val iOSWebSettings = PlatformWebSettings.IOSWebSettings

}
/**
* Android web settings
*/
data class AndroidWebSettings(
/**
* whether the WebView should support zooming using its on-screen zoom
* controls and gestures. The particular zoom mechanisms that should be used
* can be set with {@link #setBuiltInZoomControls}. This setting does not
* affect zooming performed using the {@link WebView#zoomIn()} and
* {@link WebView#zoomOut()} methods. The default is {@code true}.
*
* @param support whether the WebView should support zoom
*/
var supportZoom: Boolean = true,

/**
* The text zoom of the page in percent. The default is 100.
*
* @param textZoom the text zoom in percent
*/
var textZoom: Int = 100,

......

/**
* whether Safe Browsing is enabled. Safe Browsing allows WebView to
* protect against malware and phishing attacks by verifying the links.
*/
var safeBrowsingEnabled: Boolean = true,

/**
* Whether the DOM storage API is enabled. The default value is {@code false}.
*/
var domStorageEnabled: Boolean = false,
)

The usage is as follows:

val webViewState = rememberWebViewStateWithHTMLData(
data = html
)
webViewState.webSettings.apply {
isJavaScriptEnabled = true
androidWebSettings.apply {
isAlgorithmicDarkeningAllowed = true
safeBrowsingEnabled = true
}
}

JavaScript Evaluation Support

Secondly, we have added support for executing JavaScript by implementing the evaluateJavaScript method in WebViewNavigator.

/**
* Evaluates the given JavaScript in the context of the currently displayed page.
*
* @param script The JavaScript to evaluate.
* @param callback A callback to be invoked when the script execution completes.
*/
fun evaluateJavaScript(script: String, callback: ((String) -> Unit)? = null) {
}

The usage is as follows:

webViewNavigator.evaluateJavaScript(
"""
document.getElementById("subtitle").innerText = "Hello from KMM!";
callJS();
""".trimIndent()
) {
jsRes = it
}

Cookie management support

Lastly, We have implemented support for cookie management, defining a basic API for operating cookies and implementing it with native capabilities on each platform layer.

/**
* Cookie Manager exposing access to cookies of the WebView.
* This is an interface to allow platform specific implementations.
* ---------------------------------------------------------------
* PS: Not having it as expect/actual class was a conscious decision,
* since expect/actual classes will be marked as beta in coming kotlin releases.
* */
interface CookieManager {

/**
* Sets a cookie for the given url.
* @param url The url for which the cookie is to be set.
* @param cookie The cookie to be set.
* */
suspend fun setCookie(url: String, cookie: Cookie)

/**
* Gets all the cookies for the given url.
* @param url The url for which the cookies are to be retrieved.
*
* @return A list of cookies for the given url.
* */
suspend fun getCookies(url: String): List<Cookie>

/**
* Removes all the cookies.
* */
suspend fun removeAllCookies()

/**
* Removes all the cookies for the given url.
* @param url The url for which the cookies are to be removed.
* */
suspend fun removeCookies(url: String)
}

The usage is as follows:

LaunchedEffect(state.loadingState) {
if (state.loadingState is LoadingState.Finished) {
state.cookieManager.setCookie(
"https://github.com",
Cookie(
name = "test",
value = "value",
domain = "github.com",
expiresDate = 1896863778
)
)
Logger.i {
"cookie: ${state.cookieManager.getCookies("https://github.com")}"
}
state.cookieManager.removeAllCookies()
Logger.i {
"cookie: ${state.cookieManager.getCookies("https://github.com")}"
}
}
}

API Documentation

The last update is that we have enhanced the API documentation and made it available on the GitHub homepage. You can visit the link to explore the library’s capabilities and supported APIs.

Future Plan

The project has been released up to version 1.5.0 and has stabilized. We are continuing to develop new features to enhance WebView’s capabilities. Currently, we have two main features in the development stages.

  1. Support for loading local HTML files. Currently, we only support direct loading of HTML code provided by developers and do not support direct reading of HTML files. In the future, we will facilitate developers by supporting direct reading of HTML files located in the commonMain/resources folder.
  2. Switch to Kotlin CEF. The current project relies on Java CEF to support CEF Browser. While it performs well, there are some functionalities, such as cookie reading, that are not fully supported. Consequently, we are actively seeking optimization solutions. Fortunately, Jeff has developed a Kotlin version of CEF based on JetBrains’ Jcef. This library addresses the limitations of JCEF and offers improved performance. We are currently conducting thorough testing to ensure stability and compatibility. We also encourage early adoption of this library and welcome any suggestions.

Download

Multiplatform

repositories {
mavenCentral()
}

kotlin {
sourceSets {
commonMain {
dependencies {
// use api since the desktop app need to access the Cef to initialize it.
api("io.github.kevinnzou:compose-webview-multiplatform:1.5.0")
}
}
}
}

Single Platform

For an Android only project, you can directly use my another library. Add the dependency to app level build.gradle.kts:

repositories {
maven("https://jitpack.io")
}

dependencies {
implementation ("com.github.KevinnZou:compose-webview:0.33.2")
}

Following Readings:

Thanks for your reading!

--

--

Kevin Zou

Android Developer in NetEase. Focusing on Kotlin Multiplatform and Compose Multiplatform