tor-browser

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

test_queue.js (12553B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 ChromeUtils.defineESModuleGetters(this, {
      5  PageDataService:
      6    "moz-src:///browser/components/pagedata/PageDataService.sys.mjs",
      7  TestUtils: "resource://testing-common/TestUtils.sys.mjs",
      8 });
      9 
     10 // Test that urls are retrieved in the expected order.
     11 add_task(async function test_queueOrder() {
     12  Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 0);
     13  // Pretend we are idle.
     14  PageDataService.observe(null, "idle", null);
     15 
     16  let pageDataResults = [
     17    {
     18      date: Date.now(),
     19      url: "http://www.mozilla.org/1",
     20      siteName: "Mozilla",
     21      data: {},
     22    },
     23    {
     24      date: Date.now() - 3600,
     25      url: "http://www.google.com/2",
     26      siteName: "Google",
     27      data: {},
     28    },
     29    {
     30      date: Date.now() + 3600,
     31      url: "http://www.example.com/3",
     32      image: "http://www.example.com/banner.jpg",
     33      data: {},
     34    },
     35    {
     36      date: Date.now() / 2,
     37      url: "http://www.wikipedia.org/4",
     38      data: {},
     39    },
     40    {
     41      date: Date.now() / 3,
     42      url: "http://www.microsoft.com/5",
     43      data: {
     44        [PageDataSchema.DATA_TYPE.PRODUCT]: {
     45          name: "Windows 11",
     46        },
     47      },
     48    },
     49  ];
     50 
     51  let requests = [];
     52  PageDataService.fetchPageData = url => {
     53    requests.push(url);
     54 
     55    for (let pageData of pageDataResults) {
     56      if (pageData.url == url) {
     57        return Promise.resolve(pageData);
     58      }
     59    }
     60 
     61    return Promise.reject(new Error("Unknown url"));
     62  };
     63 
     64  let { promise: completePromise, resolve } = Promise.withResolvers();
     65 
     66  let results = [];
     67  let listener = (_, pageData) => {
     68    results.push(pageData);
     69    if (results.length == pageDataResults.length) {
     70      resolve();
     71    }
     72  };
     73 
     74  PageDataService.on("page-data", listener);
     75 
     76  for (let pageData of pageDataResults) {
     77    PageDataService.queueFetch(pageData.url);
     78  }
     79 
     80  await completePromise;
     81  PageDataService.off("page-data", listener);
     82 
     83  Assert.deepEqual(
     84    requests,
     85    pageDataResults.map(pd => pd.url)
     86  );
     87 
     88  // Because our fetch implementation is essentially synchronous the results
     89  // will be in a known order. This isn't guaranteed by the API though.
     90  Assert.deepEqual(results, pageDataResults);
     91 
     92  delete PageDataService.fetchPageData;
     93 });
     94 
     95 // Tests that limiting the number of fetches works.
     96 add_task(async function test_queueLimit() {
     97  Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 3);
     98  // Pretend we are idle.
     99  PageDataService.observe(null, "idle", null);
    100 
    101  let requests = [];
    102  PageDataService.fetchPageData = url => {
    103    let { promise, resolve, reject } = Promise.withResolvers();
    104    requests.push({ url, resolve, reject });
    105 
    106    return promise;
    107  };
    108 
    109  let results = [];
    110  let listener = (_, pageData) => {
    111    results.push(pageData?.url);
    112  };
    113 
    114  PageDataService.on("page-data", listener);
    115 
    116  PageDataService.queueFetch("https://www.mozilla.org/1");
    117  PageDataService.queueFetch("https://www.mozilla.org/2");
    118  PageDataService.queueFetch("https://www.mozilla.org/3");
    119  PageDataService.queueFetch("https://www.mozilla.org/4");
    120  PageDataService.queueFetch("https://www.mozilla.org/5");
    121  PageDataService.queueFetch("https://www.mozilla.org/6");
    122  PageDataService.queueFetch("https://www.mozilla.org/7");
    123  PageDataService.queueFetch("https://www.mozilla.org/8");
    124  PageDataService.queueFetch("https://www.mozilla.org/9");
    125  PageDataService.queueFetch("https://www.mozilla.org/10");
    126  PageDataService.queueFetch("https://www.mozilla.org/11");
    127 
    128  await TestUtils.waitForTick();
    129 
    130  Assert.deepEqual(
    131    requests.map(r => r.url),
    132    [
    133      "https://www.mozilla.org/1",
    134      "https://www.mozilla.org/2",
    135      "https://www.mozilla.org/3",
    136    ]
    137  );
    138 
    139  // Completing or rejecting a request should start new ones.
    140 
    141  requests[1].resolve({
    142    date: 2345,
    143    url: "https://www.mozilla.org/2",
    144    siteName: "Test 2",
    145    data: {},
    146  });
    147 
    148  await TestUtils.waitForTick();
    149 
    150  Assert.deepEqual(
    151    requests.map(r => r.url),
    152    [
    153      "https://www.mozilla.org/1",
    154      "https://www.mozilla.org/2",
    155      "https://www.mozilla.org/3",
    156      "https://www.mozilla.org/4",
    157    ]
    158  );
    159 
    160  requests[3].reject(new Error("Fail"));
    161 
    162  await TestUtils.waitForTick();
    163 
    164  Assert.deepEqual(
    165    requests.map(r => r.url),
    166    [
    167      "https://www.mozilla.org/1",
    168      "https://www.mozilla.org/2",
    169      "https://www.mozilla.org/3",
    170      "https://www.mozilla.org/4",
    171      "https://www.mozilla.org/5",
    172    ]
    173  );
    174 
    175  // Increasing the limit should start more requests.
    176  Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 5);
    177 
    178  await TestUtils.waitForTick();
    179 
    180  Assert.deepEqual(
    181    requests.map(r => r.url),
    182    [
    183      "https://www.mozilla.org/1",
    184      "https://www.mozilla.org/2",
    185      "https://www.mozilla.org/3",
    186      "https://www.mozilla.org/4",
    187      "https://www.mozilla.org/5",
    188      "https://www.mozilla.org/6",
    189      "https://www.mozilla.org/7",
    190    ]
    191  );
    192 
    193  // Dropping the limit shouldn't start anything new.
    194  Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 3);
    195 
    196  await TestUtils.waitForTick();
    197 
    198  Assert.deepEqual(
    199    requests.map(r => r.url),
    200    [
    201      "https://www.mozilla.org/1",
    202      "https://www.mozilla.org/2",
    203      "https://www.mozilla.org/3",
    204      "https://www.mozilla.org/4",
    205      "https://www.mozilla.org/5",
    206      "https://www.mozilla.org/6",
    207      "https://www.mozilla.org/7",
    208    ]
    209  );
    210 
    211  // But resolving should also not start new requests.
    212  requests[5].resolve({
    213    date: 345334,
    214    url: "https://www.mozilla.org/6",
    215    siteName: "Test 6",
    216    data: {},
    217  });
    218 
    219  requests[0].resolve({
    220    date: 343446434,
    221    url: "https://www.mozilla.org/1",
    222    siteName: "Test 1",
    223    data: {},
    224  });
    225 
    226  await TestUtils.waitForTick();
    227 
    228  Assert.deepEqual(
    229    requests.map(r => r.url),
    230    [
    231      "https://www.mozilla.org/1",
    232      "https://www.mozilla.org/2",
    233      "https://www.mozilla.org/3",
    234      "https://www.mozilla.org/4",
    235      "https://www.mozilla.org/5",
    236      "https://www.mozilla.org/6",
    237      "https://www.mozilla.org/7",
    238    ]
    239  );
    240 
    241  // Until a previous request completes.
    242  requests[4].resolve(null);
    243 
    244  await TestUtils.waitForTick();
    245 
    246  Assert.deepEqual(
    247    requests.map(r => r.url),
    248    [
    249      "https://www.mozilla.org/1",
    250      "https://www.mozilla.org/2",
    251      "https://www.mozilla.org/3",
    252      "https://www.mozilla.org/4",
    253      "https://www.mozilla.org/5",
    254      "https://www.mozilla.org/6",
    255      "https://www.mozilla.org/7",
    256      "https://www.mozilla.org/8",
    257    ]
    258  );
    259 
    260  // Inifinite queue should work.
    261  Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 0);
    262 
    263  await TestUtils.waitForTick();
    264 
    265  Assert.deepEqual(
    266    requests.map(r => r.url),
    267    [
    268      "https://www.mozilla.org/1",
    269      "https://www.mozilla.org/2",
    270      "https://www.mozilla.org/3",
    271      "https://www.mozilla.org/4",
    272      "https://www.mozilla.org/5",
    273      "https://www.mozilla.org/6",
    274      "https://www.mozilla.org/7",
    275      "https://www.mozilla.org/8",
    276      "https://www.mozilla.org/9",
    277      "https://www.mozilla.org/10",
    278      "https://www.mozilla.org/11",
    279    ]
    280  );
    281 
    282  requests[10].resolve({
    283    date: 345334,
    284    url: "https://www.mozilla.org/11",
    285    data: {},
    286  });
    287  requests[2].resolve({
    288    date: 345334,
    289    url: "https://www.mozilla.org/3",
    290    data: {},
    291  });
    292  requests[7].resolve({
    293    date: 345334,
    294    url: "https://www.mozilla.org/8",
    295    data: {},
    296  });
    297  requests[6].resolve({
    298    date: 345334,
    299    url: "https://www.mozilla.org/7",
    300    data: {},
    301  });
    302  requests[8].resolve({
    303    date: 345334,
    304    url: "https://www.mozilla.org/9",
    305    data: {},
    306  });
    307  requests[9].resolve({
    308    date: 345334,
    309    url: "https://www.mozilla.org/10",
    310    data: {},
    311  });
    312 
    313  await TestUtils.waitForTick();
    314 
    315  Assert.deepEqual(
    316    requests.map(r => r.url),
    317    [
    318      "https://www.mozilla.org/1",
    319      "https://www.mozilla.org/2",
    320      "https://www.mozilla.org/3",
    321      "https://www.mozilla.org/4",
    322      "https://www.mozilla.org/5",
    323      "https://www.mozilla.org/6",
    324      "https://www.mozilla.org/7",
    325      "https://www.mozilla.org/8",
    326      "https://www.mozilla.org/9",
    327      "https://www.mozilla.org/10",
    328      "https://www.mozilla.org/11",
    329    ]
    330  );
    331 
    332  PageDataService.off("page-data", listener);
    333 
    334  delete PageDataService.fetchPageData;
    335 
    336  Assert.deepEqual(results, [
    337    "https://www.mozilla.org/2",
    338    "https://www.mozilla.org/6",
    339    "https://www.mozilla.org/1",
    340    "https://www.mozilla.org/11",
    341    "https://www.mozilla.org/3",
    342    "https://www.mozilla.org/8",
    343    "https://www.mozilla.org/7",
    344    "https://www.mozilla.org/9",
    345    "https://www.mozilla.org/10",
    346  ]);
    347 });
    348 
    349 // Tests that the user idle state stops and starts fetches.
    350 add_task(async function test_idle() {
    351  Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 3);
    352  // Pretend we are active.
    353  PageDataService.observe(null, "active", null);
    354 
    355  let requests = [];
    356  PageDataService.fetchPageData = url => {
    357    let { promise, resolve, reject } = Promise.withResolvers();
    358    requests.push({ url, resolve, reject });
    359 
    360    return promise;
    361  };
    362 
    363  let results = [];
    364  let listener = (_, pageData) => {
    365    results.push(pageData?.url);
    366  };
    367 
    368  PageDataService.on("page-data", listener);
    369 
    370  PageDataService.queueFetch("https://www.mozilla.org/1");
    371  PageDataService.queueFetch("https://www.mozilla.org/2");
    372  PageDataService.queueFetch("https://www.mozilla.org/3");
    373  PageDataService.queueFetch("https://www.mozilla.org/4");
    374  PageDataService.queueFetch("https://www.mozilla.org/5");
    375  PageDataService.queueFetch("https://www.mozilla.org/6");
    376  PageDataService.queueFetch("https://www.mozilla.org/7");
    377 
    378  await TestUtils.waitForTick();
    379 
    380  // Nothing will start when active.
    381  Assert.deepEqual(
    382    requests.map(r => r.url),
    383    []
    384  );
    385 
    386  // Pretend we are idle.
    387  PageDataService.observe(null, "idle", null);
    388 
    389  await TestUtils.waitForTick();
    390 
    391  Assert.deepEqual(
    392    requests.map(r => r.url),
    393    [
    394      "https://www.mozilla.org/1",
    395      "https://www.mozilla.org/2",
    396      "https://www.mozilla.org/3",
    397    ]
    398  );
    399 
    400  // Completing or rejecting a request should start new ones.
    401 
    402  requests[1].resolve({
    403    date: 2345,
    404    url: "https://www.mozilla.org/2",
    405    data: {},
    406  });
    407 
    408  await TestUtils.waitForTick();
    409 
    410  Assert.deepEqual(
    411    requests.map(r => r.url),
    412    [
    413      "https://www.mozilla.org/1",
    414      "https://www.mozilla.org/2",
    415      "https://www.mozilla.org/3",
    416      "https://www.mozilla.org/4",
    417    ]
    418  );
    419 
    420  // But not when active
    421  PageDataService.observe(null, "active", null);
    422 
    423  requests[3].resolve({
    424    date: 2345,
    425    url: "https://www.mozilla.org/4",
    426    data: {},
    427  });
    428  requests[0].resolve({
    429    date: 2345,
    430    url: "https://www.mozilla.org/1",
    431    data: {},
    432  });
    433  requests[2].resolve({
    434    date: 2345,
    435    url: "https://www.mozilla.org/3",
    436    data: {},
    437  });
    438 
    439  await TestUtils.waitForTick();
    440 
    441  Assert.deepEqual(
    442    requests.map(r => r.url),
    443    [
    444      "https://www.mozilla.org/1",
    445      "https://www.mozilla.org/2",
    446      "https://www.mozilla.org/3",
    447      "https://www.mozilla.org/4",
    448    ]
    449  );
    450 
    451  // Going idle should start more workers
    452  PageDataService.observe(null, "idle", null);
    453 
    454  await TestUtils.waitForTick();
    455 
    456  Assert.deepEqual(
    457    requests.map(r => r.url),
    458    [
    459      "https://www.mozilla.org/1",
    460      "https://www.mozilla.org/2",
    461      "https://www.mozilla.org/3",
    462      "https://www.mozilla.org/4",
    463      "https://www.mozilla.org/5",
    464      "https://www.mozilla.org/6",
    465      "https://www.mozilla.org/7",
    466    ]
    467  );
    468 
    469  requests[4].resolve({
    470    date: 2345,
    471    url: "https://www.mozilla.org/5",
    472    data: {},
    473  });
    474  requests[5].resolve({
    475    date: 2345,
    476    url: "https://www.mozilla.org/6",
    477    data: {},
    478  });
    479  requests[6].resolve({
    480    date: 2345,
    481    url: "https://www.mozilla.org/7",
    482    data: {},
    483  });
    484 
    485  await TestUtils.waitForTick();
    486 
    487  Assert.deepEqual(
    488    requests.map(r => r.url),
    489    [
    490      "https://www.mozilla.org/1",
    491      "https://www.mozilla.org/2",
    492      "https://www.mozilla.org/3",
    493      "https://www.mozilla.org/4",
    494      "https://www.mozilla.org/5",
    495      "https://www.mozilla.org/6",
    496      "https://www.mozilla.org/7",
    497    ]
    498  );
    499 
    500  PageDataService.off("page-data", listener);
    501 
    502  delete PageDataService.fetchPageData;
    503 
    504  Assert.deepEqual(results, [
    505    "https://www.mozilla.org/2",
    506    "https://www.mozilla.org/4",
    507    "https://www.mozilla.org/1",
    508    "https://www.mozilla.org/3",
    509    "https://www.mozilla.org/5",
    510    "https://www.mozilla.org/6",
    511    "https://www.mozilla.org/7",
    512  ]);
    513 });