blob: 4a105e18e9bae0ea287295d0439dc7af25ee037f [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;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010025import android.os.Binder;
Gustav Senntonc83e3fa2016-02-18 12:19:13 +000026import android.os.PatternMatcher;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010027import android.os.Process;
Gustav Senntonc83e3fa2016-02-18 12:19:13 +000028import android.os.ResultReceiver;
Dianne Hackborn354736e2016-08-22 17:00:05 -070029import android.os.ShellCallback;
Gustav Sennton23875b22016-02-09 14:11:33 +000030import android.os.UserHandle;
Primiano Tucci810c0522014-07-25 18:03:16 +010031import android.util.Slog;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010032import android.webkit.IWebViewUpdateService;
Gustav Sennton6258dcd2015-10-30 19:25:37 +000033import android.webkit.WebViewProviderInfo;
34import android.webkit.WebViewProviderResponse;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010035
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +010036import com.android.server.SystemService;
37
Gustav Senntonc83e3fa2016-02-18 12:19:13 +000038import java.io.FileDescriptor;
Gustav Sennton1eb38202016-10-21 13:40:10 +010039import java.io.PrintWriter;
Gustav Sennton6258dcd2015-10-30 19:25:37 +000040import java.util.Arrays;
Gustav Sennton6258dcd2015-10-30 19:25:37 +000041
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010042/**
43 * Private service to wait for the updatable WebView to be ready for use.
44 * @hide
45 */
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +010046public class WebViewUpdateService extends SystemService {
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010047
48 private static final String TAG = "WebViewUpdateService";
Gustav Sennton6ce92c92015-10-23 11:10:39 +010049
Ben Murdochdc00a842014-07-17 14:55:00 +010050 private BroadcastReceiver mWebViewUpdatedReceiver;
Gustav Sennton79fea482016-04-07 14:22:56 +010051 private WebViewUpdateServiceImpl mImpl;
Ben Murdochdc00a842014-07-17 14:55:00 +010052
Gustav Sennton3a6e6b22016-04-05 14:09:09 +010053 static final int PACKAGE_CHANGED = 0;
54 static final int PACKAGE_ADDED = 1;
55 static final int PACKAGE_ADDED_REPLACED = 2;
56 static final int PACKAGE_REMOVED = 3;
57
Ben Murdochdc00a842014-07-17 14:55:00 +010058 public WebViewUpdateService(Context context) {
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +010059 super(context);
Hui Shu9455bd02016-04-08 13:25:26 -070060 mImpl = new WebViewUpdateServiceImpl(context, SystemImpl.getInstance());
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +010061 }
62
63 @Override
64 public void onStart() {
Ben Murdochdc00a842014-07-17 14:55:00 +010065 mWebViewUpdatedReceiver = new BroadcastReceiver() {
66 @Override
67 public void onReceive(Context context, Intent intent) {
Gustav Sennton0df2c552016-06-14 15:32:19 +010068 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
Gustav Sennton3a6e6b22016-04-05 14:09:09 +010069 switch (intent.getAction()) {
70 case Intent.ACTION_PACKAGE_REMOVED:
71 // When a package is replaced we will receive two intents, one
72 // representing the removal of the old package and one representing the
73 // addition of the new package.
74 // In the case where we receive an intent to remove the old version of
75 // the package that is being replaced we early-out here so that we don't
76 // run the update-logic twice.
77 if (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) return;
Gustav Sennton79fea482016-04-07 14:22:56 +010078 mImpl.packageStateChanged(packageNameFromIntent(intent),
Gustav Sennton0df2c552016-06-14 15:32:19 +010079 PACKAGE_REMOVED, userId);
Gustav Sennton3a6e6b22016-04-05 14:09:09 +010080 break;
81 case Intent.ACTION_PACKAGE_CHANGED:
82 // Ensure that we only heed PACKAGE_CHANGED intents if they change an
83 // entire package, not just a component
84 if (entirePackageChanged(intent)) {
Gustav Sennton79fea482016-04-07 14:22:56 +010085 mImpl.packageStateChanged(packageNameFromIntent(intent),
Gustav Sennton0df2c552016-06-14 15:32:19 +010086 PACKAGE_CHANGED, userId);
Gustav Sennton6258dcd2015-10-30 19:25:37 +000087 }
Gustav Sennton3a6e6b22016-04-05 14:09:09 +010088 break;
89 case Intent.ACTION_PACKAGE_ADDED:
Gustav Sennton79fea482016-04-07 14:22:56 +010090 mImpl.packageStateChanged(packageNameFromIntent(intent),
Gustav Sennton3a6e6b22016-04-05 14:09:09 +010091 (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)
Gustav Sennton0df2c552016-06-14 15:32:19 +010092 ? PACKAGE_ADDED_REPLACED : PACKAGE_ADDED), userId);
Gustav Sennton3a6e6b22016-04-05 14:09:09 +010093 break;
94 case Intent.ACTION_USER_ADDED:
Gustav Sennton79fea482016-04-07 14:22:56 +010095 mImpl.handleNewUser(userId);
Gustav Sennton3a6e6b22016-04-05 14:09:09 +010096 break;
Gustav Sennton364e1602016-12-14 09:10:50 +000097 case Intent.ACTION_USER_REMOVED:
98 mImpl.handleUserRemoved(userId);
99 break;
Ben Murdochdc00a842014-07-17 14:55:00 +0100100 }
101 }
102 };
103 IntentFilter filter = new IntentFilter();
Gustav Sennton3098cf22015-11-10 03:33:09 +0000104 filter.addAction(Intent.ACTION_PACKAGE_ADDED);
105 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000106 filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
Ben Murdochdc00a842014-07-17 14:55:00 +0100107 filter.addDataScheme("package");
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000108 // Make sure we only receive intents for WebView packages from our config file.
Gustav Sennton79fea482016-04-07 14:22:56 +0100109 for (WebViewProviderInfo provider : mImpl.getWebViewPackages()) {
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000110 filter.addDataSchemeSpecificPart(provider.packageName, PatternMatcher.PATTERN_LITERAL);
111 }
Gustav Sennton0df2c552016-06-14 15:32:19 +0100112
113 getContext().registerReceiverAsUser(mWebViewUpdatedReceiver, UserHandle.ALL, filter,
114 null /* broadcast permission */, null /* handler */);
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100115
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000116 IntentFilter userAddedFilter = new IntentFilter();
117 userAddedFilter.addAction(Intent.ACTION_USER_ADDED);
Gustav Sennton364e1602016-12-14 09:10:50 +0000118 userAddedFilter.addAction(Intent.ACTION_USER_REMOVED);
Gustav Sennton0df2c552016-06-14 15:32:19 +0100119 getContext().registerReceiverAsUser(mWebViewUpdatedReceiver, UserHandle.ALL,
120 userAddedFilter, null /* broadcast permission */, null /* handler */);
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000121
Torne (Richard Coles)fc19b0a2016-02-01 16:16:57 +0000122 publishBinderService("webviewupdate", new BinderService(), true /*allowIsolated*/);
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100123 }
Ben Murdochdc00a842014-07-17 14:55:00 +0100124
Gustav Sennton3a6e6b22016-04-05 14:09:09 +0100125 public void prepareWebViewInSystemServer() {
Gustav Sennton79fea482016-04-07 14:22:56 +0100126 mImpl.prepareWebViewInSystemServer();
Gustav Sennton3a6e6b22016-04-05 14:09:09 +0100127 }
128
129 private static String packageNameFromIntent(Intent intent) {
130 return intent.getDataString().substring("package:".length());
131 }
132
Gustav Sennton065b7e62016-04-01 15:11:43 +0100133 /**
134 * Returns whether the entire package from an ACTION_PACKAGE_CHANGED intent was changed (rather
135 * than just one of its components).
136 * @hide
137 */
138 public static boolean entirePackageChanged(Intent intent) {
139 String[] componentList =
140 intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
141 return Arrays.asList(componentList).contains(
142 intent.getDataString().substring("package:".length()));
Gustav Senntondbf5eb02016-03-30 14:53:03 +0100143 }
144
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100145 private class BinderService extends IWebViewUpdateService.Stub {
146
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000147 @Override
148 public void onShellCommand(FileDescriptor in, FileDescriptor out,
Dianne Hackborn354736e2016-08-22 17:00:05 -0700149 FileDescriptor err, String[] args, ShellCallback callback,
150 ResultReceiver resultReceiver) {
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000151 (new WebViewUpdateServiceShellCommand(this)).exec(
Dianne Hackborn354736e2016-08-22 17:00:05 -0700152 this, in, out, err, args, callback, resultReceiver);
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000153 }
154
155
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100156 /**
157 * The shared relro process calls this to notify us that it's done trying to create a relro
158 * file. This method gets called even if the relro creation has failed or the process
159 * crashed.
160 */
161 @Override // Binder call
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000162 public void notifyRelroCreationCompleted() {
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100163 // Verify that the caller is either the shared relro process (nominal case) or the
164 // system server (only in the case the relro process crashes and we get here via the
165 // crashHandler).
166 if (Binder.getCallingUid() != Process.SHARED_RELRO_UID &&
167 Binder.getCallingUid() != Process.SYSTEM_UID) {
168 return;
169 }
170
Gustav Sennton275d13c2016-02-24 10:58:09 +0000171 long callingId = Binder.clearCallingIdentity();
172 try {
Gustav Sennton79fea482016-04-07 14:22:56 +0100173 WebViewUpdateService.this.mImpl.notifyRelroCreationCompleted();
Gustav Sennton275d13c2016-02-24 10:58:09 +0000174 } finally {
175 Binder.restoreCallingIdentity(callingId);
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100176 }
177 }
178
179 /**
180 * WebViewFactory calls this to block WebView loading until the relro file is created.
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000181 * Returns the WebView provider for which we create relro files.
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100182 */
183 @Override // Binder call
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000184 public WebViewProviderResponse waitForAndGetProvider() {
Primiano Tuccie76e81a2014-07-29 16:38:33 +0100185 // The WebViewUpdateService depends on the prepareWebViewInSystemServer call, which
186 // happens later (during the PHASE_ACTIVITY_MANAGER_READY) in SystemServer.java. If
187 // another service there tries to bring up a WebView in the between, the wait below
188 // would deadlock without the check below.
189 if (Binder.getCallingPid() == Process.myPid()) {
190 throw new IllegalStateException("Cannot create a WebView from the SystemServer");
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100191 }
192
Gustav Sennton79fea482016-04-07 14:22:56 +0100193 return WebViewUpdateService.this.mImpl.waitForAndGetProvider();
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000194 }
195
196 /**
197 * This is called from DeveloperSettings when the user changes WebView provider.
198 */
199 @Override // Binder call
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000200 public String changeProviderAndSetting(String newProvider) {
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000201 if (getContext().checkCallingPermission(
202 android.Manifest.permission.WRITE_SECURE_SETTINGS)
203 != PackageManager.PERMISSION_GRANTED) {
204 String msg = "Permission Denial: changeProviderAndSetting() from pid="
205 + Binder.getCallingPid()
206 + ", uid=" + Binder.getCallingUid()
207 + " requires " + android.Manifest.permission.WRITE_SECURE_SETTINGS;
208 Slog.w(TAG, msg);
209 throw new SecurityException(msg);
210 }
211
Gustav Senntonab3b6b12016-03-16 17:38:42 +0000212 long callingId = Binder.clearCallingIdentity();
213 try {
Gustav Sennton79fea482016-04-07 14:22:56 +0100214 return WebViewUpdateService.this.mImpl.changeProviderAndSetting(
Gustav Sennton3a6e6b22016-04-05 14:09:09 +0100215 newProvider);
Gustav Senntonab3b6b12016-03-16 17:38:42 +0000216 } finally {
217 Binder.restoreCallingIdentity(callingId);
218 }
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000219 }
220
221 @Override // Binder call
222 public WebViewProviderInfo[] getValidWebViewPackages() {
Gustav Sennton79fea482016-04-07 14:22:56 +0100223 return WebViewUpdateService.this.mImpl.getValidWebViewPackages();
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000224 }
225
226 @Override // Binder call
Gustav Sennton8b179262016-03-14 11:31:14 +0000227 public WebViewProviderInfo[] getAllWebViewPackages() {
Gustav Sennton79fea482016-04-07 14:22:56 +0100228 return WebViewUpdateService.this.mImpl.getWebViewPackages();
Gustav Sennton8b179262016-03-14 11:31:14 +0000229 }
230
231 @Override // Binder call
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000232 public String getCurrentWebViewPackageName() {
Gustav Senntonbf683e02016-09-15 14:42:50 +0100233 PackageInfo pi = WebViewUpdateService.this.mImpl.getCurrentWebViewPackage();
234 return pi == null ? null : pi.packageName;
235 }
236
237 @Override // Binder call
238 public PackageInfo getCurrentWebViewPackage() {
239 return WebViewUpdateService.this.mImpl.getCurrentWebViewPackage();
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100240 }
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000241
242 @Override // Binder call
243 public boolean isFallbackPackage(String packageName) {
Gustav Sennton79fea482016-04-07 14:22:56 +0100244 return WebViewUpdateService.this.mImpl.isFallbackPackage(packageName);
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000245 }
246
247 @Override // Binder call
248 public void enableFallbackLogic(boolean enable) {
249 if (getContext().checkCallingPermission(
250 android.Manifest.permission.WRITE_SECURE_SETTINGS)
251 != PackageManager.PERMISSION_GRANTED) {
252 String msg = "Permission Denial: enableFallbackLogic() from pid="
253 + Binder.getCallingPid()
254 + ", uid=" + Binder.getCallingUid()
255 + " requires " + android.Manifest.permission.WRITE_SECURE_SETTINGS;
256 Slog.w(TAG, msg);
257 throw new SecurityException(msg);
258 }
259
Gustav Sennton6824c7c2016-04-04 14:07:23 +0100260 long callingId = Binder.clearCallingIdentity();
261 try {
262 WebViewUpdateService.this.mImpl.enableFallbackLogic(enable);
263 } finally {
264 Binder.restoreCallingIdentity(callingId);
265 }
Gustav Senntonc83e3fa2016-02-18 12:19:13 +0000266 }
Gustav Sennton1eb38202016-10-21 13:40:10 +0100267
Torne (Richard Coles)1a4c4e32017-01-10 15:57:41 +0000268 @Override // Binder call
269 public boolean isMultiProcessEnabled() {
270 return WebViewUpdateService.this.mImpl.isMultiProcessEnabled();
271 }
272
273 @Override // Binder call
274 public void enableMultiProcess(boolean enable) {
275 if (getContext().checkCallingPermission(
276 android.Manifest.permission.WRITE_SECURE_SETTINGS)
277 != PackageManager.PERMISSION_GRANTED) {
278 String msg = "Permission Denial: enableMultiProcess() from pid="
279 + Binder.getCallingPid()
280 + ", uid=" + Binder.getCallingUid()
281 + " requires " + android.Manifest.permission.WRITE_SECURE_SETTINGS;
282 Slog.w(TAG, msg);
283 throw new SecurityException(msg);
284 }
285
286 long callingId = Binder.clearCallingIdentity();
287 try {
288 WebViewUpdateService.this.mImpl.enableMultiProcess(enable);
289 } finally {
290 Binder.restoreCallingIdentity(callingId);
291 }
292 }
293
Gustav Sennton1eb38202016-10-21 13:40:10 +0100294 @Override
295 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
296 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
297 != PackageManager.PERMISSION_GRANTED) {
298
299 pw.println("Permission Denial: can't dump webviewupdate service from pid="
300 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
301 return;
302 }
303
304 WebViewUpdateService.this.mImpl.dumpState(pw);
305 }
Torne (Richard Coles)4dbeb352014-07-29 19:14:24 +0100306 }
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100307}