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


Quelle  tab.js   Sprache: JAVA

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

const {
  tabDescriptorSpec,
} = require("resource://devtools/shared/specs/descriptors/tab.js");
const DESCRIPTOR_TYPES = require("resource://devtools/client/fronts/descriptors/descriptor-types.js");

loader.lazyRequireGetter(
  this,
  "gDevTools",
  "resource://devtools/client/framework/devtools.js",
  true
);
loader.lazyRequireGetter(
  this,
  "WindowGlobalTargetFront",
  "resource://devtools/client/fronts/targets/window-global.js",
  true
);
const {
  FrontClassWithSpec,
  registerFront,
} = require("resource://devtools/shared/protocol.js");
const {
  DescriptorMixin,
} = require("resource://devtools/client/fronts/descriptors/descriptor-mixin.js");

const POPUP_DEBUG_PREF = "devtools.popups.debug";

/**
 * DescriptorFront for tab targets.
 *
 * @fires remoteness-change
 *        Fired only for target switching, when the debugged tab is a local tab.
 *        TODO: This event could move to the server in order to support
 *        remoteness change for remote debugging.
 */

class TabDescriptorFront extends DescriptorMixin(
  FrontClassWithSpec(tabDescriptorSpec)
) {
  constructor(client, targetFront, parentFront) {
    super(client, targetFront, parentFront);

    // The tab descriptor can be configured to create either local tab targets
    // (eg, regular tab toolbox) or browsing context targets (eg tab remote
    // debugging).
    this._localTab = null;

    // Flag to prevent the server from trying to spawn targets by the watcher actor.
    this._disableTargetSwitching = false;

    this._onTargetDestroyed = this._onTargetDestroyed.bind(this);
    this._handleTabEvent = this._handleTabEvent.bind(this);

    // When the target is created from the server side,
    // it is not created via TabDescriptor.getTarget.
    // Instead, it is retrieved by the TargetCommand which
    // will call TabDescriptor.setTarget from TargetCommand.onTargetAvailable
    if (this.isServerTargetSwitchingEnabled()) {
      this._targetFrontPromise = new Promise(
        r => (this._resolveTargetFrontPromise = r)
      );
    }
  }

  descriptorType = DESCRIPTOR_TYPES.TAB;

  form(json) {
    this.actorID = json.actor;
    this._form = json;
    this.traits = json.traits || {};
  }

  /**
   * Destroy the front.
   *
   * @param Boolean If true, it means that we destroy the front when receiving the descriptor-destroyed
   *                event from the server.
   */

  destroy({ isServerDestroyEvent = false } = {}) {
    if (this.isDestroyed()) {
      return;
    }

    // The descriptor may be destroyed first by the frontend.
    // When closing the tab, the toolbox document is almost immediately removed from the DOM.
    // The `unload` event fires and toolbox destroys itself, as well as its related client.
    //
    // In such case, we emit the descriptor-destroyed event
    if (!isServerDestroyEvent) {
      this.emit("descriptor-destroyed");
    }
    if (this.isLocalTab) {
      this._teardownLocalTabListeners();
    }
    super.destroy();
  }

  getWatcher() {
    const isPopupDebuggingEnabled = Services.prefs.getBoolPref(
      POPUP_DEBUG_PREF,
      false
    );
    return super.getWatcher({
      isServerTargetSwitchingEnabled: this.isServerTargetSwitchingEnabled(),
      isPopupDebuggingEnabled,
    });
  }

  setLocalTab(localTab) {
    this._localTab = localTab;
    this._setupLocalTabListeners();
  }

  get isTabDescriptor() {
    return true;
  }

  get isLocalTab() {
    return !!this._localTab;
  }

  get localTab() {
    return this._localTab;
  }

  _setupLocalTabListeners() {
    this.localTab.addEventListener("TabClose"this._handleTabEvent);
    this.localTab.addEventListener("TabRemotenessChange"this._handleTabEvent);
  }

  _teardownLocalTabListeners() {
    this.localTab.removeEventListener("TabClose"this._handleTabEvent);
    this.localTab.removeEventListener(
      "TabRemotenessChange",
      this._handleTabEvent
    );
  }

  isServerTargetSwitchingEnabled() {
    return !this._disableTargetSwitching;
  }

  /**
   * Called by CommandsFactory, when the WebExtension codebase instantiates
   * a commands. We have to flag the TabDescriptor for them as they don't support
   * target switching and gets severely broken when enabling server target which
   * introduce target switching for all navigations and reloads
   */

  setIsForWebExtension() {
    this.disableTargetSwitching();
  }

  /**
   * Method used by the WebExtension which still need to disable server side targets,
   * and also a few xpcshell tests which are using legacy API and don't support watcher actor.
   */

  disableTargetSwitching() {
    this._disableTargetSwitching = true;
    // Delete these two attributes which have to be set early from the constructor,
    // but we don't know yet if target switch should be disabled.
    delete this._targetFrontPromise;
    delete this._resolveTargetFrontPromise;
  }

  get isZombieTab() {
    return this._form.isZombieTab;
  }

  get browserId() {
    return this._form.browserId;
  }

  get selected() {
    return this._form.selected;
  }

  get title() {
    return this._form.title;
  }

  get url() {
    return this._form.url;
  }

  get favicon() {
    // Note: the favicon is not part of the default form() payload, it will be
    // added in `retrieveFavicon`.
    return this._form.favicon;
  }

  _createTabTarget(form) {
    const front = new WindowGlobalTargetFront(this._client, nullthis);

    // As these fronts aren't instantiated by protocol.js, we have to set their actor ID
    // manually like that:
    front.actorID = form.actor;
    front.form(form);
    this.manage(front);
    return front;
  }

  _onTargetDestroyed() {
    // Clear the cached targetFront when the target is destroyed.
    // Note that we are also checking that _targetFront has a valid actorID
    // in getTarget, this acts as an additional security to avoid races.
    this._targetFront = null;
  }

  /**
   * Safely retrieves the favicon via getFavicon() and populates this._form.favicon.
   *
   * We could let callers explicitly retrieve the favicon instead of inserting it in the
   * form dynamically.
   */

  async retrieveFavicon() {
    try {
      this._form.favicon = await this.getFavicon();
    } catch (e) {
      // We might request the data for a tab which is going to be destroyed.
      // In this case the TargetFront will be destroyed. Otherwise log an error.
      if (!this.isDestroyed()) {
        console.error("Failed to retrieve the favicon for " + this.url, e);
      }
    }
  }

  /**
   * Top-level targets created on the server will not be created and managed
   * by a descriptor front. Instead they are created by the Watcher actor.
   * On the client side we manually re-establish a link between the descriptor
   * and the new top-level target.
   */

  setTarget(targetFront) {
    // Completely ignore the previous target.
    // We might nullify the _targetFront unexpectely due to previous target
    // being destroyed after the new is created
    if (this._targetFront) {
      this._targetFront.off("target-destroyed"this._onTargetDestroyed);
    }
    this._targetFront = targetFront;

    targetFront.on("target-destroyed"this._onTargetDestroyed);

    if (this.isServerTargetSwitchingEnabled()) {
      this._resolveTargetFrontPromise(targetFront);

      // Set a new promise in order to:
      // 1) Avoid leaking the targetFront we just resolved into the previous promise.
      // 2) Never return an empty target from `getTarget`
      //
      // About the second point:
      // There is a race condition where we call `onTargetDestroyed` (which clears `this.targetFront`)
      // a bit before calling `setTarget`. So that `this.targetFront` could be null,
      // while we now a new target will eventually come when calling `setTarget`.
      // Setting a new promise will help wait for the next target while `_targetFront` is null.
      // Note that `getTarget` first look into `_targetFront` before checking for `_targetFrontPromise`.
      this._targetFrontPromise = new Promise(
        r => (this._resolveTargetFrontPromise = r)
      );
    }
  }
  getCachedTarget() {
    return this._targetFront;
  }
  async getTarget() {
    if (this._targetFront && !this._targetFront.isDestroyed()) {
      return this._targetFront;
    }

    if (this._targetFrontPromise) {
      return this._targetFrontPromise;
    }

    this._targetFrontPromise = (async () => {
      let newTargetFront = null;
      try {
        const targetForm = await super.getTarget();
        newTargetFront = this._createTabTarget(targetForm);
        this.setTarget(newTargetFront);
      } catch (e) {
        console.log(
          `Request to connect to TabDescriptor "${this.id}" failed: ${e}`
        );
      }

      this._targetFrontPromise = null;
      return newTargetFront;
    })();
    return this._targetFrontPromise;
  }

  /**
   * Handle tabs events.
   */

  async _handleTabEvent(event) {
    switch (event.type) {
      case "TabClose":
        // Always destroy the toolbox opened for this local tab descriptor.
        // When the toolbox is in a Window Host, it won't be removed from the
        // DOM when the tab is closed.
        const toolbox = gDevTools.getToolboxForDescriptorFront(this);
        if (toolbox) {
          // Toolbox.destroy will call target.destroy eventually.
          await toolbox.destroy();
        }
        break;
      case "TabRemotenessChange":
        this._onRemotenessChange();
        break;
    }
  }

  /**
   * Automatically respawn the toolbox when the tab changes between being
   * loaded within the parent process and loaded from a content process.
   * Process change can go in both ways.
   */

  async _onRemotenessChange() {
    // In a near future, this client side code should be replaced by actor code,
    // notifying about new tab targets.
    this.emit("remoteness-change"this._targetFront);
  }
}

exports.TabDescriptorFront = TabDescriptorFront;
registerFront(TabDescriptorFront);

Messung V0.5
C=83 H=98 G=90

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet)  ¤

*© 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