browser_favicon_change_not_in_document.js (5033B)
1 "use strict"; 2 3 const TEST_ROOT = 4 "http://mochi.test:8888/browser/browser/base/content/test/favicons/"; 5 const TEST_URL = TEST_ROOT + "file_favicon_change_not_in_document.html"; 6 7 // Runs the given task in the document of the browser. 8 function runInDoc(browser, task) { 9 return ContentTask.spawn(browser, `(${task.toString()})();`, scriptStr => { 10 let script = content.document.createElement("script"); 11 script.textContent = scriptStr; 12 content.document.body.appendChild(script); 13 14 // Link events are dispatched asynchronously so allow the event loop to run 15 // to ensure that any events are actually dispatched before returning. 16 return new Promise(resolve => content.setTimeout(resolve, 0)); 17 }); 18 } 19 20 /* 21 * This test tests a link element won't fire DOMLinkChanged/DOMLinkAdded unless 22 * it is added to the DOM. See more details in bug 1083895. 23 * 24 * Note that there is debounce logic in FaviconLoader.sys.mjs, adding a new 25 * icon link after the icon parsing timeout will trigger a new icon extraction 26 * cycle. Hence, there should be two favicons loads in this test as it appends 27 * a new link to the DOM in the timeout callback defined in the test HTML page. 28 * However, the not-yet-added link element with href as "http://example.org/other-icon" 29 * should not fire the DOMLinkAdded event, nor should it fire the DOMLinkChanged 30 * event after its href gets updated later. 31 */ 32 add_task(async function () { 33 let extraTab = (gBrowser.selectedTab = BrowserTestUtils.addTab( 34 gBrowser, 35 TEST_ROOT 36 )); 37 let domLinkAddedFired = 0; 38 let domLinkChangedFired = 0; 39 const linkAddedHandler = () => domLinkAddedFired++; 40 const linkChangedhandler = () => domLinkChangedFired++; 41 BrowserTestUtils.addContentEventListener( 42 gBrowser.selectedBrowser, 43 "DOMLinkAdded", 44 linkAddedHandler 45 ); 46 BrowserTestUtils.addContentEventListener( 47 gBrowser.selectedBrowser, 48 "DOMLinkChanged", 49 linkChangedhandler 50 ); 51 52 let expectedFavicon = TEST_ROOT + "file_generic_favicon.ico"; 53 let faviconPromise = waitForFavicon(extraTab.linkedBrowser, expectedFavicon); 54 55 BrowserTestUtils.startLoadingURIString(extraTab.linkedBrowser, TEST_URL); 56 await BrowserTestUtils.browserLoaded(extraTab.linkedBrowser); 57 58 await faviconPromise; 59 60 is( 61 domLinkAddedFired, 62 2, 63 "Should fire the correct number of DOMLinkAdded event." 64 ); 65 is(domLinkChangedFired, 0, "Should not fire any DOMLinkChanged event."); 66 67 gBrowser.removeTab(extraTab); 68 }); 69 70 /* 71 * This verifies that creating and manipulating link elements inside document 72 * fragments doesn't trigger the link events. 73 */ 74 add_task(async function () { 75 let extraTab = (gBrowser.selectedTab = BrowserTestUtils.addTab( 76 gBrowser, 77 TEST_ROOT 78 )); 79 let browser = extraTab.linkedBrowser; 80 81 let domLinkAddedFired = 0; 82 let domLinkChangedFired = 0; 83 const linkAddedHandler = () => domLinkAddedFired++; 84 const linkChangedhandler = () => domLinkChangedFired++; 85 BrowserTestUtils.addContentEventListener( 86 browser, 87 "DOMLinkAdded", 88 linkAddedHandler 89 ); 90 BrowserTestUtils.addContentEventListener( 91 browser, 92 "DOMLinkChanged", 93 linkChangedhandler 94 ); 95 96 BrowserTestUtils.startLoadingURIString(browser, TEST_ROOT + "blank.html"); 97 await BrowserTestUtils.browserLoaded(browser); 98 99 is(domLinkAddedFired, 0, "Should have been no link add events"); 100 is(domLinkChangedFired, 0, "Should have been no link change events"); 101 102 await runInDoc(browser, () => { 103 let fragment = document 104 .createRange() 105 .createContextualFragment( 106 '<link type="image/ico" href="file_generic_favicon.ico" rel="icon">' 107 ); 108 fragment.firstElementChild.setAttribute("type", "image/png"); 109 }); 110 111 is(domLinkAddedFired, 0, "Should have been no link add events"); 112 is(domLinkChangedFired, 0, "Should have been no link change events"); 113 114 await runInDoc(browser, () => { 115 let fragment = document.createDocumentFragment(); 116 let link = document.createElement("link"); 117 link.setAttribute("href", "file_generic_favicon.ico"); 118 link.setAttribute("rel", "icon"); 119 link.setAttribute("type", "image/ico"); 120 121 fragment.appendChild(link); 122 link.setAttribute("type", "image/png"); 123 }); 124 125 is(domLinkAddedFired, 0, "Should have been no link add events"); 126 is(domLinkChangedFired, 0, "Should have been no link change events"); 127 128 let expectedFavicon = TEST_ROOT + "file_generic_favicon.ico"; 129 let faviconPromise = waitForFavicon(browser, expectedFavicon); 130 131 // Moving an element from the fragment into the DOM should trigger the add 132 // events and start favicon loading. 133 await runInDoc(browser, () => { 134 let fragment = document 135 .createRange() 136 .createContextualFragment( 137 '<link type="image/ico" href="file_generic_favicon.ico" rel="icon">' 138 ); 139 document.head.appendChild(fragment); 140 }); 141 142 is(domLinkAddedFired, 1, "Should have been one link add events"); 143 is(domLinkChangedFired, 0, "Should have been no link change events"); 144 145 await faviconPromise; 146 147 gBrowser.removeTab(extraTab); 148 });