OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser; |
| 6 |
| 7 import android.test.suitebuilder.annotation.MediumTest; |
| 8 import android.text.TextUtils; |
| 9 |
| 10 import org.chromium.base.BuildInfo; |
| 11 import org.chromium.base.test.util.Feature; |
| 12 import org.chromium.chrome.test.ChromeActivityTestCaseBase; |
| 13 |
| 14 import java.io.BufferedReader; |
| 15 import java.io.IOException; |
| 16 import java.io.InputStreamReader; |
| 17 import java.util.ArrayList; |
| 18 import java.util.HashSet; |
| 19 import java.util.regex.Matcher; |
| 20 import java.util.regex.Pattern; |
| 21 |
| 22 /** |
| 23 * Test to make sure browser and renderer are seperated process. |
| 24 */ |
| 25 public class ProcessIsolationTest extends ChromeActivityTestCaseBase<ChromeActiv
ity> { |
| 26 private Pattern mUidPattern; |
| 27 |
| 28 public ProcessIsolationTest() { |
| 29 super(ChromeActivity.class); |
| 30 } |
| 31 |
| 32 /** |
| 33 * Verifies that process isolation works, i.e., that the browser and |
| 34 * renderer processes use different user IDs. |
| 35 * @throws InterruptedException |
| 36 * BUG: 471122 |
| 37 */ |
| 38 @MediumTest |
| 39 @Feature({"Browser", "Security"}) |
| 40 public void testProcessIsolationForRenderers() throws InterruptedException { |
| 41 int tabsCount = getActivity().getCurrentTabModel().getCount(); |
| 42 // The ActivityManager can be used to retrieve the current processes, bu
t the reported UID |
| 43 // in the RunningAppProcessInfo for isolated processes is the same as th
e parent process |
| 44 // (see b/7724486, closed as "Working as intended"). |
| 45 // So we have to resort to parsing the ps output. |
| 46 String packageName = BuildInfo.getPackageName(getInstrumentation().getTa
rgetContext()); |
| 47 assertFalse("Failed to retrieve package name for current version of Chro
me.", |
| 48 TextUtils.isEmpty(packageName)); |
| 49 |
| 50 ArrayList<String> uids = new ArrayList<String>(); |
| 51 BufferedReader reader = null; |
| 52 boolean hasBrowserProcess = false; |
| 53 int rendererProcessesCount = 0; |
| 54 StringBuilder sb = new StringBuilder(); |
| 55 try { |
| 56 Process psProcess = Runtime.getRuntime().exec("ps"); |
| 57 reader = new BufferedReader(new InputStreamReader(psProcess.getInput
Stream())); |
| 58 String line; |
| 59 while ((line = reader.readLine()) != null) { |
| 60 sb.append(line).append('\n'); |
| 61 if (line.indexOf(packageName) != -1) { |
| 62 String uid = retrieveUid(line); |
| 63 assertNotNull("Failed to retrieve UID from " + line, uid); |
| 64 if (line.indexOf("sandboxed_process") != -1) { |
| 65 // Renderer process. |
| 66 uids.add(uid); |
| 67 rendererProcessesCount++; |
| 68 } else if (line.indexOf(packageName + ".") == -1) { |
| 69 // Browser process. |
| 70 if (!hasBrowserProcess) { |
| 71 // On certain versions of Android 'ps' itself can ap
pear in the list of |
| 72 // processes with the same name as its parent (which
is the browser |
| 73 // process). Only the first occurence of the browser
process is kept. |
| 74 // Note that it is guaranteed that the first occuren
ce corresponds to |
| 75 // the browser process rather than 'ps' (its child)
since processes in |
| 76 // ps' output are sorted by ascending PID. |
| 77 uids.add(uid); |
| 78 hasBrowserProcess = true; |
| 79 } |
| 80 } |
| 81 } |
| 82 } |
| 83 } catch (IOException ioe) { |
| 84 fail("Failed to read ps output."); |
| 85 } finally { |
| 86 if (reader != null) { |
| 87 try { |
| 88 reader.close(); |
| 89 } catch (IOException ioe) { |
| 90 // Intentionally do nothing. |
| 91 } |
| 92 } |
| 93 } |
| 94 assertTrue("Browser process not found in ps output: \n" + sb.toString(), |
| 95 hasBrowserProcess); |
| 96 |
| 97 // We should have the same number of process as tabs count. Sometimes |
| 98 // there can be extra utility sandbox process so we check for greater th
an. |
| 99 assertTrue( |
| 100 "Renderer processes not found in ps output: \n" + sb.toString(), |
| 101 rendererProcessesCount >= tabsCount); |
| 102 |
| 103 assertEquals("Found at least two processes with the same UID in ps outpu
t: \n" |
| 104 + sb.toString(), |
| 105 uids.size(), new HashSet<String>(uids).size()); |
| 106 } |
| 107 |
| 108 private String retrieveUid(String psLine) { |
| 109 if (mUidPattern == null) { |
| 110 mUidPattern = Pattern.compile("^\\S+"); |
| 111 } |
| 112 Matcher m = mUidPattern.matcher(psLine); |
| 113 if (!m.find()) return null; |
| 114 return m.group(0); |
| 115 } |
| 116 |
| 117 @Override |
| 118 public void startMainActivity() throws InterruptedException { |
| 119 startMainActivityFromLauncher(); |
| 120 } |
| 121 } |
OLD | NEW |