tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }