blob: 75ccf355ecd7f5fb8d51ac9634dd61b19872a7aa [file] [log] [blame]
Gustav Sennton6258dcd2015-10-30 19:25:37 +00001/*
2 * Copyright (C) 2015 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
17package android.webkit;
18
19import android.app.AppGlobals;
20import android.content.pm.ApplicationInfo;
21import android.content.pm.PackageInfo;
22import android.content.pm.PackageManager;
23import android.content.pm.Signature;
24import android.os.Build;
25import android.os.Parcel;
26import android.os.Parcelable;
27import android.util.AndroidRuntimeException;
28import android.util.Base64;
29
30import java.util.Arrays;
31
32/** @hide */
33public class WebViewProviderInfo implements Parcelable {
34
35 /**
36 * @hide
37 */
38 public static class WebViewPackageNotFoundException extends AndroidRuntimeException {
39 public WebViewPackageNotFoundException(String message) { super(message); }
40 public WebViewPackageNotFoundException(Exception e) { super(e); }
41 }
42
Gustav Senntonc83e3fa2016-02-18 12:19:13 +000043 public WebViewProviderInfo(String packageName, String description, boolean availableByDefault,
44 boolean isFallback, String[] signatures) {
Gustav Sennton6258dcd2015-10-30 19:25:37 +000045 this.packageName = packageName;
46 this.description = description;
Gustav Senntonc83e3fa2016-02-18 12:19:13 +000047 this.availableByDefault = availableByDefault;
48 this.isFallback = isFallback;
Gustav Sennton5c2454c2015-12-17 15:49:33 +000049 this.signatures = signatures;
Gustav Sennton6258dcd2015-10-30 19:25:37 +000050 }
51
52 private boolean hasValidSignature() {
53 if (Build.IS_DEBUGGABLE)
54 return true;
55 Signature[] packageSignatures;
56 try {
57 // If no signature is declared, instead check whether the package is included in the
58 // system.
Gustav Sennton5c2454c2015-12-17 15:49:33 +000059 if (signatures == null || signatures.length == 0)
Gustav Sennton6258dcd2015-10-30 19:25:37 +000060 return getPackageInfo().applicationInfo.isSystemApp();
61
62 packageSignatures = getPackageInfo().signatures;
63 } catch (WebViewPackageNotFoundException e) {
64 return false;
65 }
66 if (packageSignatures.length != 1)
67 return false;
Gustav Sennton5c2454c2015-12-17 15:49:33 +000068
69 final byte[] packageSignature = packageSignatures[0].toByteArray();
70 // Return whether the package signature matches any of the valid signatures
71 for (String signature : signatures) {
72 final byte[] validSignature = Base64.decode(signature, Base64.DEFAULT);
73 if (Arrays.equals(packageSignature, validSignature))
74 return true;
75 }
76 return false;
Gustav Sennton6258dcd2015-10-30 19:25:37 +000077 }
78
79 /**
80 * Returns whether this provider is valid for use as a WebView provider.
81 */
82 public boolean isValidProvider() {
83 ApplicationInfo applicationInfo;
84 try {
85 applicationInfo = getPackageInfo().applicationInfo;
86 } catch (WebViewPackageNotFoundException e) {
87 return false;
88 }
89 if (hasValidSignature() && WebViewFactory.getWebViewLibrary(applicationInfo) != null) {
90 return true;
91 }
92 return false;
93 }
94
Gustav Sennton27f13de2016-01-05 20:22:02 +000095 /**
96 * Returns whether this package is enabled.
97 * This state can be changed by the user from Settings->Apps
98 */
99 public boolean isEnabled() {
100 try {
Gustav Sennton14c033c2016-02-11 12:51:27 +0000101 // Explicitly fetch up-to-date package info here since the enabled-state of the package
102 // might have changed since we last fetched its package info.
103 updatePackageInfo();
104 return getPackageInfo().applicationInfo.enabled;
Gustav Sennton27f13de2016-01-05 20:22:02 +0000105 } catch (WebViewPackageNotFoundException e) {
106 return false;
Gustav Sennton27f13de2016-01-05 20:22:02 +0000107 }
108 }
109
110 /**
111 * Returns whether the provider is always available as long as it is valid.
112 * If this returns false, the provider will only be used if the user chose this provider.
113 */
114 public boolean isAvailableByDefault() {
115 return availableByDefault;
116 }
117
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000118 public boolean isFallbackPackage() {
119 return isFallback;
120 }
121
Gustav Sennton14c033c2016-02-11 12:51:27 +0000122 private void updatePackageInfo() {
123 try {
124 PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
125 packageInfo = pm.getPackageInfo(packageName, PACKAGE_FLAGS);
126 } catch (PackageManager.NameNotFoundException e) {
127 throw new WebViewPackageNotFoundException(e);
128 }
129 }
130
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000131 public PackageInfo getPackageInfo() {
132 if (packageInfo == null) {
Gustav Sennton14c033c2016-02-11 12:51:27 +0000133 updatePackageInfo();
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000134 }
135 return packageInfo;
136 }
137
138 // aidl stuff
139 public static final Parcelable.Creator<WebViewProviderInfo> CREATOR =
140 new Parcelable.Creator<WebViewProviderInfo>() {
141 public WebViewProviderInfo createFromParcel(Parcel in) {
142 return new WebViewProviderInfo(in);
143 }
144
145 public WebViewProviderInfo[] newArray(int size) {
146 return new WebViewProviderInfo[size];
147 }
148 };
149
150 private WebViewProviderInfo(Parcel in) {
151 packageName = in.readString();
152 description = in.readString();
Gustav Sennton8b179262016-03-14 11:31:14 +0000153 availableByDefault = (in.readInt() > 0);
154 isFallback = (in.readInt() > 0);
Gustav Sennton5c2454c2015-12-17 15:49:33 +0000155 signatures = in.createStringArray();
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000156 packageInfo = null;
157 }
158
159 @Override
160 public int describeContents() {
161 return 0;
162 }
163
164 @Override
165 public void writeToParcel(Parcel out, int flags) {
166 out.writeString(packageName);
167 out.writeString(description);
Gustav Sennton8b179262016-03-14 11:31:14 +0000168 out.writeInt(availableByDefault ? 1 : 0);
169 out.writeInt(isFallback ? 1 : 0);
Gustav Sennton5c2454c2015-12-17 15:49:33 +0000170 out.writeStringArray(signatures);
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000171 }
172
173 // fields read from framework resource
174 public String packageName;
175 public String description;
Gustav Sennton27f13de2016-01-05 20:22:02 +0000176 private boolean availableByDefault;
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000177 private boolean isFallback;
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000178
Gustav Sennton5c2454c2015-12-17 15:49:33 +0000179 private String[] signatures;
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000180
181 private PackageInfo packageInfo;
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000182
Jeff Sharkeyc5967e92016-01-07 18:50:29 -0700183 // flags declaring we want extra info from the package manager
184 private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA
185 | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
186}