summaryrefslogtreecommitdiffstats
path: root/devtools/server/actors/layout.js
blob: 0b9242b5fdbc5733c19386b49ce95de114a9ff84 (plain)
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
/* 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 { Actor, ActorClassWithSpec } = require("devtools/shared/protocol");
const { gridSpec, layoutSpec } = require("devtools/shared/specs/layout");
const { getStringifiableFragments } = require("devtools/server/actors/utils/css-grid-utils");

/**
 * Set of actors the expose the CSS layout information to the devtools protocol clients.
 *
 * The |Layout| actor is the main entry point. It is used to get various CSS
 * layout-related information from the document.
 *
 * The |Grid| actor provides the grid fragment information to inspect the grid container.
 */

/**
 * The GridActor provides information about a given grid's fragment data.
 */
var GridActor = ActorClassWithSpec(gridSpec, {
  /**
   * @param  {LayoutActor} layoutActor
   *         The LayoutActor instance.
   * @param  {DOMNode} containerEl
   *         The grid container element.
   */
  initialize: function (layoutActor, containerEl) {
    Actor.prototype.initialize.call(this, layoutActor.conn);

    this.containerEl = containerEl;
    this.walker = layoutActor.walker;
  },

  destroy: function () {
    Actor.prototype.destroy.call(this);

    this.containerEl = null;
    this.gridFragments = null;
    this.walker = null;
  },

  form: function (detail) {
    if (detail === "actorid") {
      return this.actorID;
    }

    // Seralize the grid fragment data into JSON so protocol.js knows how to write
    // and read the data.
    let gridFragments = this.containerEl.getGridFragments();
    this.gridFragments = getStringifiableFragments(gridFragments);

    let form = {
      actor: this.actorID,
      gridFragments: this.gridFragments
    };

    return form;
  },
});

/**
 * The CSS layout actor provides layout information for the given document.
 */
var LayoutActor = ActorClassWithSpec(layoutSpec, {
  initialize: function (conn, tabActor, walker) {
    Actor.prototype.initialize.call(this, conn);

    this.tabActor = tabActor;
    this.walker = walker;
  },

  destroy: function () {
    Actor.prototype.destroy.call(this);

    this.tabActor = null;
    this.walker = null;
  },

  /**
   * Returns an array of GridActor objects for all the grid containers found by iterating
   * below the given rootNode.
   *
   * @param  {Node|NodeActor} rootNode
   *         The root node to start iterating at.
   * @return {Array} An array of GridActor objects.
   */
  getGrids: function (rootNode) {
    let grids = [];

    let treeWalker = this.walker.getDocumentWalker(rootNode);
    while (treeWalker.nextNode()) {
      let currentNode = treeWalker.currentNode;

      if (currentNode.getGridFragments && currentNode.getGridFragments().length > 0) {
        let gridActor = new GridActor(this, currentNode);
        grids.push(gridActor);
      }
    }

    return grids;
  },

  /**
   * Returns an array of GridActor objects for all existing grid containers found by
   * iterating below the given rootNode and optionally including nested frames.
   *
   * @param  {NodeActor} rootNode
   * @param  {Boolean} traverseFrames
   *         Whether or not we should iterate through nested frames.
   * @return {Array} An array of GridActor objects.
   */
  getAllGrids: function (rootNode, traverseFrames) {
    if (!traverseFrames) {
      return this.getGridActors(rootNode);
    }

    let grids = [];
    for (let {document} of this.tabActor.windows) {
      grids = [...grids, ...this.getGrids(document.documentElement)];
    }

    return grids;
  },

});

exports.GridActor = GridActor;
exports.LayoutActor = LayoutActor;