summaryrefslogtreecommitdiffstats
path: root/devtools/client/performance-new/test/browser/fake-frontend.html
blob: 67424571133f88b5892dbdf6d2fc7bf709ff35d9 (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
<!DOCTYPE html>
<!-- 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/. -->
<html>
  <head>
    <meta charset="utf-8"/>
    <title></title>
  </head>
  <body>
    <script>
      "use strict";
      // This file is used to test the injection of performance profiles into a front-end,
      // specifically the mechanism used to inject into profiler.firefox.com. Rather
      // than using some kind of complicated message passing scheme to talk to the test
      // harness, modify the title of the page. The tests can easily read the window
      // title to see if things worked as expected.

      // The following are the titles used to communicate the page's state to the tests.
      // Keep these in sync with any tests that read them.
      const initialTitle = "Waiting on the profile";
      const successTitle = "Profile received";
      const errorTitle = "Error"

      document.title = initialTitle;

      // A function which requests the profile from the browser using the GET_PROFILE
      // WebChannel message.
      function getProfile() {
        return new Promise((resolve, reject) => {
          const requestId = 0;

          function listener(event) {
            window.removeEventListener(
              "WebChannelMessageToContent",
              listener,
              true
            );

            const { id, message } = event.detail;

            if (id !== "profiler.firefox.com" ||
              !message ||
              typeof message !== "object"
            ) {
              console.error(message);
              reject(new Error("A malformed WebChannel event was received."));
              return;
            }

            if (!message.type) {
              console.error(message);
              reject(new Error("The WebChannel event indicates an error."));
              return;
            }

            if (message.requestId === requestId) {
              if (message.type === "SUCCESS_RESPONSE") {
                resolve(message.response);
              } else {
                reject(new Error(message.error));
              }
            }
          }

          window.addEventListener("WebChannelMessageToContent", listener, true);

          window.dispatchEvent(
            new CustomEvent("WebChannelMessageToChrome", {
              detail: JSON.stringify({
                id: "profiler.firefox.com",
                message: { type: "GET_PROFILE", requestId },
              }),
            })
          );
        })
      }

      async function runTest() {
        try {
          // Get the profile.
          const profile = await getProfile();

          // Check that the profile is somewhat reasonable. It should be a gzipped
          // profile, so we can only lightly check some properties about it, and check
          // that it is an ArrayBuffer.
          //
          // After the check, modify the title of the document, so the tab title gets
          // updated. This is an easy way to pass a message to the test script.
          if (
            profile &&
            typeof profile === 'object' &&
            (
              // The popup injects the compressed profile as an ArrayBuffer.
              (profile instanceof ArrayBuffer) ||
              // DevTools injects the profile as just the plain object, although
              // maybe in the future it could also do it as a compressed profile
              // to make this faster (bug 1581963).
              Object.keys(profile).includes("threads")
            )
          ) {
            // The profile looks good!
            document.title = successTitle;
          } else {
            // The profile doesn't look right, surface the error to the terminal.
            dump('The gecko profile was malformed in fake-frontend.html\n');
            dump(`Profile: ${JSON.stringify(profile)}\n`);

            // Also to the web console.
            console.error(profile);

            // Report the error to the tab title.
            document.title = errorTitle;
          }
        } catch (error) {
          // Catch any error and notify the test.
          document.title = errorTitle;
          dump('An error was caught in fake-frontend.html\n');
          dump(`${error}\n`);
        }
      }

      runTest();
    </script>
  </body>
</html>