157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton/*
257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton * Copyright 2018 The Android Open Source Project
357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton *
457d3714176493740842e8e2d0700106a6b64f048Gustav Sennton * Licensed under the Apache License, Version 2.0 (the "License");
557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton * you may not use this file except in compliance with the License.
657d3714176493740842e8e2d0700106a6b64f048Gustav Sennton * You may obtain a copy of the License at
757d3714176493740842e8e2d0700106a6b64f048Gustav Sennton *
857d3714176493740842e8e2d0700106a6b64f048Gustav Sennton *      http://www.apache.org/licenses/LICENSE-2.0
957d3714176493740842e8e2d0700106a6b64f048Gustav Sennton *
1057d3714176493740842e8e2d0700106a6b64f048Gustav Sennton * Unless required by applicable law or agreed to in writing, software
1157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton * distributed under the License is distributed on an "AS IS" BASIS,
1257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton * See the License for the specific language governing permissions and
1457d3714176493740842e8e2d0700106a6b64f048Gustav Sennton * limitations under the License.
1557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton */
1657d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
1757d3714176493740842e8e2d0700106a6b64f048Gustav Senntonpackage androidx.webkit.internal;
1857d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
1957d3714176493740842e8e2d0700106a6b64f048Gustav Senntonimport android.annotation.SuppressLint;
2057d3714176493740842e8e2d0700106a6b64f048Gustav Senntonimport android.webkit.ServiceWorkerWebSettings;
2157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
222ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Senntonimport androidx.annotation.NonNull;
232ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Senntonimport androidx.annotation.RequiresApi;
2457d3714176493740842e8e2d0700106a6b64f048Gustav Senntonimport androidx.webkit.ServiceWorkerWebSettingsCompat;
2557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
2657d3714176493740842e8e2d0700106a6b64f048Gustav Senntonimport org.chromium.support_lib_boundary.ServiceWorkerWebSettingsBoundaryInterface;
272ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Senntonimport org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil;
282ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton
292ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Senntonimport java.lang.reflect.InvocationHandler;
302ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Senntonimport java.lang.reflect.Proxy;
3157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
3257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton/**
3357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton * Implementation of {@link ServiceWorkerWebSettingsCompat}.
3457d3714176493740842e8e2d0700106a6b64f048Gustav Sennton * This class uses either the framework, the WebView APK, or both, to implement
3557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton * {@link ServiceWorkerWebSettingsCompat} functionality.
3657d3714176493740842e8e2d0700106a6b64f048Gustav Sennton */
3757d3714176493740842e8e2d0700106a6b64f048Gustav Senntonpublic class ServiceWorkerWebSettingsImpl extends ServiceWorkerWebSettingsCompat {
382ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton    private ServiceWorkerWebSettings mFrameworksImpl;
3957d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    private ServiceWorkerWebSettingsBoundaryInterface mBoundaryInterface;
4057d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
4157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    /**
4257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton     * This class handles three different scenarios:
4357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton     * 1. The Android version on the device is high enough to support all APIs used.
4457d3714176493740842e8e2d0700106a6b64f048Gustav Sennton     * 2. The Android version on the device is too low to support any ServiceWorkerWebSettings APIs
4557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton     * so we use the support library glue instead through
4657d3714176493740842e8e2d0700106a6b64f048Gustav Sennton     * {@link ServiceWorkerWebSettingsBoundaryInterface}.
4757d3714176493740842e8e2d0700106a6b64f048Gustav Sennton     * 3. The Android version on the device is high enough to support some ServiceWorkerWebSettings
4857d3714176493740842e8e2d0700106a6b64f048Gustav Sennton     * APIs, so we call into them using {@link android.webkit.ServiceWorkerWebSettings}, but the
4957d3714176493740842e8e2d0700106a6b64f048Gustav Sennton     * rest of the APIs are only supported by the support library glue, so whenever we call such an
5057d3714176493740842e8e2d0700106a6b64f048Gustav Sennton     * API we fetch a {@link ServiceWorkerWebSettingsBoundaryInterface} corresponding to our
5157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton     * {@link android.webkit.ServiceWorkerWebSettings}.
5257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton     */
532ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton    public ServiceWorkerWebSettingsImpl(@NonNull ServiceWorkerWebSettings settings) {
542ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton        mFrameworksImpl = settings;
552ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton    }
562ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton
572ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton    public ServiceWorkerWebSettingsImpl(@NonNull InvocationHandler invocationHandler) {
582ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton        mBoundaryInterface = BoundaryInterfaceReflectionUtil.castToSuppLibClass(
592ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton                ServiceWorkerWebSettingsBoundaryInterface.class, invocationHandler);
602ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton    }
612ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton
622ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton    @RequiresApi(24)
632ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton    private ServiceWorkerWebSettings getFrameworksImpl() {
642ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton        if (mFrameworksImpl == null) {
652ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            mFrameworksImpl =
662ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton                    WebViewGlueCommunicator.getCompatConverter().convertServiceWorkerSettings(
672ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton                            Proxy.getInvocationHandler(mBoundaryInterface));
6857d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        }
692ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton        return mFrameworksImpl;
7057d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    }
7157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
7257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    private ServiceWorkerWebSettingsBoundaryInterface getBoundaryInterface() {
732ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton        if (mBoundaryInterface == null) {
742ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            // If the boundary interface is null we must have a working frameworks implementation to
752ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            // convert into a boundary interface.
762ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            // The case of the boundary interface being null here only occurs if we created the
772ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            // ServiceWorkerWebSettingsImpl using a frameworks API, but now want to call an API on
782ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            // the ServiceWorkerWebSettingsImpl that is only supported by the support library glue.
792ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            // This could happen for example if we introduce a new ServiceWorkerWebSettings API in
802ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            // level 30 and we run the support library on an N device (whose framework supports
812ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            // ServiceWorkerWebSettings).
822ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            mBoundaryInterface = BoundaryInterfaceReflectionUtil.castToSuppLibClass(
832ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton                    ServiceWorkerWebSettingsBoundaryInterface.class,
842ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton                    WebViewGlueCommunicator.getCompatConverter().convertServiceWorkerSettings(
852ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton                            mFrameworksImpl));
862ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton        }
8757d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        return mBoundaryInterface;
8857d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    }
8957d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
9057d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @SuppressLint("NewApi")
9157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @Override
9257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    public void setCacheMode(int mode) {
9357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_CACHE_MODE;
9457d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        if (feature.isSupportedByFramework()) {
952ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            getFrameworksImpl().setCacheMode(mode);
9657d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else if (feature.isSupportedByWebView()) {
9757d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            getBoundaryInterface().setCacheMode(mode);
9857d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else {
9957d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            throw WebViewFeatureInternal.getUnsupportedOperationException();
10057d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        }
10157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    }
10257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
10357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @SuppressLint("NewApi")
10457d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @Override
10557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    public int getCacheMode() {
10657d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_CACHE_MODE;
10757d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        if (feature.isSupportedByFramework()) {
1082ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            return getFrameworksImpl().getCacheMode();
10957d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else if (feature.isSupportedByWebView()) {
11057d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            return getBoundaryInterface().getCacheMode();
11157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else {
11257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            throw WebViewFeatureInternal.getUnsupportedOperationException();
11357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        }
11457d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    }
11557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
11657d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @SuppressLint("NewApi")
11757d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @Override
11857d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    public void setAllowContentAccess(boolean allow) {
11957d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_CONTENT_ACCESS;
12057d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        if (feature.isSupportedByFramework()) {
1212ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            getFrameworksImpl().setAllowContentAccess(allow);
12257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else if (feature.isSupportedByWebView()) {
12357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            getBoundaryInterface().setAllowContentAccess(allow);
12457d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else {
12557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            throw WebViewFeatureInternal.getUnsupportedOperationException();
12657d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        }
12757d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    }
12857d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
12957d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @SuppressLint("NewApi")
13057d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @Override
13157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    public boolean getAllowContentAccess() {
13257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_CONTENT_ACCESS;
13357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        if (feature.isSupportedByFramework()) {
1342ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            return getFrameworksImpl().getAllowContentAccess();
13557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else if (feature.isSupportedByWebView()) {
13657d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            return getBoundaryInterface().getAllowContentAccess();
13757d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else {
13857d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            throw WebViewFeatureInternal.getUnsupportedOperationException();
13957d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        }
14057d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    }
14157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
14257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @SuppressLint("NewApi")
14357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @Override
14457d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    public void setAllowFileAccess(boolean allow) {
14557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_FILE_ACCESS;
14657d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        if (feature.isSupportedByFramework()) {
1472ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            getFrameworksImpl().setAllowFileAccess(allow);
14857d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else if (feature.isSupportedByWebView()) {
14957d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            getBoundaryInterface().setAllowFileAccess(allow);
15057d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else {
15157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            throw WebViewFeatureInternal.getUnsupportedOperationException();
15257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        }
15357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    }
15457d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
15557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @SuppressLint("NewApi")
15657d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @Override
15757d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    public boolean getAllowFileAccess() {
15857d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_FILE_ACCESS;
15957d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        if (feature.isSupportedByFramework()) {
1602ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            return getFrameworksImpl().getAllowFileAccess();
16157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else if (feature.isSupportedByWebView()) {
16257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            return getBoundaryInterface().getAllowFileAccess();
16357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else {
16457d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            throw WebViewFeatureInternal.getUnsupportedOperationException();
16557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        }
16657d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    }
16757d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
16857d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @SuppressLint("NewApi")
16957d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @Override
17057d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    public void setBlockNetworkLoads(boolean flag) {
17157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        final WebViewFeatureInternal feature =
17257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton                WebViewFeatureInternal.SERVICE_WORKER_BLOCK_NETWORK_LOADS;
17357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        if (feature.isSupportedByFramework()) {
1742ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            getFrameworksImpl().setBlockNetworkLoads(flag);
17557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else if (feature.isSupportedByWebView()) {
17657d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            getBoundaryInterface().setBlockNetworkLoads(flag);
17757d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else {
17857d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            throw WebViewFeatureInternal.getUnsupportedOperationException();
17957d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        }
18057d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    }
18157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton
18257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @SuppressLint("NewApi")
18357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    @Override
18457d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    public boolean getBlockNetworkLoads() {
18557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        final WebViewFeatureInternal feature =
18657d3714176493740842e8e2d0700106a6b64f048Gustav Sennton                WebViewFeatureInternal.SERVICE_WORKER_BLOCK_NETWORK_LOADS;
18757d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        if (feature.isSupportedByFramework()) {
1882ce86e26e35d90fc8a12484710c2cacedfaf9f9dGustav Sennton            return getFrameworksImpl().getBlockNetworkLoads();
18957d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else if (feature.isSupportedByWebView()) {
19057d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            return getBoundaryInterface().getBlockNetworkLoads();
19157d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        } else {
19257d3714176493740842e8e2d0700106a6b64f048Gustav Sennton            throw WebViewFeatureInternal.getUnsupportedOperationException();
19357d3714176493740842e8e2d0700106a6b64f048Gustav Sennton        }
19457d3714176493740842e8e2d0700106a6b64f048Gustav Sennton    }
19557d3714176493740842e8e2d0700106a6b64f048Gustav Sennton}
196