Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  head.js   Sprache: JAVA

 
/**
 * This function would create a new foreround tab and load the url for it. In
 * addition, instead of returning a tab element, we return a tab wrapper that
 * helps us to automatically detect if the media controller of that tab
 * dispatches the first (activated) and the last event (deactivated) correctly.
 * @ param url
 *         the page url which tab would load
 * @ param input window (optional)
 *         if it exists, the tab would be created from the input window. If not,
 *         then the tab would be created in current window.
 * @ param needCheck (optional)
 *         it decides if we would perform the check for the first and last event
 *         on the media controller. It's default true.
 */

async function createLoadedTabWrapper(
  url,
  { inputWindow = window, needCheck = true } = {}
) {
  class tabWrapper {
    constructor(tab, needCheck) {
      this._tab = tab;
      this._controller = tab.linkedBrowser.browsingContext.mediaController;
      this._firstEvent = "";
      this._lastEvent = "";
      this._events = [
        "activated",
        "deactivated",
        "metadatachange",
        "playbackstatechange",
        "positionstatechange",
        "supportedkeyschange",
      ];
      this._needCheck = needCheck;
      if (this._needCheck) {
        this._registerAllEvents();
      }
    }
    _registerAllEvents() {
      for (let event of this._events) {
        this._controller.addEventListener(event, this._handleEvent.bind(this));
      }
    }
    _unregisterAllEvents() {
      for (let event of this._events) {
        this._controller.removeEventListener(
          event,
          this._handleEvent.bind(this)
        );
      }
    }
    _handleEvent(event) {
      info(`handle event=${event.type}`);
      if (this._firstEvent === "") {
        this._firstEvent = event.type;
      }
      this._lastEvent = event.type;
    }
    get linkedBrowser() {
      return this._tab.linkedBrowser;
    }
    get controller() {
      return this._controller;
    }
    get tabElement() {
      return this._tab;
    }
    async close() {
      info(`wait until finishing close tab wrapper`);
      const deactivationPromise = this._controller.isActive
        ? new Promise(r => (this._controller.ondeactivated = r))
        : Promise.resolve();
      BrowserTestUtils.removeTab(this._tab);
      await deactivationPromise;
      if (this._needCheck) {
        is(this._firstEvent, "activated""First event should be 'activated'");
        is(
          this._lastEvent,
          "deactivated",
          "Last event should be 'deactivated'"
        );
        this._unregisterAllEvents();
      }
    }
  }
  const browser = inputWindow ? inputWindow.gBrowser : window.gBrowser;
  let tab = await BrowserTestUtils.openNewForegroundTab(browser, url);
  return new tabWrapper(tab, needCheck);
}

/**
 * Returns a promise that resolves when generated media control keys has
 * triggered the main media controller's corresponding method and changes its
 * playback state.
 *
 * @param {string} event
 *        The event name of the media control key
 * @return {Promise}
 *         Resolve when the main controller receives the media control key event
 *         and change its playback state.
 */

function generateMediaControlKeyEvent(event) {
  const playbackStateChanged = waitUntilDisplayedPlaybackChanged();
  MediaControlService.generateMediaControlKey(event);
  return playbackStateChanged;
}

/**
 * Play the specific media and wait until it plays successfully and the main
 * controller has been updated.
 *
 * @param {tab} tab
 *        The tab that contains the media which we would play
 * @param {string} elementId
 *        The element Id of the media which we would play
 * @return {Promise}
 *         Resolve when the media has been starting playing and the main
 *         controller has been updated.
 */

async function playMedia(tab, elementId) {
  const playbackStatePromise = waitUntilDisplayedPlaybackChanged();
  await SpecialPowers.spawn(tab.linkedBrowser, [elementId], async Id => {
    const video = content.document.getElementById(Id);
    if (!video) {
      ok(false, `can't get the media element!`);
    }
    ok(
      await video.play().then(
        _ => true,
        _ => false
      ),
      "video started playing"
    );
  });
  return playbackStatePromise;
}

/**
 * Pause the specific media and wait until it pauses successfully and the main
 * controller has been updated.
 *
 * @param {tab} tab
 *        The tab that contains the media which we would pause
 * @param {string} elementId
 *        The element Id of the media which we would pause
 * @return {Promise}
 *         Resolve when the media has been paused and the main controller has
 *         been updated.
 */

function pauseMedia(tab, elementId) {
  const pausePromise = SpecialPowers.spawn(
    tab.linkedBrowser,
    [elementId],
    Id => {
      const video = content.document.getElementById(Id);
      if (!video) {
        ok(false, `can't get the media element!`);
      }
      ok(!video.paused, `video is playing before calling pause`);
      video.pause();
    }
  );
  return Promise.all([pausePromise, waitUntilDisplayedPlaybackChanged()]);
}

/**
 * Returns a promise that resolves when the specific media starts playing.
 *
 * @param {tab} tab
 *        The tab that contains the media which we would check
 * @param {string} elementId
 *        The element Id of the media which we would check
 * @return {Promise}
 *         Resolve when the media has been starting playing.
 */

function checkOrWaitUntilMediaStartedPlaying(tab, elementId) {
  return SpecialPowers.spawn(tab.linkedBrowser, [elementId], Id => {
    return new Promise(resolve => {
      const video = content.document.getElementById(Id);
      if (!video) {
        ok(false, `can't get the media element!`);
      }
      if (!video.paused) {
        ok(true, `media started playing`);
        resolve();
      } else {
        info(`wait until media starts playing`);
        video.onplaying = () => {
          video.onplaying = null;
          ok(true, `media started playing`);
          resolve();
        };
      }
    });
  });
}

/**
 * Set the playback rate on a media element.
 *
 * @param {tab} tab
 *        The tab that contains the media which we would check
 * @param {string} elementId
 *        The element Id of the media which we would check
 * @param {number} rate
 *        The playback rate to set
 * @return {Promise}
 *         Resolve when the playback rate has been set
 */

function setPlaybackRate(tab, elementId, rate) {
  return SpecialPowers.spawn(
    tab.linkedBrowser,
    [elementId, rate],
    (Id, rate) => {
      const video = content.document.getElementById(Id);
      if (!video) {
        ok(false, `can't get the media element!`);
      }
      video.playbackRate = rate;
    }
  );
}

/**
 * Set the time on a media element.
 *
 * @param {tab} tab
 *        The tab that contains the media which we would check
 * @param {string} elementId
 *        The element Id of the media which we would check
 * @param {number} currentTime
 *        The time to set
 * @return {Promise}
 *         Resolve when the time has been set
 */

function setCurrentTime(tab, elementId, currentTime) {
  return SpecialPowers.spawn(
    tab.linkedBrowser,
    [elementId, currentTime],
    (Id, currentTime) => {
      const video = content.document.getElementById(Id);
      if (!video) {
        ok(false, `can't get the media element!`);
      }
      video.currentTime = currentTime;
    }
  );
}

/**
 * Returns a promise that resolves when the specific media stops playing.
 *
 * @param {tab} tab
 *        The tab that contains the media which we would check
 * @param {string} elementId
 *        The element Id of the media which we would check
 * @return {Promise}
 *         Resolve when the media has been stopped playing.
 */

function checkOrWaitUntilMediaStoppedPlaying(tab, elementId) {
  return SpecialPowers.spawn(tab.linkedBrowser, [elementId], Id => {
    return new Promise(resolve => {
      const video = content.document.getElementById(Id);
      if (!video) {
        ok(false, `can't get the media element!`);
      }
      if (video.paused) {
        ok(true, `media stopped playing`);
        resolve();
      } else {
        info(`wait until media stops playing`);
        video.onpause = () => {
          video.onpause = null;
          ok(true, `media stopped playing`);
          resolve();
        };
      }
    });
  });
}

/**
 * Check if the active metadata is empty.
 */

function isCurrentMetadataEmpty() {
  const current = MediaControlService.getCurrentActiveMediaMetadata();
  is(current.title, "", `current title should be empty`);
  is(current.artist, "", `current title should be empty`);
  is(current.album, "", `current album should be empty`);
  is(current.artwork.length, 0, `current artwork should be empty`);
}

/**
 * Check if the active metadata is equal to the given metadata.artwork
 *
 * @param {object} metadata
 *        The metadata that would be compared with the active metadata
 */

function isCurrentMetadataEqualTo(metadata) {
  const current = MediaControlService.getCurrentActiveMediaMetadata();
  is(
    current.title,
    metadata.title,
    `tile '${current.title}' is equal to ${metadata.title}`
  );
  is(
    current.artist,
    metadata.artist,
    `artist '${current.artist}' is equal to ${metadata.artist}`
  );
  is(
    current.album,
    metadata.album,
    `album '${current.album}' is equal to ${metadata.album}`
  );
  is(
    current.artwork.length,
    metadata.artwork.length,
    `artwork length '${current.artwork.length}' is equal to ${metadata.artwork.length}`
  );
  for (let idx = 0; idx < metadata.artwork.length; idx++) {
    // the current src we got would be a completed path of the image, so we do
    // not check if they are equal, we check if the current src includes the
    // metadata's file name. Eg. "http://foo/bar.jpg" v.s. "bar.jpg"
    ok(
      current.artwork[idx].src.includes(metadata.artwork[idx].src),
      `artwork src '${current.artwork[idx].src}' includes ${metadata.artwork[idx].src}`
    );
    is(
      current.artwork[idx].sizes,
      metadata.artwork[idx].sizes,
      `artwork sizes '${current.artwork[idx].sizes}' is equal to ${metadata.artwork[idx].sizes}`
    );
    is(
      current.artwork[idx].type,
      metadata.artwork[idx].type,
      `artwork type '${current.artwork[idx].type}' is equal to ${metadata.artwork[idx].type}`
    );
  }
}

/**
 * Check if the given tab is using the default metadata. If the tab is being
 * used in the private browsing mode, `isPrivateBrowsing` should be definded in
 * the `options`.
 */

async function isGivenTabUsingDefaultMetadata(tab, options = {}) {
  const localization = new Localization([
    "branding/brand.ftl",
    "dom/media.ftl",
  ]);
  const fallbackTitle = await localization.formatValue(
    "mediastatus-fallback-title"
  );
  ok(fallbackTitle.length, "l10n fallback title is not empty");

  const metadata =
    tab.linkedBrowser.browsingContext.mediaController.getMetadata();

  await SpecialPowers.spawn(
    tab.linkedBrowser,
    [metadata.title, fallbackTitle, options.isPrivateBrowsing],
    (title, fallbackTitle, isPrivateBrowsing) => {
      if (isPrivateBrowsing || !content.document.title.length) {
        is(title, fallbackTitle, "Using a generic default fallback title");
      } else {
        is(
          title,
          content.document.title,
          "Using website title as a default title"
        );
      }
    }
  );
  is(metadata.artwork.length, 1, "Default metada contains one artwork");
  ok(
    metadata.artwork[0].src.includes("defaultFavicon.svg"),
    "Using default favicon as a default art work"
  );
}

/**
 * Wait until the main media controller changes its playback state, we would
 * observe that by listening for `media-displayed-playback-changed`
 * notification.
 *
 * @return {Promise}
 *         Resolve when observing `media-displayed-playback-changed`
 */

function waitUntilDisplayedPlaybackChanged() {
  return BrowserUtils.promiseObserved("media-displayed-playback-changed");
}

/**
 * Wait until the metadata that would be displayed on the virtual control
 * interface changes. we would observe that by listening for
 * `media-displayed-metadata-changed` notification.
 *
 * @return {Promise}
 *         Resolve when observing `media-displayed-metadata-changed`
 */

function waitUntilDisplayedMetadataChanged() {
  return BrowserUtils.promiseObserved("media-displayed-metadata-changed");
}

/**
 * Wait until the main media controller has been changed, we would observe that
 * by listening for the `main-media-controller-changed` notification.
 *
 * @return {Promise}
 *         Resolve when observing `main-media-controller-changed`
 */

function waitUntilMainMediaControllerChanged() {
  return BrowserUtils.promiseObserved("main-media-controller-changed");
}

/**
 * Wait until any media controller updates its metadata even if it's not the
 * main controller. The difference between this function and
 * `waitUntilDisplayedMetadataChanged()` is that the changed metadata might come
 * from non-main controller so it won't be show on the virtual control
 * interface. we would observe that by listening for
 * `media-session-controller-metadata-changed` notification.
 *
 * @return {Promise}
 *         Resolve when observing `media-session-controller-metadata-changed`
 */

function waitUntilControllerMetadataChanged() {
  return BrowserUtils.promiseObserved(
    "media-session-controller-metadata-changed"
  );
}

/**
 * Wait until media controller amount changes, we would observe that by
 * listening for `media-controller-amount-changed` notification.
 *
 * @return {Promise}
 *         Resolve when observing `media-controller-amount-changed`
 */

function waitUntilMediaControllerAmountChanged() {
  return BrowserUtils.promiseObserved("media-controller-amount-changed");
}

/**
 * Wait until the position state that would be displayed on the virtual control
 * interface changes. we would observe that by listening for
 * `media-position-state-changed` notification.
 *
 * @return {Promise}
 *         Resolve when observing `media-position-state-changed`
 */

function waitUntilPositionStateChanged() {
  return BrowserUtils.promiseObserved("media-position-state-changed");
}

/**
 * check if the media controll from given tab is active. If not, return a
 * promise and resolve it when controller become active.
 */

async function checkOrWaitUntilControllerBecomeActive(tab) {
  const controller = tab.linkedBrowser.browsingContext.mediaController;
  if (controller.isActive) {
    return;
  }
  await new Promise(r => (controller.onactivated = r));
}

/**
 * Logs all `positionstatechange` events in a tab.
 */

function logPositionStateChangeEvents(tab) {
  tab.linkedBrowser.browsingContext.mediaController.addEventListener(
    "positionstatechange",
    event =>
      info(
        `got position state: ${JSON.stringify({
          duration: event.duration,
          playbackRate: event.playbackRate,
          position: event.position,
        })}`
      )
  );
}

Messung V0.5
C=97 H=95 G=95

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge