test_ext_history.js (24610B)
1 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ 2 /* vim: set sts=2 sw=2 et tw=80: */ 3 "use strict"; 4 5 const { AddonTestUtils } = ChromeUtils.importESModule( 6 "resource://testing-common/AddonTestUtils.sys.mjs" 7 ); 8 9 ChromeUtils.defineESModuleGetters(this, { 10 ExtensionCommon: "resource://gre/modules/ExtensionCommon.sys.mjs", 11 PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs", 12 PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs", 13 }); 14 15 AddonTestUtils.init(this); 16 AddonTestUtils.overrideCertDB(); 17 AddonTestUtils.createAppInfo( 18 "xpcshell@tests.mozilla.org", 19 "XPCShell", 20 "1", 21 "43" 22 ); 23 24 add_task(async function test_delete() { 25 function background() { 26 let historyClearedCount = 0; 27 let removedUrls = []; 28 29 browser.history.onVisitRemoved.addListener(data => { 30 if (data.allHistory) { 31 historyClearedCount++; 32 browser.test.assertEq( 33 0, 34 data.urls.length, 35 "onVisitRemoved received an empty urls array" 36 ); 37 } else { 38 removedUrls.push(...data.urls); 39 } 40 }); 41 42 browser.test.onMessage.addListener((msg, arg) => { 43 if (msg === "delete-url") { 44 browser.history.deleteUrl({ url: arg }).then(result => { 45 browser.test.assertEq( 46 undefined, 47 result, 48 "browser.history.deleteUrl returns nothing" 49 ); 50 browser.test.sendMessage("url-deleted"); 51 }); 52 } else if (msg === "delete-range") { 53 browser.history.deleteRange(arg).then(result => { 54 browser.test.assertEq( 55 undefined, 56 result, 57 "browser.history.deleteRange returns nothing" 58 ); 59 browser.test.sendMessage("range-deleted", removedUrls); 60 }); 61 } else if (msg === "delete-all") { 62 browser.history.deleteAll().then(result => { 63 browser.test.assertEq( 64 undefined, 65 result, 66 "browser.history.deleteAll returns nothing" 67 ); 68 browser.test.sendMessage("history-cleared", [ 69 historyClearedCount, 70 removedUrls, 71 ]); 72 }); 73 } 74 }); 75 76 browser.test.sendMessage("ready"); 77 } 78 79 const BASE_URL = "http://mozilla.com/test_history/"; 80 81 let extension = ExtensionTestUtils.loadExtension({ 82 manifest: { 83 permissions: ["history"], 84 }, 85 background: `(${background})()`, 86 }); 87 88 await extension.startup(); 89 await extension.awaitMessage("ready"); 90 await PlacesUtils.history.clear(); 91 92 let historyClearedCount; 93 let visits = []; 94 let visitDate = new Date(1999, 9, 9, 9, 9).getTime(); 95 96 function pushVisit(subvisits) { 97 visitDate += 1000; 98 subvisits.push({ date: new Date(visitDate) }); 99 } 100 101 // Add 5 visits for one uri and 3 visits for 3 others 102 for (let i = 0; i < 4; ++i) { 103 let visit = { 104 url: `${BASE_URL}${i}`, 105 title: "visit " + i, 106 visits: [], 107 }; 108 if (i === 0) { 109 for (let j = 0; j < 5; ++j) { 110 pushVisit(visit.visits); 111 } 112 } else { 113 pushVisit(visit.visits); 114 } 115 visits.push(visit); 116 } 117 118 await PlacesUtils.history.insertMany(visits); 119 equal( 120 await PlacesTestUtils.visitsInDB(visits[0].url), 121 5, 122 "5 visits for uri found in history database" 123 ); 124 125 let testUrl = visits[2].url; 126 ok( 127 await PlacesTestUtils.isPageInDB(testUrl), 128 "expected url found in history database" 129 ); 130 131 extension.sendMessage("delete-url", testUrl); 132 await extension.awaitMessage("url-deleted"); 133 equal( 134 await PlacesTestUtils.isPageInDB(testUrl), 135 false, 136 "expected url not found in history database" 137 ); 138 139 // delete 3 of the 5 visits for url 1 140 let filter = { 141 startTime: visits[0].visits[0].date, 142 endTime: visits[0].visits[2].date, 143 }; 144 145 extension.sendMessage("delete-range", filter); 146 let removedUrls = await extension.awaitMessage("range-deleted"); 147 ok( 148 !removedUrls.includes(visits[0].url), 149 `${visits[0].url} not received by onVisitRemoved` 150 ); 151 ok( 152 await PlacesTestUtils.isPageInDB(visits[0].url), 153 "expected uri found in history database" 154 ); 155 equal( 156 await PlacesTestUtils.visitsInDB(visits[0].url), 157 2, 158 "2 visits for uri found in history database" 159 ); 160 ok( 161 await PlacesTestUtils.isPageInDB(visits[1].url), 162 "expected uri found in history database" 163 ); 164 equal( 165 await PlacesTestUtils.visitsInDB(visits[1].url), 166 1, 167 "1 visit for uri found in history database" 168 ); 169 170 // delete the rest of the visits for url 1, and the visit for url 2 171 filter.startTime = visits[0].visits[0].date; 172 filter.endTime = visits[1].visits[0].date; 173 174 extension.sendMessage("delete-range", filter); 175 await extension.awaitMessage("range-deleted"); 176 177 equal( 178 await PlacesTestUtils.isPageInDB(visits[0].url), 179 false, 180 "expected uri not found in history database" 181 ); 182 equal( 183 await PlacesTestUtils.visitsInDB(visits[0].url), 184 0, 185 "0 visits for uri found in history database" 186 ); 187 equal( 188 await PlacesTestUtils.isPageInDB(visits[1].url), 189 false, 190 "expected uri not found in history database" 191 ); 192 equal( 193 await PlacesTestUtils.visitsInDB(visits[1].url), 194 0, 195 "0 visits for uri found in history database" 196 ); 197 198 ok( 199 await PlacesTestUtils.isPageInDB(visits[3].url), 200 "expected uri found in history database" 201 ); 202 203 extension.sendMessage("delete-all"); 204 [historyClearedCount, removedUrls] = 205 await extension.awaitMessage("history-cleared"); 206 equal( 207 historyClearedCount, 208 2, 209 "onVisitRemoved called for each clearing of history" 210 ); 211 equal( 212 removedUrls.length, 213 3, 214 "onVisitRemoved called the expected number of times" 215 ); 216 for (let i = 1; i < 3; ++i) { 217 let url = visits[i].url; 218 ok(removedUrls.includes(url), `${url} received by onVisitRemoved`); 219 } 220 await extension.unload(); 221 }); 222 223 const SINGLE_VISIT_URL = "http://example.com/"; 224 const DOUBLE_VISIT_URL = "http://example.com/2/"; 225 const MOZILLA_VISIT_URL = "http://mozilla.com/"; 226 const REFERENCE_DATE = new Date(); 227 // pages/visits to add via History.insert 228 const PAGE_INFOS = [ 229 { 230 url: SINGLE_VISIT_URL, 231 title: `test visit for ${SINGLE_VISIT_URL}`, 232 visits: [{ date: new Date(Number(REFERENCE_DATE) - 1000) }], 233 }, 234 { 235 url: DOUBLE_VISIT_URL, 236 title: `test visit for ${DOUBLE_VISIT_URL}`, 237 visits: [ 238 { date: REFERENCE_DATE }, 239 { date: new Date(Number(REFERENCE_DATE) - 2000) }, 240 ], 241 }, 242 { 243 url: MOZILLA_VISIT_URL, 244 title: `test visit for ${MOZILLA_VISIT_URL}`, 245 visits: [{ date: new Date(Number(REFERENCE_DATE) - 3000) }], 246 }, 247 ]; 248 249 add_task(async function test_search() { 250 function background(BGSCRIPT_REFERENCE_DATE) { 251 const futureTime = Date.now() + 24 * 60 * 60 * 1000; 252 253 browser.test.onMessage.addListener(() => { 254 browser.history 255 .search({ text: "" }) 256 .then(results => { 257 browser.test.sendMessage("empty-search", results); 258 return browser.history.search({ text: "mozilla.com" }); 259 }) 260 .then(results => { 261 browser.test.sendMessage("text-search", results); 262 return browser.history.search({ text: "example.com", maxResults: 1 }); 263 }) 264 .then(results => { 265 browser.test.sendMessage("max-results-search", results); 266 return browser.history.search({ 267 text: "", 268 startTime: BGSCRIPT_REFERENCE_DATE - 2000, 269 endTime: BGSCRIPT_REFERENCE_DATE - 1000, 270 }); 271 }) 272 .then(results => { 273 browser.test.sendMessage("date-range-search", results); 274 return browser.history.search({ text: "", startTime: futureTime }); 275 }) 276 .then(results => { 277 browser.test.assertEq( 278 0, 279 results.length, 280 "no results returned for late start time" 281 ); 282 return browser.history.search({ text: "", endTime: 0 }); 283 }) 284 .then(results => { 285 browser.test.assertEq( 286 0, 287 results.length, 288 "no results returned for early end time" 289 ); 290 return browser.history.search({ 291 text: "", 292 startTime: Date.now(), 293 endTime: 0, 294 }); 295 }) 296 .then( 297 () => { 298 browser.test.fail( 299 "history.search rejects with startTime that is after the endTime" 300 ); 301 }, 302 error => { 303 browser.test.assertEq( 304 "The startTime cannot be after the endTime", 305 error.message, 306 "history.search rejects with startTime that is after the endTime" 307 ); 308 } 309 ) 310 .then(() => { 311 browser.test.notifyPass("search"); 312 }); 313 }); 314 315 browser.test.sendMessage("ready"); 316 } 317 318 let extension = ExtensionTestUtils.loadExtension({ 319 manifest: { 320 permissions: ["history"], 321 }, 322 background: `(${background})(${Number(REFERENCE_DATE)})`, 323 }); 324 325 function findResult(url, results) { 326 return results.find(r => r.url === url); 327 } 328 329 function checkResult(results, url, expectedCount) { 330 let result = findResult(url, results); 331 notEqual(result, null, `history.search result was found for ${url}`); 332 equal( 333 result.visitCount, 334 expectedCount, 335 `history.search reports ${expectedCount} visit(s)` 336 ); 337 equal( 338 result.title, 339 `test visit for ${url}`, 340 "title for search result is correct" 341 ); 342 } 343 344 await extension.startup(); 345 await extension.awaitMessage("ready"); 346 await PlacesUtils.history.clear(); 347 348 await PlacesUtils.history.insertMany(PAGE_INFOS); 349 350 extension.sendMessage("check-history"); 351 352 let results = await extension.awaitMessage("empty-search"); 353 equal(results.length, 3, "history.search with empty text returned 3 results"); 354 checkResult(results, SINGLE_VISIT_URL, 1); 355 checkResult(results, DOUBLE_VISIT_URL, 2); 356 checkResult(results, MOZILLA_VISIT_URL, 1); 357 358 results = await extension.awaitMessage("text-search"); 359 equal( 360 results.length, 361 1, 362 "history.search with specific text returned 1 result" 363 ); 364 checkResult(results, MOZILLA_VISIT_URL, 1); 365 366 results = await extension.awaitMessage("max-results-search"); 367 equal(results.length, 1, "history.search with maxResults returned 1 result"); 368 checkResult(results, DOUBLE_VISIT_URL, 2); 369 370 results = await extension.awaitMessage("date-range-search"); 371 equal( 372 results.length, 373 2, 374 "history.search with a date range returned 2 result" 375 ); 376 checkResult(results, DOUBLE_VISIT_URL, 2); 377 checkResult(results, SINGLE_VISIT_URL, 1); 378 379 await extension.awaitFinish("search"); 380 await extension.unload(); 381 await PlacesUtils.history.clear(); 382 }); 383 384 add_task(async function test_add_url() { 385 function background() { 386 const TEST_DOMAIN = "http://example.com/"; 387 388 browser.test.onMessage.addListener((msg, testData) => { 389 let [details, type] = testData; 390 details.url = details.url || `${TEST_DOMAIN}${type}`; 391 if (msg === "add-url") { 392 details.title = `Title for ${type}`; 393 browser.history 394 .addUrl(details) 395 .then(() => { 396 return browser.history.search({ text: details.url }); 397 }) 398 .then(results => { 399 browser.test.assertEq( 400 1, 401 results.length, 402 "1 result found when searching for added URL" 403 ); 404 browser.test.sendMessage("url-added", { 405 details, 406 result: results[0], 407 }); 408 }); 409 } else if (msg === "expect-failure") { 410 let expectedMsg = testData[2]; 411 browser.history.addUrl(details).then( 412 () => { 413 browser.test.fail(`Expected error thrown for ${type}`); 414 }, 415 error => { 416 browser.test.assertTrue( 417 error.message.includes(expectedMsg), 418 `"Expected error thrown when trying to add a URL with ${type}` 419 ); 420 browser.test.sendMessage("add-failed"); 421 } 422 ); 423 } 424 }); 425 426 browser.test.sendMessage("ready"); 427 } 428 429 let addTestData = [ 430 [{}, "default"], 431 [{ visitTime: new Date() }, "with_date"], 432 [{ visitTime: Date.now() }, "with_ms_number"], 433 [{ visitTime: new Date().toISOString() }, "with_iso_string"], 434 [{ transition: "typed" }, "valid_transition"], 435 ]; 436 437 let failTestData = [ 438 [ 439 { transition: "generated" }, 440 "an invalid transition", 441 "|generated| is not a supported transition for history", 442 ], 443 [{ visitTime: Date.now() + 1000000 }, "a future date", "Invalid value"], 444 [{ url: "about.config" }, "an invalid url", "Invalid value"], 445 ]; 446 447 async function checkUrl(results) { 448 ok( 449 await PlacesTestUtils.isPageInDB(results.details.url), 450 `${results.details.url} found in history database` 451 ); 452 ok( 453 PlacesUtils.isValidGuid(results.result.id), 454 "URL was added with a valid id" 455 ); 456 equal( 457 results.result.title, 458 results.details.title, 459 "URL was added with the correct title" 460 ); 461 if (results.details.visitTime) { 462 equal( 463 results.result.lastVisitTime, 464 Number(ExtensionCommon.normalizeTime(results.details.visitTime)), 465 "URL was added with the correct date" 466 ); 467 } 468 } 469 470 let extension = ExtensionTestUtils.loadExtension({ 471 manifest: { 472 permissions: ["history"], 473 }, 474 background: `(${background})()`, 475 }); 476 477 await PlacesUtils.history.clear(); 478 await extension.startup(); 479 await extension.awaitMessage("ready"); 480 481 for (let data of addTestData) { 482 extension.sendMessage("add-url", data); 483 let results = await extension.awaitMessage("url-added"); 484 await checkUrl(results); 485 } 486 487 for (let data of failTestData) { 488 extension.sendMessage("expect-failure", data); 489 await extension.awaitMessage("add-failed"); 490 } 491 492 await extension.unload(); 493 }); 494 495 add_task(async function test_get_visits() { 496 async function background() { 497 const TEST_DOMAIN = "http://example.com/"; 498 const FIRST_DATE = Date.now(); 499 const INITIAL_DETAILS = { 500 url: TEST_DOMAIN, 501 visitTime: FIRST_DATE, 502 transition: "link", 503 }; 504 505 let visitIds = new Set(); 506 507 async function checkVisit(visit, expected) { 508 visitIds.add(visit.visitId); 509 browser.test.assertEq( 510 expected.visitTime, 511 visit.visitTime, 512 "visit has the correct visitTime" 513 ); 514 browser.test.assertEq( 515 expected.transition, 516 visit.transition, 517 "visit has the correct transition" 518 ); 519 let results = await browser.history.search({ text: expected.url }); 520 // all results will have the same id, so we only need to use the first one 521 browser.test.assertEq( 522 results[0].id, 523 visit.id, 524 "visit has the correct id" 525 ); 526 } 527 528 let details = Object.assign({}, INITIAL_DETAILS); 529 530 await browser.history.addUrl(details); 531 let results = await browser.history.getVisits({ url: details.url }); 532 533 browser.test.assertEq( 534 1, 535 results.length, 536 "the expected number of visits were returned" 537 ); 538 await checkVisit(results[0], details); 539 540 details.url = `${TEST_DOMAIN}/1/`; 541 await browser.history.addUrl(details); 542 543 results = await browser.history.getVisits({ url: details.url }); 544 browser.test.assertEq( 545 1, 546 results.length, 547 "the expected number of visits were returned" 548 ); 549 await checkVisit(results[0], details); 550 551 details.visitTime = FIRST_DATE - 1000; 552 details.transition = "typed"; 553 await browser.history.addUrl(details); 554 results = await browser.history.getVisits({ url: details.url }); 555 556 browser.test.assertEq( 557 2, 558 results.length, 559 "the expected number of visits were returned" 560 ); 561 await checkVisit(results[0], INITIAL_DETAILS); 562 await checkVisit(results[1], details); 563 browser.test.assertEq(3, visitIds.size, "each visit has a unique visitId"); 564 await browser.test.notifyPass("get-visits"); 565 } 566 567 let extension = ExtensionTestUtils.loadExtension({ 568 manifest: { 569 permissions: ["history"], 570 }, 571 background: `(${background})()`, 572 }); 573 574 await PlacesUtils.history.clear(); 575 await extension.startup(); 576 577 await extension.awaitFinish("get-visits"); 578 await extension.unload(); 579 }); 580 581 add_task(async function test_transition_types() { 582 const VISIT_URL_PREFIX = "http://example.com/"; 583 const TRANSITIONS = [ 584 ["link", Ci.nsINavHistoryService.TRANSITION_LINK], 585 ["typed", Ci.nsINavHistoryService.TRANSITION_TYPED], 586 ["auto_bookmark", Ci.nsINavHistoryService.TRANSITION_BOOKMARK], 587 // Only session history contains TRANSITION_EMBED visits, 588 // So global history query cannot find them. 589 // ["auto_subframe", Ci.nsINavHistoryService.TRANSITION_EMBED], 590 // Redirects are not correctly tested here because History 591 // will not make redirect entries hidden. 592 ["link", Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT], 593 ["link", Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY], 594 ["link", Ci.nsINavHistoryService.TRANSITION_DOWNLOAD], 595 ["manual_subframe", Ci.nsINavHistoryService.TRANSITION_FRAMED_LINK], 596 ["reload", Ci.nsINavHistoryService.TRANSITION_RELOAD], 597 ]; 598 599 // pages/visits to add via History.insertMany 600 let pageInfos = []; 601 let visitDate = new Date(1999, 9, 9, 9, 9).getTime(); 602 for (let [, transitionType] of TRANSITIONS) { 603 pageInfos.push({ 604 url: VISIT_URL_PREFIX + transitionType + "/", 605 visits: [ 606 { transition: transitionType, date: new Date((visitDate -= 1000)) }, 607 ], 608 }); 609 } 610 611 function background() { 612 browser.test.onMessage.addListener(async (msg, url) => { 613 switch (msg) { 614 case "search": { 615 let results = await browser.history.search({ 616 text: "", 617 startTime: new Date(0), 618 }); 619 browser.test.sendMessage("search-result", results); 620 break; 621 } 622 case "get-visits": { 623 let results = await browser.history.getVisits({ url }); 624 browser.test.sendMessage("get-visits-result", results); 625 break; 626 } 627 } 628 }); 629 630 browser.test.sendMessage("ready"); 631 } 632 633 let extension = ExtensionTestUtils.loadExtension({ 634 manifest: { 635 permissions: ["history"], 636 }, 637 background, 638 }); 639 640 await PlacesUtils.history.clear(); 641 await extension.startup(); 642 await extension.awaitMessage("ready"); 643 644 await PlacesUtils.history.insertMany(pageInfos); 645 646 extension.sendMessage("search"); 647 let results = await extension.awaitMessage("search-result"); 648 equal( 649 results.length, 650 pageInfos.length, 651 "search returned expected length of results" 652 ); 653 for (let i = 0; i < pageInfos.length; ++i) { 654 equal(results[i].url, pageInfos[i].url, "search returned the expected url"); 655 656 extension.sendMessage("get-visits", pageInfos[i].url); 657 let visits = await extension.awaitMessage("get-visits-result"); 658 equal(visits.length, 1, "getVisits returned expected length of visits"); 659 equal( 660 visits[0].transition, 661 TRANSITIONS[i][0], 662 "getVisits returned the expected transition" 663 ); 664 } 665 666 await extension.unload(); 667 }); 668 669 add_task(async function test_on_visited() { 670 const SINGLE_VISIT_URL = "http://example.com/1/"; 671 const DOUBLE_VISIT_URL = "http://example.com/2/"; 672 let visitDate = new Date(1999, 9, 9, 9, 9).getTime(); 673 674 // pages/visits to add via History.insertMany 675 const PAGE_INFOS = [ 676 { 677 url: SINGLE_VISIT_URL, 678 title: `visit to ${SINGLE_VISIT_URL}`, 679 visits: [{ date: new Date(visitDate) }], 680 }, 681 { 682 url: DOUBLE_VISIT_URL, 683 title: `visit to ${DOUBLE_VISIT_URL}`, 684 visits: [ 685 { date: new Date((visitDate += 1000)) }, 686 { date: new Date((visitDate += 1000)) }, 687 ], 688 }, 689 { 690 url: SINGLE_VISIT_URL, 691 title: "Title Changed", 692 visits: [{ date: new Date(visitDate) }], 693 }, 694 ]; 695 696 function background() { 697 let onVisitedData = []; 698 699 browser.history.onVisited.addListener(data => { 700 if (data.url.includes("moz-extension")) { 701 return; 702 } 703 onVisitedData.push(data); 704 if (onVisitedData.length == 4) { 705 browser.test.sendMessage("on-visited-data", onVisitedData); 706 } 707 }); 708 709 // Verifying onTitleChange Event along with onVisited event 710 browser.history.onTitleChanged.addListener(data => { 711 browser.test.sendMessage("on-title-changed-data", data); 712 }); 713 714 browser.test.sendMessage("ready"); 715 } 716 717 let extension = ExtensionTestUtils.loadExtension({ 718 manifest: { 719 permissions: ["history"], 720 }, 721 background: `(${background})()`, 722 }); 723 724 await PlacesUtils.history.clear(); 725 await extension.startup(); 726 await extension.awaitMessage("ready"); 727 728 await PlacesUtils.history.insertMany(PAGE_INFOS); 729 730 let onVisitedData = await extension.awaitMessage("on-visited-data"); 731 732 function checkOnVisitedData(index, expected) { 733 let onVisited = onVisitedData[index]; 734 ok(PlacesUtils.isValidGuid(onVisited.id), "onVisited received a valid id"); 735 equal(onVisited.url, expected.url, "onVisited received the expected url"); 736 equal( 737 onVisited.title, 738 expected.title, 739 "onVisited received the expected title" 740 ); 741 equal( 742 onVisited.lastVisitTime, 743 expected.time, 744 "onVisited received the expected time" 745 ); 746 equal( 747 onVisited.visitCount, 748 expected.visitCount, 749 "onVisited received the expected visitCount" 750 ); 751 } 752 753 let expected = { 754 url: PAGE_INFOS[0].url, 755 title: PAGE_INFOS[0].title, 756 time: PAGE_INFOS[0].visits[0].date.getTime(), 757 visitCount: 1, 758 }; 759 checkOnVisitedData(0, expected); 760 761 expected.url = PAGE_INFOS[1].url; 762 expected.title = PAGE_INFOS[1].title; 763 expected.time = PAGE_INFOS[1].visits[0].date.getTime(); 764 checkOnVisitedData(1, expected); 765 766 expected.time = PAGE_INFOS[1].visits[1].date.getTime(); 767 expected.visitCount = 2; 768 checkOnVisitedData(2, expected); 769 770 expected.url = PAGE_INFOS[2].url; 771 expected.title = PAGE_INFOS[2].title; 772 expected.time = PAGE_INFOS[2].visits[0].date.getTime(); 773 expected.visitCount = 2; 774 checkOnVisitedData(3, expected); 775 776 let onTitleChangedData = await extension.awaitMessage( 777 "on-title-changed-data" 778 ); 779 Assert.deepEqual( 780 { 781 id: onVisitedData[3].id, 782 url: SINGLE_VISIT_URL, 783 title: "Title Changed", 784 }, 785 onTitleChangedData, 786 "expected event data for onTitleChanged" 787 ); 788 789 await extension.unload(); 790 }); 791 792 add_task( 793 { 794 pref_set: [["extensions.eventPages.enabled", true]], 795 }, 796 async function test_history_event_page() { 797 await AddonTestUtils.promiseStartupManager(); 798 let extension = ExtensionTestUtils.loadExtension({ 799 useAddonManager: "permanent", 800 manifest: { 801 browser_specific_settings: { gecko: { id: "eventpage@history" } }, 802 permissions: ["history"], 803 background: { persistent: false }, 804 }, 805 background() { 806 browser.history.onVisited.addListener(() => { 807 browser.test.sendMessage("onVisited"); 808 }); 809 browser.history.onVisitRemoved.addListener(() => { 810 browser.test.sendMessage("onVisitRemoved"); 811 }); 812 browser.history.onTitleChanged.addListener(() => {}); 813 browser.test.sendMessage("ready"); 814 }, 815 }); 816 817 const EVENTS = ["onVisited", "onVisitRemoved", "onTitleChanged"]; 818 await PlacesUtils.history.clear(); 819 820 await extension.startup(); 821 await extension.awaitMessage("ready"); 822 for (let event of EVENTS) { 823 assertPersistentListeners(extension, "history", event, { 824 primed: false, 825 }); 826 } 827 828 // test events waken background 829 await extension.terminateBackground(); 830 for (let event of EVENTS) { 831 assertPersistentListeners(extension, "history", event, { 832 primed: true, 833 }); 834 } 835 836 await PlacesUtils.history.insertMany(PAGE_INFOS); 837 838 await extension.awaitMessage("ready"); 839 await extension.awaitMessage("onVisited"); 840 ok(true, "persistent event woke background"); 841 for (let event of EVENTS) { 842 assertPersistentListeners(extension, "history", event, { 843 primed: false, 844 }); 845 } 846 847 await AddonTestUtils.promiseRestartManager(); 848 await extension.awaitStartup(); 849 850 for (let event of EVENTS) { 851 assertPersistentListeners(extension, "history", event, { 852 primed: true, 853 }); 854 } 855 856 await PlacesUtils.history.clear(); 857 await extension.awaitMessage("ready"); 858 await extension.awaitMessage("onVisitRemoved"); 859 860 await extension.unload(); 861 await AddonTestUtils.promiseShutdownManager(); 862 } 863 );