browser_shutdown_remote_own_reference.js (5863B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 add_task(async function () { 8 await BrowserTestUtils.withNewTab( 9 { 10 gBrowser, 11 url: `data:text/html, 12 <html> 13 <head> 14 <meta charset="utf-8"/> 15 <title>Accessibility Test</title> 16 </head> 17 <body></body> 18 </html>`, 19 }, 20 async function (browser) { 21 info( 22 "Creating a service in parent and waiting for service to be created " + 23 "in content" 24 ); 25 await loadContentScripts(browser, { 26 script: "Common.sys.mjs", 27 symbol: "CommonUtils", 28 }); 29 // Create a11y service in the main process. This will trigger creating of 30 // the a11y service in parent as well. 31 const [parentA11yInitObserver, parentA11yInit] = initAccService(); 32 const [contentA11yInitObserver, contentA11yInit] = 33 initAccService(browser); 34 let [contentConsumersChangedObserver, contentConsumersChanged] = 35 accConsumersChanged(browser); 36 37 await Promise.all([ 38 parentA11yInitObserver, 39 contentA11yInitObserver, 40 contentConsumersChangedObserver, 41 ]); 42 43 let accService = Cc["@mozilla.org/accessibilityService;1"].getService( 44 Ci.nsIAccessibilityService 45 ); 46 ok(accService, "Service initialized in parent"); 47 await Promise.all([parentA11yInit, contentA11yInit]); 48 await contentConsumersChanged.then(data => 49 Assert.deepEqual( 50 data, 51 { 52 XPCOM: false, 53 MainProcess: true, 54 PlatformAPI: false, 55 }, 56 "Accessibility service consumers in content are correct." 57 ) 58 ); 59 60 info( 61 "Adding additional reference to accessibility service in content " + 62 "process" 63 ); 64 [contentConsumersChangedObserver, contentConsumersChanged] = 65 accConsumersChanged(browser); 66 await contentConsumersChangedObserver; 67 // Add a new reference to the a11y service inside the content process. 68 await SpecialPowers.spawn(browser, [], () => { 69 content.CommonUtils.accService; 70 }); 71 await contentConsumersChanged.then(data => 72 Assert.deepEqual( 73 data, 74 { 75 XPCOM: true, 76 MainProcess: true, 77 PlatformAPI: false, 78 }, 79 "Accessibility service consumers in content are correct." 80 ) 81 ); 82 83 const contentConsumers = await SpecialPowers.spawn(browser, [], () => 84 content.CommonUtils.accService.getConsumers() 85 ); 86 Assert.deepEqual( 87 JSON.parse(contentConsumers), 88 { 89 XPCOM: true, 90 MainProcess: true, 91 PlatformAPI: false, 92 }, 93 "Accessibility service consumers in parent are correct." 94 ); 95 96 info( 97 "Shutting down a service in parent and making sure the one in " + 98 "content stays alive" 99 ); 100 let contentCanShutdown = false; 101 const [parentA11yShutdownObserver, parentA11yShutdown] = 102 shutdownAccService(); 103 [contentConsumersChangedObserver, contentConsumersChanged] = 104 accConsumersChanged(browser); 105 // This promise will resolve only if contentCanShutdown flag is set to true. 106 // If 'a11y-init-or-shutdown' event with '0' flag (in content) comes before 107 // it can be shut down, the promise will reject. 108 const [contentA11yShutdownObserver, contentA11yShutdownPromise] = 109 shutdownAccService(browser); 110 const contentA11yShutdown = new Promise((resolve, reject) => 111 contentA11yShutdownPromise.then(() => 112 contentCanShutdown 113 ? resolve() 114 : reject("Accessible service was shut down incorrectly") 115 ) 116 ); 117 118 await Promise.all([ 119 parentA11yShutdownObserver, 120 contentA11yShutdownObserver, 121 contentConsumersChangedObserver, 122 ]); 123 // Remove a11y service reference in the main process and force garbage 124 // collection. This should not trigger shutdown in content since a11y 125 // service is used by XPCOM. 126 accService = null; 127 ok(!accService, "Service is removed in parent"); 128 // Force garbage collection that should not trigger shutdown because there 129 // is a reference in a content process. 130 forceGC(); 131 await SpecialPowers.spawn(browser, [], () => { 132 SpecialPowers.Cu.forceGC(); 133 }); 134 await parentA11yShutdown; 135 await contentConsumersChanged.then(data => 136 Assert.deepEqual( 137 data, 138 { 139 XPCOM: true, 140 MainProcess: false, 141 PlatformAPI: false, 142 }, 143 "Accessibility service consumers in content are correct." 144 ) 145 ); 146 147 // Have some breathing room between a11y service shutdowns. 148 await TestUtils.waitForTick(); 149 150 info("Removing a service in content"); 151 // Now allow a11y service to shutdown in content. 152 contentCanShutdown = true; 153 [contentConsumersChangedObserver, contentConsumersChanged] = 154 accConsumersChanged(browser); 155 await contentConsumersChangedObserver; 156 // Remove last reference to a11y service in content and force garbage 157 // collection that should trigger shutdown. 158 await SpecialPowers.spawn(browser, [], () => { 159 content.CommonUtils.clearAccService(); 160 }); 161 await contentA11yShutdown; 162 await contentConsumersChanged.then(data => 163 Assert.deepEqual( 164 data, 165 { 166 XPCOM: false, 167 MainProcess: false, 168 PlatformAPI: false, 169 }, 170 "Accessibility service consumers in content are correct." 171 ) 172 ); 173 } 174 ); 175 });