1 /*
2  * Copyright 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.webkit.internal;
18 
19 import androidx.annotation.NonNull;
20 import androidx.webkit.BlockingStartUpLocation;
21 import androidx.webkit.WebViewCompat;
22 import androidx.webkit.WebViewStartUpResult;
23 
24 import org.chromium.support_lib_boundary.WebViewStartUpCallbackBoundaryInterface;
25 import org.chromium.support_lib_boundary.WebViewStartUpResultBoundaryInterface;
26 import org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil;
27 
28 import java.io.PrintWriter;
29 import java.io.StringWriter;
30 import java.lang.reflect.InvocationHandler;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.Objects;
34 
35 /**
36  * Adapter between WebViewCompat.WebViewStartUpCallback and WebViewStartUpCallbackBoundaryInterface
37  * (the corresponding interface shared with the support library glue in the WebView APK).
38  */
39 public class WebViewStartUpCallbackAdapter implements WebViewStartUpCallbackBoundaryInterface {
40     private final WebViewCompat.WebViewStartUpCallback mWebViewStartUpCallback;
41 
WebViewStartUpCallbackAdapter( @onNull WebViewCompat.WebViewStartUpCallback webViewStartUpCallback)42     public WebViewStartUpCallbackAdapter(
43             @NonNull WebViewCompat.WebViewStartUpCallback webViewStartUpCallback) {
44         mWebViewStartUpCallback = webViewStartUpCallback;
45     }
46 
47     /**
48      * Adapter method for
49      * {@link androidx.webkit.WebViewCompat.WebViewStartUpCallback#onSuccess(WebViewStartUpResult)}.
50      */
51     @Override
onSuccess(@onNull InvocationHandler resultInvocationHandler)52     public void onSuccess(@NonNull InvocationHandler resultInvocationHandler) {
53         final WebViewStartUpResult result = webViewStartUpResultFromBoundaryInterface(
54                 Objects.requireNonNull(BoundaryInterfaceReflectionUtil.castToSuppLibClass(
55                         WebViewStartUpResultBoundaryInterface.class, resultInvocationHandler)));
56         mWebViewStartUpCallback.onSuccess(result);
57     }
58 
59     private static class BlockingStartUpLocationImpl implements BlockingStartUpLocation {
60         private final Throwable mThrowable;
61 
BlockingStartUpLocationImpl(Throwable t)62         BlockingStartUpLocationImpl(Throwable t) {
63             mThrowable = t;
64         }
65 
66         /**
67          * Gets the stack information depicting the code location.
68          */
69         @Override
getStackInformation()70         public String getStackInformation() {
71             StringWriter sw = new StringWriter();
72             mThrowable.printStackTrace(new PrintWriter(sw));
73             return sw.toString();
74         }
75     }
76 
webViewStartUpResultFromBoundaryInterface( @onNull WebViewStartUpResultBoundaryInterface result)77     private WebViewStartUpResult webViewStartUpResultFromBoundaryInterface(
78             @NonNull WebViewStartUpResultBoundaryInterface result) {
79         return new WebViewStartUpResult() {
80             private final List<BlockingStartUpLocation> mBlockingStartUpLocations =
81                     convertFromThrowables(result.getBlockingStartUpLocations());
82 
83             @Override
84             public Long getTotalTimeInUiThreadMillis() {
85                 return result.getTotalTimeInUiThreadMillis();
86             }
87 
88             @Override
89             public Long getMaxTimePerTaskInUiThreadMillis() {
90                 return result.getMaxTimePerTaskInUiThreadMillis();
91             }
92 
93             @Override
94             public List<BlockingStartUpLocation> getBlockingStartUpLocations() {
95                 return mBlockingStartUpLocations;
96             }
97 
98             private List<BlockingStartUpLocation> convertFromThrowables(
99                     List<Throwable> throwables) {
100                 List<BlockingStartUpLocation> blockingStartUpLocations = new ArrayList<>();
101                 for (Throwable location: throwables) {
102                     blockingStartUpLocations.add(new BlockingStartUpLocationImpl(location));
103                 }
104                 return blockingStartUpLocations;
105             }
106         };
107     }
108 }
109