tor-browser

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

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 }