new file mode 100644
--- /dev/null
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/SystemTheme.jsm
@@ -0,0 +1,238 @@
+/* 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 = [ "SystemTheme" ];
+
+ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+
+ Cu.import("resource://gre/modules/Services.jsm");
+ Cu.import("resource://gre/modules/ctypes.jsm");
+ Cu.import("resource://gre/modules/Timer.jsm");
+ Cu.import("resource://gre/modules/Console.jsm");
+ Cu.import("resource://gre/modules/AppConstants.jsm")
+ Cu.import("resource://testing-common/TestUtils.jsm");
+
+ let SystemTheme = {
+ _libDir: null,
+ configurations: {},
+
+ init(libDir) {
+ this._libDir = libDir;
+
+ if (Services.appinfo.OS === "WINNT") {
+ Cu.import("resource://gre/modules/WindowsRegistry.jsm")
+ let env = Cc["@mozilla.org/process/environment;1"]
+ .getService(Ci.nsIEnvironment);
+ let resourcesDir = env.get("SystemRoot") + "\\Resources";
+ let winVersion = getWindowsVersion();
+ let currentThemePath = getCurrentThemePath();
+
+ if (winVersion.majorVersion == 10) { // Windows 10
+ this.configurations = {
+ highContrast1: {
+ selectors: [":root"],
+ async applyConfig() {
+ await SystemTheme._changeWindowsTheme(resourcesDir + "\\Ease of Access Themes\\hc1.theme");
+ }
+ },
+ highContrast2: {
+ selectors: [":root"],
+ async applyConfig() {
+ await SystemTheme._changeWindowsTheme(resourcesDir + "\\Ease of Access Themes\\hc2.theme");
+ }
+ },
+ highContrastBlack: {
+ selectors: [":root"],
+ async applyConfig() {
+ await SystemTheme._changeWindowsTheme(resourcesDir + "\\Ease of Access Themes\\hcblack.theme");
+ }
+ },
+ highContrastWhite: {
+ selectors: [":root"],
+ async applyConfig() {
+ await SystemTheme._changeWindowsTheme(resourcesDir + "\\Ease of Access Themes\\hcwhite.theme");
+ }
+ },
+ aero: {
+ selectors: [":root"],
+ async applyConfig() {
+ await SystemTheme._changeWindowsTheme(resourcesDir + "\\Themes\\aero.theme");
+ }
+ },
+ userTheme: {
+ selectors: [":root"],
+ async applyConfig() {
+ await SystemTheme._changeWindowsTheme(currentThemePath);
+ }
+ }
+ }
+ } else if (AppConstants.isPlatformAndVersionAtLeast("win", "6")) { // Windows 7 and 8
+ this.configurations = {
+ aeroGlass: {
+ selectors: [":root"],
+ async applyConfig() {
+ await SystemTheme._changeWindowsTheme(resourcesDir + "\\Themes\\aero.theme");
+ },
+ },
+ aeroBasic: {
+ selectors: [":root"],
+ async applyConfig() {
+ await SystemTheme._changeWindowsTheme(resourcesDir + "\\Ease of Access Themes\\basic.theme");
+ },
+ },
+ classic: {
+ selectors: [":root"],
+ async applyConfig() {
+ await SystemTheme._changeWindowsTheme(resourcesDir + "\\Ease of Access Themes\\classic.theme");
+ },
+ },
+ highContrast1: {
+ selectors: [":root"],
+ async applyConfig() {
+ await SystemTheme._changeWindowsTheme(resourcesDir + "\\Ease of Access Themes\\hc1.theme");
+ },
+ },
+ userTheme: {
+ selectors: [":root"],
+ async applyConfig() {
+ await SystemTheme._changeWindowsTheme(currentThemePath);
+ }
+ }
+ };
+ }
+ } else {
+ this.configurations = {
+ defaultTheme: {
+ async applyConfig() {
+ return Promise.reject("SystemTheme is only supported on Windows");
+ },
+ },
+ };
+ }
+ },
+
+
+ // helpers //
+
+ _changeWindowsTheme(themeFilePath) {
+ let changeWindowsThemeBat = this._libDir.clone();
+ changeWindowsThemeBat.append("ChangeWindowsTheme.bat");
+ let process = Cc["@mozilla.org/process/util;1"]
+ .createInstance(Ci.nsIProcess);
+ process.init(changeWindowsThemeBat);
+
+ // Run the process.
+ let args = [themeFilePath];
+ process.runAsync(args, args.length, function themeChangeComplete() {
+ // Focus the browser again (instead of the theme selector)
+ setTimeout(this._closeWindowsPersonalizationWindow, 1000);
+
+ setTimeout(function focusTab() {
+ let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
+ browserWindow.gBrowser.selectedBrowser.focus();
+ }, 5000);
+ }.bind(this));
+
+ // The line below fails to take screenshots, unsure why.
+ // return TestUtils.waitForCondition(() => getCurrentThemePath() == themeFilePath, "Waiting for theme to load");
+
+ return new Promise((c) => setTimeout(c, 5000)); // Need to wait for everything to settle
+ },
+
+ _closeWindowsPersonalizationWindow() {
+ try {
+ let lib = ctypes.open("user32.dll");
+
+ let findWindowFunc = lib.declare("FindWindowW", ctypes.winapi_abi, ctypes.int32_t, ctypes.jschar.ptr, ctypes.jschar.ptr);
+ // Get the Personalization window
+ let hWnd;
+ if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
+ hWnd = findWindowFunc("ApplicationFrameWindow", "Settings");
+ } else if (AppConstants.isPlatformAndVersionAtLeast("win", "6")) {
+ hWnd = findWindowFunc("CabinetWClass", "Personalization");
+ }
+
+ if (!hWnd) {
+ console.error("Cannot find the Personalization window");
+ return;
+ }
+
+ // Post the close event to the window
+ let postMessageFunc = lib.declare("PostMessageW", ctypes.winapi_abi, ctypes.bool, ctypes.int32_t, ctypes.uint32_t, ctypes.size_t, ctypes.size_t);
+ const WM_CLOSE = 16;
+ postMessageFunc(hWnd, WM_CLOSE, 0, 0);
+
+ lib.close();
+ } catch (ex) {
+ console.error(ex);
+ }
+ },
+ };
+
+
+ // helpers
+
+ /**
+ * Based on getServicePack from toolkit/mozapps/update/test/unit/test_0040_general.js
+ */
+ function getWindowsVersion() {
+ if (Services.appinfo.OS !== "WINNT")
+ throw ("getWindowsVersion called on non-Windows operating system");
+
+ const BYTE = ctypes.uint8_t;
+ const WORD = ctypes.uint16_t;
+ const DWORD = ctypes.uint32_t;
+ const WCHAR = ctypes.jschar;
+ const BOOL = ctypes.int;
+
+ // This structure is described at:
+ // http://msdn.microsoft.com/en-us/library/ms724833%28v=vs.85%29.aspx
+ const SZCSDVERSIONLENGTH = 128;
+ const OSVERSIONINFOEXW = new ctypes.StructType("OSVERSIONINFOEXW",
+ [
+ {dwOSVersionInfoSize: DWORD},
+ {dwMajorVersion: DWORD},
+ {dwMinorVersion: DWORD},
+ {dwBuildNumber: DWORD},
+ {dwPlatformId: DWORD},
+ {szCSDVersion: ctypes.ArrayType(WCHAR, SZCSDVERSIONLENGTH)},
+ {wServicePackMajor: WORD},
+ {wServicePackMinor: WORD},
+ {wSuiteMask: WORD},
+ {wProductType: BYTE},
+ {wReserved: BYTE}
+ ]);
+
+ let kernel32 = ctypes.open("kernel32");
+ try {
+ let GetVersionEx = kernel32.declare("GetVersionExW",
+ ctypes.default_abi,
+ BOOL,
+ OSVERSIONINFOEXW.ptr);
+ let winVer = OSVERSIONINFOEXW();
+ winVer.dwOSVersionInfoSize = OSVERSIONINFOEXW.size;
+
+ if (0 === GetVersionEx(winVer.address())) {
+ throw ("Failure in GetVersionEx (returned 0)");
+ }
+
+ let versionInfo = {
+ majorVersion: winVer.dwMajorVersion,
+ minorVersion: winVer.dwMinorVersion,
+ servicePackMajor: winVer.wServicePackMajor,
+ servicePackMinor: winVer.wServicePackMinor,
+ };
+
+ return versionInfo;
+ } finally {
+ kernel32.close();
+ }
+ }
+
+ function getCurrentThemePath() {
+ return WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Themes", "CurrentTheme");
+ }