DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (d6844fe546ad)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
/* vim: set ts=2 sw=2 sts=2 et tw=80: */
/* 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";

var EXPORTED_SYMBOLS = ["DOMFullscreenChild"];

const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");

class DOMFullscreenChild extends JSWindowActorChild {
  receiveMessage(aMessage) {
    let window = this.contentWindow;
    let windowUtils = window && window.windowUtils;

    if (!windowUtils) {
      return;
    }

    switch (aMessage.name) {
      case "DOMFullscreen:Entered": {
        let remoteFrameBC = aMessage.data.remoteFrameBC;
        if (remoteFrameBC) {
          let remoteFrame = remoteFrameBC.embedderElement;
          this._isNotTheRequestSource = true;
          windowUtils.remoteFrameFullscreenChanged(remoteFrame);
        } else {
          this._lastTransactionId = windowUtils.lastTransactionId;
          if (
            !windowUtils.handleFullscreenRequests() &&
            !this.document.fullscreenElement
          ) {
            // If we don't actually have any pending fullscreen request
            // to handle, neither we have been in fullscreen, tell the
            // parent to just exit.
            this.sendAsyncMessage("DOMFullscreen:Exit", {});
          }
        }
        break;
      }
      case "DOMFullscreen:CleanUp": {
        let remoteFrameBC = aMessage.data.remoteFrameBC;
        if (remoteFrameBC) {
          this._isNotTheRequestSource = true;
        }

        // If we've exited fullscreen at this point, no need to record
        // transaction id or call exit fullscreen. This is especially
        // important for pre-e10s, since in that case, it is possible
        // that no more paint would be triggered after this point.
        if (this.document.fullscreenElement) {
          this._lastTransactionId = windowUtils.lastTransactionId;
          windowUtils.exitFullscreen();
        }
        break;
      }
      case "DOMFullscreen:Painted": {
        Services.obs.notifyObservers(this.contentWindow, "fullscreen-painted");
        break;
      }
    }
  }

  handleEvent(aEvent) {
    if (this.hasBeenDestroyed()) {
      // Make sure that this actor is alive before going further because
      // if it's not the case, any attempt to send a message or access
      // objects such as 'contentWindow' will fail. (See bug 1590138)
      return;
    }

    switch (aEvent.type) {
      case "MozDOMFullscreen:Request": {
        this.sendAsyncMessage("DOMFullscreen:Request", {});
        break;
      }
      case "MozDOMFullscreen:NewOrigin": {
        this.sendAsyncMessage("DOMFullscreen:NewOrigin", {
          originNoSuffix: aEvent.target.nodePrincipal.originNoSuffix,
        });
        break;
      }
      case "MozDOMFullscreen:Exit": {
        this.sendAsyncMessage("DOMFullscreen:Exit", {});
        break;
      }
      case "MozDOMFullscreen:Entered":
      case "MozDOMFullscreen:Exited": {
        if (this._isNotTheRequestSource) {
          // Fullscreen change event for a frame in the
          // middle (content frame embedding the oop frame where the
          // request comes from)

          delete this._isNotTheRequestSource;
          this.sendAsyncMessage(aEvent.type.replace("Moz", ""), {});
        } else {
          let rootWindow = this.contentWindow.windowRoot;
          rootWindow.addEventListener("MozAfterPaint", this);
          if (!this.document || !this.document.fullscreenElement) {
            // If we receive any fullscreen change event, and find we are
            // actually not in fullscreen, also ask the parent to exit to
            // ensure that the parent always exits fullscreen when we do.
            this.sendAsyncMessage("DOMFullscreen:Exit", {});
          }
        }
        break;
      }
      case "MozAfterPaint": {
        // Only send Painted signal after we actually finish painting
        // the transition for the fullscreen change.
        // Note that this._lastTransactionId is not set when in pre-e10s
        // mode, so we need to check that explicitly.
        if (
          !this._lastTransactionId ||
          aEvent.transactionId > this._lastTransactionId
        ) {
          let rootWindow = this.contentWindow.windowRoot;
          rootWindow.removeEventListener("MozAfterPaint", this);
          this.sendAsyncMessage("DOMFullscreen:Painted", {});
        }
        break;
      }
    }
  }

  hasBeenDestroyed() {
    // The 'didDestroy' callback is not always getting called.
    // So we can't rely on it here. Instead, we will try to access
    // the browsing context to judge wether the actor has
    // been destroyed or not.
    try {
      return !this.browsingContext;
    } catch {
      return true;
    }
  }
}