test_permmanager_remote.js (11934B)
1 /* Any copyright is dedicated to the Public Domain. 2 https://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 ChromeUtils.defineESModuleGetters(this, { 7 RemoteSettings: "resource://services-settings/remote-settings.sys.mjs", 8 }); 9 10 const COLLECTION_NAME = "remote-permissions"; 11 const ORIGIN_1 = "https://example.com"; 12 const PRINCIPAL_1 = Services.scriptSecurityManager.createContentPrincipal( 13 Services.io.newURI(ORIGIN_1), 14 {} 15 ); 16 const PRINCIPAL_1_PB = Services.scriptSecurityManager.createContentPrincipal( 17 Services.io.newURI(ORIGIN_1), 18 { privateBrowsingId: 1 } 19 ); 20 const ORIGIN_2 = "https://example.org"; 21 const PRINCIPAL_2 = Services.scriptSecurityManager.createContentPrincipal( 22 Services.io.newURI(ORIGIN_2), 23 {} 24 ); 25 const PRINCIPAL_2_PB = Services.scriptSecurityManager.createContentPrincipal( 26 Services.io.newURI(ORIGIN_2), 27 { privateBrowsingId: 1 } 28 ); 29 const ORIGIN_INVALID = "not a valid origin"; 30 const TEST_PERMISSION_1 = "test-permission-1"; 31 const TEST_PERMISSION_2 = "test-permission-2"; 32 33 let rs = RemoteSettings(COLLECTION_NAME); 34 let pm = Services.perms; 35 let rps = Cc["@mozilla.org/remote-permission-service;1"].getService( 36 Ci.nsIRemotePermissionService 37 ); 38 39 async function remoteSettingsSync({ created, updated, deleted }) { 40 await rs.emit("sync", { 41 data: { 42 created, 43 updated, 44 deleted, 45 }, 46 }); 47 } 48 49 function expectPermissions(perms) { 50 Assert.deepEqual( 51 pm.all 52 .map(({ principal, type, capability }) => ({ 53 principal: principal.siteOrigin, 54 type, 55 capability, 56 })) 57 .sort((a, b) => a.principal.localeCompare(b.principal)), 58 perms 59 .map(({ principal, type, capability }) => ({ 60 principal: principal.siteOrigin, 61 type, 62 capability, 63 })) 64 .sort((a, b) => a.principal.localeCompare(b.principal)), 65 "Permission manager should have expected permissions" 66 ); 67 } 68 69 add_setup(async function () { 70 Services.prefs.setCharPref("permissions.manager.defaultsUrl", ""); 71 do_get_profile(); 72 73 // This needs to be restored on cleanup 74 let originalPermissionValues = structuredClone( 75 rps.testAllowedPermissionValues 76 ); 77 78 await rps.isInitialized; 79 80 // Make sure we start off "empty". Any RemoteSettings values must be 81 // purged now to comply with test expectations. 82 Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk"); 83 84 registerCleanupFunction(async () => { 85 info("Cleaning up"); 86 rps.testAllowedPermissionValues = originalPermissionValues; 87 Services.prefs.clearUserPref("permissions.manager.defaultsUrl"); 88 Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk"); 89 Services.perms.removeAll(); 90 }); 91 92 // Allow setting everything 93 rps.testAllowedPermissionValues = { 94 "*": ["*"], 95 }; 96 }); 97 98 add_task(async function test_create_permission() { 99 info("Creating permission"); 100 101 await remoteSettingsSync({ 102 created: [ 103 { 104 origin: ORIGIN_1, 105 type: TEST_PERMISSION_1, 106 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 107 }, 108 ], 109 }); 110 111 expectPermissions([ 112 { 113 principal: PRINCIPAL_1, 114 type: TEST_PERMISSION_1, 115 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 116 }, 117 { 118 principal: PRINCIPAL_1_PB, 119 type: TEST_PERMISSION_1, 120 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 121 }, 122 ]); 123 }); 124 125 add_task(async function test_update_permission_value() { 126 info("Updating permission value"); 127 128 await remoteSettingsSync({ 129 updated: [ 130 { 131 old: { 132 origin: ORIGIN_1, 133 type: TEST_PERMISSION_1, 134 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 135 }, 136 new: { 137 origin: ORIGIN_1, 138 type: TEST_PERMISSION_1, 139 capability: Ci.nsIPermissionManager.DENY_ACTION, 140 }, 141 }, 142 ], 143 }); 144 145 expectPermissions([ 146 { 147 principal: PRINCIPAL_1, 148 type: TEST_PERMISSION_1, 149 capability: Ci.nsIPermissionManager.DENY_ACTION, 150 }, 151 { 152 principal: PRINCIPAL_1_PB, 153 type: TEST_PERMISSION_1, 154 capability: Ci.nsIPermissionManager.DENY_ACTION, 155 }, 156 ]); 157 }); 158 159 add_task(async function test_update_permission_origin() { 160 info("Updating permission origin"); 161 162 await remoteSettingsSync({ 163 updated: [ 164 { 165 old: { 166 origin: ORIGIN_1, 167 type: TEST_PERMISSION_1, 168 capability: Ci.nsIPermissionManager.DENY_ACTION, 169 }, 170 new: { 171 origin: ORIGIN_2, 172 type: TEST_PERMISSION_1, 173 capability: Ci.nsIPermissionManager.DENY_ACTION, 174 }, 175 }, 176 ], 177 }); 178 179 expectPermissions([ 180 { 181 principal: PRINCIPAL_2, 182 type: TEST_PERMISSION_1, 183 capability: Ci.nsIPermissionManager.DENY_ACTION, 184 }, 185 { 186 principal: PRINCIPAL_2_PB, 187 type: TEST_PERMISSION_1, 188 capability: Ci.nsIPermissionManager.DENY_ACTION, 189 }, 190 ]); 191 }); 192 193 add_task(async function test_user_permission_restoration() { 194 info("Overriding with user permission"); 195 196 pm.addFromPrincipal( 197 PRINCIPAL_2, 198 TEST_PERMISSION_1, 199 Ci.nsIPermissionManager.ALLOW_ACTION 200 ); 201 202 expectPermissions([ 203 { 204 principal: PRINCIPAL_2, 205 type: TEST_PERMISSION_1, 206 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 207 }, 208 { 209 principal: PRINCIPAL_2_PB, 210 type: TEST_PERMISSION_1, 211 capability: Ci.nsIPermissionManager.DENY_ACTION, 212 }, 213 ]); 214 215 info("Removing user permission"); 216 217 pm.removeFromPrincipal(PRINCIPAL_2, TEST_PERMISSION_1); 218 219 expectPermissions([ 220 { 221 principal: PRINCIPAL_2, 222 type: TEST_PERMISSION_1, 223 capability: Ci.nsIPermissionManager.DENY_ACTION, 224 }, 225 { 226 principal: PRINCIPAL_2_PB, 227 type: TEST_PERMISSION_1, 228 capability: Ci.nsIPermissionManager.DENY_ACTION, 229 }, 230 ]); 231 }); 232 233 add_task(async function test_remove_all_restoration() { 234 info("Overriding with user permission and adding new user permission"); 235 236 pm.addFromPrincipal( 237 PRINCIPAL_1, 238 TEST_PERMISSION_1, 239 Ci.nsIPermissionManager.ALLOW_ACTION 240 ); 241 pm.addFromPrincipal( 242 PRINCIPAL_2, 243 TEST_PERMISSION_1, 244 Ci.nsIPermissionManager.ALLOW_ACTION 245 ); 246 247 expectPermissions([ 248 { 249 principal: PRINCIPAL_1, 250 type: TEST_PERMISSION_1, 251 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 252 }, 253 { 254 principal: PRINCIPAL_2, 255 type: TEST_PERMISSION_1, 256 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 257 }, 258 { 259 principal: PRINCIPAL_2_PB, 260 type: TEST_PERMISSION_1, 261 capability: Ci.nsIPermissionManager.DENY_ACTION, 262 }, 263 ]); 264 265 info("Removing all permissions"); 266 267 pm.removeAll(); 268 269 expectPermissions([ 270 { 271 principal: PRINCIPAL_2, 272 type: TEST_PERMISSION_1, 273 capability: Ci.nsIPermissionManager.DENY_ACTION, 274 }, 275 { 276 principal: PRINCIPAL_2_PB, 277 type: TEST_PERMISSION_1, 278 capability: Ci.nsIPermissionManager.DENY_ACTION, 279 }, 280 ]); 281 }); 282 283 add_task(async function test_delete_permission() { 284 info("Deleting permission"); 285 286 await remoteSettingsSync({ 287 deleted: [ 288 { 289 origin: ORIGIN_2, 290 type: TEST_PERMISSION_1, 291 capability: Ci.nsIPermissionManager.DENY_ACTION, 292 }, 293 ], 294 }); 295 296 expectPermissions([]); 297 }); 298 299 add_task(async function test_allowlist() { 300 info("Only allowing TEST_PERMISSION_1 with value ALLOW_ACTION"); 301 302 rps.testAllowedPermissionValues = { 303 [TEST_PERMISSION_1]: [Ci.nsIPermissionManager.ALLOW_ACTION], 304 }; 305 306 info("Trying to add all sorts of default permissions"); 307 308 await remoteSettingsSync({ 309 created: [ORIGIN_1, ORIGIN_2].flatMap(origin => 310 [TEST_PERMISSION_1, TEST_PERMISSION_2].flatMap(type => 311 [ 312 Ci.nsIPermissionManager.ALLOW_ACTION, 313 Ci.nsIPermissionManager.DENY_ACTION, 314 Ci.nsIPermissionManager.PROMPT_ACTION, 315 ].flatMap(capability => ({ origin, type, capability })) 316 ) 317 ), 318 }); 319 320 expectPermissions([ 321 { 322 principal: PRINCIPAL_1, 323 type: TEST_PERMISSION_1, 324 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 325 }, 326 { 327 principal: PRINCIPAL_1_PB, 328 type: TEST_PERMISSION_1, 329 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 330 }, 331 { 332 principal: PRINCIPAL_2, 333 type: TEST_PERMISSION_1, 334 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 335 }, 336 { 337 principal: PRINCIPAL_2_PB, 338 type: TEST_PERMISSION_1, 339 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 340 }, 341 ]); 342 343 rps.testAllowedPermissionValues = { 344 "*": ["*"], 345 }; 346 }); 347 348 add_task(async function test_defaults_url() { 349 info("Testing interaction with permissions.manager.defaultsUrl"); 350 351 info("Setting up permissions.manager.defaultsUrl"); 352 353 let file = do_get_tempdir(); 354 file.append("test_default_permissions"); 355 let ostream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance( 356 Ci.nsIFileOutputStream 357 ); 358 ostream.init(file, -1, 0o666, 0); 359 let conv = Cc["@mozilla.org/intl/converter-output-stream;1"].createInstance( 360 Ci.nsIConverterOutputStream 361 ); 362 conv.init(ostream, "UTF-8"); 363 conv.writeString( 364 [ 365 "host", 366 TEST_PERMISSION_1, 367 Ci.nsIPermissionManager.ALLOW_ACTION, 368 ORIGIN_1, 369 ].join("\t") + "\n" 370 ); 371 conv.writeString( 372 [ 373 "host", 374 TEST_PERMISSION_2, 375 Ci.nsIPermissionManager.ALLOW_ACTION, 376 ORIGIN_1, 377 ].join("\t") + "\n" 378 ); 379 ostream.close(); 380 381 Services.prefs.setCharPref( 382 "permissions.manager.defaultsUrl", 383 "file://" + file.path 384 ); 385 386 info("Re-initializing permission manager"); 387 388 // Start from a clean slate with our new default permissions from 389 // permissions.manager.defaultsUrl 390 Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk"); 391 Services.perms.removeAll(); 392 393 expectPermissions([ 394 { 395 principal: PRINCIPAL_1, 396 type: TEST_PERMISSION_1, 397 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 398 }, 399 { 400 principal: PRINCIPAL_1_PB, 401 type: TEST_PERMISSION_1, 402 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 403 }, 404 { 405 principal: PRINCIPAL_1, 406 type: TEST_PERMISSION_2, 407 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 408 }, 409 { 410 principal: PRINCIPAL_1_PB, 411 type: TEST_PERMISSION_2, 412 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 413 }, 414 ]); 415 416 info("Overriding permissions from permissions.manager.defaultsUrl"); 417 418 await remoteSettingsSync({ 419 created: [ 420 { 421 origin: ORIGIN_1, 422 type: TEST_PERMISSION_1, 423 capability: Ci.nsIPermissionManager.DENY_ACTION, 424 }, 425 { 426 origin: ORIGIN_1, 427 type: TEST_PERMISSION_2, 428 capability: Ci.nsIPermissionManager.UNKNOWN_ACTION, 429 }, 430 ], 431 }); 432 433 expectPermissions([ 434 { 435 principal: PRINCIPAL_1, 436 type: TEST_PERMISSION_1, 437 capability: Ci.nsIPermissionManager.DENY_ACTION, 438 }, 439 { 440 principal: PRINCIPAL_1_PB, 441 type: TEST_PERMISSION_1, 442 capability: Ci.nsIPermissionManager.DENY_ACTION, 443 }, 444 ]); 445 }); 446 447 add_task(async function test_malformed_origin() { 448 info( 449 "Testing that import will continue after encountering a malformed origin" 450 ); 451 452 await remoteSettingsSync({ 453 created: [ 454 { 455 origin: ORIGIN_INVALID, 456 type: TEST_PERMISSION_1, 457 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 458 }, 459 // TEST_PERMISSION_1 still exists for ORIGIN_1 from the previous step, but 460 // for simplicity we act like it is new here. We will see if the value has 461 // changed from deny to allow. 462 { 463 origin: ORIGIN_1, 464 type: TEST_PERMISSION_1, 465 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 466 }, 467 ], 468 }); 469 470 expectPermissions([ 471 { 472 principal: PRINCIPAL_1, 473 type: TEST_PERMISSION_1, 474 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 475 }, 476 { 477 principal: PRINCIPAL_1_PB, 478 type: TEST_PERMISSION_1, 479 capability: Ci.nsIPermissionManager.ALLOW_ACTION, 480 }, 481 ]); 482 });