tor-browser

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

test_getPotentialBreachesByLoginGUID.js (10290B)


      1 /**
      2 * Test LoginBreaches.getPotentialBreachesByLoginGUID
      3 */
      4 
      5 "use strict";
      6 
      7 const { RemoteSettings } = ChromeUtils.importESModule(
      8  "resource://services-settings/remote-settings.sys.mjs"
      9 );
     10 
     11 // Initializing BrowserGlue requires a profile on Windows.
     12 do_get_profile();
     13 
     14 const gBrowserGlue = Cc["@mozilla.org/browser/browserglue;1"].getService(
     15  Ci.nsIObserver
     16 );
     17 
     18 ChromeUtils.defineESModuleGetters(this, {
     19  LoginBreaches: "resource:///modules/LoginBreaches.sys.mjs",
     20 });
     21 
     22 const TEST_BREACHES = [
     23  {
     24    AddedDate: "2018-12-20T23:56:26Z",
     25    BreachDate: "2018-12-16",
     26    Domain: "breached.com",
     27    Name: "Breached",
     28    PwnCount: 1643100,
     29    DataClasses: ["Email addresses", "Usernames", "Passwords", "IP addresses"],
     30    _status: "synced",
     31    id: "047940fe-d2fd-4314-b636-b4a952ee0043",
     32    last_modified: "1541615610052",
     33    schema: "1541615609018",
     34  },
     35  {
     36    AddedDate: "2018-12-20T23:56:26Z",
     37    BreachDate: "2018-12-16",
     38    Domain: "breached-subdomain.host.com",
     39    Name: "Only a Sub-Domain was Breached",
     40    PwnCount: 2754200,
     41    DataClasses: ["Email addresses", "Usernames", "Passwords", "IP addresses"],
     42    _status: "synced",
     43    id: "047940fe-d2fd-4314-b636-b4a952ee0044",
     44    last_modified: "1541615610052",
     45    schema: "1541615609018",
     46  },
     47  {
     48    AddedDate: "2018-12-20T23:56:26Z",
     49    BreachDate: "2018-12-16",
     50    Domain: "breached-site-without-passwords.com",
     51    Name: "Breached Site without passwords",
     52    PwnCount: 987654,
     53    DataClasses: ["Email addresses", "Usernames", "IP addresses"],
     54    _status: "synced",
     55    id: "047940fe-d2fd-4314-b636-b4a952ee0045",
     56    last_modified: "1541615610052",
     57    schema: "1541615609018",
     58  },
     59 ];
     60 
     61 const CRASHING_URI_LOGIN = LoginTestUtils.testData.formLogin({
     62  origin: "chrome://grwatcher",
     63  formActionOrigin: "https://www.example.com",
     64  username: "username",
     65  password: "password",
     66  timePasswordChanged: new Date("2018-12-15").getTime(),
     67 });
     68 const NOT_BREACHED_LOGIN = LoginTestUtils.testData.formLogin({
     69  origin: "https://www.example.com",
     70  formActionOrigin: "https://www.example.com",
     71  username: "username",
     72  password: "password",
     73  timePasswordChanged: new Date("2018-12-15").getTime(),
     74 });
     75 const BREACHED_LOGIN = LoginTestUtils.testData.formLogin({
     76  origin: "https://www.breached.com",
     77  formActionOrigin: "https://www.breached.com",
     78  username: "username",
     79  password: "password",
     80  timePasswordChanged: new Date("2018-12-15").getTime(),
     81 });
     82 const NOT_BREACHED_SUBDOMAIN_LOGIN = LoginTestUtils.testData.formLogin({
     83  origin: "https://not-breached-subdomain.host.com",
     84  formActionOrigin: "https://not-breached-subdomain.host.com",
     85  username: "username",
     86  password: "password",
     87 });
     88 const BREACHED_SUBDOMAIN_LOGIN = LoginTestUtils.testData.formLogin({
     89  origin: "https://breached-subdomain.host.com",
     90  formActionOrigin: "https://breached-subdomain.host.com",
     91  username: "username",
     92  password: "password",
     93  timePasswordChanged: new Date("2018-12-15").getTime(),
     94 });
     95 const LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS =
     96  LoginTestUtils.testData.formLogin({
     97    origin: "https://breached-site-without-passwords.com",
     98    formActionOrigin: "https://breached-site-without-passwords.com",
     99    username: "username",
    100    password: "password",
    101    timePasswordChanged: new Date("2018-12-15").getTime(),
    102  });
    103 const LOGIN_WITH_NON_STANDARD_URI = LoginTestUtils.testData.formLogin({
    104  origin: "someApp://random/path/to/login",
    105  formActionOrigin: "someApp://random/path/to/login",
    106  username: "username",
    107  password: "password",
    108  timePasswordChanged: new Date("2018-12-15").getTime(),
    109 });
    110 
    111 add_task(async function test_notBreachedLogin() {
    112  await Services.logins.addLoginAsync(NOT_BREACHED_LOGIN);
    113  const breachesByLoginGUID =
    114    await LoginBreaches.getPotentialBreachesByLoginGUID(
    115      [NOT_BREACHED_LOGIN],
    116      TEST_BREACHES
    117    );
    118  Assert.strictEqual(
    119    breachesByLoginGUID.size,
    120    0,
    121    "Should be 0 breached logins."
    122  );
    123 });
    124 
    125 add_task(async function test_breachedLogin() {
    126  await Services.logins.addLoginAsync(BREACHED_LOGIN);
    127  const breachesByLoginGUID =
    128    await LoginBreaches.getPotentialBreachesByLoginGUID(
    129      [NOT_BREACHED_LOGIN, BREACHED_LOGIN],
    130      TEST_BREACHES
    131    );
    132  Assert.strictEqual(
    133    breachesByLoginGUID.size,
    134    1,
    135    "Should be 1 breached login: " + BREACHED_LOGIN.origin
    136  );
    137  Assert.strictEqual(
    138    breachesByLoginGUID.get(BREACHED_LOGIN.guid).breachAlertURL,
    139    "https://monitor.firefox.com/breach-details/Breached?utm_source=firefox-desktop&utm_medium=referral&utm_campaign=about-logins&utm_content=about-logins",
    140    "Breach alert link should be equal to the breachAlertURL"
    141  );
    142 });
    143 
    144 add_task(async function test_breachedLoginAfterCrashingUriLogin() {
    145  await Services.logins.addLoginAsync(CRASHING_URI_LOGIN);
    146 
    147  const breachesByLoginGUID =
    148    await LoginBreaches.getPotentialBreachesByLoginGUID(
    149      [CRASHING_URI_LOGIN, BREACHED_LOGIN],
    150      TEST_BREACHES
    151    );
    152  Assert.strictEqual(
    153    breachesByLoginGUID.size,
    154    1,
    155    "Should be 1 breached login: " + BREACHED_LOGIN.origin
    156  );
    157  Assert.strictEqual(
    158    breachesByLoginGUID.get(BREACHED_LOGIN.guid).breachAlertURL,
    159    "https://monitor.firefox.com/breach-details/Breached?utm_source=firefox-desktop&utm_medium=referral&utm_campaign=about-logins&utm_content=about-logins",
    160    "Breach alert link should be equal to the breachAlertURL"
    161  );
    162 });
    163 
    164 add_task(async function test_notBreachedSubdomain() {
    165  await Services.logins.addLoginAsync(NOT_BREACHED_SUBDOMAIN_LOGIN);
    166 
    167  const breachesByLoginGUID =
    168    await LoginBreaches.getPotentialBreachesByLoginGUID(
    169      [NOT_BREACHED_LOGIN, NOT_BREACHED_SUBDOMAIN_LOGIN],
    170      TEST_BREACHES
    171    );
    172  Assert.strictEqual(
    173    breachesByLoginGUID.size,
    174    0,
    175    "Should be 0 breached logins."
    176  );
    177 });
    178 
    179 add_task(async function test_breachedSubdomain() {
    180  await Services.logins.addLoginAsync(BREACHED_SUBDOMAIN_LOGIN);
    181 
    182  const breachesByLoginGUID =
    183    await LoginBreaches.getPotentialBreachesByLoginGUID(
    184      [NOT_BREACHED_SUBDOMAIN_LOGIN, BREACHED_SUBDOMAIN_LOGIN],
    185      TEST_BREACHES
    186    );
    187  Assert.strictEqual(
    188    breachesByLoginGUID.size,
    189    1,
    190    "Should be 1 breached login: " + BREACHED_SUBDOMAIN_LOGIN.origin
    191  );
    192 });
    193 
    194 add_task(async function test_breachedSiteWithoutPasswords() {
    195  await Services.logins.addLoginAsync(
    196    LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS
    197  );
    198 
    199  const breachesByLoginGUID =
    200    await LoginBreaches.getPotentialBreachesByLoginGUID(
    201      [LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS],
    202      TEST_BREACHES
    203    );
    204  Assert.strictEqual(
    205    breachesByLoginGUID.size,
    206    0,
    207    "Should be 0 breached login: " +
    208      LOGIN_FOR_BREACHED_SITE_WITHOUT_PASSWORDS.origin
    209  );
    210 });
    211 
    212 add_task(async function test_breachAlertHiddenAfterDismissal() {
    213  BREACHED_LOGIN.guid = "{d2de5ac1-4de6-e544-a7af-1f75abcba92b}";
    214 
    215  await Services.logins.initializationPromise;
    216  const storageJSON = Services.logins.wrappedJSObject._storage;
    217 
    218  storageJSON.recordBreachAlertDismissal(BREACHED_LOGIN.guid);
    219 
    220  const breachesByLoginGUID =
    221    await LoginBreaches.getPotentialBreachesByLoginGUID(
    222      [BREACHED_LOGIN, NOT_BREACHED_LOGIN],
    223      TEST_BREACHES
    224    );
    225  Assert.strictEqual(
    226    breachesByLoginGUID.size,
    227    0,
    228    "Should be 0 breached logins after dismissal: " + BREACHED_LOGIN.origin
    229  );
    230 
    231  info("Clear login storage");
    232  Services.logins.removeAllUserFacingLogins();
    233 
    234  const breachesByLoginGUID2 =
    235    await LoginBreaches.getPotentialBreachesByLoginGUID(
    236      [BREACHED_LOGIN, NOT_BREACHED_LOGIN],
    237      TEST_BREACHES
    238    );
    239  Assert.strictEqual(
    240    breachesByLoginGUID2.size,
    241    1,
    242    "Breached login should re-appear after clearing storage: " +
    243      BREACHED_LOGIN.origin
    244  );
    245 });
    246 
    247 add_task(async function test_newBreachAfterDismissal() {
    248  TEST_BREACHES[0].AddedDate = new Date().toISOString();
    249 
    250  const breachesByLoginGUID =
    251    await LoginBreaches.getPotentialBreachesByLoginGUID(
    252      [BREACHED_LOGIN, NOT_BREACHED_LOGIN],
    253      TEST_BREACHES
    254    );
    255 
    256  Assert.strictEqual(
    257    breachesByLoginGUID.size,
    258    1,
    259    "Should be 1 breached login after new breach following the dismissal of a previous breach: " +
    260      BREACHED_LOGIN.origin
    261  );
    262 });
    263 
    264 add_task(async function test_ExceptionsThrownByNonStandardURIsAreCaught() {
    265  await Services.logins.addLoginAsync(LOGIN_WITH_NON_STANDARD_URI);
    266 
    267  const breachesByLoginGUID =
    268    await LoginBreaches.getPotentialBreachesByLoginGUID(
    269      [LOGIN_WITH_NON_STANDARD_URI, BREACHED_LOGIN],
    270      TEST_BREACHES
    271    );
    272 
    273  Assert.strictEqual(
    274    breachesByLoginGUID.size,
    275    1,
    276    "Exceptions thrown by logins with non-standard URIs should be caught."
    277  );
    278 });
    279 
    280 add_task(async function test_setBreachesFromRemoteSettingsSync() {
    281  const login = NOT_BREACHED_SUBDOMAIN_LOGIN;
    282  const nowExampleIsInBreachedRecords = [
    283    {
    284      AddedDate: "2018-12-20T23:56:26Z",
    285      BreachDate: "2018-12-16",
    286      Domain: "not-breached-subdomain.host.com",
    287      Name: "not-breached-subdomain.host.com is now breached!",
    288      PwnCount: 1643100,
    289      DataClasses: [
    290        "Email addresses",
    291        "Usernames",
    292        "Passwords",
    293        "IP addresses",
    294      ],
    295      _status: "synced",
    296      id: "047940fe-d2fd-4314-b636-b4a952ee0044",
    297      last_modified: "1541615610052",
    298      schema: "1541615609018",
    299    },
    300  ];
    301  async function emitSync() {
    302    await RemoteSettings(LoginBreaches.REMOTE_SETTINGS_COLLECTION).emit(
    303      "sync",
    304      { data: { current: nowExampleIsInBreachedRecords } }
    305    );
    306  }
    307 
    308  const beforeSyncBreachesByLoginGUID =
    309    await LoginBreaches.getPotentialBreachesByLoginGUID([login]);
    310  Assert.strictEqual(
    311    beforeSyncBreachesByLoginGUID.size,
    312    0,
    313    "Should be 0 breached login before not-breached-subdomain.host.com is added to fxmonitor-breaches collection and synced: "
    314  );
    315  gBrowserGlue.observe(null, "browser-glue-test", "add-breaches-sync-handler");
    316  const db = RemoteSettings(LoginBreaches.REMOTE_SETTINGS_COLLECTION).db;
    317  await db.importChanges({}, Date.now(), [nowExampleIsInBreachedRecords[0]]);
    318  await emitSync();
    319 
    320  const breachesByLoginGUID =
    321    await LoginBreaches.getPotentialBreachesByLoginGUID([login]);
    322  Assert.strictEqual(
    323    breachesByLoginGUID.size,
    324    1,
    325    "Should be 1 breached login after not-breached-subdomain.host.com is added to fxmonitor-breaches collection and synced: "
    326  );
    327 });