test_Chrome_permissions.js (5881B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 /** 7 * Tests that if the migrator does not have the permission to 8 * read from the Chrome data directory, that it can request 9 * permission to read from it, if the system allows. 10 */ 11 12 const { ChromeMigrationUtils } = ChromeUtils.importESModule( 13 "resource:///modules/ChromeMigrationUtils.sys.mjs" 14 ); 15 16 const { ChromeProfileMigrator } = ChromeUtils.importESModule( 17 "resource:///modules/ChromeProfileMigrator.sys.mjs" 18 ); 19 20 const { sinon } = ChromeUtils.importESModule( 21 "resource://testing-common/Sinon.sys.mjs" 22 ); 23 24 const { MockFilePicker } = ChromeUtils.importESModule( 25 "resource://testing-common/MockFilePicker.sys.mjs" 26 ); 27 28 let gTempDir; 29 30 add_setup(async () => { 31 Services.prefs.setBoolPref( 32 "browser.migrate.chrome.get_permissions.enabled", 33 true 34 ); 35 gTempDir = do_get_tempdir(); 36 await IOUtils.writeJSON(PathUtils.join(gTempDir.path, "Local State"), []); 37 38 MockFilePicker.init(/* mock BrowsingContext */ { window: globalThis }); 39 registerCleanupFunction(() => { 40 MockFilePicker.cleanup(); 41 }); 42 }); 43 44 /** 45 * Tests that canGetPermissions will return false if the platform does 46 * not allow for folder selection in the native file picker, and returns 47 * the data path otherwise. 48 */ 49 add_task(async function test_canGetPermissions() { 50 let sandbox = sinon.createSandbox(); 51 registerCleanupFunction(() => { 52 sandbox.restore(); 53 }); 54 55 let migrator = new ChromeProfileMigrator(); 56 let canGetPermissionsStub = sandbox 57 .stub(MigrationUtils, "canGetPermissionsOnPlatform") 58 .resolves(false); 59 sandbox.stub(ChromeMigrationUtils, "getDataPath").resolves(gTempDir.path); 60 61 Assert.ok( 62 !(await migrator.canGetPermissions()), 63 "Should not be able to get permissions." 64 ); 65 66 canGetPermissionsStub.resolves(true); 67 68 Assert.equal( 69 await migrator.canGetPermissions(), 70 gTempDir.path, 71 "Should be able to get the permissions path." 72 ); 73 74 sandbox.restore(); 75 }); 76 77 /** 78 * Tests that getPermissions will show the native file picker in a 79 * loop until either the user cancels or selects a folder that grants 80 * read permissions to the data directory. 81 */ 82 add_task(async function test_getPermissions() { 83 let sandbox = sinon.createSandbox(); 84 registerCleanupFunction(() => { 85 sandbox.restore(); 86 }); 87 88 let migrator = new ChromeProfileMigrator(); 89 sandbox.stub(MigrationUtils, "canGetPermissionsOnPlatform").resolves(true); 90 sandbox.stub(ChromeMigrationUtils, "getDataPath").resolves(gTempDir.path); 91 let hasPermissionsStub = sandbox 92 .stub(migrator, "hasPermissions") 93 .resolves(false); 94 95 Assert.equal( 96 await migrator.canGetPermissions(), 97 gTempDir.path, 98 "Should be able to get the permissions path." 99 ); 100 101 let filePickerSeenCount = 0; 102 103 let filePickerShownPromise = new Promise(resolve => { 104 MockFilePicker.showCallback = () => { 105 Assert.ok(true, "Filepicker shown."); 106 MockFilePicker.useDirectory([gTempDir.path]); 107 filePickerSeenCount++; 108 if (filePickerSeenCount > 3) { 109 Assert.ok(true, "File picker looped 3 times."); 110 hasPermissionsStub.resolves(true); 111 resolve(); 112 } 113 }; 114 }); 115 MockFilePicker.returnValue = MockFilePicker.returnOK; 116 Assert.ok( 117 await migrator.getPermissions(), 118 "Should report that we got permissions." 119 ); 120 121 await filePickerShownPromise; 122 123 // Make sure that the user can also hit "cancel" and that we 124 // file picker loop. 125 126 hasPermissionsStub.resolves(false); 127 128 filePickerSeenCount = 0; 129 filePickerShownPromise = new Promise(resolve => { 130 MockFilePicker.showCallback = () => { 131 Assert.ok(true, "Filepicker shown."); 132 filePickerSeenCount++; 133 Assert.equal(filePickerSeenCount, 1, "Saw the picker once."); 134 resolve(); 135 }; 136 }); 137 MockFilePicker.returnValue = MockFilePicker.returnCancel; 138 Assert.ok( 139 !(await migrator.getPermissions()), 140 "Should report that we didn't get permissions." 141 ); 142 await filePickerShownPromise; 143 144 sandbox.restore(); 145 }); 146 147 /** 148 * Tests that if the native file picker chooses a different directory 149 * than the one we originally asked for, that we remap attempts to 150 * read profiles from that new directory. This is because Ubuntu Snaps 151 * will return us paths from the native file picker that are symlinks 152 * to the original directories. 153 */ 154 add_task(async function test_remapDirectories() { 155 let remapDir = new FileUtils.File( 156 await IOUtils.createUniqueDirectory( 157 PathUtils.tempDir, 158 "test-chrome-migration" 159 ) 160 ); 161 let localStatePath = PathUtils.join(remapDir.path, "Local State"); 162 await IOUtils.writeJSON(localStatePath, []); 163 164 let sandbox = sinon.createSandbox(); 165 registerCleanupFunction(() => { 166 sandbox.restore(); 167 }); 168 169 let migrator = new ChromeProfileMigrator(); 170 sandbox.stub(MigrationUtils, "canGetPermissionsOnPlatform").resolves(true); 171 sandbox.stub(ChromeMigrationUtils, "getDataPath").resolves(gTempDir.path); 172 let hasPermissionsStub = sandbox 173 .stub(migrator, "hasPermissions") 174 .resolves(false); 175 176 Assert.equal( 177 await migrator.canGetPermissions(), 178 gTempDir.path, 179 "Should be able to get the permissions path." 180 ); 181 182 let filePickerShownPromise = new Promise(resolve => { 183 MockFilePicker.showCallback = () => { 184 Assert.ok(true, "Filepicker shown."); 185 MockFilePicker.useDirectory([remapDir.path]); 186 hasPermissionsStub.resolves(true); 187 resolve(); 188 }; 189 }); 190 MockFilePicker.returnValue = MockFilePicker.returnOK; 191 Assert.ok( 192 await migrator.getPermissions(), 193 "Should report that we got permissions." 194 ); 195 196 Assert.equal( 197 PathUtils.normalize(await migrator.canGetPermissions()), 198 PathUtils.normalize(remapDir.path), 199 "Should be able to get the remapped permissions path." 200 ); 201 202 await filePickerShownPromise; 203 204 sandbox.restore(); 205 });