blob: 4dbd02d1ede5ef3980b5b53037af2527696a843b [file] [log] [blame]
Gustav Sennton8b179262016-03-14 11:31:14 +00001/*
2 * Copyright (C) 2016 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 com.android.server.webkit;
18
19import android.app.ActivityManagerNative;
20import android.app.AppGlobals;
21import android.content.Context;
22import android.content.pm.PackageInfo;
23import android.content.res.XmlResourceParser;
24import android.os.RemoteException;
25import android.os.UserHandle;
26import android.provider.Settings;
27import android.util.AndroidRuntimeException;
28import android.util.Log;
29import android.webkit.WebViewFactory;
30import android.webkit.WebViewFactory.MissingWebViewPackageException;
31import android.webkit.WebViewProviderInfo;
32
33import com.android.internal.util.XmlUtils;
34
35import java.io.IOException;
36import java.util.ArrayList;
37import java.util.List;
38
39import org.xmlpull.v1.XmlPullParserException;
40
41/**
42 * Default implementation for the WebView preparation Utility interface.
43 * @hide
44 */
45public class WebViewUtilityImpl implements WebViewUtilityInterface {
46 private static final String TAG = WebViewUtilityImpl.class.getSimpleName();
47 private static final String TAG_START = "webviewproviders";
48 private static final String TAG_WEBVIEW_PROVIDER = "webviewprovider";
49 private static final String TAG_PACKAGE_NAME = "packageName";
50 private static final String TAG_DESCRIPTION = "description";
51 // Whether or not the provider must be explicitly chosen by the user to be used.
52 private static final String TAG_AVAILABILITY = "availableByDefault";
53 private static final String TAG_SIGNATURE = "signature";
54 private static final String TAG_FALLBACK = "isFallback";
55
56 /**
57 * Returns all packages declared in the framework resources as potential WebView providers.
58 * @hide
59 * */
60 @Override
61 public WebViewProviderInfo[] getWebViewPackages() {
62 int numFallbackPackages = 0;
63 XmlResourceParser parser = null;
64 List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>();
65 try {
66 parser = AppGlobals.getInitialApplication().getResources().getXml(
67 com.android.internal.R.xml.config_webview_packages);
68 XmlUtils.beginDocument(parser, TAG_START);
69 while(true) {
70 XmlUtils.nextElement(parser);
71 String element = parser.getName();
72 if (element == null) {
73 break;
74 }
75 if (element.equals(TAG_WEBVIEW_PROVIDER)) {
76 String packageName = parser.getAttributeValue(null, TAG_PACKAGE_NAME);
77 if (packageName == null) {
78 throw new MissingWebViewPackageException(
79 "WebView provider in framework resources missing package name");
80 }
81 String description = parser.getAttributeValue(null, TAG_DESCRIPTION);
82 if (description == null) {
83 throw new MissingWebViewPackageException(
84 "WebView provider in framework resources missing description");
85 }
86 boolean availableByDefault = "true".equals(
87 parser.getAttributeValue(null, TAG_AVAILABILITY));
88 boolean isFallback = "true".equals(
89 parser.getAttributeValue(null, TAG_FALLBACK));
90 WebViewProviderInfo currentProvider =
91 new WebViewProviderInfo(packageName, description, availableByDefault,
92 isFallback, readSignatures(parser));
93 if (currentProvider.isFallbackPackage()) {
94 numFallbackPackages++;
95 if (numFallbackPackages > 1) {
96 throw new AndroidRuntimeException(
97 "There can be at most one webview fallback package.");
98 }
99 }
100 webViewProviders.add(currentProvider);
101 }
102 else {
103 Log.e(TAG, "Found an element that is not a webview provider");
104 }
105 }
106 } catch(XmlPullParserException e) {
107 throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e);
108 } catch(IOException e) {
109 throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e);
110 } finally {
111 if (parser != null) parser.close();
112 }
113 return webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]);
114 }
115
116 /**
117 * Reads all signatures at the current depth (within the current provider) from the XML parser.
118 */
119 private static String[] readSignatures(XmlResourceParser parser) throws IOException,
120 XmlPullParserException {
121 List<String> signatures = new ArrayList<String>();
122 int outerDepth = parser.getDepth();
123 while(XmlUtils.nextElementWithin(parser, outerDepth)) {
124 if (parser.getName().equals(TAG_SIGNATURE)) {
125 // Parse the value within the signature tag
126 String signature = parser.nextText();
127 signatures.add(signature);
128 } else {
129 Log.e(TAG, "Found an element in a webview provider that is not a signature");
130 }
131 }
132 return signatures.toArray(new String[signatures.size()]);
133 }
134
135 @Override
136 public int onWebViewProviderChanged(PackageInfo packageInfo) {
137 return WebViewFactory.onWebViewProviderChanged(packageInfo);
138 }
139
140 @Override
141 public String getUserChosenWebViewProvider(Context context) {
142 return Settings.Global.getString(context.getContentResolver(),
143 Settings.Global.WEBVIEW_PROVIDER);
144 }
145
146 @Override
147 public void updateUserSetting(Context context, String newProviderName) {
148 Settings.Global.putString(context.getContentResolver(),
149 Settings.Global.WEBVIEW_PROVIDER,
150 newProviderName == null ? "" : newProviderName);
151 }
152
153 @Override
154 public void killPackageDependents(String packageName) {
155 try {
156 ActivityManagerNative.getDefault().killPackageDependents(packageName,
157 UserHandle.USER_ALL);
158 } catch (RemoteException e) {
159 }
160 }
161}