tor-browser

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

test_SessionStoreBackupResource_mockSessionStore.js (8231B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 https://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 /**
      7 * This tests that SessionStore backups contain the info that we want and do
      8 * not contain info we don't want.  This is separate from
      9 * test_SessionStoreBackupResource because that uses the real SessionStore
     10 * service and can only check what that includes.  This test adds things that
     11 * are not usually testable in xpcshell tests, like window session state
     12 * serialization.  It is based on test_SessionStoreBackupResource.js.
     13 */
     14 
     15 const { SessionStoreBackupResource } = ChromeUtils.importESModule(
     16  "resource:///modules/backup/SessionStoreBackupResource.sys.mjs"
     17 );
     18 
     19 const mockSessionStore = {
     20  getCurrentState: _ignored => {
     21    return {
     22      cookies: [],
     23      windows: [
     24        {
     25          tabs: [
     26            {
     27              someData: "hi I am data, I will get serialized",
     28              moreData: -3.7,
     29              storage: {
     30                message: "I don't get serialized!",
     31              },
     32            },
     33            {
     34              stillMoreData: -3.71,
     35              storage: {
     36                message: "I don't get serialized either!",
     37              },
     38            },
     39          ],
     40          _closedTabs: [
     41            {
     42              state: {
     43                closedTabData: "hi I am a closed tab",
     44                moreData: -3.7,
     45                storage: {
     46                  message: "I don't get serialized!",
     47                },
     48              },
     49              etc: {
     50                dataNotInState: true,
     51              },
     52            },
     53            {
     54              state: {
     55                storage: {
     56                  message: "I don't get serialized either!",
     57                },
     58              },
     59            },
     60          ],
     61        },
     62        {
     63          tabs: [
     64            {
     65              someData: "hi I am window #2's data, I will get serialized",
     66              moreData: -3.7,
     67              storage: {
     68                message: "I don't get serialized!",
     69              },
     70            },
     71          ],
     72          _closedTabs: [
     73            {
     74              state: {
     75                storage: {
     76                  message: "I don't get serialized either!",
     77                },
     78              },
     79              notState: {
     80                notStateData: "not state data",
     81              },
     82            },
     83          ],
     84        },
     85        {
     86          tabs: [
     87            {
     88              someData: "hi I am the private window's data",
     89              storage: {
     90                message: "I don't get serialized!",
     91              },
     92            },
     93          ],
     94          isPrivate: true,
     95          _closedTabs: [],
     96        },
     97        {
     98          tabs: [
     99            {
    100              someData: "hi I am the private window #2's data",
    101              storage: {
    102                message: "I don't get serialized!",
    103              },
    104            },
    105          ],
    106          isPrivate: true,
    107          _closedTabs: [],
    108        },
    109      ],
    110      savedGroups: [
    111        {
    112          tabs: [
    113            {
    114              state: {
    115                savedGroupData: -3.7,
    116                storage: {
    117                  message: "I don't get serialized!",
    118                },
    119              },
    120            },
    121            {
    122              state: {
    123                someData: "hi I am window #2's data",
    124                moreData: -3.71,
    125                // tab has no storage
    126              },
    127            },
    128          ],
    129          notTabData: "notTabData",
    130        },
    131      ],
    132    };
    133  },
    134 };
    135 
    136 // This is mockSessionStore but with the data that should not be saved removed.
    137 let filteredMockSessionData;
    138 let sessionStoreBackupResource;
    139 
    140 add_setup(() => {
    141  // let's use the SessionStoreBackupResource's filtering
    142  sessionStoreBackupResource = new SessionStoreBackupResource(mockSessionStore);
    143 
    144  filteredMockSessionData =
    145    sessionStoreBackupResource.filteredSessionStoreState;
    146 });
    147 
    148 /**
    149 * Test that the backup method properly serializes window session state.  This
    150 * includes checking that it does NOT serialize window storage state.
    151 */
    152 add_task(async function test_backups_have_correct_window_state() {
    153  let sandbox = sinon.createSandbox();
    154 
    155  let sourcePath = await IOUtils.createUniqueDirectory(
    156    PathUtils.tempDir,
    157    "SessionStoreBackupResource-src"
    158  );
    159  let stagingPath = await IOUtils.createUniqueDirectory(
    160    PathUtils.tempDir,
    161    "SessionStoreBackupResource-stage"
    162  );
    163 
    164  // This "filtered" session store state is what we expect to write.  It should
    165  // not include any WebStorage items.
    166  // Quick sanity-check that the filtering was done correctly and we will still
    167  // serialize windows.
    168  Assert.equal(
    169    filteredMockSessionData.windows.length,
    170    2,
    171    "will serialize only 2 windows, since we don't backup private window sessions"
    172  );
    173  Assert.equal(
    174    filteredMockSessionData.windows[0].tabs.length,
    175    2,
    176    "will serialize 2 tabs for 1st window"
    177  );
    178  Assert.equal(
    179    filteredMockSessionData.windows[0].tabs[0].storage,
    180    undefined,
    181    "does not contain win 0 tab storage"
    182  );
    183  Assert.equal(
    184    filteredMockSessionData.windows[0]._closedTabs[0].storage,
    185    undefined,
    186    "does not contain win 0 closed tab storage"
    187  );
    188  Assert.equal(
    189    filteredMockSessionData.savedGroups.length,
    190    1,
    191    "will serialize 1 savedGroup"
    192  );
    193  Assert.equal(
    194    filteredMockSessionData.savedGroups[0].tabs.length,
    195    2,
    196    "will serialize 2 savedGroup tabs"
    197  );
    198 
    199  let manifestEntry = await sessionStoreBackupResource.backup(
    200    stagingPath,
    201    sourcePath,
    202    false /* isEncrypted */
    203  );
    204  Assert.equal(
    205    manifestEntry,
    206    null,
    207    "SessionStoreBackupResource.backup should return null as its ManifestEntry"
    208  );
    209 
    210  /**
    211   * We don't expect the actual file sessionstore.jsonlz4 to exist in the profile directory before calling the backup method.
    212   * Instead, verify that it is created by the backup method and exists in the staging folder right after.
    213   */
    214  await assertFilesExist(stagingPath, [{ path: "sessionstore.jsonlz4" }]);
    215 
    216  /**
    217   * Do a deep comparison between the filtered session state before backup
    218   * and contents of the file made in the staging folder, to verify that
    219   * information about session state was correctly written for backup.
    220   */
    221  let sessionStoreStateStaged = await IOUtils.readJSON(
    222    PathUtils.join(stagingPath, "sessionstore.jsonlz4"),
    223    { decompress: true }
    224  );
    225 
    226  Assert.deepEqual(
    227    sessionStoreStateStaged,
    228    filteredMockSessionData,
    229    "sessionstore.jsonlz4 in the staging folder matches the recorded session state"
    230  );
    231 
    232  await maybeRemovePath(stagingPath);
    233  await maybeRemovePath(sourcePath);
    234 
    235  sandbox.restore();
    236 });
    237 
    238 /**
    239 * Minor test that the recover method correctly copies the session store from
    240 * the recovery directory into the destination profile directory.
    241 */
    242 add_task(async function test_recover() {
    243  let recoveryPath = await IOUtils.createUniqueDirectory(
    244    PathUtils.tempDir,
    245    "SessionStoreBackupResource-recover"
    246  );
    247  let destProfilePath = await IOUtils.createUniqueDirectory(
    248    PathUtils.tempDir,
    249    "SessionStoreBackupResource-restored-profile"
    250  );
    251 
    252  // We backup a copy of sessionstore.jsonlz4, so ensure it exists in the recovery path
    253  let sessionStoreBackupPath = PathUtils.join(
    254    recoveryPath,
    255    "sessionstore.jsonlz4"
    256  );
    257  await IOUtils.writeJSON(sessionStoreBackupPath, filteredMockSessionData, {
    258    compress: true,
    259  });
    260 
    261  // The backup method is expected to have returned a null ManifestEntry
    262  let postRecoveryEntry = await sessionStoreBackupResource.recover(
    263    null /* manifestEntry */,
    264    recoveryPath,
    265    destProfilePath
    266  );
    267  Assert.equal(
    268    postRecoveryEntry,
    269    null,
    270    "SessionStoreBackupResource.recover should return null as its post recovery entry"
    271  );
    272 
    273  await assertFilesExist(destProfilePath, [{ path: "sessionstore.jsonlz4" }]);
    274 
    275  let sessionStateCopied = await IOUtils.readJSON(
    276    PathUtils.join(destProfilePath, "sessionstore.jsonlz4"),
    277    { decompress: true }
    278  );
    279 
    280  Assert.deepEqual(
    281    sessionStateCopied,
    282    filteredMockSessionData,
    283    "sessionstore.jsonlz4 in the destination profile folder matches the backed up session state"
    284  );
    285 
    286  await maybeRemovePath(recoveryPath);
    287  await maybeRemovePath(destProfilePath);
    288 });