test_permmanager_defaults.js (17520B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 // The origin we use in most of the tests. 5 const TEST_ORIGIN = NetUtil.newURI("http://example.org"); 6 const TEST_ORIGIN_HTTPS = NetUtil.newURI("https://example.org"); 7 const TEST_ORIGIN_NOTUPDATED = NetUtil.newURI("https://example.net"); 8 const TEST_ORIGIN_2 = NetUtil.newURI("http://example.com"); 9 const TEST_ORIGIN_3 = NetUtil.newURI("https://example2.com:8080"); 10 const TEST_PERMISSION = "test-permission"; 11 12 function promiseTimeout(delay) { 13 return new Promise(resolve => { 14 do_timeout(delay, resolve); 15 }); 16 } 17 18 add_task(async function do_test() { 19 // setup a profile. 20 do_get_profile(); 21 22 // setup the time for removeAllSince() before defaults are loaded 23 let since = Number(Date.now()); 24 await promiseTimeout(20); 25 26 // create a file in the temp directory with the defaults. 27 let file = do_get_tempdir(); 28 file.append("test_default_permissions"); 29 30 // write our test data to it. 31 let ostream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance( 32 Ci.nsIFileOutputStream 33 ); 34 ostream.init(file, -1, 0o666, 0); 35 let conv = Cc["@mozilla.org/intl/converter-output-stream;1"].createInstance( 36 Ci.nsIConverterOutputStream 37 ); 38 conv.init(ostream, "UTF-8"); 39 40 conv.writeString("# this is a comment\n"); 41 conv.writeString("\n"); // a blank line! 42 conv.writeString( 43 "host\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN.host + "\n" 44 ); 45 conv.writeString( 46 "host\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN_2.host + "\n" 47 ); 48 conv.writeString( 49 "host\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN_NOTUPDATED.host + "\n" 50 ); 51 conv.writeString( 52 "origin\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN_3.spec + "\n" 53 ); 54 conv.writeString( 55 "origin\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN.spec + "^inBrowser=1\n" 56 ); 57 ostream.close(); 58 59 // Set the preference used by the permission manager so the file is read. 60 Services.prefs.setCharPref( 61 "permissions.manager.defaultsUrl", 62 "file://" + file.path 63 ); 64 65 // This will force the permission-manager to reload the data. 66 Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk"); 67 68 let permIsolateUserContext = Services.prefs.getBoolPref( 69 "permissions.isolateBy.userContext" 70 ); 71 let permIsolatePrivateBrowsing = Services.prefs.getBoolPref( 72 "permissions.isolateBy.privateBrowsing" 73 ); 74 75 let pm = Services.perms; 76 77 // test the default permission was applied. 78 let principal = Services.scriptSecurityManager.createContentPrincipal( 79 TEST_ORIGIN, 80 {} 81 ); 82 let principalHttps = Services.scriptSecurityManager.createContentPrincipal( 83 TEST_ORIGIN_HTTPS, 84 {} 85 ); 86 let principalNotUpdated = 87 Services.scriptSecurityManager.createContentPrincipal( 88 TEST_ORIGIN_NOTUPDATED, 89 {} 90 ); 91 let principal2 = Services.scriptSecurityManager.createContentPrincipal( 92 TEST_ORIGIN_2, 93 {} 94 ); 95 let principal3 = Services.scriptSecurityManager.createContentPrincipal( 96 TEST_ORIGIN_3, 97 {} 98 ); 99 100 let attrs = { userContextId: 1 }; 101 let principal1UserContext = 102 Services.scriptSecurityManager.createContentPrincipal(TEST_ORIGIN, attrs); 103 attrs = { privateBrowsingId: 1 }; 104 let principal1PrivateBrowsing = 105 Services.scriptSecurityManager.createContentPrincipal(TEST_ORIGIN, attrs); 106 attrs = { firstPartyDomain: "cnn.com" }; 107 let principal7 = Services.scriptSecurityManager.createContentPrincipal( 108 TEST_ORIGIN, 109 attrs 110 ); 111 attrs = { userContextId: 1, firstPartyDomain: "cnn.com" }; 112 let principal8 = Services.scriptSecurityManager.createContentPrincipal( 113 TEST_ORIGIN, 114 attrs 115 ); 116 117 Assert.equal( 118 Ci.nsIPermissionManager.ALLOW_ACTION, 119 pm.testPermissionFromPrincipal(principal, TEST_PERMISSION) 120 ); 121 Assert.equal( 122 Ci.nsIPermissionManager.ALLOW_ACTION, 123 pm.testPermissionFromPrincipal(principalHttps, TEST_PERMISSION) 124 ); 125 Assert.equal( 126 Ci.nsIPermissionManager.ALLOW_ACTION, 127 pm.testPermissionFromPrincipal(principalNotUpdated, TEST_PERMISSION) 128 ); 129 Assert.equal( 130 Ci.nsIPermissionManager.ALLOW_ACTION, 131 pm.testPermissionFromPrincipal(principal3, TEST_PERMISSION) 132 ); 133 // Depending on the prefs there are two scenarios here: 134 // 1. We isolate by private browsing: The permission mgr should 135 // add default permissions for these principals too. 136 // 2. We don't isolate by private browsing: The permission 137 // check will strip the private browsing origin attribute. 138 // In this case the used internally for the lookup is always principal1. 139 Assert.equal( 140 Ci.nsIPermissionManager.ALLOW_ACTION, 141 pm.testPermissionFromPrincipal(principal1PrivateBrowsing, TEST_PERMISSION) 142 ); 143 144 // the permission should exist in the enumerator. 145 Assert.equal( 146 Ci.nsIPermissionManager.ALLOW_ACTION, 147 findCapabilityViaEnum(TEST_ORIGIN) 148 ); 149 Assert.equal( 150 Ci.nsIPermissionManager.ALLOW_ACTION, 151 findCapabilityViaEnum(TEST_ORIGIN_3) 152 ); 153 154 // but should not have been written to the DB 155 await checkCapabilityViaDB(null); 156 157 // removeallsince should not get rid of defaults 158 pm.removeAllSince(since); 159 160 Assert.equal( 161 Ci.nsIPermissionManager.ALLOW_ACTION, 162 pm.testPermissionFromPrincipal(principal, TEST_PERMISSION) 163 ); 164 Assert.equal( 165 Ci.nsIPermissionManager.ALLOW_ACTION, 166 pm.testPermissionFromPrincipal(principalNotUpdated, TEST_PERMISSION) 167 ); 168 Assert.equal( 169 Ci.nsIPermissionManager.ALLOW_ACTION, 170 pm.testPermissionFromPrincipal(principal3, TEST_PERMISSION) 171 ); 172 173 // remove all should not throw and the default should remain 174 pm.removeAll(); 175 176 Assert.equal( 177 Ci.nsIPermissionManager.ALLOW_ACTION, 178 pm.testPermissionFromPrincipal(principal, TEST_PERMISSION) 179 ); 180 Assert.equal( 181 Ci.nsIPermissionManager.ALLOW_ACTION, 182 pm.testPermissionFromPrincipal(principalNotUpdated, TEST_PERMISSION) 183 ); 184 Assert.equal( 185 Ci.nsIPermissionManager.ALLOW_ACTION, 186 pm.testPermissionFromPrincipal(principal3, TEST_PERMISSION) 187 ); 188 // Default permission should have also been added for private browsing. 189 Assert.equal( 190 Ci.nsIPermissionManager.ALLOW_ACTION, 191 pm.testPermissionFromPrincipal(principal1PrivateBrowsing, TEST_PERMISSION) 192 ); 193 // make sure principals with userContextId use the same / different permissions 194 // depending on pref state 195 Assert.equal( 196 permIsolateUserContext 197 ? Ci.nsIPermissionManager.UNKNOWN_ACTION 198 : Ci.nsIPermissionManager.ALLOW_ACTION, 199 pm.testPermissionFromPrincipal(principal1UserContext, TEST_PERMISSION) 200 ); 201 // make sure principals with a firstPartyDomain use different permissions 202 Assert.equal( 203 Ci.nsIPermissionManager.UNKNOWN_ACTION, 204 pm.testPermissionFromPrincipal(principal7, TEST_PERMISSION) 205 ); 206 Assert.equal( 207 Ci.nsIPermissionManager.UNKNOWN_ACTION, 208 pm.testPermissionFromPrincipal(principal8, TEST_PERMISSION) 209 ); 210 211 // Asking for this permission to be removed should result in that permission 212 // having UNKNOWN_ACTION 213 pm.removeFromPrincipal(principal, TEST_PERMISSION); 214 Assert.equal( 215 Ci.nsIPermissionManager.UNKNOWN_ACTION, 216 pm.testPermissionFromPrincipal(principal, TEST_PERMISSION) 217 ); 218 // make sure principals with userContextId use the correct permissions 219 // (Should be unknown with and without OA stripping ) 220 Assert.equal( 221 Ci.nsIPermissionManager.UNKNOWN_ACTION, 222 pm.testPermissionFromPrincipal(principal1UserContext, TEST_PERMISSION) 223 ); 224 // If we isolate by private browsing, the permission should still be present 225 // for the private browsing principal. 226 Assert.equal( 227 permIsolatePrivateBrowsing 228 ? Ci.nsIPermissionManager.ALLOW_ACTION 229 : Ci.nsIPermissionManager.UNKNOWN_ACTION, 230 pm.testPermissionFromPrincipal(principal1PrivateBrowsing, TEST_PERMISSION) 231 ); 232 // and we should have this UNKNOWN_ACTION reflected in the DB 233 await checkCapabilityViaDB(Ci.nsIPermissionManager.UNKNOWN_ACTION); 234 // but the permission should *not* appear in the enumerator. 235 Assert.equal(null, findCapabilityViaEnum()); 236 237 // and a subsequent RemoveAll should restore the default 238 pm.removeAll(); 239 240 Assert.equal( 241 Ci.nsIPermissionManager.ALLOW_ACTION, 242 pm.testPermissionFromPrincipal(principal, TEST_PERMISSION) 243 ); 244 Assert.equal( 245 Ci.nsIPermissionManager.ALLOW_ACTION, 246 pm.testPermissionFromPrincipal(principalNotUpdated, TEST_PERMISSION) 247 ); 248 // Make sure default imports work for private browsing after removeAll. 249 Assert.equal( 250 Ci.nsIPermissionManager.ALLOW_ACTION, 251 pm.testPermissionFromPrincipal(principal1PrivateBrowsing, TEST_PERMISSION) 252 ); 253 // make sure principals with userContextId share permissions depending on pref state 254 Assert.equal( 255 permIsolateUserContext 256 ? Ci.nsIPermissionManager.UNKNOWN_ACTION 257 : Ci.nsIPermissionManager.ALLOW_ACTION, 258 pm.testPermissionFromPrincipal(principal1UserContext, TEST_PERMISSION) 259 ); 260 // make sure principals with firstPartyDomain use different permissions 261 Assert.equal( 262 Ci.nsIPermissionManager.UNKNOWN_ACTION, 263 pm.testPermissionFromPrincipal(principal7, TEST_PERMISSION) 264 ); 265 Assert.equal( 266 Ci.nsIPermissionManager.UNKNOWN_ACTION, 267 pm.testPermissionFromPrincipal(principal8, TEST_PERMISSION) 268 ); 269 // and allow it to again be seen in the enumerator. 270 Assert.equal(Ci.nsIPermissionManager.ALLOW_ACTION, findCapabilityViaEnum()); 271 272 // now explicitly add a permission - this too should override the default. 273 pm.addFromPrincipal( 274 principal, 275 TEST_PERMISSION, 276 Ci.nsIPermissionManager.DENY_ACTION 277 ); 278 279 // it should be reflected in a permission check, in the enumerator and the DB 280 Assert.equal( 281 Ci.nsIPermissionManager.DENY_ACTION, 282 pm.testPermissionFromPrincipal(principal, TEST_PERMISSION) 283 ); 284 // make sure principals with userContextId use the same / different permissions 285 // depending on pref state 286 Assert.equal( 287 permIsolateUserContext 288 ? Ci.nsIPermissionManager.UNKNOWN_ACTION 289 : Ci.nsIPermissionManager.DENY_ACTION, 290 pm.testPermissionFromPrincipal(principal1UserContext, TEST_PERMISSION) 291 ); 292 // If we isolate by private browsing, we should still have the default perm 293 // for the private browsing principal. 294 Assert.equal( 295 permIsolatePrivateBrowsing 296 ? Ci.nsIPermissionManager.ALLOW_ACTION 297 : Ci.nsIPermissionManager.DENY_ACTION, 298 pm.testPermissionFromPrincipal(principal1PrivateBrowsing, TEST_PERMISSION) 299 ); 300 // make sure principals with firstPartyDomain use different permissions 301 Assert.equal( 302 Ci.nsIPermissionManager.UNKNOWN_ACTION, 303 pm.testPermissionFromPrincipal(principal7, TEST_PERMISSION) 304 ); 305 Assert.equal( 306 Ci.nsIPermissionManager.UNKNOWN_ACTION, 307 pm.testPermissionFromPrincipal(principal8, TEST_PERMISSION) 308 ); 309 Assert.equal(Ci.nsIPermissionManager.DENY_ACTION, findCapabilityViaEnum()); 310 await checkCapabilityViaDB(Ci.nsIPermissionManager.DENY_ACTION); 311 312 // explicitly add a different permission - in this case we are no longer 313 // replacing the default, but instead replacing the replacement! 314 pm.addFromPrincipal( 315 principal, 316 TEST_PERMISSION, 317 Ci.nsIPermissionManager.PROMPT_ACTION 318 ); 319 320 // it should be reflected in a permission check, in the enumerator and the DB 321 Assert.equal( 322 Ci.nsIPermissionManager.PROMPT_ACTION, 323 pm.testPermissionFromPrincipal(principal, TEST_PERMISSION) 324 ); 325 // make sure principals with userContextId use the same / different permissions 326 // depending on pref state 327 Assert.equal( 328 permIsolateUserContext 329 ? Ci.nsIPermissionManager.UNKNOWN_ACTION 330 : Ci.nsIPermissionManager.PROMPT_ACTION, 331 pm.testPermissionFromPrincipal(principal1UserContext, TEST_PERMISSION) 332 ); 333 // If we isolate by private browsing, we should still have the default perm 334 // for the private browsing principal. 335 Assert.equal( 336 permIsolatePrivateBrowsing 337 ? Ci.nsIPermissionManager.ALLOW_ACTION 338 : Ci.nsIPermissionManager.PROMPT_ACTION, 339 pm.testPermissionFromPrincipal(principal1PrivateBrowsing, TEST_PERMISSION) 340 ); 341 // make sure principals with firstPartyDomain use different permissions 342 Assert.equal( 343 Ci.nsIPermissionManager.UNKNOWN_ACTION, 344 pm.testPermissionFromPrincipal(principal7, TEST_PERMISSION) 345 ); 346 Assert.equal( 347 Ci.nsIPermissionManager.UNKNOWN_ACTION, 348 pm.testPermissionFromPrincipal(principal8, TEST_PERMISSION) 349 ); 350 Assert.equal(Ci.nsIPermissionManager.PROMPT_ACTION, findCapabilityViaEnum()); 351 await checkCapabilityViaDB(Ci.nsIPermissionManager.PROMPT_ACTION); 352 353 // -------------------------------------------------------------- 354 // check default permissions and removeAllSince work as expected. 355 pm.removeAll(); // ensure only defaults are there. 356 357 // default for principals is allow. 358 Assert.equal( 359 Ci.nsIPermissionManager.ALLOW_ACTION, 360 pm.testPermissionFromPrincipal(principal, TEST_PERMISSION) 361 ); 362 Assert.equal( 363 Ci.nsIPermissionManager.ALLOW_ACTION, 364 pm.testPermissionFromPrincipal(principalNotUpdated, TEST_PERMISSION) 365 ); 366 Assert.equal( 367 Ci.nsIPermissionManager.ALLOW_ACTION, 368 pm.testPermissionFromPrincipal(principal2, TEST_PERMISSION) 369 ); 370 371 // Add a default override for TEST_ORIGIN_2 - this one should *not* be 372 // restored in removeAllSince() 373 pm.addFromPrincipal( 374 principal2, 375 TEST_PERMISSION, 376 Ci.nsIPermissionManager.DENY_ACTION 377 ); 378 Assert.equal( 379 Ci.nsIPermissionManager.DENY_ACTION, 380 pm.testPermissionFromPrincipal(principal2, TEST_PERMISSION) 381 ); 382 await promiseTimeout(20); 383 384 // update since to now 385 since = Number(Date.now()); 386 await promiseTimeout(20); 387 388 // explicitly add a permission which overrides the default for the first 389 // principal - this one *should* be removed by removeAllSince. 390 pm.addFromPrincipal( 391 principal, 392 TEST_PERMISSION, 393 Ci.nsIPermissionManager.DENY_ACTION 394 ); 395 Assert.equal( 396 Ci.nsIPermissionManager.DENY_ACTION, 397 pm.testPermissionFromPrincipal(principal, TEST_PERMISSION) 398 ); 399 400 // do a removeAllSince. 401 pm.removeAllSince(since); 402 403 // the default for the first principal should re-appear as we modified it 404 // later then |since| 405 Assert.equal( 406 Ci.nsIPermissionManager.ALLOW_ACTION, 407 pm.testPermissionFromPrincipal(principal, TEST_PERMISSION) 408 ); 409 // the default permission for principal that wasn't updated should be allowed 410 Assert.equal( 411 Ci.nsIPermissionManager.ALLOW_ACTION, 412 pm.testPermissionFromPrincipal(principalNotUpdated, TEST_PERMISSION) 413 ); 414 // but the default permission for principal2 should remain as we added that before |since|. 415 Assert.equal( 416 Ci.nsIPermissionManager.DENY_ACTION, 417 pm.testPermissionFromPrincipal(principal2, TEST_PERMISSION) 418 ); 419 420 // remove the temp file we created. 421 file.remove(false); 422 }); 423 424 // use an enumerator to find the requested permission. Returns the permission 425 // value (ie, the "capability" in nsIPermission parlance) or null if it can't 426 // be found. 427 function findCapabilityViaEnum(origin = TEST_ORIGIN, type = TEST_PERMISSION) { 428 let result = undefined; 429 for (let perm of Services.perms.all) { 430 if (perm.matchesURI(origin, true) && perm.type == type) { 431 if (result !== undefined) { 432 // we've already found one previously - that's bad! 433 do_throw("enumerator found multiple entries"); 434 } 435 result = perm.capability; 436 } 437 } 438 return result || null; 439 } 440 441 // A function to check the DB has the specified capability. As the permission 442 // manager uses async DB operations without a completion callback, the 443 // distinct possibility exists that our checking of the DB will happen before 444 // the permission manager update has completed - so we just retry a few times. 445 // Returns a promise. 446 function checkCapabilityViaDB( 447 expected, 448 origin = TEST_ORIGIN, 449 type = TEST_PERMISSION 450 ) { 451 return new Promise(resolve => { 452 let count = 0; 453 let max = 20; 454 let do_check = () => { 455 let got = findCapabilityViaDB(origin, type); 456 if (got == expected) { 457 // the do_check_eq() below will succeed - which is what we want. 458 Assert.equal(got, expected, "The database has the expected value"); 459 resolve(); 460 return; 461 } 462 // value isn't correct - see if we've retried enough 463 if (count++ == max) { 464 // the do_check_eq() below will fail - which is what we want. 465 Assert.equal( 466 got, 467 expected, 468 "The database wasn't updated with the expected value" 469 ); 470 resolve(); 471 return; 472 } 473 // we can retry... 474 do_timeout(100, do_check); 475 }; 476 do_check(); 477 }); 478 } 479 480 // use the DB to find the requested permission. Returns the permission 481 // value (ie, the "capability" in nsIPermission parlance) or null if it can't 482 // be found. 483 function findCapabilityViaDB(origin = TEST_ORIGIN, type = TEST_PERMISSION) { 484 let principal = Services.scriptSecurityManager.createContentPrincipal( 485 origin, 486 {} 487 ); 488 let originStr = principal.origin; 489 490 let file = Services.dirsvc.get("ProfD", Ci.nsIFile); 491 file.append("permissions.sqlite"); 492 493 let connection = Services.storage.openDatabase(file); 494 495 let query = connection.createStatement( 496 "SELECT permission FROM moz_perms WHERE origin = :origin AND type = :type" 497 ); 498 query.bindByName("origin", originStr); 499 query.bindByName("type", type); 500 501 if (!query.executeStep()) { 502 // no row 503 return null; 504 } 505 let result = query.getInt32(0); 506 if (query.executeStep()) { 507 // this is bad - we never expect more than 1 row here. 508 do_throw("More than 1 row found!"); 509 } 510 return result; 511 }