mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-03 10:54:38 -05:00
Minor bug fixes for Webview, Permission request support (#1723)
* fix: Match URLs with trailing / * Handle permission requests and attempt to enable Widevine * Tie CEF loglevel to server debug logs * Lint * Add missing file Forgot to add in previous commits * Provide WebResourceResponse * Fix NullException if headers are not set * fix: Don't allow interception for initial page load fixes #1713 * Lint
This commit is contained in:
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* http://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.webkit;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class defines a permission request and is used when web content
|
||||||
|
* requests access to protected resources. The permission request related events
|
||||||
|
* are delivered via {@link WebChromeClient#onPermissionRequest} and
|
||||||
|
* {@link WebChromeClient#onPermissionRequestCanceled}.
|
||||||
|
*
|
||||||
|
* Either {@link #grant(String[]) grant()} or {@link #deny()} must be called in UI
|
||||||
|
* thread to respond to the request.
|
||||||
|
*
|
||||||
|
* New protected resources whose names are not defined here may be requested in
|
||||||
|
* future versions of WebView, even when running on an older Android release. To
|
||||||
|
* avoid unintentionally granting requests for new permissions, you should pass the
|
||||||
|
* specific permissions you intend to grant to {@link #grant(String[]) grant()},
|
||||||
|
* and avoid writing code like this example:
|
||||||
|
* <pre class="prettyprint">
|
||||||
|
* permissionRequest.grant(permissionRequest.getResources()) // This is wrong!!!
|
||||||
|
* </pre>
|
||||||
|
* See the WebView's release notes for information about new protected resources.
|
||||||
|
*/
|
||||||
|
public abstract class PermissionRequest {
|
||||||
|
/**
|
||||||
|
* Resource belongs to video capture device, like camera.
|
||||||
|
*/
|
||||||
|
public final static String RESOURCE_VIDEO_CAPTURE = "android.webkit.resource.VIDEO_CAPTURE";
|
||||||
|
/**
|
||||||
|
* Resource belongs to audio capture device, like microphone.
|
||||||
|
*/
|
||||||
|
public final static String RESOURCE_AUDIO_CAPTURE = "android.webkit.resource.AUDIO_CAPTURE";
|
||||||
|
/**
|
||||||
|
* Resource belongs to protected media identifier.
|
||||||
|
* After the user grants this resource, the origin can use EME APIs to generate the license
|
||||||
|
* requests.
|
||||||
|
*/
|
||||||
|
public final static String RESOURCE_PROTECTED_MEDIA_ID =
|
||||||
|
"android.webkit.resource.PROTECTED_MEDIA_ID";
|
||||||
|
/**
|
||||||
|
* Resource will allow sysex messages to be sent to or received from MIDI devices. These
|
||||||
|
* messages are privileged operations, e.g. modifying sound libraries and sampling data, or
|
||||||
|
* even updating the MIDI device's firmware.
|
||||||
|
*
|
||||||
|
* Permission may be requested for this resource in API levels 21 and above, if the Android
|
||||||
|
* device has been updated to WebView 45 or above.
|
||||||
|
*/
|
||||||
|
public final static String RESOURCE_MIDI_SYSEX = "android.webkit.resource.MIDI_SYSEX";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this method to get the origin of the web page which is trying to access
|
||||||
|
* the restricted resources.
|
||||||
|
*
|
||||||
|
* @return the origin of web content which attempt to access the restricted
|
||||||
|
* resources.
|
||||||
|
*/
|
||||||
|
public abstract Uri getOrigin();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this method to get the resources the web page is trying to access.
|
||||||
|
*
|
||||||
|
* @return the array of resources the web content wants to access.
|
||||||
|
*/
|
||||||
|
public abstract String[] getResources();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this method to grant origin the permission to access the given resources.
|
||||||
|
* The granted permission is only valid for this WebView.
|
||||||
|
*
|
||||||
|
* @param resources the resources granted to be accessed by origin, to grant
|
||||||
|
* request, the requested resources returned by {@link #getResources()}
|
||||||
|
* must be equals or a subset of granted resources.
|
||||||
|
* This parameter is designed to avoid granting permission by accident
|
||||||
|
* especially when new resources are requested by web content.
|
||||||
|
*/
|
||||||
|
public abstract void grant(String[] resources);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this method to deny the request.
|
||||||
|
*/
|
||||||
|
public abstract void deny();
|
||||||
|
}
|
||||||
@@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* http://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.webkit;
|
||||||
|
|
||||||
|
import android.annotation.SystemApi;
|
||||||
|
import android.os.Build;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.StringBufferInputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates a resource response. Applications can return an instance of this
|
||||||
|
* class from {@link WebViewClient#shouldInterceptRequest} to provide a custom
|
||||||
|
* response when the WebView requests a particular resource.
|
||||||
|
*/
|
||||||
|
public class WebResourceResponse {
|
||||||
|
private boolean mImmutable;
|
||||||
|
private String mMimeType;
|
||||||
|
private String mEncoding;
|
||||||
|
private int mStatusCode;
|
||||||
|
private String mReasonPhrase;
|
||||||
|
private Map<String, String> mResponseHeaders;
|
||||||
|
private InputStream mInputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a resource response with the given MIME type, character encoding,
|
||||||
|
* and input stream. Callers must implement {@link InputStream#read(byte[])} for
|
||||||
|
* the input stream. {@link InputStream#close()} will be called after the WebView
|
||||||
|
* has finished with the response.
|
||||||
|
*
|
||||||
|
* <p class="note"><b>Note:</b> The MIME type and character encoding must
|
||||||
|
* be specified as separate parameters (for example {@code "text/html"} and
|
||||||
|
* {@code "utf-8"}), not a single value like the {@code "text/html; charset=utf-8"}
|
||||||
|
* format used in the HTTP Content-Type header. Do not use the value of a HTTP
|
||||||
|
* Content-Encoding header for {@code encoding}, as that header does not specify a
|
||||||
|
* character encoding. Content without a defined character encoding (for example
|
||||||
|
* image resources) should pass {@code null} for {@code encoding}.
|
||||||
|
*
|
||||||
|
* @param mimeType the resource response's MIME type, for example {@code "text/html"}.
|
||||||
|
* @param encoding the resource response's character encoding, for example {@code "utf-8"}.
|
||||||
|
* @param data the input stream that provides the resource response's data. Must not be a
|
||||||
|
* StringBufferInputStream.
|
||||||
|
*/
|
||||||
|
public WebResourceResponse(String mimeType, String encoding,
|
||||||
|
InputStream data) {
|
||||||
|
mMimeType = mimeType;
|
||||||
|
mEncoding = encoding;
|
||||||
|
setData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a resource response with the given parameters. Callers must implement
|
||||||
|
* {@link InputStream#read(byte[])} for the input stream. {@link InputStream#close()} will be
|
||||||
|
* called after the WebView has finished with the response.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* <p class="note"><b>Note:</b> See {@link #WebResourceResponse(String,String,InputStream)}
|
||||||
|
* for details on what should be specified for {@code mimeType} and {@code encoding}.
|
||||||
|
*
|
||||||
|
* @param mimeType the resource response's MIME type, for example {@code "text/html"}.
|
||||||
|
* @param encoding the resource response's character encoding, for example {@code "utf-8"}.
|
||||||
|
* @param statusCode the status code needs to be in the ranges [100, 299], [400, 599].
|
||||||
|
* Causing a redirect by specifying a 3xx code is not supported.
|
||||||
|
* @param reasonPhrase the phrase describing the status code, for example "OK". Must be
|
||||||
|
* non-empty.
|
||||||
|
* @param responseHeaders the resource response's headers represented as a mapping of header
|
||||||
|
* name -> header value.
|
||||||
|
* @param data the input stream that provides the resource response's data. Must not be a
|
||||||
|
* StringBufferInputStream.
|
||||||
|
*/
|
||||||
|
public WebResourceResponse(String mimeType, String encoding, int statusCode,
|
||||||
|
@NonNull String reasonPhrase, Map<String, String> responseHeaders, InputStream data) {
|
||||||
|
this(mimeType, encoding, data);
|
||||||
|
setStatusCodeAndReasonPhrase(statusCode, reasonPhrase);
|
||||||
|
setResponseHeaders(responseHeaders);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the resource response's MIME type, for example "text/html".
|
||||||
|
*
|
||||||
|
* @param mimeType The resource response's MIME type
|
||||||
|
*/
|
||||||
|
public void setMimeType(String mimeType) {
|
||||||
|
checkImmutable();
|
||||||
|
mMimeType = mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the resource response's MIME type.
|
||||||
|
*
|
||||||
|
* @return The resource response's MIME type
|
||||||
|
*/
|
||||||
|
public String getMimeType() {
|
||||||
|
return mMimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the resource response's encoding, for example "UTF-8". This is used
|
||||||
|
* to decode the data from the input stream.
|
||||||
|
*
|
||||||
|
* @param encoding The resource response's encoding
|
||||||
|
*/
|
||||||
|
public void setEncoding(String encoding) {
|
||||||
|
checkImmutable();
|
||||||
|
mEncoding = encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the resource response's encoding.
|
||||||
|
*
|
||||||
|
* @return The resource response's encoding
|
||||||
|
*/
|
||||||
|
public String getEncoding() {
|
||||||
|
return mEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the resource response's status code and reason phrase.
|
||||||
|
*
|
||||||
|
* @param statusCode the status code needs to be in the ranges [100, 299], [400, 599].
|
||||||
|
* Causing a redirect by specifying a 3xx code is not supported.
|
||||||
|
* @param reasonPhrase the phrase describing the status code, for example "OK". Must be
|
||||||
|
* non-empty.
|
||||||
|
*/
|
||||||
|
public void setStatusCodeAndReasonPhrase(int statusCode, @NonNull String reasonPhrase) {
|
||||||
|
checkImmutable();
|
||||||
|
if (statusCode < 100)
|
||||||
|
throw new IllegalArgumentException("statusCode can't be less than 100.");
|
||||||
|
if (statusCode > 599)
|
||||||
|
throw new IllegalArgumentException("statusCode can't be greater than 599.");
|
||||||
|
if (statusCode > 299 && statusCode < 400)
|
||||||
|
throw new IllegalArgumentException("statusCode can't be in the [300, 399] range.");
|
||||||
|
if (reasonPhrase == null)
|
||||||
|
throw new IllegalArgumentException("reasonPhrase can't be null.");
|
||||||
|
if (reasonPhrase.trim().isEmpty())
|
||||||
|
throw new IllegalArgumentException("reasonPhrase can't be empty.");
|
||||||
|
for (int i = 0; i < reasonPhrase.length(); i++) {
|
||||||
|
int c = reasonPhrase.charAt(i);
|
||||||
|
if (c > 0x7F) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"reasonPhrase can't contain non-ASCII characters.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mStatusCode = statusCode;
|
||||||
|
mReasonPhrase = reasonPhrase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the resource response's status code.
|
||||||
|
*
|
||||||
|
* @return The resource response's status code.
|
||||||
|
*/
|
||||||
|
public int getStatusCode() {
|
||||||
|
return mStatusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the description of the resource response's status code.
|
||||||
|
*
|
||||||
|
* @return The description of the resource response's status code.
|
||||||
|
*/
|
||||||
|
public String getReasonPhrase() {
|
||||||
|
return mReasonPhrase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the headers for the resource response.
|
||||||
|
*
|
||||||
|
* @param headers Mapping of header name -> header value.
|
||||||
|
*/
|
||||||
|
public void setResponseHeaders(Map<String, String> headers) {
|
||||||
|
checkImmutable();
|
||||||
|
mResponseHeaders = headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the headers for the resource response.
|
||||||
|
*
|
||||||
|
* @return The headers for the resource response.
|
||||||
|
*/
|
||||||
|
public Map<String, String> getResponseHeaders() {
|
||||||
|
return mResponseHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the input stream that provides the resource response's data. Callers
|
||||||
|
* must implement {@link InputStream#read(byte[])}. {@link InputStream#close()}
|
||||||
|
* will be called after the WebView has finished with the response.
|
||||||
|
*
|
||||||
|
* @param data the input stream that provides the resource response's data. Must not be a
|
||||||
|
* StringBufferInputStream.
|
||||||
|
*/
|
||||||
|
public void setData(InputStream data) {
|
||||||
|
checkImmutable();
|
||||||
|
// If data is (or is a subclass of) StringBufferInputStream
|
||||||
|
if (data != null && StringBufferInputStream.class.isAssignableFrom(data.getClass())) {
|
||||||
|
throw new IllegalArgumentException("StringBufferInputStream is deprecated and must " +
|
||||||
|
"not be passed to a WebResourceResponse");
|
||||||
|
}
|
||||||
|
mInputStream = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the input stream that provides the resource response's data.
|
||||||
|
*
|
||||||
|
* @return The input stream that provides the resource response's data
|
||||||
|
*/
|
||||||
|
public InputStream getData() {
|
||||||
|
return mInputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The internal version of the constructor that doesn't perform arguments checks.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
public WebResourceResponse(boolean immutable, String mimeType, String encoding, int statusCode,
|
||||||
|
String reasonPhrase, Map<String, String> responseHeaders, InputStream data) {
|
||||||
|
mImmutable = immutable;
|
||||||
|
mMimeType = mimeType;
|
||||||
|
mEncoding = encoding;
|
||||||
|
mStatusCode = statusCode;
|
||||||
|
mReasonPhrase = reasonPhrase;
|
||||||
|
mResponseHeaders = responseHeaders;
|
||||||
|
mInputStream = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkImmutable() {
|
||||||
|
if (mImmutable)
|
||||||
|
throw new IllegalStateException("This WebResourceResponse instance is immutable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -31,6 +31,7 @@ import android.view.inputmethod.EditorInfo
|
|||||||
import android.view.inputmethod.InputConnection
|
import android.view.inputmethod.InputConnection
|
||||||
import android.view.textclassifier.TextClassifier
|
import android.view.textclassifier.TextClassifier
|
||||||
import android.webkit.DownloadListener
|
import android.webkit.DownloadListener
|
||||||
|
import android.webkit.PermissionRequest
|
||||||
import android.webkit.RenderProcessGoneDetail
|
import android.webkit.RenderProcessGoneDetail
|
||||||
import android.webkit.ValueCallback
|
import android.webkit.ValueCallback
|
||||||
import android.webkit.WebBackForwardList
|
import android.webkit.WebBackForwardList
|
||||||
@@ -62,11 +63,13 @@ import org.cef.browser.CefFrame
|
|||||||
import org.cef.browser.CefMessageRouter
|
import org.cef.browser.CefMessageRouter
|
||||||
import org.cef.browser.CefRendering
|
import org.cef.browser.CefRendering
|
||||||
import org.cef.callback.CefCallback
|
import org.cef.callback.CefCallback
|
||||||
|
import org.cef.callback.CefMediaAccessCallback
|
||||||
import org.cef.callback.CefQueryCallback
|
import org.cef.callback.CefQueryCallback
|
||||||
import org.cef.handler.CefDisplayHandlerAdapter
|
import org.cef.handler.CefDisplayHandlerAdapter
|
||||||
import org.cef.handler.CefLoadHandler
|
import org.cef.handler.CefLoadHandler
|
||||||
import org.cef.handler.CefLoadHandlerAdapter
|
import org.cef.handler.CefLoadHandlerAdapter
|
||||||
import org.cef.handler.CefMessageRouterHandlerAdapter
|
import org.cef.handler.CefMessageRouterHandlerAdapter
|
||||||
|
import org.cef.handler.CefPermissionHandler
|
||||||
import org.cef.handler.CefRequestHandler
|
import org.cef.handler.CefRequestHandler
|
||||||
import org.cef.handler.CefRequestHandlerAdapter
|
import org.cef.handler.CefRequestHandlerAdapter
|
||||||
import org.cef.handler.CefResourceHandler
|
import org.cef.handler.CefResourceHandler
|
||||||
@@ -167,6 +170,30 @@ class KcefWebViewProvider(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class CefPermissionRequest(
|
||||||
|
private val url: String,
|
||||||
|
private val permissionMask: Int,
|
||||||
|
private val callback: CefMediaAccessCallback,
|
||||||
|
) : PermissionRequest() {
|
||||||
|
override fun getOrigin(): Uri = Uri.parse(url)
|
||||||
|
|
||||||
|
override fun getResources(): Array<String> {
|
||||||
|
val retVal = mutableListOf<String>()
|
||||||
|
if ((permissionMask and (1 shl 0)) > 0) retVal.add(PermissionRequest.RESOURCE_AUDIO_CAPTURE)
|
||||||
|
if ((permissionMask and (1 shl 1)) > 0) retVal.add(PermissionRequest.RESOURCE_VIDEO_CAPTURE)
|
||||||
|
return retVal.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun grant(resources: Array<String>) {
|
||||||
|
// TODO: respect given resource grant
|
||||||
|
callback.Continue(permissionMask)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deny() {
|
||||||
|
callback.Cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private inner class DisplayHandler : CefDisplayHandlerAdapter() {
|
private inner class DisplayHandler : CefDisplayHandlerAdapter() {
|
||||||
override fun onConsoleMessage(
|
override fun onConsoleMessage(
|
||||||
browser: CefBrowser,
|
browser: CefBrowser,
|
||||||
@@ -363,7 +390,9 @@ class KcefWebViewProvider(
|
|||||||
Log.v(TAG, "Handling request from client's response for ${request.url}")
|
Log.v(TAG, "Handling request from client's response for ${request.url}")
|
||||||
try {
|
try {
|
||||||
resolvedData = webResponse.data.readAllBytes()
|
resolvedData = webResponse.data.readAllBytes()
|
||||||
|
Log.v(TAG, "Resolved client response for ${resolvedData?.size} bytes")
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
|
Log.w(TAG, "Failed to read client data", e)
|
||||||
}
|
}
|
||||||
callback.Continue()
|
callback.Continue()
|
||||||
return true
|
return true
|
||||||
@@ -375,7 +404,7 @@ class KcefWebViewProvider(
|
|||||||
redirectUrl: StringRef,
|
redirectUrl: StringRef,
|
||||||
) {
|
) {
|
||||||
super.getResponseHeaders(response, responseLength, redirectUrl)
|
super.getResponseHeaders(response, responseLength, redirectUrl)
|
||||||
webResponse.responseHeaders.forEach { response.setHeaderByName(it.key, it.value, true) }
|
webResponse.responseHeaders?.forEach { response.setHeaderByName(it.key, it.value, true) }
|
||||||
response.status = webResponse.statusCode
|
response.status = webResponse.statusCode
|
||||||
response.mimeType = webResponse.mimeType
|
response.mimeType = webResponse.mimeType
|
||||||
}
|
}
|
||||||
@@ -424,15 +453,22 @@ class KcefWebViewProvider(
|
|||||||
frame: CefFrame,
|
frame: CefFrame,
|
||||||
request: CefRequest,
|
request: CefRequest,
|
||||||
): CefResourceHandler? {
|
): CefResourceHandler? {
|
||||||
// TODO: we should be calling this on the handler, since CEF calls us on its IO thread
|
val isInitialLoad = frame.url == "" && request.method == "GET"
|
||||||
|
Log.v(TAG, "Request ${request.method} ${request.url} is initial? $isInitialLoad")
|
||||||
|
// NOTE: we should be calling this on the handler, since CEF calls us on its IO thread
|
||||||
|
// but docs say "This method is called on a thread other than the UI thread" so should be fine
|
||||||
val response =
|
val response =
|
||||||
viewClient.shouldInterceptRequest(
|
if (isInitialLoad) {
|
||||||
view,
|
null
|
||||||
CefWebResourceRequest(request, frame, false),
|
} else {
|
||||||
)
|
viewClient.shouldInterceptRequest(
|
||||||
|
view,
|
||||||
|
CefWebResourceRequest(request, frame, false),
|
||||||
|
)
|
||||||
|
}
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
// prefer user's response override
|
// prefer user's response override
|
||||||
urlHttpMapping.get(request.url)?.let {
|
urlHttpMapping.get(request.url.trimEnd('/'))?.let {
|
||||||
return HtmlResponseResourceHandler(it)
|
return HtmlResponseResourceHandler(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -469,6 +505,22 @@ class KcefWebViewProvider(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inner class PermissionHandler : CefPermissionHandler {
|
||||||
|
override fun onRequestMediaAccessPermission(
|
||||||
|
browser: CefBrowser,
|
||||||
|
frame: CefFrame,
|
||||||
|
requesting_url: String,
|
||||||
|
requested_permissions: Int,
|
||||||
|
callback: CefMediaAccessCallback,
|
||||||
|
): Boolean {
|
||||||
|
handler.post {
|
||||||
|
Log.v(TAG, "Checking permission for $requesting_url: $requested_permissions")
|
||||||
|
chromeClient.onPermissionRequest(CefPermissionRequest(requesting_url, requested_permissions, callback))
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun init(
|
override fun init(
|
||||||
javaScriptInterfaces: Map<String, Any>?,
|
javaScriptInterfaces: Map<String, Any>?,
|
||||||
privateBrowsing: Boolean,
|
privateBrowsing: Boolean,
|
||||||
@@ -480,6 +532,7 @@ class KcefWebViewProvider(
|
|||||||
addDisplayHandler(DisplayHandler())
|
addDisplayHandler(DisplayHandler())
|
||||||
addLoadHandler(LoadHandler())
|
addLoadHandler(LoadHandler())
|
||||||
addRequestHandler(RequestHandler())
|
addRequestHandler(RequestHandler())
|
||||||
|
addPermissionHandler(PermissionHandler())
|
||||||
|
|
||||||
val config = CefMessageRouter.CefMessageRouterConfig()
|
val config = CefMessageRouter.CefMessageRouterConfig()
|
||||||
config.jsQueryFunction = QUERY_FN
|
config.jsQueryFunction = QUERY_FN
|
||||||
@@ -615,7 +668,7 @@ class KcefWebViewProvider(
|
|||||||
browser =
|
browser =
|
||||||
(
|
(
|
||||||
baseUrl?.let { url ->
|
baseUrl?.let { url ->
|
||||||
urlHttpMapping.put(url, data)
|
urlHttpMapping.put(url.trimEnd('/'), data)
|
||||||
kcefClient!!.createBrowser(
|
kcefClient!!.createBrowser(
|
||||||
url,
|
url,
|
||||||
CefRendering.OFFSCREEN,
|
CefRendering.OFFSCREEN,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import com.typesafe.config.ConfigRenderOptions
|
|||||||
import com.typesafe.config.ConfigValue
|
import com.typesafe.config.ConfigValue
|
||||||
import com.typesafe.config.parser.ConfigDocument
|
import com.typesafe.config.parser.ConfigDocument
|
||||||
import dev.datlag.kcef.KCEF
|
import dev.datlag.kcef.KCEF
|
||||||
|
import dev.datlag.kcef.KCEFBuilder.Settings.LogSeverity
|
||||||
import eu.kanade.tachiyomi.App
|
import eu.kanade.tachiyomi.App
|
||||||
import eu.kanade.tachiyomi.createAppModule
|
import eu.kanade.tachiyomi.createAppModule
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
@@ -522,10 +523,11 @@ fun applicationSetup() {
|
|||||||
settings {
|
settings {
|
||||||
windowlessRenderingEnabled = true
|
windowlessRenderingEnabled = true
|
||||||
cachePath = (Path(applicationDirs.dataRoot) / "cache/kcef").toString()
|
cachePath = (Path(applicationDirs.dataRoot) / "cache/kcef").toString()
|
||||||
|
logSeverity = if (serverConfig.debugLogsEnabled.value) LogSeverity.Verbose else LogSeverity.Default
|
||||||
}
|
}
|
||||||
appHandler(
|
appHandler(
|
||||||
KCEF.AppHandler(
|
KCEF.AppHandler(
|
||||||
arrayOf("--disable-gpu", "--off-screen-rendering-enabled", "--disable-dev-shm-usage"),
|
arrayOf("--disable-gpu", "--off-screen-rendering-enabled", "--disable-dev-shm-usage", "--enable-widevine-cdm"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user