mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1169179 - Run mozscreenshots as a mochitest-browser-chrome test. r=felipe,glandium
This commit is contained in:
parent
97b9c00329
commit
244a926991
@ -26,5 +26,9 @@ DIRS += [
|
||||
if CONFIG['MAKENSISU']:
|
||||
DIRS += ['installer/windows']
|
||||
|
||||
TEST_DIRS += [
|
||||
'tools/mozscreenshots',
|
||||
]
|
||||
|
||||
DIST_SUBDIR = 'browser'
|
||||
export('DIST_SUBDIR')
|
||||
|
7
browser/tools/mozscreenshots/browser.ini
Normal file
7
browser/tools/mozscreenshots/browser.ini
Normal file
@ -0,0 +1,7 @@
|
||||
[DEFAULT]
|
||||
subsuite = screenshots
|
||||
support-files =
|
||||
head.js
|
||||
|
||||
[browser_screenshots.js]
|
||||
tags = screenshots
|
18
browser/tools/mozscreenshots/browser_screenshots.js
Normal file
18
browser/tools/mozscreenshots/browser_screenshots.js
Normal file
@ -0,0 +1,18 @@
|
||||
/* 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 env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
|
||||
|
||||
add_task(function* test() {
|
||||
let { TestRunner } = Cu.import("chrome://mozscreenshots/content/TestRunner.jsm", {});
|
||||
let sets = ["TabsInTitlebar", "Tabs", "WindowSize", "Toolbars", "LightweightThemes"];
|
||||
let setsEnv = env.get("MOZSCREENSHOTS_SETS");
|
||||
if (setsEnv) {
|
||||
sets = setsEnv.trim().split(",");
|
||||
}
|
||||
|
||||
yield TestRunner.start(sets);
|
||||
});
|
20
browser/tools/mozscreenshots/head.js
Normal file
20
browser/tools/mozscreenshots/head.js
Normal file
@ -0,0 +1,20 @@
|
||||
/* 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 {AddonWatcher} = Cu.import("resource://gre/modules/AddonWatcher.jsm", {});
|
||||
let TestRunner;
|
||||
|
||||
function setup() {
|
||||
requestLongerTimeout(10);
|
||||
|
||||
info("Checking for mozscreenshots extension");
|
||||
AddonManager.getAddonByID("mozscreenshots@mozilla.org", function(aAddon) {
|
||||
isnot(aAddon, null, "The mozscreenshots extension should be installed");
|
||||
AddonWatcher.ignoreAddonPermanently(aAddon.id);
|
||||
});
|
||||
}
|
||||
|
||||
add_task(setup);
|
11
browser/tools/mozscreenshots/moz.build
Normal file
11
browser/tools/mozscreenshots/moz.build
Normal file
@ -0,0 +1,11 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['browser.ini']
|
||||
|
||||
TEST_DIRS += [
|
||||
'mozscreenshots/extension',
|
||||
]
|
@ -0,0 +1,12 @@
|
||||
# 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/.
|
||||
|
||||
TEST_EXTENSIONS_DIR = $(DEPTH)/_tests/testing/mochitest/extensions
|
||||
GENERATED_DIRS = $(TEST_EXTENSIONS_DIR)
|
||||
XPI_PKGNAME = mozscreenshots@mozilla.org
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
(cd $(DIST)/xpi-stage && tar $(TAR_CREATE_FLAGS) - $(XPI_NAME)) | (cd $(TEST_EXTENSIONS_DIR) && tar -xf -)
|
@ -0,0 +1,175 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Screenshot"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
|
||||
// Create a new instance of the ConsoleAPI so we can control the maxLogLevel with a pref.
|
||||
// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
|
||||
const PREF_LOG_LEVEL = "extensions.mozscreenshots@mozilla.org.loglevel";
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let ConsoleAPI = Cu.import("resource://gre/modules/Console.jsm", {}).ConsoleAPI;
|
||||
let consoleOptions = {
|
||||
maxLogLevel: "info",
|
||||
maxLogLevelPref: PREF_LOG_LEVEL,
|
||||
prefix: "mozscreenshots",
|
||||
};
|
||||
return new ConsoleAPI(consoleOptions);
|
||||
});
|
||||
|
||||
let Screenshot = {
|
||||
_extensionPath: null,
|
||||
_path: null,
|
||||
_imagePrefix: "",
|
||||
_imageExtension: ".png",
|
||||
_screenshotFunction: null,
|
||||
|
||||
init(path, extensionPath, imagePrefix = "") {
|
||||
this._path = path;
|
||||
|
||||
let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
dir.initWithPath(this._path);
|
||||
if (!dir.exists()) {
|
||||
dir.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8));
|
||||
}
|
||||
|
||||
this._extensionPath = extensionPath;
|
||||
this._imagePrefix = imagePrefix;
|
||||
switch (Services.appinfo.OS) {
|
||||
case "WINNT":
|
||||
this._screenshotFunction = this._screenshotWindows;
|
||||
break;
|
||||
case "Darwin":
|
||||
this._screenshotFunction = this._screenshotOSX;
|
||||
break;
|
||||
case "Linux":
|
||||
this._screenshotFunction = this._screenshotLinux;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unsupported operating system");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_buildImagePath(baseName) {
|
||||
return OS.Path.join(this._path, this._imagePrefix + baseName + this._imageExtension);
|
||||
},
|
||||
|
||||
// Capture the whole screen using an external application.
|
||||
captureExternal(filename) {
|
||||
let imagePath = this._buildImagePath(filename);
|
||||
return this._screenshotFunction(imagePath).then(() => {
|
||||
log.debug("saved screenshot: " + filename);
|
||||
});
|
||||
},
|
||||
|
||||
///// helpers /////
|
||||
|
||||
_screenshotWindows(filename) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let exe = Services.dirsvc.get("GreBinD", Ci.nsIFile);
|
||||
exe.append("screenshot.exe");
|
||||
if (!exe.exists()) {
|
||||
exe = this._extensionPath.QueryInterface(Ci.nsIFileURL).file;
|
||||
exe.append("lib");
|
||||
exe.append("screenshot.exe");
|
||||
}
|
||||
let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
|
||||
process.init(exe);
|
||||
|
||||
let args = [filename];
|
||||
process.runAsync(args, args.length, this._processObserver(resolve, reject));
|
||||
});
|
||||
},
|
||||
|
||||
_screenshotOSX: Task.async(function*(filename) {
|
||||
let screencapture = (windowID = null) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Get the screencapture executable
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
file.initWithPath("/usr/sbin/screencapture");
|
||||
|
||||
let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
|
||||
process.init(file);
|
||||
|
||||
// Run the process.
|
||||
let args = ["-x", "-t", "png"];
|
||||
// Darwin version number for OS X 10.6 is 10.x
|
||||
if (windowID && Services.sysinfo.getProperty("version").indexOf("10.") !== 0) {
|
||||
// Capture only that window on 10.7+
|
||||
args.push("-l");
|
||||
args.push(windowID);
|
||||
}
|
||||
args.push(filename);
|
||||
process.runAsync(args, args.length, this._processObserver(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
function readWindowID() {
|
||||
let decoder = new TextDecoder();
|
||||
let promise = OS.File.read("/tmp/mozscreenshots-windowid");
|
||||
return promise.then(function onSuccess(array) {
|
||||
return decoder.decode(array);
|
||||
});
|
||||
}
|
||||
|
||||
let promiseWindowID = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Get the window ID of the application (assuming its front-most)
|
||||
let osascript = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
osascript.initWithPath("/bin/bash");
|
||||
|
||||
let osascriptP = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
|
||||
osascriptP.init(osascript);
|
||||
let osaArgs = ["-c", "/usr/bin/osascript -e 'tell application (path to frontmost application as text) to set winID to id of window 1' > /tmp/mozscreenshots-windowid"];
|
||||
osascriptP.runAsync(osaArgs, osaArgs.length, this._processObserver(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
yield promiseWindowID();
|
||||
let windowID = yield readWindowID();
|
||||
yield screencapture(windowID);
|
||||
}),
|
||||
|
||||
_screenshotLinux(filename) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let file = Services.dirsvc.get("GreBinD", Ci.nsIFile);
|
||||
file.append("screentopng");
|
||||
let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
|
||||
process.init(file);
|
||||
|
||||
let args = [filename];
|
||||
process.runAsync(args, args.length, this._processObserver(resolve, reject));
|
||||
});
|
||||
},
|
||||
|
||||
_processObserver(resolve, reject) {
|
||||
return {
|
||||
observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "process-finished":
|
||||
try {
|
||||
// Wait 1s after process to resolve
|
||||
setTimeout(resolve, 1000);
|
||||
} catch (ex) {
|
||||
reject(ex);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reject(topic);
|
||||
break;
|
||||
};
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
@ -0,0 +1,256 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["TestRunner"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
const defaultSetNames = ["TabsInTitlebar", "Tabs", "WindowSize", "Toolbars", "LightweightThemes"];
|
||||
const env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
|
||||
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
Cu.import("chrome://mozscreenshots/content/Screenshot.jsm");
|
||||
|
||||
// Create a new instance of the ConsoleAPI so we can control the maxLogLevel with a pref.
|
||||
// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
|
||||
const PREF_LOG_LEVEL = "extensions.mozscreenshots@mozilla.org.loglevel";
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let ConsoleAPI = Cu.import("resource://gre/modules/Console.jsm", {}).ConsoleAPI;
|
||||
let consoleOptions = {
|
||||
maxLogLevel: "info",
|
||||
maxLogLevelPref: PREF_LOG_LEVEL,
|
||||
prefix: "mozscreenshots",
|
||||
};
|
||||
return new ConsoleAPI(consoleOptions);
|
||||
});
|
||||
|
||||
this.TestRunner = {
|
||||
combos: null,
|
||||
completedCombos: 0,
|
||||
currentComboIndex: 0,
|
||||
_lastCombo: null,
|
||||
_libDir: null,
|
||||
|
||||
init(extensionPath) {
|
||||
let subDirs = ["mozscreenshots",
|
||||
(new Date()).toISOString().replace(/:/g, "-") + "_" + Services.appinfo.OS];
|
||||
let screenshotPath = FileUtils.getFile("TmpD", subDirs).path;
|
||||
|
||||
const MOZ_UPLOAD_DIR = env.get("MOZ_UPLOAD_DIR");
|
||||
if (MOZ_UPLOAD_DIR) {
|
||||
screenshotPath = MOZ_UPLOAD_DIR;
|
||||
}
|
||||
|
||||
log.info("Saving screenshots to:", screenshotPath);
|
||||
log.debug("TestRunner.init");
|
||||
|
||||
let screenshotPrefix = Services.appinfo.appBuildID + "_";
|
||||
Screenshot.init(screenshotPath, extensionPath, screenshotPrefix);
|
||||
this._libDir = extensionPath.QueryInterface(Ci.nsIFileURL).file.clone();
|
||||
this._libDir.append("chrome");
|
||||
this._libDir.append("mozscreenshots");
|
||||
this._libDir.append("lib");
|
||||
|
||||
// Setup some prefs
|
||||
Services.prefs.setCharPref("browser.aboutHomeSnippets.updateUrl", "data:");
|
||||
Services.prefs.setCharPref("extensions.ui.lastCategory", "addons://list/extension");
|
||||
// Don't let the caret blink since it causes false positives for image diffs
|
||||
Services.prefs.setIntPref("ui.caretBlinkTime", -1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Load specified sets, execute all combinations of them, and capture screenshots.
|
||||
*/
|
||||
start(setNames = null) {
|
||||
setNames = setNames || defaultSetNames;
|
||||
let sets = this.loadSets(setNames);
|
||||
|
||||
log.info(sets.length + " sets:", setNames);
|
||||
this.combos = new LazyProduct(sets);
|
||||
log.info(this.combos.length + " combinations");
|
||||
|
||||
this.currentComboIndex = this.completedCombos = 0;
|
||||
this._lastCombo = null;
|
||||
|
||||
return Task.spawn(function* doStart() {
|
||||
for (let i = 0; i < this.combos.length;
|
||||
i++){
|
||||
this.currentComboIndex = i;
|
||||
yield* this._performCombo(this.combos.item(this.currentComboIndex));
|
||||
}
|
||||
|
||||
log.info("Done: Completed " + this.completedCombos + " out of " +
|
||||
this.combos.length + " configurations.");
|
||||
this.cleanup();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Load sets of configurations from JSMs.
|
||||
* @param {String[]} setNames - array of set names (e.g. ["Tabs", "WindowSize"].
|
||||
* @return {Object[]} Array of sets containing `name` and `configurations` properties.
|
||||
*/
|
||||
loadSets(setNames) {
|
||||
let sets = [];
|
||||
for (let setName of setNames) {
|
||||
try {
|
||||
let imported = {};
|
||||
Cu.import("chrome://mozscreenshots/content/configurations/" + setName + ".jsm",
|
||||
imported);
|
||||
imported[setName].init(this._libDir);
|
||||
let configurationNames = Object.keys(imported[setName].configurations);
|
||||
if (!configurationNames.length) {
|
||||
throw new Error(setName + " has no configurations for this environment");
|
||||
}
|
||||
for (let config of configurationNames) {
|
||||
// Automatically set the name property of the configuration object to
|
||||
// its name from the configuration object.
|
||||
imported[setName].configurations[config].name = config;
|
||||
}
|
||||
sets.push(imported[setName].configurations);
|
||||
} catch (ex) {
|
||||
log.error("Error loading set: " + setName);
|
||||
log.error(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
return sets;
|
||||
},
|
||||
|
||||
cleanup() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let gBrowser = browserWindow.gBrowser;
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
}
|
||||
gBrowser.unpinTab(gBrowser.selectedTab);
|
||||
gBrowser.selectedBrowser.loadURI("data:text/html;charset=utf-8,<h1>Done!");
|
||||
browserWindow.restore();
|
||||
},
|
||||
|
||||
///// helpers /////
|
||||
|
||||
_performCombo: function*(combo) {
|
||||
let paddedComboIndex = padLeft(this.currentComboIndex + 1, String(this.combos.length).length);
|
||||
log.info("Combination " + paddedComboIndex + "/" + this.combos.length + ": " +
|
||||
this._comboName(combo).substring(1));
|
||||
|
||||
function changeConfig(config) {
|
||||
log.debug("calling " + config.name);
|
||||
let promise = config.applyConfig();
|
||||
log.debug("called " + config.name);
|
||||
return promise;
|
||||
}
|
||||
|
||||
try {
|
||||
// First go through and actually apply all of the configs
|
||||
for (let i = 0; i < combo.length; i++) {
|
||||
let config = combo[i];
|
||||
if (!this._lastCombo || config !== this._lastCombo[i]) {
|
||||
log.debug("promising", config.name);
|
||||
yield changeConfig(config);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the lastCombo since it's now been applied regardless of whether it's accepted below.
|
||||
log.debug("fulfilled all applyConfig so setting lastCombo.");
|
||||
this._lastCombo = combo;
|
||||
|
||||
// Then ask configs if the current setup is valid. We can't can do this in
|
||||
// the applyConfig methods of the config since it doesn't know what configs
|
||||
// later in the loop will do that may invalidate the combo.
|
||||
for (let i = 0; i < combo.length; i++) {
|
||||
let config = combo[i];
|
||||
// A configuration can specify an optional verifyConfig method to indicate
|
||||
// if the current config is valid for a screenshot. This gets called even
|
||||
// if the this config was used in the lastCombo since another config may
|
||||
// have invalidated it.
|
||||
if (config.verifyConfig) {
|
||||
log.debug("checking if the combo is valid with", config.name);
|
||||
yield config.verifyConfig();
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
log.warn("\tskipped configuration: " + ex);
|
||||
// Don't set lastCombo here so that we properly know which configurations
|
||||
// need to be applied since the last screenshot
|
||||
|
||||
// Return so we don't take a screenshot.
|
||||
return;
|
||||
}
|
||||
|
||||
yield this._onConfigurationReady(combo);
|
||||
},
|
||||
|
||||
_onConfigurationReady(combo) {
|
||||
let delayedScreenshot = () => {
|
||||
let filename = padLeft(this.currentComboIndex + 1,
|
||||
String(this.combos.length).length) + this._comboName(combo);
|
||||
return Screenshot.captureExternal(filename)
|
||||
.then(() => {
|
||||
this.completedCombos++;
|
||||
});
|
||||
};
|
||||
|
||||
log.debug("_onConfigurationReady");
|
||||
return Task.spawn(delayedScreenshot);
|
||||
},
|
||||
|
||||
_comboName(combo) {
|
||||
return combo.reduce(function(a, b) {
|
||||
return a + "_" + b.name;
|
||||
}, "");
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper to lazily compute the Cartesian product of all of the sets of configurations.
|
||||
**/
|
||||
function LazyProduct(sets) {
|
||||
/**
|
||||
* An entry for each set with the value being:
|
||||
* [the number of permutations of the sets with lower index,
|
||||
* the number of items in the set at the index]
|
||||
*/
|
||||
this.sets = sets;
|
||||
this.lookupTable = [];
|
||||
let combinations = 1;
|
||||
for (let i = this.sets.length - 1; i >= 0; i--) {
|
||||
let set = this.sets[i];
|
||||
let setLength = Object.keys(set).length;
|
||||
this.lookupTable[i] = [combinations, setLength];
|
||||
combinations *= setLength;
|
||||
}
|
||||
}
|
||||
LazyProduct.prototype = {
|
||||
get length() {
|
||||
let last = this.lookupTable[0];
|
||||
if (!last)
|
||||
return 0;
|
||||
return last[0] * last[1];
|
||||
},
|
||||
|
||||
item(n) {
|
||||
// For set i, get the item from the set with the floored value of
|
||||
// (n / the number of permutations of the sets already chosen from) modulo the length of set i
|
||||
let result = [];
|
||||
for (let i = this.sets.length - 1; i >= 0; i--) {
|
||||
let priorCombinations = this.lookupTable[i][0];
|
||||
let setLength = this.lookupTable[i][1];
|
||||
let keyIndex = Math.floor(n / priorCombinations) % setLength;
|
||||
let keys = Object.keys(this.sets[i]);
|
||||
result[i] = this.sets[i][keys[keyIndex]];
|
||||
}
|
||||
return result;
|
||||
},
|
||||
};
|
||||
|
||||
function padLeft(number, width, padding = "0") {
|
||||
return padding.repeat(Math.max(0, width - String(number).length)) + number;
|
||||
}
|
72
browser/tools/mozscreenshots/mozscreenshots/extension/bootstrap.js
vendored
Normal file
72
browser/tools/mozscreenshots/mozscreenshots/extension/bootstrap.js
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
/* 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/. */
|
||||
/*
|
||||
#if 0
|
||||
Workaround a build system bug where this file doesn't get packaged if not pre-processed.
|
||||
#endif
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
const env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/AddonManager.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TestRunner",
|
||||
"chrome://mozscreenshots/content/TestRunner.jsm");
|
||||
|
||||
function install(data, reason) {
|
||||
if (!isAppSupported()) {
|
||||
uninstallExtension(data);
|
||||
return;
|
||||
}
|
||||
|
||||
AddonManager.getAddonByID(data.id, function(addon) {
|
||||
// Enable on install in case the user disabled a prior version
|
||||
if (addon) {
|
||||
addon.userDisabled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function startup(data, reason) {
|
||||
if (!isAppSupported()) {
|
||||
uninstallExtension(data);
|
||||
return;
|
||||
}
|
||||
|
||||
AddonManager.getAddonByID(data.id, function(addon) {
|
||||
let extensionPath = addon.getResourceURI();
|
||||
TestRunner.init(extensionPath);
|
||||
});
|
||||
}
|
||||
|
||||
function shutdown(data, reason) { }
|
||||
|
||||
function uninstall(data, reason) { }
|
||||
|
||||
/**
|
||||
* @return boolean whether the test suite applies to the application.
|
||||
*/
|
||||
function isAppSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function uninstallExtension(data) {
|
||||
AddonManager.getAddonByID(data.id, function(addon) {
|
||||
addon.uninstall();
|
||||
});
|
||||
}
|
||||
|
||||
function startRun() {
|
||||
let env = Cc["@mozilla.org/process/environment;1"]
|
||||
.getService(Ci.nsIEnvironment);
|
||||
let setsEnv = env.get("MOZSCREENSHOTS_SETS");
|
||||
let sets = setsEnv ? setsEnv.split(",") : null;
|
||||
TestRunner.start(sets);
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["AppMenu"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
this.AppMenu = {
|
||||
|
||||
init(libDir) {},
|
||||
|
||||
configurations: {
|
||||
appMenuClosed: {
|
||||
applyConfig: Task.async(function*() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browserWindow.PanelUI.hide();
|
||||
}),
|
||||
},
|
||||
|
||||
appMenuMainView: {
|
||||
applyConfig() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let promise = browserWindow.PanelUI.show();
|
||||
browserWindow.PanelUI.showMainView();
|
||||
return promise;
|
||||
},
|
||||
},
|
||||
|
||||
appMenuHistorySubview: {
|
||||
applyConfig() {
|
||||
// History has a footer
|
||||
if (isCustomizing()) {
|
||||
return Promise.reject("Can't show subviews while customizing");
|
||||
}
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let promise = browserWindow.PanelUI.show();
|
||||
return promise.then(() => {
|
||||
browserWindow.PanelUI.showMainView();
|
||||
browserWindow.document.getElementById("history-panelmenu").click();
|
||||
});
|
||||
},
|
||||
|
||||
verifyConfig: verifyConfigHelper,
|
||||
},
|
||||
|
||||
appMenuHelpSubview: {
|
||||
applyConfig() {
|
||||
if (isCustomizing()) {
|
||||
return Promise.reject("Can't show subviews while customizing");
|
||||
}
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let promise = browserWindow.PanelUI.show();
|
||||
return promise.then(() => {
|
||||
browserWindow.PanelUI.showMainView();
|
||||
browserWindow.document.getElementById("PanelUI-help").click();
|
||||
});
|
||||
},
|
||||
|
||||
verifyConfig: verifyConfigHelper,
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
function verifyConfigHelper() {
|
||||
if (isCustomizing()) {
|
||||
return Promise.reject("AppMenu verifyConfigHelper");
|
||||
}
|
||||
return Promise.resolve("AppMenu verifyConfigHelper");
|
||||
}
|
||||
|
||||
function isCustomizing() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (browserWindow.document.documentElement.hasAttribute("customizing")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Buttons"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource:///modules/CustomizableUI.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
this.Buttons = {
|
||||
|
||||
init(libDir) {
|
||||
createWidget();
|
||||
},
|
||||
|
||||
configurations: {
|
||||
navBarButtons: {
|
||||
applyConfig: Task.async(() =>{
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
CustomizableUI.addWidgetToArea("screenshot-widget", CustomizableUI.AREA_NAVBAR);
|
||||
}),
|
||||
},
|
||||
|
||||
tabsToolbarButtons: {
|
||||
applyConfig: Task.async(() => {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
CustomizableUI.addWidgetToArea("screenshot-widget", CustomizableUI.AREA_TABSTRIP);
|
||||
}),
|
||||
},
|
||||
|
||||
menuPanelButtons: {
|
||||
applyConfig: Task.async(() => {
|
||||
CustomizableUI.addWidgetToArea("screenshot-widget", CustomizableUI.AREA_PANEL);
|
||||
}),
|
||||
|
||||
verifyConfig() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (browserWindow.PanelUI.panel.state == "closed") {
|
||||
return Promise.reject("The button isn't shown when the panel isn't open.");
|
||||
}
|
||||
return Promise.resolve("menuPanelButtons.verifyConfig");
|
||||
},
|
||||
},
|
||||
|
||||
custPaletteButtons: {
|
||||
applyConfig: Task.async(() => {
|
||||
CustomizableUI.removeWidgetFromArea("screenshot-widget");
|
||||
}),
|
||||
|
||||
verifyConfig() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (browserWindow.document.documentElement.getAttribute("customizing") != "true") {
|
||||
return Promise.reject("The button isn't shown when we're not in customize mode.");
|
||||
}
|
||||
return Promise.resolve("custPaletteButtons.verifyConfig");
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function createWidget() {
|
||||
let id = "screenshot-widget";
|
||||
let spec = {
|
||||
id: id,
|
||||
label: "My Button",
|
||||
removable: true,
|
||||
tooltiptext: "",
|
||||
type: "button",
|
||||
};
|
||||
CustomizableUI.createWidget(spec);
|
||||
|
||||
// Append a <style> for the image
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let st = browserWindow.document.createElementNS("http://www.w3.org/1999/xhtml", "style");
|
||||
let styles = "" +
|
||||
"#screenshot-widget > .toolbarbutton-icon {" +
|
||||
" list-style-image: url(chrome://browser/skin/Toolbar.png);" +
|
||||
" -moz-image-region: rect(0px, 18px, 18px, 0px);" +
|
||||
"}";
|
||||
st.appendChild(browserWindow.document.createTextNode(styles));
|
||||
browserWindow.document.documentElement.appendChild(st);
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["CustomizeMode"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
this.CustomizeMode = {
|
||||
|
||||
init(libDir) {},
|
||||
|
||||
configurations: {
|
||||
notCustomizing: {
|
||||
applyConfig() {
|
||||
return new Promise((resolve) => {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (!browserWindow.document.documentElement.hasAttribute("customizing")) {
|
||||
resolve("notCustomizing: already not customizing");
|
||||
return;
|
||||
}
|
||||
function onCustomizationEnds() {
|
||||
browserWindow.gNavToolbox.removeEventListener("aftercustomization",
|
||||
onCustomizationEnds);
|
||||
// Wait for final changes
|
||||
setTimeout(() => resolve("notCustomizing: onCustomizationEnds"), 500);
|
||||
}
|
||||
browserWindow.gNavToolbox.addEventListener("aftercustomization",
|
||||
onCustomizationEnds);
|
||||
browserWindow.gCustomizeMode.exit();
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
customizing: {
|
||||
applyConfig() {
|
||||
return new Promise((resolve) => {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (browserWindow.document.documentElement.hasAttribute("customizing")) {
|
||||
resolve("customizing: already customizing");
|
||||
return;
|
||||
}
|
||||
function onCustomizing() {
|
||||
browserWindow.gNavToolbox.removeEventListener("customizationready",
|
||||
onCustomizing);
|
||||
// Wait for final changes
|
||||
setTimeout(() => resolve("customizing: onCustomizing"), 500);
|
||||
}
|
||||
browserWindow.gNavToolbox.addEventListener("customizationready",
|
||||
onCustomizing);
|
||||
browserWindow.gCustomizeMode.enter();
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
@ -0,0 +1,42 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["DevEdition"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
const THEME_ID = "firefox-devedition@mozilla.org";
|
||||
|
||||
Cu.import("resource://gre/modules/LightweightThemeManager.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
this.DevEdition = {
|
||||
init(libDir) {},
|
||||
|
||||
configurations: {
|
||||
devEditionLight: {
|
||||
applyConfig: Task.async(() => {
|
||||
Services.prefs.setCharPref("devtools.theme", "light");
|
||||
LightweightThemeManager.currentTheme = LightweightThemeManager.getUsedTheme(THEME_ID);
|
||||
Services.prefs.setBoolPref("browser.devedition.theme.showCustomizeButton", true);
|
||||
}),
|
||||
},
|
||||
devEditionDark: {
|
||||
applyConfig: Task.async(() => {
|
||||
Services.prefs.setCharPref("devtools.theme", "dark");
|
||||
LightweightThemeManager.currentTheme = LightweightThemeManager.getUsedTheme(THEME_ID);
|
||||
Services.prefs.setBoolPref("browser.devedition.theme.showCustomizeButton", true);
|
||||
}),
|
||||
},
|
||||
devEditionOff: {
|
||||
applyConfig: Task.async(() => {
|
||||
Services.prefs.clearUserPref("devtools.theme");
|
||||
LightweightThemeManager.currentTheme = null;
|
||||
Services.prefs.clearUserPref("browser.devedition.theme.showCustomizeButton");
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
@ -0,0 +1,50 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["DevTools"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://devtools/client/framework/gDevTools.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let TargetFactory = devtools.TargetFactory;
|
||||
|
||||
function getTargetForSelectedTab() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let target = TargetFactory.forTab(browserWindow.gBrowser.selectedTab);
|
||||
return target;
|
||||
}
|
||||
|
||||
this.DevTools = {
|
||||
init(libDir) {
|
||||
let panels = ["options", "webconsole", "inspector", "jsdebugger", "netmonitor"];
|
||||
panels.forEach(panel => {
|
||||
this.configurations[panel] = {};
|
||||
this.configurations[panel].applyConfig = () => {
|
||||
return gDevTools.showToolbox(getTargetForSelectedTab(), panel, "bottom");
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
configurations: {
|
||||
bottomToolbox: {
|
||||
applyConfig() {
|
||||
return gDevTools.showToolbox(getTargetForSelectedTab(), "inspector", "bottom");
|
||||
},
|
||||
},
|
||||
sideToolbox: {
|
||||
applyConfig() {
|
||||
return gDevTools.showToolbox(getTargetForSelectedTab(), "inspector", "side");
|
||||
},
|
||||
},
|
||||
undockedToolbox: {
|
||||
applyConfig() {
|
||||
return gDevTools.showToolbox(getTargetForSelectedTab(), "inspector", "window");
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
@ -0,0 +1,92 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["LightweightThemes"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/LightweightThemeManager.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
this.LightweightThemes = {
|
||||
init(libDir) {
|
||||
// convert -size 3000x200 canvas:black black_theme.png
|
||||
let blackImage = libDir.clone();
|
||||
blackImage.append("black_theme.png");
|
||||
this._blackImageURL = Services.io.newFileURI(blackImage).spec;
|
||||
|
||||
// convert -size 3000x200 canvas:white white_theme.png
|
||||
let whiteImage = libDir.clone();
|
||||
whiteImage.append("white_theme.png");
|
||||
this._whiteImageURL = Services.io.newFileURI(whiteImage).spec;
|
||||
},
|
||||
|
||||
configurations: {
|
||||
noLWT: {
|
||||
applyConfig: Task.async(function*() {
|
||||
LightweightThemeManager.currentTheme = null;
|
||||
}),
|
||||
},
|
||||
|
||||
darkLWT: {
|
||||
applyConfig() {
|
||||
LightweightThemeManager.setLocalTheme({
|
||||
id: "black",
|
||||
name: "black",
|
||||
headerURL: LightweightThemes._blackImageURL,
|
||||
footerURL: LightweightThemes._blackImageURL,
|
||||
textcolor: "#ffffff",
|
||||
accentcolor: "#111111",
|
||||
});
|
||||
|
||||
// Wait for LWT listener
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve("darkLWT");
|
||||
}, 500);
|
||||
});
|
||||
},
|
||||
|
||||
verifyConfig: verifyConfigHelper,
|
||||
},
|
||||
|
||||
lightLWT: {
|
||||
applyConfig() {
|
||||
LightweightThemeManager.setLocalTheme({
|
||||
id: "white",
|
||||
name: "white",
|
||||
headerURL: LightweightThemes._whiteImageURL,
|
||||
footerURL: LightweightThemes._whiteImageURL,
|
||||
textcolor: "#000000",
|
||||
accentcolor: "#eeeeee",
|
||||
});
|
||||
// Wait for LWT listener
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve("lightLWT");
|
||||
}, 500);
|
||||
});
|
||||
},
|
||||
|
||||
verifyConfig: verifyConfigHelper,
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
function verifyConfigHelper() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (browserWindow.document.documentElement.hasAttribute("lwtheme")) {
|
||||
resolve("verifyConfigHelper");
|
||||
} else {
|
||||
reject("The @lwtheme attribute wasn't present so themes may not be available");
|
||||
}
|
||||
});
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Preferences"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
this.Preferences = {
|
||||
|
||||
init(libDir) {
|
||||
Services.prefs.setBoolPref("browser.preferences.inContent", true);
|
||||
|
||||
let panes = [
|
||||
["paneGeneral", null],
|
||||
["paneSearch", null],
|
||||
["paneContent", null],
|
||||
["paneApplications", null],
|
||||
["panePrivacy", null],
|
||||
["paneSecurity", null],
|
||||
["paneSync", null],
|
||||
["paneAdvanced", "generalTab"],
|
||||
["paneAdvanced", "dataChoicesTab"],
|
||||
["paneAdvanced", "networkTab"],
|
||||
["paneAdvanced", "updateTab"],
|
||||
["paneAdvanced", "encryptionTab"],
|
||||
];
|
||||
for (let [primary, advanced] of panes) {
|
||||
let configName = primary + ("-" + advanced || "");
|
||||
this.configurations[configName] = {};
|
||||
this.configurations[configName].applyConfig = prefHelper.bind(null, primary, advanced);
|
||||
}
|
||||
},
|
||||
|
||||
configurations: {},
|
||||
};
|
||||
|
||||
function prefHelper(primary, advanced) {
|
||||
return new Promise((resolve) => {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (primary == "paneAdvanced") {
|
||||
browserWindow.openAdvancedPreferences(advanced);
|
||||
} else {
|
||||
browserWindow.openPreferences(primary);
|
||||
}
|
||||
setTimeout(resolve, 50);
|
||||
});
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Tabs"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
const CUST_TAB = "chrome://browser/skin/customizableui/customizeFavicon.ico";
|
||||
const PREFS_TAB = "chrome://browser/skin/preferences/in-content/favicon.ico";
|
||||
const DEFAULT_FAVICON_TAB = `data:text/html,<meta charset="utf-8">
|
||||
<title>No favicon</title>`;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
this.Tabs = {
|
||||
init(libDir) {},
|
||||
|
||||
configurations: {
|
||||
fiveTabs: {
|
||||
applyConfig: Task.async(function*() {
|
||||
fiveTabsHelper();
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
hoverTab(browserWindow.gBrowser.tabs[3]);
|
||||
}),
|
||||
},
|
||||
|
||||
fourPinned: {
|
||||
applyConfig: Task.async(function*() {
|
||||
fiveTabsHelper();
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let tab = browserWindow.gBrowser.addTab(PREFS_TAB);
|
||||
browserWindow.gBrowser.pinTab(tab);
|
||||
tab = browserWindow.gBrowser.addTab(CUST_TAB);
|
||||
browserWindow.gBrowser.pinTab(tab);
|
||||
tab = browserWindow.gBrowser.addTab("about:privatebrowsing");
|
||||
browserWindow.gBrowser.pinTab(tab);
|
||||
tab = browserWindow.gBrowser.addTab("about:home");
|
||||
browserWindow.gBrowser.pinTab(tab);
|
||||
browserWindow.gBrowser.selectTabAtIndex(5);
|
||||
hoverTab(browserWindow.gBrowser.tabs[2]);
|
||||
// also hover the new tab button
|
||||
let newTabButton = browserWindow.document.getAnonymousElementByAttribute(browserWindow.
|
||||
gBrowser.tabContainer, "class", "tabs-newtab-button");
|
||||
hoverTab(newTabButton);
|
||||
browserWindow.gBrowser.tabs[browserWindow.gBrowser.tabs.length - 1].
|
||||
setAttribute("beforehovered", true);
|
||||
}),
|
||||
},
|
||||
|
||||
twoPinnedWithOverflow: {
|
||||
applyConfig: Task.async(function*() {
|
||||
fiveTabsHelper();
|
||||
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browserWindow.gBrowser.loadTabs([
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
], true, true);
|
||||
let tab = browserWindow.gBrowser.addTab(PREFS_TAB);
|
||||
browserWindow.gBrowser.pinTab(tab);
|
||||
tab = browserWindow.gBrowser.addTab(CUST_TAB);
|
||||
browserWindow.gBrowser.pinTab(tab);
|
||||
browserWindow.gBrowser.selectTabAtIndex(4);
|
||||
hoverTab(browserWindow.gBrowser.tabs[6]);
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/* helpers */
|
||||
|
||||
function fiveTabsHelper() {
|
||||
// some with no favicon and some with. Selected tab in middle.
|
||||
closeAllButOneTab("about:addons");
|
||||
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browserWindow.gBrowser.loadTabs([
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
CUST_TAB,
|
||||
], true, true);
|
||||
browserWindow.gBrowser.selectTabAtIndex(1);
|
||||
}
|
||||
|
||||
function closeAllButOneTab(url = "about:blank") {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let gBrowser = browserWindow.gBrowser;
|
||||
// Close all tabs except the last so we don't quit the browser.
|
||||
while (gBrowser.tabs.length > 1)
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
gBrowser.selectedBrowser.loadURI(url);
|
||||
if (gBrowser.selectedTab.pinned)
|
||||
gBrowser.unpinTab(gBrowser.selectedTab);
|
||||
let newTabButton = browserWindow.document.getAnonymousElementByAttribute(browserWindow.gBrowser.tabContainer, "class", "tabs-newtab-button");
|
||||
hoverTab(newTabButton, false);
|
||||
}
|
||||
|
||||
function hoverTab(tab, hover = true) {
|
||||
const inIDOMUtils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||
if (hover) {
|
||||
inIDOMUtils.addPseudoClassLock(tab, ":hover");
|
||||
} else {
|
||||
inIDOMUtils.clearPseudoClassLocks(tab);
|
||||
}
|
||||
// XXX TODO: this isn't necessarily testing what we ship
|
||||
if (tab.nextElementSibling)
|
||||
tab.nextElementSibling.setAttribute("afterhovered", hover || null);
|
||||
if (tab.previousElementSibling)
|
||||
tab.previousElementSibling.setAttribute("beforehovered", hover || null);
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["TabsInTitlebar"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
const PREF_TABS_IN_TITLEBAR = "browser.tabs.drawInTitlebar";
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
this.TabsInTitlebar = {
|
||||
|
||||
init(libDir) {},
|
||||
|
||||
configurations: {
|
||||
tabsInTitlebar: {
|
||||
applyConfig: Task.async(function*() {
|
||||
if (Services.appinfo.OS == "Linux") {
|
||||
return Promise.reject("TabsInTitlebar isn't supported on Linux");
|
||||
}
|
||||
Services.prefs.setBoolPref(PREF_TABS_IN_TITLEBAR, true);
|
||||
}),
|
||||
},
|
||||
|
||||
tabsOutsideTitlebar: {
|
||||
applyConfig: Task.async(function*() {
|
||||
Services.prefs.setBoolPref(PREF_TABS_IN_TITLEBAR, false);
|
||||
}),
|
||||
},
|
||||
|
||||
},
|
||||
};
|
@ -0,0 +1,56 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Toolbars"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
this.Toolbars = {
|
||||
init(libDir) {},
|
||||
|
||||
configurations: {
|
||||
onlyNavBar: {
|
||||
applyConfig: Task.async(function*() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let personalToolbar = browserWindow.document.getElementById("PersonalToolbar");
|
||||
browserWindow.setToolbarVisibility(personalToolbar, false);
|
||||
toggleMenubarIfNecessary(false);
|
||||
}),
|
||||
},
|
||||
|
||||
allToolbars: {
|
||||
applyConfig: Task.async(function*() { // Boookmarks and menubar
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let personalToolbar = browserWindow.document.getElementById("PersonalToolbar");
|
||||
browserWindow.setToolbarVisibility(personalToolbar, true);
|
||||
toggleMenubarIfNecessary(true);
|
||||
}),
|
||||
|
||||
verifyConfig: Task.async(function*() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (browserWindow.fullScreen) {
|
||||
return Promise.reject("The bookmark toolbar and menubar are not shown in fullscreen.");
|
||||
}
|
||||
}),
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
///// helpers /////
|
||||
|
||||
function toggleMenubarIfNecessary(visible) {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
// The menubar is not shown on OS X or while in fullScreen
|
||||
if (Services.appinfo.OS != "Darwin" /*&& !browserWindow.fullScreen*/) {
|
||||
let menubar = browserWindow.document.getElementById("toolbar-menubar");
|
||||
browserWindow.setToolbarVisibility(menubar, visible);
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["WindowSize"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
this.WindowSize = {
|
||||
|
||||
init(libDir) {
|
||||
Services.prefs.setBoolPref("browser.fullscreen.autohide", false);
|
||||
},
|
||||
|
||||
configurations: {
|
||||
maximized: {
|
||||
applyConfig: Task.async(function*() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browserWindow.fullScreen = false;
|
||||
|
||||
// Wait for the Lion fullscreen transition to end as there doesn't seem to be an event
|
||||
// and trying to maximize while still leaving fullscreen doesn't work.
|
||||
yield new Promise((resolve, reject) => {
|
||||
setTimeout(function waitToLeaveFS() {
|
||||
browserWindow.maximize();
|
||||
resolve();
|
||||
}, Services.appinfo.OS == "Darwin" ? 1500 : 0);
|
||||
});
|
||||
}),
|
||||
},
|
||||
|
||||
normal: {
|
||||
applyConfig: Task.async(() => {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browserWindow.fullScreen = false;
|
||||
browserWindow.restore();
|
||||
}),
|
||||
},
|
||||
|
||||
fullScreen: {
|
||||
applyConfig: Task.async(function*() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browserWindow.fullScreen = true;
|
||||
// OS X Lion fullscreen transition takes a while
|
||||
yield new Promise((resolve, reject) => {
|
||||
setTimeout(function waitAfterEnteringFS() {
|
||||
resolve();
|
||||
}, Services.appinfo.OS == "Darwin" ? 1500 : 0);
|
||||
});
|
||||
}),
|
||||
},
|
||||
|
||||
},
|
||||
};
|
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>mozscreenshots@mozilla.org</em:id>
|
||||
#expand <em:version>__MOZILLA_VERSION_U__</em:version>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
|
||||
<!-- for running custom screenshot binaries -->
|
||||
<em:unpack>true</em:unpack>
|
||||
|
||||
<!-- Front End MetaData -->
|
||||
<em:name>mozscreenshots</em:name>
|
||||
<em:description>Take screenshots of Mozilla applications in various UI configurations.</em:description>
|
||||
<em:creator>Mozilla</em:creator>
|
||||
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<!-- Firefox -->
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||
#expand <em:minVersion>__MOZILLA_VERSION_U__</em:minVersion>
|
||||
<em:maxVersion>*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
|
||||
</Description>
|
||||
</RDF>
|
@ -0,0 +1,6 @@
|
||||
mozscreenshots.jar:
|
||||
% content mozscreenshots chrome/mozscreenshots/
|
||||
Screenshot.jsm
|
||||
TestRunner.jsm
|
||||
configurations/ (configurations/*.jsm)
|
||||
lib/ (lib/*.png)
|
Binary file not shown.
After Width: | Height: | Size: 343 B |
Binary file not shown.
After Width: | Height: | Size: 522 B |
@ -0,0 +1,17 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
XPI_NAME = 'mozscreenshots'
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
USE_EXTENSION_MANIFEST = True
|
||||
NO_JS_MANIFEST = True
|
||||
|
||||
FINAL_TARGET_PP_FILES += [
|
||||
'bootstrap.js',
|
||||
'install.rdf',
|
||||
]
|
Loading…
Reference in New Issue
Block a user