1 // Copyright (c) 2012 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.
5 // Processes API test for Chrome.
6 // browser_tests.exe --gtest_filter=ExtensionApiTest.Processes
8 var pass = chrome.test.callbackPass;
9 var fail = chrome.test.callbackFail;
10 var assertEq = chrome.test.assertEq;
11 var assertTrue = chrome.test.assertTrue;
12 var assertFalse = chrome.test.assertFalse;
13 var listenOnce = chrome.test.listenOnce;
16 var hangingTabProcess = -1;
18 function createTab(index, url) {
19 chrome.tabs.create({"url": url}, pass(function(tab) {
24 var getProcessId = chrome.processes.getProcessIdForTab;
26 function pageUrl(letter) {
27 return chrome.extension.getURL(letter + ".html");
30 function dumpProcess(process) {
31 console.log("id " + process.id);
32 console.log("title " + process.title);
33 console.log("osProcId " + process.osProcessId);
34 console.log("type " + process.type);
35 console.log("profile " + process.profile);
36 console.log("tabs " + process.tabs);
37 console.log("cpu " + process.cpu);
38 console.log("privMem " + process.privateMemory);
39 console.log("network " + process.network);
40 console.log("jsMemAlloc " + process.jsMemoryAllocated);
41 console.log("jsMemUsed " + process.jsMemoryUsed);
42 console.log("sqliteMem " + process.sqliteMemory);
43 console.log("fps " + process.fps);
44 console.log("naclDebugPort " + process.naclDebugPort);
45 if ("imageCache" in process) {
46 console.log("imageCache.size " + process.imageCache.size);
47 console.log("imageCache.liveSize " + process.imageCache.liveSize);
49 if ("scriptCache" in process) {
50 console.log("scriptCache.size " + process.scriptCache.size);
51 console.log("scriptCache.liveSize " + process.scriptCache.liveSize);
53 if ("cssCache" in process) {
54 console.log("cssCache.size " + process.cssCache.size);
55 console.log("cssCache .liveSize " + process.cssCache.liveSize);
59 function validateProcessProperties(process, updating, memory_included) {
61 assertTrue("id" in process);
62 assertTrue("title" in process);
63 assertTrue("naclDebugPort" in process);
64 assertTrue("osProcessId" in process);
65 assertTrue("type" in process);
66 assertTrue("profile" in process);
67 assertTrue("tabs" in process);
69 // Present if onUpdate(WithMemory) listener is registered.
70 assertEq(("cpu" in process), updating);
71 assertEq(("network" in process), updating);
72 assertEq(("fps" in process), updating);
74 // Present if memory details are requested.
75 assertEq(("privateMemory" in process), memory_included);
77 // sqliteMemory is only reported for the browser process
78 if (process.type == "browser") {
79 assertEq(("sqliteMemory" in process), updating);
80 } else if (process.type == "renderer") {
81 // The rest are not present in the browser process
82 assertEq(("jsMemoryAllocated" in process), updating);
83 assertEq(("jsMemoryUsed" in process), updating);
84 assertEq(("imageCache" in process), updating);
85 assertEq(("scriptCache" in process), updating);
86 assertEq(("cssCache" in process), updating);
90 chrome.test.runTests([
91 function setupProcessTests() {
92 // Open 4 tabs for test, then wait and create a 5th
93 createTab(0, "about:blank");
94 createTab(1, pageUrl("a"));
95 createTab(2, pageUrl("b"));
96 createTab(3, "chrome://newtab/");
98 // Wait for all loads to complete.
99 var completedCount = 0;
100 var onUpdatedCompleted = chrome.test.listenForever(
101 chrome.tabs.onUpdated,
102 function(changedTabId, changeInfo, changedTab) {
103 if (changedTab.status == "complete") {
106 // Once the NTP finishes loading, create another one. This ensures
107 // both NTPs end up in the same process.
108 if (changedTabId == tabs[3].id) {
109 createTab(4, "chrome://newtab/");
113 // Once all tabs are done loading, continue with the next test.
114 if (completedCount == 4) {
115 onUpdatedCompleted();
122 function extensionPageInOwnProcess() {
123 getProcessId(tabs[0].id, pass(function(pid0) {
124 getProcessId(tabs[1].id, pass(function(pid1) {
125 // about:blank and extension page should not share a process
126 assertTrue(pid0 != pid1);
131 function extensionPagesShareProcess() {
132 getProcessId(tabs[1].id, pass(function(pid1) {
133 getProcessId(tabs[2].id, pass(function(pid2) {
134 // Pages from same extension should share a process
135 assertEq(pid1, pid2);
140 function extensionPagesMatchTabs() {
141 getProcessId(tabs[1].id, pass(function(pid1) {
142 getProcessId(tabs[2].id, pass(function(pid2) {
143 // Pages from same extension should share a process
144 assertEq(pid1, pid2);
145 chrome.processes.getProcessInfo(pid1, false,
147 chrome.processes.getProcessInfo(pid2, false,
149 var proc1 = pl1[pid1];
150 var proc2 = pl2[pid2];
151 assertTrue(proc1.tabs.length == proc2.tabs.length);
152 for (var i = 0; i < proc1.tabs.length; ++i) {
153 assertEq(proc1.tabs[i], proc2.tabs[i]);
161 function newTabPageInOwnProcess() {
162 getProcessId(tabs[0].id, pass(function(pid0) {
163 getProcessId(tabs[3].id, pass(function(pid3) {
164 // NTP should not share a process with current tabs
165 assertTrue(pid0 != pid3);
170 function newTabPagesShareProcess() {
171 getProcessId(tabs[3].id, pass(function(pid3) {
172 getProcessId(tabs[4].id, pass(function(pid4) {
173 // Multiple NTPs should share a process
174 assertEq(pid3, pid4);
179 function idsInUpdateEvent() {
180 listenOnce(chrome.processes.onUpdated, function(processes) {
181 // onUpdated should return a valid dictionary of processes,
182 // indexed by process ID.
183 var pids = Object.keys(processes);
184 // There should be at least 5 processes: 1 browser, 1 extension, and 3
185 // renderers (for the 5 tabs).
186 assertTrue(pids.length >= 5, "Unexpected size of pids");
188 // Should be able to look up process object by ID.
189 assertTrue(processes[pids[0]].id == pids[0]);
190 assertTrue(processes[pids[0]].id != processes[pids[1]].id);
192 getProcessId(tabs[0].id, pass(function(pidTab0) {
193 // Process ID for tab 0 should be listed in pids.
194 assertTrue(processes[pidTab0] != undefined, "Undefined Process");
195 assertEq("renderer", processes[pidTab0].type, "Tab0 is not renderer");
200 function typesInUpdateEvent() {
201 listenOnce(chrome.processes.onUpdated, function(processes) {
202 // Check types: 1 browser, 3 renderers, and 1 extension
203 var browserCount = 0;
204 var rendererCount = 0;
205 var extensionCount = 0;
207 for (pid in processes) {
208 switch (processes[pid].type) {
222 assertEq(1, browserCount);
223 assertTrue(rendererCount >= 3);
224 assertTrue(extensionCount >= 1);
228 function propertiesOfProcesses() {
229 listenOnce(chrome.processes.onUpdated, function(processes) {
230 for (pid in processes) {
231 var process = processes[pid];
232 validateProcessProperties(process, true, false);
237 function propertiesOfProcessesWithMemory() {
238 listenOnce(chrome.processes.onUpdatedWithMemory,
239 function(processes) {
240 for (pid in processes) {
241 var process = processes[pid];
242 validateProcessProperties(process, true, true);
247 function terminateProcess() {
248 listenOnce(chrome.processes.onExited,
249 function(processId, type, code) {
250 assertTrue(processId > 0);
252 getProcessId(tabs[4].id, function(pid0) {
253 chrome.processes.terminate(pid0, function(killed) {
254 chrome.test.assertTrue(killed);
259 function terminateProcessNonExisting() {
260 chrome.processes.terminate(31337, fail("Process not found: 31337."));
263 function testOnCreated() {
264 listenOnce(chrome.processes.onCreated, function(process) {
265 assertTrue("id" in process, "process doesn't have id property");
266 assertTrue(process.id > 0, "id is not positive " + process.id);
268 createTab(5, "chrome://newtab/");
271 // DISABLED: crbug.com/345411
272 // Hangs consistently.
274 function testOnExited() {
275 listenOnce(chrome.processes.onExited,
276 function(processId, type, code) {
277 assertTrue(type >= 0 && type < 5);
279 chrome.tabs.create({"url": "http://google.com/"}, pass(function(tab) {
280 chrome.tabs.remove(tab.id);
285 function testGetProcessInfoList() {
286 getProcessId(tabs[0].id, pass(function(pidTab0) {
287 getProcessId(tabs[1].id, pass(function(pidTab1) {
288 chrome.processes.getProcessInfo([pidTab0, pidTab1], false,
289 pass(function(processes) {
290 assertTrue(Object.keys(processes).length == 2);
296 function testGetProcessInfoSingle() {
297 chrome.processes.getProcessInfo(0, false, pass(function(processes) {
298 assertTrue(Object.keys(processes).length == 1);
302 function testGetProcessInfo() {
303 chrome.processes.getProcessInfo([], false, pass(function(processes) {
304 assertTrue(Object.keys(processes).length >= 1);
305 for (pid in processes) {
306 var process = processes[pid];
307 validateProcessProperties(process, false, false);
308 assertFalse("privateMemory" in process);
313 function testGetProcessInfoWithMemory() {
314 chrome.processes.getProcessInfo(0, true, pass(function(processes) {
315 for (pid in processes) {
316 var process = processes[pid];
317 validateProcessProperties(process, false, true);
318 assertTrue("privateMemory" in process);
323 function testOnUnresponsive() {
324 listenOnce(chrome.processes.onUnresponsive, function(process) {
325 assertTrue(process.id == hangingTabProcess);
326 // actually kill the process, just to make sure it won't hang the test
327 chrome.processes.terminate(process.id, function(killed) {
328 chrome.test.assertTrue(killed);
331 chrome.tabs.create({"url": "chrome://hang" }, function(tab) {
332 getProcessId(tab.id, function(pid0) {
333 hangingTabProcess = pid0;
335 chrome.tabs.update(tab.id, { "url": "chrome://flags" });