summaryrefslogtreecommitdiffstats
path: root/browser/components/shell/test/head.js
blob: d2114941e40975a393c317d3a66e95bc2c8c5b66 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
"use strict";

const { Subprocess } = ChromeUtils.importESModule(
  "resource://gre/modules/Subprocess.sys.mjs"
);

const TEMP_DIR = Services.dirsvc.get("TmpD", Ci.nsIFile).path;

const screenshotPath = PathUtils.join(TEMP_DIR, "headless_test_screenshot.png");

async function runFirefox(args) {
  const XRE_EXECUTABLE_FILE = "XREExeF";
  const firefoxExe = Services.dirsvc.get(XRE_EXECUTABLE_FILE, Ci.nsIFile).path;
  const NS_APP_PREFS_50_FILE = "PrefF";
  const mochiPrefsFile = Services.dirsvc.get(NS_APP_PREFS_50_FILE, Ci.nsIFile);
  const mochiPrefsPath = mochiPrefsFile.path;
  const mochiPrefsName = mochiPrefsFile.leafName;
  const profilePath = PathUtils.join(
    TEMP_DIR,
    "headless_test_screenshot_profile"
  );
  const prefsPath = PathUtils.join(profilePath, mochiPrefsName);
  const firefoxArgs = ["-profile", profilePath, "-no-remote"];

  await IOUtils.makeDirectory(profilePath);
  await IOUtils.copy(mochiPrefsPath, prefsPath);
  let proc = await Subprocess.call({
    command: firefoxExe,
    arguments: firefoxArgs.concat(args),
    // Disable leak detection to avoid intermittent failure bug 1331152.
    environmentAppend: true,
    environment: {
      ASAN_OPTIONS:
        "detect_leaks=0:quarantine_size=50331648:malloc_context_size=5",
      // Don't enable Marionette.
      MOZ_MARIONETTE: null,
    },
  });
  let stdout;
  while ((stdout = await proc.stdout.readString())) {
    dump(`>>> ${stdout}\n`);
  }
  let { exitCode } = await proc.wait();
  is(exitCode, 0, "Firefox process should exit with code 0");
  await IOUtils.remove(profilePath, { recursive: true });
}

async function testFileCreationPositive(args, path) {
  await runFirefox(args);

  let saved = IOUtils.exists(path);
  ok(saved, "A screenshot should be saved as " + path);
  if (!saved) {
    return;
  }

  let info = await IOUtils.stat(path);
  ok(info.size > 0, "Screenshot should not be an empty file");
  await IOUtils.remove(path);
}

async function testFileCreationNegative(args, path) {
  await runFirefox(args);

  let saved = await IOUtils.exists(path);
  ok(!saved, "A screenshot should not be saved");
  await IOUtils.remove(path);
}

async function testWindowSizePositive(width, height) {
  let size = String(width);
  if (height) {
    size += "," + height;
  }

  await runFirefox([
    "-url",
    "http://mochi.test:8888/browser/browser/components/shell/test/headless.html",
    "-screenshot",
    screenshotPath,
    "-window-size",
    size,
  ]);

  let saved = await IOUtils.exists(screenshotPath);
  ok(saved, "A screenshot should be saved in the tmp directory");
  if (!saved) {
    return;
  }

  let data = await IOUtils.read(screenshotPath);
  await new Promise((resolve, reject) => {
    let blob = new Blob([data], { type: "image/png" });
    let reader = new FileReader();
    reader.onloadend = function () {
      let screenshot = new Image();
      screenshot.onload = function () {
        is(
          screenshot.width,
          width,
          "Screenshot should be " + width + " pixels wide"
        );
        if (height) {
          is(
            screenshot.height,
            height,
            "Screenshot should be " + height + " pixels tall"
          );
        }
        resolve();
      };
      screenshot.src = reader.result;
    };
    reader.readAsDataURL(blob);
  });
  await IOUtils.remove(screenshotPath);
}

async function testGreen(url, path) {
  await runFirefox(["-url", url, `--screenshot=${path}`]);

  let saved = await IOUtils.exists(path);
  ok(saved, "A screenshot should be saved in the tmp directory");
  if (!saved) {
    return;
  }

  let data = await IOUtils.read(path);
  let image = await new Promise((resolve, reject) => {
    let blob = new Blob([data], { type: "image/png" });
    let reader = new FileReader();
    reader.onloadend = function () {
      let screenshot = new Image();
      screenshot.onload = function () {
        resolve(screenshot);
      };
      screenshot.src = reader.result;
    };
    reader.readAsDataURL(blob);
  });
  let canvas = document.createElement("canvas");
  canvas.width = image.naturalWidth;
  canvas.height = image.naturalHeight;
  let ctx = canvas.getContext("2d");
  ctx.drawImage(image, 0, 0);
  let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  let rgba = imageData.data;

  let found = false;
  for (let i = 0; i < rgba.length; i += 4) {
    if (rgba[i] === 0 && rgba[i + 1] === 255 && rgba[i + 2] === 0) {
      found = true;
      break;
    }
  }
  ok(found, "There should be a green pixel in the screenshot.");

  await IOUtils.remove(path);
}