tor-browser

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

head_migration.js (8086B)


      1 "use strict";
      2 
      3 var { MigrationUtils } = ChromeUtils.importESModule(
      4  "resource:///modules/MigrationUtils.sys.mjs"
      5 );
      6 var { LoginHelper } = ChromeUtils.importESModule(
      7  "resource://gre/modules/LoginHelper.sys.mjs"
      8 );
      9 var { NetUtil } = ChromeUtils.importESModule(
     10  "resource://gre/modules/NetUtil.sys.mjs"
     11 );
     12 var { PlacesUtils } = ChromeUtils.importESModule(
     13  "resource://gre/modules/PlacesUtils.sys.mjs"
     14 );
     15 var { Preferences } = ChromeUtils.importESModule(
     16  "resource://gre/modules/Preferences.sys.mjs"
     17 );
     18 var { XPCOMUtils } = ChromeUtils.importESModule(
     19  "resource://gre/modules/XPCOMUtils.sys.mjs"
     20 );
     21 var { TestUtils } = ChromeUtils.importESModule(
     22  "resource://testing-common/TestUtils.sys.mjs"
     23 );
     24 var { PlacesTestUtils } = ChromeUtils.importESModule(
     25  "resource://testing-common/PlacesTestUtils.sys.mjs"
     26 );
     27 const { AppConstants } = ChromeUtils.importESModule(
     28  "resource://gre/modules/AppConstants.sys.mjs"
     29 );
     30 
     31 ChromeUtils.defineESModuleGetters(this, {
     32  FileUtils: "resource://gre/modules/FileUtils.sys.mjs",
     33  Sqlite: "resource://gre/modules/Sqlite.sys.mjs",
     34 });
     35 
     36 // Initialize profile.
     37 var gProfD = do_get_profile();
     38 
     39 var { getAppInfo, newAppInfo, updateAppInfo } = ChromeUtils.importESModule(
     40  "resource://testing-common/AppInfo.sys.mjs"
     41 );
     42 updateAppInfo();
     43 
     44 /**
     45 * Migrates the requested resource and waits for the migration to be complete.
     46 *
     47 * @param {MigratorBase} migrator
     48 *   The migrator being used to migrate the data.
     49 * @param {number} resourceType
     50 *   This is a bitfield with bits from nsIBrowserProfileMigrator flipped to indicate what
     51 *   resources should be migrated.
     52 * @param {object|string|null} [aProfile=null]
     53 *   The profile to be migrated. If set to null, the default profile will be
     54 *   migrated.
     55 * @param {boolean} succeeds
     56 *   True if this migration is expected to succeed.
     57 * @returns {Promise<Array<string[]>>}
     58 *   An array of the results from each nsIObserver topics being observed to
     59 *   verify if the migration succeeded or failed. Those results are 2-element
     60 *   arrays of [subject, data].
     61 */
     62 async function promiseMigration(
     63  migrator,
     64  resourceType,
     65  aProfile = null,
     66  succeeds = null
     67 ) {
     68  // Ensure resource migration is available.
     69  let availableSources = await migrator.getMigrateData(aProfile);
     70  Assert.greater(
     71    availableSources & resourceType,
     72    0,
     73    "Resource supported by migrator"
     74  );
     75  let promises = [TestUtils.topicObserved("Migration:Ended")];
     76 
     77  if (succeeds !== null) {
     78    // Check that the specific resource type succeeded
     79    promises.push(
     80      TestUtils.topicObserved(
     81        succeeds ? "Migration:ItemAfterMigrate" : "Migration:ItemError",
     82        (_, data) => data == resourceType
     83      )
     84    );
     85  }
     86 
     87  // Start the migration.
     88  migrator.migrate(resourceType, null, aProfile);
     89 
     90  return Promise.all(promises);
     91 }
     92 
     93 /**
     94 * Takes an array of page URIs and checks that the favicon was imported for each page URI
     95 *
     96 * @param {Array} pageURIs An array of page URIs
     97 */
     98 async function assertFavicons(pageURIs) {
     99  for (let uri of pageURIs) {
    100    let favicon = await PlacesUtils.favicons.getFaviconForPage(uri);
    101    Assert.ok(favicon, `Got favicon for ${favicon.uri.spec}`);
    102  }
    103 }
    104 
    105 /**
    106 * Check the image data for favicon of given page uri.
    107 *
    108 * @param {string} pageURI
    109 *                 The page URI to which the favicon belongs.
    110 * @param {Array} expectedImageData
    111 *                 Expected image data of the favicon.
    112 * @param {string} expectedMimeType
    113 *                 Expected mime type of the favicon.
    114 */
    115 async function assertFavicon(pageURI, expectedImageData, expectedMimeType) {
    116  let result = await PlacesUtils.favicons.getFaviconForPage(
    117    Services.io.newURI(pageURI)
    118  );
    119  Assert.ok(!!result, `Got favicon for ${pageURI}`);
    120  Assert.equal(
    121    result.rawData.join(","),
    122    expectedImageData.join(","),
    123    "Image data is correct"
    124  );
    125  Assert.equal(result.mimeType, expectedMimeType, "Mime type is correct");
    126 }
    127 
    128 /**
    129 * Replaces a directory service entry with a given nsIFile.
    130 *
    131 * @param {string} key
    132 *   The nsIDirectoryService directory key to register a fake path for.
    133 *   For example: "AppData", "ULibDir".
    134 * @param {nsIFile} file
    135 *   The nsIFile to map the key to. Note that this nsIFile should represent
    136 *   a directory and not an individual file.
    137 * @see nsDirectoryServiceDefs.h for the list of directories that can be
    138 *   overridden.
    139 */
    140 function registerFakePath(key, file) {
    141  let dirsvc = Services.dirsvc.QueryInterface(Ci.nsIProperties);
    142  let originalFile;
    143  try {
    144    // If a file is already provided save it and undefine, otherwise set will
    145    // throw for persistent entries (ones that are cached).
    146    originalFile = dirsvc.get(key, Ci.nsIFile);
    147    dirsvc.undefine(key);
    148  } catch (e) {
    149    // dirsvc.get will throw if nothing provides for the key and dirsvc.undefine
    150    // will throw if it's not a persistent entry, in either case we don't want
    151    // to set the original file in cleanup.
    152    originalFile = undefined;
    153  }
    154 
    155  dirsvc.set(key, file);
    156  registerCleanupFunction(() => {
    157    dirsvc.undefine(key);
    158    if (originalFile) {
    159      dirsvc.set(key, originalFile);
    160    }
    161  });
    162 }
    163 
    164 function getRootPath() {
    165  let dirKey;
    166  if (AppConstants.platform == "win") {
    167    dirKey = "LocalAppData";
    168  } else if (AppConstants.platform == "macosx") {
    169    dirKey = "ULibDir";
    170  } else {
    171    dirKey = "Home";
    172  }
    173  return Services.dirsvc.get(dirKey, Ci.nsIFile).path;
    174 }
    175 
    176 /**
    177 * Returns a PRTime value for the current date minus daysAgo number
    178 * of days.
    179 *
    180 * @param {number} daysAgo
    181 *   How many days in the past from now the returned date should be.
    182 * @returns {number}
    183 */
    184 function PRTimeDaysAgo(daysAgo) {
    185  return PlacesUtils.toPRTime(Date.now() - daysAgo * 24 * 60 * 60 * 1000);
    186 }
    187 
    188 /**
    189 * Returns a Date value for the current date minus daysAgo number
    190 * of days.
    191 *
    192 * @param {number} daysAgo
    193 *   How many days in the past from now the returned date should be.
    194 * @returns {Date}
    195 */
    196 function dateDaysAgo(daysAgo) {
    197  return new Date(Date.now() - daysAgo * 24 * 60 * 60 * 1000);
    198 }
    199 
    200 /**
    201 * Constructs and returns a data structure consistent with the Chrome
    202 * browsers bookmarks storage. This data structure can then be serialized
    203 * to JSON and written to disk to simulate a Chrome browser's bookmarks
    204 * database.
    205 *
    206 * @param {number} [totalBookmarks=100]
    207 *   How many bookmarks to create.
    208 * @returns {object}
    209 */
    210 function createChromeBookmarkStructure(totalBookmarks = 100) {
    211  let bookmarksData = {
    212    roots: {
    213      bookmark_bar: { children: [] },
    214      other: { children: [] },
    215      synced: { children: [] },
    216    },
    217  };
    218  const MAX_BMS = totalBookmarks;
    219  let barKids = bookmarksData.roots.bookmark_bar.children;
    220  let menuKids = bookmarksData.roots.other.children;
    221  let syncedKids = bookmarksData.roots.synced.children;
    222  let currentMenuKids = menuKids;
    223  let currentBarKids = barKids;
    224  let currentSyncedKids = syncedKids;
    225  for (let i = 0; i < MAX_BMS; i++) {
    226    currentBarKids.push({
    227      url: "https://www.chrome-bookmark-bar-bookmark" + i + ".com",
    228      name: "bookmark " + i,
    229      type: "url",
    230    });
    231    currentMenuKids.push({
    232      url: "https://www.chrome-menu-bookmark" + i + ".com",
    233      name: "bookmark for menu " + i,
    234      type: "url",
    235    });
    236    currentSyncedKids.push({
    237      url: "https://www.chrome-synced-bookmark" + i + ".com",
    238      name: "bookmark for synced " + i,
    239      type: "url",
    240    });
    241    if (i % 20 == 19) {
    242      let nextFolder = {
    243        name: "toolbar folder " + Math.ceil(i / 20),
    244        type: "folder",
    245        children: [],
    246      };
    247      currentBarKids.push(nextFolder);
    248      currentBarKids = nextFolder.children;
    249 
    250      nextFolder = {
    251        name: "menu folder " + Math.ceil(i / 20),
    252        type: "folder",
    253        children: [],
    254      };
    255      currentMenuKids.push(nextFolder);
    256      currentMenuKids = nextFolder.children;
    257 
    258      nextFolder = {
    259        name: "synced folder " + Math.ceil(i / 20),
    260        type: "folder",
    261        children: [],
    262      };
    263      currentSyncedKids.push(nextFolder);
    264      currentSyncedKids = nextFolder.children;
    265    }
    266  }
    267  return bookmarksData;
    268 }