browser_media_control_metadata.js (12337B)
1 const PAGE_NON_AUTOPLAY = 2 "https://example.com/browser/dom/media/mediacontrol/tests/browser/file_non_autoplay.html"; 3 const PAGE_EMPTY_TITLE_URL = 4 "https://example.com/browser/dom/media/mediacontrol/tests/browser/file_empty_title.html"; 5 6 const testVideoId = "video"; 7 const defaultFaviconName = "defaultFavicon.svg"; 8 9 add_task(async function setupTestingPref() { 10 await SpecialPowers.pushPrefEnv({ 11 set: [["media.mediacontrol.testingevents.enabled", true]], 12 }); 13 }); 14 15 /** 16 * This test includes many different test cases of checking the current media 17 * metadata from the tab which is being controlled by the media control. Each 18 * `add_task(..)` is a different testing scenario. 19 * 20 * Media metadata is the information that can tell user about what title, artist, 21 * album and even art work the tab is currently playing to. The metadta is 22 * usually set from MediaSession API, but if the site doesn't use that API, we 23 * would also generate a default metadata instead. 24 * 25 * The current metadata would only be available after the page starts playing 26 * media at least once, if the page hasn't started any media before, then the 27 * current metadata is always empty. 28 * 29 * For following situations, we would create a default metadata which title is 30 * website's title and artwork is from our default favicon icon. 31 * (1) the page doesn't use MediaSession API 32 * (2) media session doesn't has metadata 33 * (3) media session has an empty metadata 34 * 35 * Otherwise, the current metadata would be media session's metadata from the 36 * tab which is currently controlled by the media control. 37 */ 38 add_task(async function testDefaultMetadataForPageWithoutMediaSession() { 39 info(`open media page`); 40 const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY); 41 42 info(`start media`); 43 await playMedia(tab, testVideoId); 44 45 info(`should use default metadata because of lacking of media session`); 46 await isGivenTabUsingDefaultMetadata(tab); 47 48 info(`remove tab`); 49 await tab.close(); 50 }); 51 52 add_task( 53 async function testDefaultMetadataForEmptyTitlePageWithoutMediaSession() { 54 info(`open media page`); 55 const tab = await createLoadedTabWrapper(PAGE_EMPTY_TITLE_URL); 56 57 info(`start media`); 58 await playMedia(tab, testVideoId); 59 60 info(`should use default metadata because of lacking of media session`); 61 await isGivenTabUsingDefaultMetadata(tab); 62 63 info(`remove tab`); 64 await tab.close(); 65 } 66 ); 67 68 add_task(async function testDefaultMetadataForPageUsingEmptyMetadata() { 69 info(`open media page`); 70 const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY); 71 72 info(`start media`); 73 await playMedia(tab, testVideoId); 74 75 info(`create empty media metadata`); 76 await setMediaMetadata(tab, { 77 title: "", 78 artist: "", 79 album: "", 80 artwork: [], 81 }); 82 83 info(`should use default metadata because of empty media metadata`); 84 await isGivenTabUsingDefaultMetadata(tab); 85 86 info(`remove tab`); 87 await tab.close(); 88 }); 89 90 add_task(async function testDefaultMetadataForPageUsingNullMetadata() { 91 info(`open media page`); 92 const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY); 93 94 info(`start media`); 95 await playMedia(tab, testVideoId); 96 97 info(`create empty media metadata`); 98 await setNullMediaMetadata(tab); 99 100 info(`should use default metadata because of lacking of media metadata`); 101 await isGivenTabUsingDefaultMetadata(tab); 102 103 info(`remove tab`); 104 await tab.close(); 105 }); 106 107 add_task(async function testMetadataWithEmptyTitleAndArtwork() { 108 info(`open media page`); 109 const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY); 110 111 info(`start media`); 112 await playMedia(tab, testVideoId); 113 114 info(`create media metadata with empty title and artwork`); 115 await setMediaMetadata(tab, { 116 title: "", 117 artist: "foo", 118 album: "bar", 119 artwork: [], 120 }); 121 122 info(`should use default metadata because of empty title and artwork`); 123 await isGivenTabUsingDefaultMetadata(tab); 124 125 info(`remove tab`); 126 await tab.close(); 127 }); 128 129 add_task(async function testMetadataWithoutTitleAndArtwork() { 130 info(`open media page`); 131 const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY); 132 133 info(`start media`); 134 await playMedia(tab, testVideoId); 135 136 info(`create media metadata with empty title and artwork`); 137 await setMediaMetadata(tab, { 138 artist: "foo", 139 album: "bar", 140 }); 141 142 info(`should use default metadata because of lacking of title and artwork`); 143 await isGivenTabUsingDefaultMetadata(tab); 144 145 info(`remove tab`); 146 await tab.close(); 147 }); 148 149 add_task(async function testMetadataInPrivateBrowsing() { 150 info(`create a private window`); 151 const inputWindow = await BrowserTestUtils.openNewBrowserWindow({ 152 private: true, 153 }); 154 155 info(`open media page`); 156 const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY, { inputWindow }); 157 158 info(`start media`); 159 await playMedia(tab, testVideoId); 160 161 info(`set metadata`); 162 let metadata = { 163 title: "foo", 164 artist: "bar", 165 album: "foo", 166 artwork: [{ src: "bar.jpg", sizes: "128x128", type: "image/jpeg" }], 167 }; 168 await setMediaMetadata(tab, metadata); 169 170 info(`should use default metadata because of in private browsing mode`); 171 await isGivenTabUsingDefaultMetadata(tab, { isPrivateBrowsing: true }); 172 173 info(`remove tab`); 174 await tab.close(); 175 176 info(`close private window`); 177 await BrowserTestUtils.closeWindow(inputWindow); 178 }); 179 180 add_task(async function testSetMetadataFromMediaSessionAPI() { 181 info(`open media page`); 182 const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY); 183 184 info(`start media`); 185 await playMedia(tab, testVideoId); 186 187 info(`set metadata`); 188 let metadata = { 189 title: "foo", 190 artist: "bar", 191 album: "foo", 192 artwork: [{ src: "bar.jpg", sizes: "128x128", type: "image/jpeg" }], 193 }; 194 await setMediaMetadata(tab, metadata); 195 196 info(`check if current active metadata is equal to what we've set before`); 197 await isCurrentMetadataEqualTo(metadata); 198 199 info(`set metadata again to see if current metadata would change`); 200 metadata = { 201 title: "foo2", 202 artist: "bar2", 203 album: "foo2", 204 artwork: [{ src: "bar2.jpg", sizes: "129x129", type: "image/jpeg" }], 205 }; 206 await setMediaMetadata(tab, metadata); 207 208 info(`check if current active metadata is equal to what we've set before`); 209 await isCurrentMetadataEqualTo(metadata); 210 211 info(`remove tab`); 212 await tab.close(); 213 }); 214 215 add_task(async function testSetMetadataBeforeMediaStarts() { 216 info(`open media page`); 217 const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY, { 218 needCheck: false, 219 }); 220 221 info(`set metadata`); 222 let metadata = { 223 title: "foo", 224 artist: "bar", 225 album: "foo", 226 artwork: [{ src: "bar.jpg", sizes: "128x128", type: "image/jpeg" }], 227 }; 228 await setMediaMetadata(tab, metadata, { notExpectChange: true }); 229 230 info(`current media metadata should be empty before media starts`); 231 isCurrentMetadataEmpty(); 232 233 info(`remove tab`); 234 await tab.close(); 235 }); 236 237 add_task(async function testSetMetadataAfterMediaPaused() { 238 info(`open media page`); 239 const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY); 240 241 info(`start media in order to let this tab be controlled`); 242 await playMedia(tab, testVideoId); 243 244 info(`pause media`); 245 await pauseMedia(tab, testVideoId); 246 247 info(`set metadata after media is paused`); 248 let metadata = { 249 title: "foo", 250 artist: "bar", 251 album: "foo", 252 artwork: [{ src: "bar.jpg", sizes: "128x128", type: "image/jpeg" }], 253 }; 254 await setMediaMetadata(tab, metadata); 255 256 info(`check if current active metadata is equal to what we've set before`); 257 await isCurrentMetadataEqualTo(metadata); 258 259 info(`remove tab`); 260 await tab.close(); 261 }); 262 263 add_task(async function testSetMetadataAmongMultipleTabs() { 264 info(`open media page in tab1`); 265 const tab1 = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY); 266 267 info(`start media in tab1`); 268 await playMedia(tab1, testVideoId); 269 270 info(`set metadata for tab1`); 271 let metadata = { 272 title: "foo", 273 artist: "bar", 274 album: "foo", 275 artwork: [{ src: "bar.jpg", sizes: "128x128", type: "image/jpeg" }], 276 }; 277 await setMediaMetadata(tab1, metadata); 278 279 info(`check if current active metadata is equal to what we've set before`); 280 await isCurrentMetadataEqualTo(metadata); 281 282 info(`open another page in tab2`); 283 const tab2 = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY); 284 285 info(`start media in tab2`); 286 await playMedia(tab2, testVideoId); 287 288 info(`set metadata for tab2`); 289 metadata = { 290 title: "foo2", 291 artist: "bar2", 292 album: "foo2", 293 artwork: [{ src: "bar2.jpg", sizes: "129x129", type: "image/jpeg" }], 294 }; 295 await setMediaMetadata(tab2, metadata); 296 297 info(`current active metadata should become metadata from tab2`); 298 await isCurrentMetadataEqualTo(metadata); 299 300 info( 301 `update metadata for tab1, which should not affect current metadata ` + 302 `because media session in tab2 is the one we're controlling right now` 303 ); 304 await setMediaMetadata(tab1, { 305 title: "foo3", 306 artist: "bar3", 307 album: "foo3", 308 artwork: [{ src: "bar3.jpg", sizes: "130x130", type: "image/jpeg" }], 309 }); 310 311 info(`current active metadata should still be metadata from tab2`); 312 await isCurrentMetadataEqualTo(metadata); 313 314 info(`remove tabs`); 315 await Promise.all([tab1.close(), tab2.close()]); 316 }); 317 318 add_task(async function testMetadataAfterTabNavigation() { 319 info(`open media page`); 320 const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY); 321 322 info(`start media`); 323 await playMedia(tab, testVideoId); 324 325 info(`set metadata`); 326 let metadata = { 327 title: "foo", 328 artist: "bar", 329 album: "foo", 330 artwork: [{ src: "bar.jpg", sizes: "128x128", type: "image/jpeg" }], 331 }; 332 await setMediaMetadata(tab, metadata); 333 334 info(`check if current active metadata is equal to what we've set before`); 335 await isCurrentMetadataEqualTo(metadata); 336 337 info(`navigate tab to blank page`); 338 await Promise.all([ 339 new Promise(r => (tab.controller.ondeactivated = r)), 340 BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, "about:blank"), 341 ]); 342 343 info(`current media metadata should be reset`); 344 isCurrentMetadataEmpty(); 345 346 info(`remove tab`); 347 await tab.close(); 348 }); 349 350 add_task(async function testUpdateDefaultMetadataWhenPageTitleChanges() { 351 info(`open media page`); 352 const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY); 353 354 info(`start media`); 355 await playMedia(tab, testVideoId); 356 357 info(`should use default metadata because of lacking of media session`); 358 await isGivenTabUsingDefaultMetadata(tab); 359 360 info(`default metadata should be updated after page title changes`); 361 await changePageTitle(tab, { shouldAffectMetadata: true }); 362 await isGivenTabUsingDefaultMetadata(tab); 363 364 info(`after setting metadata, title change won't affect current metadata`); 365 const metadata = { 366 title: "foo", 367 artist: "bar", 368 album: "foo", 369 artwork: [{ src: "bar.jpg", sizes: "128x128", type: "image/jpeg" }], 370 }; 371 await setMediaMetadata(tab, metadata); 372 await changePageTitle(tab, { shouldAffectMetadata: false }); 373 await isCurrentMetadataEqualTo(metadata); 374 375 info(`remove tab`); 376 await tab.close(); 377 }); 378 379 /** 380 * The following are helper functions. 381 */ 382 function setMediaMetadata(tab, metadata, { notExpectChange } = {}) { 383 const controller = tab.linkedBrowser.browsingContext.mediaController; 384 const metadatachangePromise = notExpectChange 385 ? Promise.resolve() 386 : new Promise(r => (controller.onmetadatachange = r)); 387 return Promise.all([ 388 metadatachangePromise, 389 SpecialPowers.spawn(tab.linkedBrowser, [metadata], data => { 390 content.navigator.mediaSession.metadata = new content.MediaMetadata(data); 391 }), 392 ]); 393 } 394 395 function setNullMediaMetadata(tab) { 396 const promise = SpecialPowers.spawn(tab.linkedBrowser, [], () => { 397 content.navigator.mediaSession.metadata = null; 398 }); 399 return Promise.all([promise, waitUntilControllerMetadataChanged()]); 400 } 401 402 async function changePageTitle(tab, { shouldAffectMetadata } = {}) { 403 const controller = tab.linkedBrowser.browsingContext.mediaController; 404 const shouldWaitMetadataChangePromise = shouldAffectMetadata 405 ? new Promise(r => (controller.onmetadatachange = r)) 406 : Promise.resolve(); 407 await Promise.all([ 408 shouldWaitMetadataChangePromise, 409 SpecialPowers.spawn(tab.linkedBrowser, [], _ => { 410 content.document.title = "new title"; 411 }), 412 ]); 413 }