1 /*
2  * Copyright (C) 2023 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 com.android.webview.tests;
18 
19 import com.android.tradefed.device.DeviceNotAvailableException;
20 import com.android.tradefed.invoker.TestInformation;
21 import com.android.tradefed.log.LogUtil.CLog;
22 import com.android.tradefed.util.CommandResult;
23 import com.android.tradefed.util.CommandStatus;
24 
25 import org.json.JSONException;
26 import org.json.JSONObject;
27 import org.junit.Assert;
28 
29 import java.io.BufferedReader;
30 import java.io.IOException;
31 import java.io.InputStreamReader;
32 import java.net.MalformedURLException;
33 import java.net.URL;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.List;
37 
38 public class WebviewUtils {
39     private TestInformation mTestInformation;
40 
WebviewUtils(TestInformation testInformation)41     public WebviewUtils(TestInformation testInformation) {
42         mTestInformation = testInformation;
43     }
44 
installWebview(String webviewVersion, String releaseChannel)45     public WebviewPackage installWebview(String webviewVersion, String releaseChannel)
46             throws IOException, InterruptedException, DeviceNotAvailableException,
47                     JSONException {
48         List<String> extraArgs = new ArrayList<>();
49         if (webviewVersion == null
50                 && Arrays.asList("beta", "stable").contains(releaseChannel.toLowerCase())) {
51             // Get current version of WebView in the stable or beta release channels.
52             CLog.i(
53                     "Getting the latest nightly official release version of the %s branch",
54                     releaseChannel);
55             String releaseChannelVersion = getNightlyBranchBuildVersion(releaseChannel);
56             Assert.assertNotNull(
57                     String.format(
58                             "Could not retrieve the latest "
59                                     + "nightly release version of the %s channel",
60                             releaseChannel),
61                     releaseChannelVersion);
62             // Install the latest official build compiled for the beta or stable branches.
63             extraArgs.addAll(
64                     Arrays.asList("--milestone", releaseChannelVersion.split("\\.", 2)[0]));
65         }
66         CommandResult commandResult =
67                 WebviewInstallerToolPreparer.runWebviewInstallerToolCommand(
68                         mTestInformation, webviewVersion, releaseChannel, extraArgs);
69 
70         Assert.assertEquals(
71                 "The WebView installer tool failed to install WebView:\n"
72                         + commandResult.toString(),
73                 commandResult.getStatus(),
74                 CommandStatus.SUCCESS);
75 
76         printWebviewVersion();
77         return getCurrentWebviewPackage();
78     }
79 
getNightlyBranchBuildVersion(String releaseChannel)80     private static String getNightlyBranchBuildVersion(String releaseChannel)
81             throws IOException, JSONException, MalformedURLException {
82         final URL versionHistoryUrl = new URL(
83             "https://versionhistory.googleapis.com/v1/chrome/platforms/webview/channels/"
84             + releaseChannel.toLowerCase() + "/versions/");
85         StringBuilder json = new StringBuilder();
86         try (BufferedReader bufferedReader =
87                 new BufferedReader(
88                         new InputStreamReader(versionHistoryUrl.openConnection().getInputStream()))) {
89             String jsonLine = null;
90             while ((jsonLine = bufferedReader.readLine()) != null) {
91                 json.append(jsonLine);
92             }
93         }
94         String content = json.toString();
95         JSONObject object = new JSONObject(content);
96         return object.getJSONArray("versions").getJSONObject(0).getString("version");
97     }
98 
uninstallWebview( WebviewPackage webviewPackage, WebviewPackage preInstalledWebviewPackage)99     public void uninstallWebview(
100             WebviewPackage webviewPackage, WebviewPackage preInstalledWebviewPackage)
101             throws DeviceNotAvailableException {
102         Assert.assertNotEquals(
103                 "Test is attempting to uninstall the preinstalled WebView provider",
104                 webviewPackage,
105                 preInstalledWebviewPackage);
106         updateWebviewImplementation(preInstalledWebviewPackage.getPackageName());
107         mTestInformation
108                 .getDevice()
109                 .executeAdbCommand("uninstall", webviewPackage.getPackageName());
110         printWebviewVersion();
111     }
112 
updateWebviewImplementation(String webviewPackageName)113     private void updateWebviewImplementation(String webviewPackageName)
114             throws DeviceNotAvailableException {
115         CommandResult res =
116                 mTestInformation
117                         .getDevice()
118                         .executeShellV2Command(
119                                 String.format(
120                                         "cmd webviewupdate set-webview-implementation %s",
121                                         webviewPackageName));
122         Assert.assertEquals(
123                 "Failed to set webview update: " + res, res.getStatus(), CommandStatus.SUCCESS);
124     }
125 
getCurrentWebviewPackage()126     public WebviewPackage getCurrentWebviewPackage() throws DeviceNotAvailableException {
127         String dumpsys = mTestInformation.getDevice().executeShellCommand("dumpsys webviewupdate");
128         return WebviewPackage.buildFromDumpsys(dumpsys);
129     }
130 
printWebviewVersion()131     public void printWebviewVersion() throws DeviceNotAvailableException {
132         WebviewPackage currentWebview = getCurrentWebviewPackage();
133         printWebviewVersion(currentWebview);
134     }
135 
printWebviewVersion(WebviewPackage currentWebview)136     public void printWebviewVersion(WebviewPackage currentWebview)
137             throws DeviceNotAvailableException {
138         CLog.i("Current webview implementation: %s", currentWebview.getPackageName());
139         CLog.i("Current webview version: %s", currentWebview.getVersion());
140     }
141 }
142