forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			527 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			527 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* Any copyright is dedicated to the Public Domain.
 | |
|  * http://creativecommons.org/publicdomain/zero/1.0/ */
 | |
| 
 | |
| ChromeUtils.defineESModuleGetters(this, {
 | |
|   PageDataService: "resource:///modules/pagedata/PageDataService.sys.mjs",
 | |
|   PromiseUtils: "resource://gre/modules/PromiseUtils.sys.mjs",
 | |
| });
 | |
| 
 | |
| // Test that urls are retrieved in the expected order.
 | |
| add_task(async function test_queueOrder() {
 | |
|   Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 0);
 | |
|   // Pretend we are idle.
 | |
|   PageDataService.observe(null, "idle", null);
 | |
| 
 | |
|   let pageDataResults = [
 | |
|     {
 | |
|       date: Date.now(),
 | |
|       url: "http://www.mozilla.org/1",
 | |
|       siteName: "Mozilla",
 | |
|       data: {},
 | |
|     },
 | |
|     {
 | |
|       date: Date.now() - 3600,
 | |
|       url: "http://www.google.com/2",
 | |
|       siteName: "Google",
 | |
|       data: {},
 | |
|     },
 | |
|     {
 | |
|       date: Date.now() + 3600,
 | |
|       url: "http://www.example.com/3",
 | |
|       image: "http://www.example.com/banner.jpg",
 | |
|       data: {},
 | |
|     },
 | |
|     {
 | |
|       date: Date.now() / 2,
 | |
|       url: "http://www.wikipedia.org/4",
 | |
|       data: {},
 | |
|     },
 | |
|     {
 | |
|       date: Date.now() / 3,
 | |
|       url: "http://www.microsoft.com/5",
 | |
|       data: {
 | |
|         [PageDataSchema.DATA_TYPE.PRODUCT]: {
 | |
|           name: "Windows 11",
 | |
|         },
 | |
|       },
 | |
|     },
 | |
|   ];
 | |
| 
 | |
|   let requests = [];
 | |
|   PageDataService.fetchPageData = url => {
 | |
|     requests.push(url);
 | |
| 
 | |
|     for (let pageData of pageDataResults) {
 | |
|       if (pageData.url == url) {
 | |
|         return Promise.resolve(pageData);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return Promise.reject(new Error("Unknown url"));
 | |
|   };
 | |
| 
 | |
|   let { promise: completePromise, resolve } = PromiseUtils.defer();
 | |
| 
 | |
|   let results = [];
 | |
|   let listener = (_, pageData) => {
 | |
|     results.push(pageData);
 | |
|     if (results.length == pageDataResults.length) {
 | |
|       resolve();
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   PageDataService.on("page-data", listener);
 | |
| 
 | |
|   for (let pageData of pageDataResults) {
 | |
|     PageDataService.queueFetch(pageData.url);
 | |
|   }
 | |
| 
 | |
|   await completePromise;
 | |
|   PageDataService.off("page-data", listener);
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests,
 | |
|     pageDataResults.map(pd => pd.url)
 | |
|   );
 | |
| 
 | |
|   // Because our fetch implementation is essentially synchronous the results
 | |
|   // will be in a known order. This isn't guaranteed by the API though.
 | |
|   Assert.deepEqual(results, pageDataResults);
 | |
| 
 | |
|   delete PageDataService.fetchPageData;
 | |
| });
 | |
| 
 | |
| // Tests that limiting the number of fetches works.
 | |
| add_task(async function test_queueLimit() {
 | |
|   Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 3);
 | |
|   // Pretend we are idle.
 | |
|   PageDataService.observe(null, "idle", null);
 | |
| 
 | |
|   let requests = [];
 | |
|   PageDataService.fetchPageData = url => {
 | |
|     let { promise, resolve, reject } = PromiseUtils.defer();
 | |
|     requests.push({ url, resolve, reject });
 | |
| 
 | |
|     return promise;
 | |
|   };
 | |
| 
 | |
|   let results = [];
 | |
|   let listener = (_, pageData) => {
 | |
|     results.push(pageData?.url);
 | |
|   };
 | |
| 
 | |
|   PageDataService.on("page-data", listener);
 | |
| 
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/1");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/2");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/3");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/4");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/5");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/6");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/7");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/8");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/9");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/10");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/11");
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     [
 | |
|       "https://www.mozilla.org/1",
 | |
|       "https://www.mozilla.org/2",
 | |
|       "https://www.mozilla.org/3",
 | |
|     ]
 | |
|   );
 | |
| 
 | |
|   // Completing or rejecting a request should start new ones.
 | |
| 
 | |
|   requests[1].resolve({
 | |
|     date: 2345,
 | |
|     url: "https://www.mozilla.org/2",
 | |
|     siteName: "Test 2",
 | |
|     data: {},
 | |
|   });
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     [
 | |
|       "https://www.mozilla.org/1",
 | |
|       "https://www.mozilla.org/2",
 | |
|       "https://www.mozilla.org/3",
 | |
|       "https://www.mozilla.org/4",
 | |
|     ]
 | |
|   );
 | |
| 
 | |
|   requests[3].reject(new Error("Fail"));
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     [
 | |
|       "https://www.mozilla.org/1",
 | |
|       "https://www.mozilla.org/2",
 | |
|       "https://www.mozilla.org/3",
 | |
|       "https://www.mozilla.org/4",
 | |
|       "https://www.mozilla.org/5",
 | |
|     ]
 | |
|   );
 | |
| 
 | |
|   // Increasing the limit should start more requests.
 | |
|   Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 5);
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     [
 | |
|       "https://www.mozilla.org/1",
 | |
|       "https://www.mozilla.org/2",
 | |
|       "https://www.mozilla.org/3",
 | |
|       "https://www.mozilla.org/4",
 | |
|       "https://www.mozilla.org/5",
 | |
|       "https://www.mozilla.org/6",
 | |
|       "https://www.mozilla.org/7",
 | |
|     ]
 | |
|   );
 | |
| 
 | |
|   // Dropping the limit shouldn't start anything new.
 | |
|   Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 3);
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     [
 | |
|       "https://www.mozilla.org/1",
 | |
|       "https://www.mozilla.org/2",
 | |
|       "https://www.mozilla.org/3",
 | |
|       "https://www.mozilla.org/4",
 | |
|       "https://www.mozilla.org/5",
 | |
|       "https://www.mozilla.org/6",
 | |
|       "https://www.mozilla.org/7",
 | |
|     ]
 | |
|   );
 | |
| 
 | |
|   // But resolving should also not start new requests.
 | |
|   requests[5].resolve({
 | |
|     date: 345334,
 | |
|     url: "https://www.mozilla.org/6",
 | |
|     siteName: "Test 6",
 | |
|     data: {},
 | |
|   });
 | |
| 
 | |
|   requests[0].resolve({
 | |
|     date: 343446434,
 | |
|     url: "https://www.mozilla.org/1",
 | |
|     siteName: "Test 1",
 | |
|     data: {},
 | |
|   });
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     [
 | |
|       "https://www.mozilla.org/1",
 | |
|       "https://www.mozilla.org/2",
 | |
|       "https://www.mozilla.org/3",
 | |
|       "https://www.mozilla.org/4",
 | |
|       "https://www.mozilla.org/5",
 | |
|       "https://www.mozilla.org/6",
 | |
|       "https://www.mozilla.org/7",
 | |
|     ]
 | |
|   );
 | |
| 
 | |
|   // Until a previous request completes.
 | |
|   requests[4].resolve(null);
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     [
 | |
|       "https://www.mozilla.org/1",
 | |
|       "https://www.mozilla.org/2",
 | |
|       "https://www.mozilla.org/3",
 | |
|       "https://www.mozilla.org/4",
 | |
|       "https://www.mozilla.org/5",
 | |
|       "https://www.mozilla.org/6",
 | |
|       "https://www.mozilla.org/7",
 | |
|       "https://www.mozilla.org/8",
 | |
|     ]
 | |
|   );
 | |
| 
 | |
|   // Inifinite queue should work.
 | |
|   Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 0);
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     [
 | |
|       "https://www.mozilla.org/1",
 | |
|       "https://www.mozilla.org/2",
 | |
|       "https://www.mozilla.org/3",
 | |
|       "https://www.mozilla.org/4",
 | |
|       "https://www.mozilla.org/5",
 | |
|       "https://www.mozilla.org/6",
 | |
|       "https://www.mozilla.org/7",
 | |
|       "https://www.mozilla.org/8",
 | |
|       "https://www.mozilla.org/9",
 | |
|       "https://www.mozilla.org/10",
 | |
|       "https://www.mozilla.org/11",
 | |
|     ]
 | |
|   );
 | |
| 
 | |
|   requests[10].resolve({
 | |
|     date: 345334,
 | |
|     url: "https://www.mozilla.org/11",
 | |
|     data: {},
 | |
|   });
 | |
|   requests[2].resolve({
 | |
|     date: 345334,
 | |
|     url: "https://www.mozilla.org/3",
 | |
|     data: {},
 | |
|   });
 | |
|   requests[7].resolve({
 | |
|     date: 345334,
 | |
|     url: "https://www.mozilla.org/8",
 | |
|     data: {},
 | |
|   });
 | |
|   requests[6].resolve({
 | |
|     date: 345334,
 | |
|     url: "https://www.mozilla.org/7",
 | |
|     data: {},
 | |
|   });
 | |
|   requests[8].resolve({
 | |
|     date: 345334,
 | |
|     url: "https://www.mozilla.org/9",
 | |
|     data: {},
 | |
|   });
 | |
|   requests[9].resolve({
 | |
|     date: 345334,
 | |
|     url: "https://www.mozilla.org/10",
 | |
|     data: {},
 | |
|   });
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     [
 | |
|       "https://www.mozilla.org/1",
 | |
|       "https://www.mozilla.org/2",
 | |
|       "https://www.mozilla.org/3",
 | |
|       "https://www.mozilla.org/4",
 | |
|       "https://www.mozilla.org/5",
 | |
|       "https://www.mozilla.org/6",
 | |
|       "https://www.mozilla.org/7",
 | |
|       "https://www.mozilla.org/8",
 | |
|       "https://www.mozilla.org/9",
 | |
|       "https://www.mozilla.org/10",
 | |
|       "https://www.mozilla.org/11",
 | |
|     ]
 | |
|   );
 | |
| 
 | |
|   PageDataService.off("page-data", listener);
 | |
| 
 | |
|   delete PageDataService.fetchPageData;
 | |
| 
 | |
|   Assert.deepEqual(results, [
 | |
|     "https://www.mozilla.org/2",
 | |
|     "https://www.mozilla.org/6",
 | |
|     "https://www.mozilla.org/1",
 | |
|     "https://www.mozilla.org/11",
 | |
|     "https://www.mozilla.org/3",
 | |
|     "https://www.mozilla.org/8",
 | |
|     "https://www.mozilla.org/7",
 | |
|     "https://www.mozilla.org/9",
 | |
|     "https://www.mozilla.org/10",
 | |
|   ]);
 | |
| });
 | |
| 
 | |
| // Tests that the user idle state stops and starts fetches.
 | |
| add_task(async function test_idle() {
 | |
|   Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 3);
 | |
|   // Pretend we are active.
 | |
|   PageDataService.observe(null, "active", null);
 | |
| 
 | |
|   let requests = [];
 | |
|   PageDataService.fetchPageData = url => {
 | |
|     let { promise, resolve, reject } = PromiseUtils.defer();
 | |
|     requests.push({ url, resolve, reject });
 | |
| 
 | |
|     return promise;
 | |
|   };
 | |
| 
 | |
|   let results = [];
 | |
|   let listener = (_, pageData) => {
 | |
|     results.push(pageData?.url);
 | |
|   };
 | |
| 
 | |
|   PageDataService.on("page-data", listener);
 | |
| 
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/1");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/2");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/3");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/4");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/5");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/6");
 | |
|   PageDataService.queueFetch("https://www.mozilla.org/7");
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   // Nothing will start when active.
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     []
 | |
|   );
 | |
| 
 | |
|   // Pretend we are idle.
 | |
|   PageDataService.observe(null, "idle", null);
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     [
 | |
|       "https://www.mozilla.org/1",
 | |
|       "https://www.mozilla.org/2",
 | |
|       "https://www.mozilla.org/3",
 | |
|     ]
 | |
|   );
 | |
| 
 | |
|   // Completing or rejecting a request should start new ones.
 | |
| 
 | |
|   requests[1].resolve({
 | |
|     date: 2345,
 | |
|     url: "https://www.mozilla.org/2",
 | |
|     data: {},
 | |
|   });
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     [
 | |
|       "https://www.mozilla.org/1",
 | |
|       "https://www.mozilla.org/2",
 | |
|       "https://www.mozilla.org/3",
 | |
|       "https://www.mozilla.org/4",
 | |
|     ]
 | |
|   );
 | |
| 
 | |
|   // But not when active
 | |
|   PageDataService.observe(null, "active", null);
 | |
| 
 | |
|   requests[3].resolve({
 | |
|     date: 2345,
 | |
|     url: "https://www.mozilla.org/4",
 | |
|     data: {},
 | |
|   });
 | |
|   requests[0].resolve({
 | |
|     date: 2345,
 | |
|     url: "https://www.mozilla.org/1",
 | |
|     data: {},
 | |
|   });
 | |
|   requests[2].resolve({
 | |
|     date: 2345,
 | |
|     url: "https://www.mozilla.org/3",
 | |
|     data: {},
 | |
|   });
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     [
 | |
|       "https://www.mozilla.org/1",
 | |
|       "https://www.mozilla.org/2",
 | |
|       "https://www.mozilla.org/3",
 | |
|       "https://www.mozilla.org/4",
 | |
|     ]
 | |
|   );
 | |
| 
 | |
|   // Going idle should start more workers
 | |
|   PageDataService.observe(null, "idle", null);
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     [
 | |
|       "https://www.mozilla.org/1",
 | |
|       "https://www.mozilla.org/2",
 | |
|       "https://www.mozilla.org/3",
 | |
|       "https://www.mozilla.org/4",
 | |
|       "https://www.mozilla.org/5",
 | |
|       "https://www.mozilla.org/6",
 | |
|       "https://www.mozilla.org/7",
 | |
|     ]
 | |
|   );
 | |
| 
 | |
|   requests[4].resolve({
 | |
|     date: 2345,
 | |
|     url: "https://www.mozilla.org/5",
 | |
|     data: {},
 | |
|   });
 | |
|   requests[5].resolve({
 | |
|     date: 2345,
 | |
|     url: "https://www.mozilla.org/6",
 | |
|     data: {},
 | |
|   });
 | |
|   requests[6].resolve({
 | |
|     date: 2345,
 | |
|     url: "https://www.mozilla.org/7",
 | |
|     data: {},
 | |
|   });
 | |
| 
 | |
|   // Let a tick pass.
 | |
|   await Promise.resolve();
 | |
| 
 | |
|   Assert.deepEqual(
 | |
|     requests.map(r => r.url),
 | |
|     [
 | |
|       "https://www.mozilla.org/1",
 | |
|       "https://www.mozilla.org/2",
 | |
|       "https://www.mozilla.org/3",
 | |
|       "https://www.mozilla.org/4",
 | |
|       "https://www.mozilla.org/5",
 | |
|       "https://www.mozilla.org/6",
 | |
|       "https://www.mozilla.org/7",
 | |
|     ]
 | |
|   );
 | |
| 
 | |
|   PageDataService.off("page-data", listener);
 | |
| 
 | |
|   delete PageDataService.fetchPageData;
 | |
| 
 | |
|   Assert.deepEqual(results, [
 | |
|     "https://www.mozilla.org/2",
 | |
|     "https://www.mozilla.org/4",
 | |
|     "https://www.mozilla.org/1",
 | |
|     "https://www.mozilla.org/3",
 | |
|     "https://www.mozilla.org/5",
 | |
|     "https://www.mozilla.org/6",
 | |
|     "https://www.mozilla.org/7",
 | |
|   ]);
 | |
| });
 | 
