blob: 8130546e26990a02a9e3f06ff95bcd9531c6d24a [file] [log] [blame]
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +01001/*
2 * Copyright (C) 2012 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
Ben Murdochdc00a842014-07-17 14:55:00 +010019import android.content.BroadcastReceiver;
20import android.content.Context;
21import android.content.Intent;
22import android.content.IntentFilter;
Gustav Senntonbf683e02016-09-15 14:42:50 +010023import android.content.pm.PackageInfo;
Gustav Sennton6258dcd2015-10-30 19:25:37 +000024import android.content.pm.PackageManager;
Patrick Baumannefb37362020-01-14 14:49:07 -080025import android.content.pm.PackageManagerInternal;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010026import android.os.Binder;
Gustav Senntonc83e3fa2016-02-18 12:19:13 +000027import android.os.PatternMatcher;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010028import android.os.Process;
Gustav Senntonc83e3fa2016-02-18 12:19:13 +000029import android.os.ResultReceiver;
Dianne Hackborn354736e2016-08-22 17:00:05 -070030import android.os.ShellCallback;
Gustav Sennton23875b22016-02-09 14:11:33 +000031import android.os.UserHandle;
Primiano Tucci810c0522014-07-25 18:03:16 +010032import android.util.Slog;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010033import android.webkit.IWebViewUpdateService;
Gustav Sennton6258dcd2015-10-30 19:25:37 +000034import android.webkit.WebViewProviderInfo;
35import android.webkit.WebViewProviderResponse;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010036
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060037import com.android.internal.util.DumpUtils;
Patrick Baumannefb37362020-01-14 14:49:07 -080038import com.android.server.LocalServices;
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +010039import com.android.server.SystemService;
40
Gustav Senntonc83e3fa2016-02-18 12:19:13 +000041import java.io.FileDescriptor;
Gustav Sennton1eb38202016-10-21 13:40:10 +010042import java.io.PrintWriter;
Gustav Sennton6258dcd2015-10-30 19:25:37 +000043import java.util.Arrays;
Gustav Sennton6258dcd2015-10-30 19:25:37 +000044
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010045/**
46 * Private service to wait for the updatable WebView to be ready for use.
47 * @hide
48 */
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +010049public class WebViewUpdateService extends SystemService {
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010050
51 private static final String TAG = "WebViewUpdateService";
Gustav Sennton6ce92c92015-10-23 11:10:39 +010052
Ben Murdochdc00a842014-07-17 14:55:00 +010053 private BroadcastReceiver mWebViewUpdatedReceiver;
Gustav Sennton79fea482016-04-07 14:22:56 +010054 private WebViewUpdateServiceImpl mImpl;
Ben Murdochdc00a842014-07-17 14:55:00 +010055
Gustav Sennton3a6e6b22016-04-05 14:09:09 +010056 static final int PACKAGE_CHANGED = 0;
57 static final int PACKAGE_ADDED = 1;
58 static final int PACKAGE_ADDED_REPLACED = 2;
59 static final int PACKAGE_REMOVED = 3;
60
Ben Murdochdc00a842014-07-17 14:55:00 +010061 public WebViewUpdateService(Context context) {
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +010062 super(context);
Hui Shu9455bd02016-04-08 13:25:26 -070063 mImpl = new WebViewUpdateServiceImpl(context, SystemImpl.getInstance());
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +010064 }
65
66 @Override
67 public void onStart() {
Ben Murdochdc00a842014-07-17 14:55:00 +010068 mWebViewUpdatedReceiver = new BroadcastReceiver() {
69 @Override
70 public void onReceive(Context context, Intent intent) {
Gustav Sennton0df2c552016-06-14 15:32:19 +010071 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
Gustav Sennton3a6e6b22016-04-05 14:09:09 +010072 switch (intent.getAction()) {
73 case Intent.ACTION_PACKAGE_REMOVED:
74 // When a package is replaced we will receive two intents, one
75 // representing the removal of the old package and one representing the
76 // addition of the new package.
77 // In the case where we receive an intent to remove the old version of
78 // the package that is being replaced we early-out here so that we don't
79 // run the update-logic twice.
80 if (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) return;
Gustav Sennton79fea482016-04-07 14:22:56 +010081 mImpl.packageStateChanged(packageNameFromIntent(intent),
Gustav Sennton0df2c552016-06-14 15:32:19 +010082 PACKAGE_REMOVED, userId);
Gustav Sennton3a6e6b22016-04-05 14:09:09 +010083 break;
84 case Intent.ACTION_PACKAGE_CHANGED:
85 // Ensure that we only heed PACKAGE_CHANGED intents if they change an
86 // entire package, not just a component
87 if (entirePackageChanged(intent)) {
Gustav Sennton79fea482016-04-07 14:22:56 +010088 mImpl.packageStateChanged(packageNameFromIntent(intent),
Gustav Sennton0df2c552016-06-14 15:32:19 +010089 PACKAGE_CHANGED, userId);
Gustav Sennton6258dcd2015-10-30 19:25:37 +000090 }
Gustav Sennton3a6e6b22016-04-05 14:09:09 +010091 break;
92 case Intent.ACTION_PACKAGE_ADDED:
Gustav Sennton79fea482016-04-07 14:22:56 +010093 mImpl.packageStateChanged(packageNameFromIntent(intent),
Gustav Sennton3a6e6b22016-04-05 14:09:09 +010094 (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)
Gustav Sennton0df2c552016-06-14 15:32:19 +010095 ? PACKAGE_ADDED_REPLACED : PACKAGE_ADDED), userId);
Gustav Sennton3a6e6b22016-04-05 14:09:09 +010096 break;
Gustav Senntona43f1442017-03-23 17:04:23 +000097 case Intent.ACTION_USER_STARTED:
Gustav Sennton79fea482016-04-07 14:22:56 +010098 mImpl.handleNewUser(userId);
Gustav Sennton3a6e6b22016-04-05 14:09:09 +010099 break;
Gustav Sennton364e1602016-12-14 09:10:50 +0000100 case Intent.ACTION_USER_REMOVED:
101 mImpl.handleUserRemoved(userId);
102 break;
Ben Murdochdc00a842014-07-17 14:55:00 +0100103 }
104 }
105 };
106 IntentFilter filter = new IntentFilter();
Gustav Sennton3098cf22015-11-10 03:33:09 +0000107 filter.addAction(Intent.ACTION_PACKAGE_ADDED);
108 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000109 filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
Ben Murdochdc00a842014-07-17 14:55:00 +0100110 filter.addDataScheme("package");
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000111 // Make sure we only receive intents for WebView packages from our config file.
Gustav Sennton79fea482016-04-07 14:22:56 +0100112 for (WebViewProviderInfo provider : mImpl.getWebViewPackages()) {
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000113 filter.addDataSchemeSpecificPart(provider.packageName, PatternMatcher.PATTERN_LITERAL);
114 }
Gustav Sennton0df2c552016-06-14 15:32:19 +0100115
116 getContext().registerReceiverAsUser(mWebViewUpdatedReceiver, UserHandle.ALL, filter,
117 null /* broadcast permission */, null /* handler */);
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100118
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000119 IntentFilter userAddedFilter = new IntentFilter();
Gustav Senntona43f1442017-03-23 17:04:23 +0000120 userAddedFilter.addAction(Intent.ACTION_USER_STARTED);
Gustav Sennton364e1602016-12-14 09:10:50 +0000121 userAddedFilter.addAction(Intent.ACTION_USER_REMOVED);
Gustav Sennton0df2c552016-06-14 15:32:19 +0100122 getContext().registerReceiverAsUser(mWebViewUpdatedReceiver, UserHandle.ALL,
123 userAddedFilter, null /* broadcast permission */, null /* handler */);
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000124
Torne (Richard Coles)fc19b0a2016-02-01 16:16:57 +0000125 publishBinderService("webviewupdate", new BinderService(), true /*allowIsolated*/);
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100126 }
Ben Murdochdc00a842014-07-17 14:55:00 +0100127
Gustav Sennton3a6e6b22016-04-05 14:09:09 +0100128 public void prepareWebViewInSystemServer() {
Gustav Sennton79fea482016-04-07 14:22:56 +0100129 mImpl.prepareWebViewInSystemServer();
Gustav Sennton3a6e6b22016-04-05 14:09:09 +0100130 }
131
132 private static String packageNameFromIntent(Intent intent) {
133 return intent.getDataString().substring("package:".length());
134 }
135
Gustav Sennton065b7e62016-04-01 15:11:43 +0100136 /**
137 * Returns whether the entire package from an ACTION_PACKAGE_CHANGED intent was changed (rather
138 * than just one of its components).
139 * @hide
140 */
141 public static boolean entirePackageChanged(Intent intent) {
142 String[] componentList =
143 intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
144 return Arrays.asList(componentList).contains(
145 intent.getDataString().substring("package:".length()));
Gustav Senntondbf5eb02016-03-30 14:53:03 +0100146 }
147
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100148 private class BinderService extends IWebViewUpdateService.Stub {
149
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000150 @Override
151 public void onShellCommand(FileDescriptor in, FileDescriptor out,
Dianne Hackborn354736e2016-08-22 17:00:05 -0700152 FileDescriptor err, String[] args, ShellCallback callback,
153 ResultReceiver resultReceiver) {
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000154 (new WebViewUpdateServiceShellCommand(this)).exec(
Dianne Hackborn354736e2016-08-22 17:00:05 -0700155 this, in, out, err, args, callback, resultReceiver);
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000156 }
157
158
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100159 /**
160 * The shared relro process calls this to notify us that it's done trying to create a relro
161 * file. This method gets called even if the relro creation has failed or the process
162 * crashed.
163 */
164 @Override // Binder call
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000165 public void notifyRelroCreationCompleted() {
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100166 // Verify that the caller is either the shared relro process (nominal case) or the
167 // system server (only in the case the relro process crashes and we get here via the
168 // crashHandler).
169 if (Binder.getCallingUid() != Process.SHARED_RELRO_UID &&
170 Binder.getCallingUid() != Process.SYSTEM_UID) {
171 return;
172 }
173
Gustav Sennton275d13c2016-02-24 10:58:09 +0000174 long callingId = Binder.clearCallingIdentity();
175 try {
Gustav Sennton79fea482016-04-07 14:22:56 +0100176 WebViewUpdateService.this.mImpl.notifyRelroCreationCompleted();
Gustav Sennton275d13c2016-02-24 10:58:09 +0000177 } finally {
178 Binder.restoreCallingIdentity(callingId);
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100179 }
180 }
181
182 /**
183 * WebViewFactory calls this to block WebView loading until the relro file is created.
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000184 * Returns the WebView provider for which we create relro files.
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100185 */
186 @Override // Binder call
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000187 public WebViewProviderResponse waitForAndGetProvider() {
Primiano Tuccie76e81a2014-07-29 16:38:33 +0100188 // The WebViewUpdateService depends on the prepareWebViewInSystemServer call, which
189 // happens later (during the PHASE_ACTIVITY_MANAGER_READY) in SystemServer.java. If
190 // another service there tries to bring up a WebView in the between, the wait below
191 // would deadlock without the check below.
192 if (Binder.getCallingPid() == Process.myPid()) {
193 throw new IllegalStateException("Cannot create a WebView from the SystemServer");
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100194 }
195
Patrick Baumannefb37362020-01-14 14:49:07 -0800196 final WebViewProviderResponse webViewProviderResponse =
197 WebViewUpdateService.this.mImpl.waitForAndGetProvider();
198 if (webViewProviderResponse.packageInfo != null) {
199 grantVisibilityToCaller(
200 webViewProviderResponse.packageInfo.packageName, Binder.getCallingUid());
201 }
202 return webViewProviderResponse;
203 }
204
205 /**
206 * Grants app visibility of the webViewPackageName to the currently bound caller.
207 * @param webViewPackageName
208 */
209 private void grantVisibilityToCaller(String webViewPackageName, int callingUid) {
210 final PackageManagerInternal pmInternal = LocalServices.getService(
211 PackageManagerInternal.class);
212 final int webviewUid = pmInternal.getPackageUidInternal(
213 webViewPackageName, 0, UserHandle.getUserId(callingUid));
214 pmInternal.grantImplicitAccess(UserHandle.getUserId(callingUid), null, webviewUid,
215 UserHandle.getAppId(callingUid));
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000216 }
217
218 /**
219 * This is called from DeveloperSettings when the user changes WebView provider.
220 */
221 @Override // Binder call
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000222 public String changeProviderAndSetting(String newProvider) {
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000223 if (getContext().checkCallingPermission(
224 android.Manifest.permission.WRITE_SECURE_SETTINGS)
225 != PackageManager.PERMISSION_GRANTED) {
226 String msg = "Permission Denial: changeProviderAndSetting() from pid="
227 + Binder.getCallingPid()
228 + ", uid=" + Binder.getCallingUid()
229 + " requires " + android.Manifest.permission.WRITE_SECURE_SETTINGS;
230 Slog.w(TAG, msg);
231 throw new SecurityException(msg);
232 }
233
Gustav Senntonab3b6b12016-03-16 17:38:42 +0000234 long callingId = Binder.clearCallingIdentity();
235 try {
Gustav Sennton79fea482016-04-07 14:22:56 +0100236 return WebViewUpdateService.this.mImpl.changeProviderAndSetting(
Gustav Sennton3a6e6b22016-04-05 14:09:09 +0100237 newProvider);
Gustav Senntonab3b6b12016-03-16 17:38:42 +0000238 } finally {
239 Binder.restoreCallingIdentity(callingId);
240 }
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000241 }
242
243 @Override // Binder call
244 public WebViewProviderInfo[] getValidWebViewPackages() {
Gustav Sennton79fea482016-04-07 14:22:56 +0100245 return WebViewUpdateService.this.mImpl.getValidWebViewPackages();
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000246 }
247
248 @Override // Binder call
Gustav Sennton8b179262016-03-14 11:31:14 +0000249 public WebViewProviderInfo[] getAllWebViewPackages() {
Gustav Sennton79fea482016-04-07 14:22:56 +0100250 return WebViewUpdateService.this.mImpl.getWebViewPackages();
Gustav Sennton8b179262016-03-14 11:31:14 +0000251 }
252
253 @Override // Binder call
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000254 public String getCurrentWebViewPackageName() {
Patrick Baumannefb37362020-01-14 14:49:07 -0800255 PackageInfo pi = getCurrentWebViewPackage();
Gustav Senntonbf683e02016-09-15 14:42:50 +0100256 return pi == null ? null : pi.packageName;
257 }
258
259 @Override // Binder call
260 public PackageInfo getCurrentWebViewPackage() {
Patrick Baumannefb37362020-01-14 14:49:07 -0800261 final PackageInfo currentWebViewPackage =
262 WebViewUpdateService.this.mImpl.getCurrentWebViewPackage();
263 if (currentWebViewPackage != null) {
264 grantVisibilityToCaller(currentWebViewPackage.packageName, Binder.getCallingUid());
265 }
266 return currentWebViewPackage;
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100267 }
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000268
269 @Override // Binder call
Torne (Richard Coles)1a4c4e32017-01-10 15:57:41 +0000270 public boolean isMultiProcessEnabled() {
271 return WebViewUpdateService.this.mImpl.isMultiProcessEnabled();
272 }
273
274 @Override // Binder call
275 public void enableMultiProcess(boolean enable) {
276 if (getContext().checkCallingPermission(
277 android.Manifest.permission.WRITE_SECURE_SETTINGS)
278 != PackageManager.PERMISSION_GRANTED) {
279 String msg = "Permission Denial: enableMultiProcess() from pid="
280 + Binder.getCallingPid()
281 + ", uid=" + Binder.getCallingUid()
282 + " requires " + android.Manifest.permission.WRITE_SECURE_SETTINGS;
283 Slog.w(TAG, msg);
284 throw new SecurityException(msg);
285 }
286
287 long callingId = Binder.clearCallingIdentity();
288 try {
289 WebViewUpdateService.this.mImpl.enableMultiProcess(enable);
290 } finally {
291 Binder.restoreCallingIdentity(callingId);
292 }
293 }
294
Gustav Sennton1eb38202016-10-21 13:40:10 +0100295 @Override
296 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600297 if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
Gustav Sennton1eb38202016-10-21 13:40:10 +0100298 WebViewUpdateService.this.mImpl.dumpState(pw);
299 }
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100300 }
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100301}