1 /*
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 
17 package com.android.server.webkit;
18 
19 import android.content.Context;
20 import android.content.pm.PackageInfo;
21 import android.content.pm.PackageManager.NameNotFoundException;
22 import android.content.pm.UserInfo;
23 import android.webkit.UserPackage;
24 import android.webkit.WebViewProviderInfo;
25 
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 
31 public class TestSystemImpl implements SystemInterface {
32     private String mUserProvider = null;
33     private final WebViewProviderInfo[] mPackageConfigs;
34     List<Integer> mUsers = new ArrayList<>();
35     // Package -> [user, package]
36     Map<String, Map<Integer, PackageInfo>> mPackages = new HashMap();
37     private final int mNumRelros;
38     private final boolean mIsDebuggable;
39     private int mMultiProcessSetting;
40     private final boolean mMultiProcessDefault;
41 
42     public static final int PRIMARY_USER_ID = 0;
43 
TestSystemImpl(WebViewProviderInfo[] packageConfigs, int numRelros, boolean isDebuggable, boolean multiProcessDefault)44     public TestSystemImpl(WebViewProviderInfo[] packageConfigs, int numRelros, boolean isDebuggable,
45             boolean multiProcessDefault) {
46         mPackageConfigs = packageConfigs;
47         mNumRelros = numRelros;
48         mIsDebuggable = isDebuggable;
49         mUsers.add(PRIMARY_USER_ID);
50         mMultiProcessDefault = multiProcessDefault;
51     }
52 
addUser(int userId)53     public void addUser(int userId) {
54         mUsers.add(userId);
55     }
56 
57     @Override
getWebViewPackages()58     public WebViewProviderInfo[] getWebViewPackages() {
59         return mPackageConfigs;
60     }
61 
62     @Override
onWebViewProviderChanged(PackageInfo packageInfo)63     public int onWebViewProviderChanged(PackageInfo packageInfo) {
64         return mNumRelros;
65     }
66 
67     @Override
getUserChosenWebViewProvider(Context context)68     public String getUserChosenWebViewProvider(Context context) { return mUserProvider; }
69 
70     @Override
updateUserSetting(Context context, String newProviderName)71     public void updateUserSetting(Context context, String newProviderName) {
72         mUserProvider = newProviderName;
73     }
74 
75     @Override
killPackageDependents(String packageName)76     public void killPackageDependents(String packageName) {}
77 
78     @Override
enablePackageForAllUsers(Context context, String packageName, boolean enable)79     public void enablePackageForAllUsers(Context context, String packageName, boolean enable) {
80         for(int userId : mUsers) {
81             enablePackageForUser(packageName, enable, userId);
82         }
83     }
84 
enablePackageForUser(String packageName, boolean enable, int userId)85     private void enablePackageForUser(String packageName, boolean enable, int userId) {
86         Map<Integer, PackageInfo> userPackages = mPackages.get(packageName);
87         if (userPackages == null) {
88             throw new IllegalArgumentException("There is no package called " + packageName);
89         }
90         PackageInfo packageInfo = userPackages.get(userId);
91         packageInfo.applicationInfo.enabled = enable;
92         setPackageInfoForUser(userId, packageInfo);
93     }
94 
95     @Override
systemIsDebuggable()96     public boolean systemIsDebuggable() { return mIsDebuggable; }
97 
98     @Override
getPackageInfoForProvider(WebViewProviderInfo info)99     public PackageInfo getPackageInfoForProvider(WebViewProviderInfo info) throws
100             NameNotFoundException {
101         Map<Integer, PackageInfo> userPackages = mPackages.get(info.packageName);
102         if (userPackages == null) throw new NameNotFoundException(info.packageName);
103         PackageInfo ret = userPackages.get(PRIMARY_USER_ID);
104         if (ret == null) throw new NameNotFoundException(info.packageName);
105         return ret;
106     }
107 
108     @Override
getPackageInfoForProviderAllUsers( Context context, WebViewProviderInfo info)109     public List<UserPackage> getPackageInfoForProviderAllUsers(
110             Context context, WebViewProviderInfo info) {
111         Map<Integer, PackageInfo> userPackages = mPackages.get(info.packageName);
112         List<UserPackage> ret = new ArrayList();
113         // Loop over defined users, and find the corresponding package for each user.
114         for (int userId : mUsers) {
115             ret.add(new UserPackage(createUserInfo(userId),
116                     userPackages == null ? null : userPackages.get(userId)));
117         }
118         return ret;
119     }
120 
createUserInfo(int userId)121     private static UserInfo createUserInfo(int userId) {
122         return new UserInfo(userId, "User nr. " + userId, 0 /* flags */);
123     }
124 
125     /**
126      * Set package for primary user.
127      */
setPackageInfo(PackageInfo pi)128     public void setPackageInfo(PackageInfo pi) {
129         setPackageInfoForUser(PRIMARY_USER_ID, pi);
130     }
131 
setPackageInfoForUser(int userId, PackageInfo pi)132     public void setPackageInfoForUser(int userId, PackageInfo pi) {
133         if (!mUsers.contains(userId)) {
134             throw new IllegalArgumentException("User nr. " + userId + " doesn't exist");
135         }
136         if (!mPackages.containsKey(pi.packageName)) {
137             mPackages.put(pi.packageName, new HashMap<Integer, PackageInfo>());
138         }
139         mPackages.get(pi.packageName).put(userId, pi);
140     }
141 
142     /**
143      * Removes the package {@param packageName} for the primary user.
144      */
removePackageInfo(String packageName)145     public void removePackageInfo(String packageName) {
146         mPackages.get(packageName).remove(PRIMARY_USER_ID);
147     }
148 
149     @Override
getFactoryPackageVersion(String packageName)150     public long getFactoryPackageVersion(String packageName) throws NameNotFoundException {
151         PackageInfo pi = null;
152         Map<Integer, PackageInfo> userPackages = mPackages.get(packageName);
153         if (userPackages == null) throw new NameNotFoundException();
154 
155         pi = userPackages.get(PRIMARY_USER_ID);
156         if (pi != null && pi.applicationInfo.isSystemApp()) {
157             return pi.applicationInfo.longVersionCode;
158         }
159         throw new NameNotFoundException();
160     }
161 
162     @Override
getMultiProcessSetting(Context context)163     public int getMultiProcessSetting(Context context) {
164         return mMultiProcessSetting;
165     }
166 
167     @Override
setMultiProcessSetting(Context context, int value)168     public void setMultiProcessSetting(Context context, int value) {
169         mMultiProcessSetting = value;
170     }
171 
172     @Override
notifyZygote(boolean enableMultiProcess)173     public void notifyZygote(boolean enableMultiProcess) {}
174 
175     @Override
ensureZygoteStarted()176     public void ensureZygoteStarted() {}
177 
178     @Override
isMultiProcessDefaultEnabled()179     public boolean isMultiProcessDefaultEnabled() {
180         return mMultiProcessDefault;
181     }
182 }
183