/* 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 { Cc, Ci, Cu } = require("chrome"); const { Task } = require("resource://gre/modules/Task.jsm"); loader.lazyRequireGetter(this, "Services"); loader.lazyRequireGetter(this, "promise"); loader.lazyRequireGetter(this, "OS", "resource://gre/modules/commonjs/node/os.js"); loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true); loader.lazyRequireGetter(this, "AppConstants", "resource://gre/modules/AppConstants.jsm", true); loader.lazyGetter(this, "screenManager", () => { return Cc["@mozilla.org/gfx/screenmanager;1"].getService(Ci.nsIScreenManager); }); loader.lazyGetter(this, "oscpu", () => { return Cc["@mozilla.org/network/protocol;1?name=http"] .getService(Ci.nsIHttpProtocolHandler).oscpu; }); const APP_MAP = { "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}": "firefox", "{3550f703-e582-4d05-9a08-453d09bdfdc6}": "thunderbird", "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}": "seamonkey", "{718e30fb-e89b-41dd-9da7-e25a45638b28}": "sunbird", "{3c2e2abc-06d4-11e1-ac3b-374f68613e61}": "b2g", "{aa3c5121-dab2-40e2-81ca-7ea25febc110}": "mobile/android", "{a23983c0-fd0e-11dc-95ff-0800200c9a66}": "mobile/xul" }; var CACHED_INFO = null; function *getSystemInfo() { if (CACHED_INFO) { return CACHED_INFO; } let appInfo = Services.appinfo; let win = Services.wm.getMostRecentWindow(DebuggerServer.chromeWindowType); let [processor, compiler] = appInfo.XPCOMABI.split("-"); let dpi, useragent, width, height, os, brandName; let appid = appInfo.ID; let apptype = APP_MAP[appid]; let geckoVersion = appInfo.platformVersion; let hardware = "unknown"; let version = "unknown"; // B2G specific if (apptype === "b2g") { os = "B2G"; // `getSetting` does not work in child processes on b2g. // TODO bug 1205797, make this work in child processes. try { hardware = yield exports.getSetting("deviceinfo.hardware"); version = yield exports.getSetting("deviceinfo.os"); } catch (e) { } } // Not B2G else { os = appInfo.OS; version = appInfo.version; } let bundle = Services.strings.createBundle("chrome://branding/locale/brand.properties"); if (bundle) { brandName = bundle.GetStringFromName("brandFullName"); } else { brandName = null; } if (win) { let utils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); dpi = utils.displayDPI; useragent = win.navigator.userAgent; width = win.screen.width; height = win.screen.height; } let info = { /** * Information from nsIXULAppInfo, regarding * the application itself. */ // The XUL application's UUID. appid, // Name of the app, "firefox", "thunderbird", etc., listed in APP_MAP apptype, // Mixed-case or empty string of vendor, like "Mozilla" vendor: appInfo.vendor, // Name of the application, like "Firefox", "Thunderbird". name: appInfo.name, // The application's version, for example "0.8.0+" or "3.7a1pre". // Typically, the version of Firefox, for example. // It is different than the version of Gecko or the XULRunner platform. // On B2G, this is the Gaia version. version, // The application's build ID/date, for example "2004051604". appbuildid: appInfo.appBuildID, // The application's changeset. changeset: exports.getAppIniString("App", "SourceStamp"), // The build ID/date of Gecko and the XULRunner platform. platformbuildid: appInfo.platformBuildID, geckobuildid: appInfo.platformBuildID, // The version of Gecko or XULRunner platform, for example "1.8.1.19" or // "1.9.3pre". In "Firefox 3.7 alpha 1" the application version is "3.7a1pre" // while the platform version is "1.9.3pre" platformversion: geckoVersion, geckoversion: geckoVersion, // Locale used in this build locale: Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry).getSelectedLocale("global"), /** * Information regarding the operating system. */ // Returns the endianness of the architecture: either "LE" or "BE" endianness: OS.endianness(), // Returns the hostname of the machine hostname: OS.hostname(), // Name of the OS type. Typically the same as `uname -s`. Possible values: // https://developer.mozilla.org/en/OS_TARGET // Also may be "B2G". os, platform: os, // hardware and version info from `deviceinfo.hardware` // and `deviceinfo.os`. hardware, // Type of process architecture running: // "arm", "ia32", "x86", "x64" // Alias to both `arch` and `processor` for node/deviceactor compat arch: processor, processor, // Name of compiler used for build: // `'msvc', 'n32', 'gcc2', 'gcc3', 'sunc', 'ibmc'...` compiler, // Location for the current profile profile: getProfileLocation(), // Update channel channel: AppConstants.MOZ_UPDATE_CHANNEL, dpi, useragent, width, height, brandName, }; CACHED_INFO = info; return info; } function getProfileLocation () { // In child processes, we cannot access the profile location. try { let profd = Services.dirsvc.get("ProfD", Ci.nsILocalFile); let profservice = Cc["@mozilla.org/toolkit/profile-service;1"].getService(Ci.nsIToolkitProfileService); var profiles = profservice.profiles; while (profiles.hasMoreElements()) { let profile = profiles.getNext().QueryInterface(Ci.nsIToolkitProfile); if (profile.rootDir.path == profd.path) { return profile = profile.name; } } return profd.leafName; } catch (e) { return ""; } } function getAppIniString(section, key) { let inifile = Services.dirsvc.get("GreD", Ci.nsIFile); inifile.append("application.ini"); if (!inifile.exists()) { inifile = Services.dirsvc.get("CurProcD", Ci.nsIFile); inifile.append("application.ini"); } if (!inifile.exists()) { return undefined; } let iniParser = Cc["@mozilla.org/xpcom/ini-parser-factory;1"].getService(Ci.nsIINIParserFactory).createINIParser(inifile); try { return iniParser.getString(section, key); } catch (e) { return undefined; } } /** * Function for fetching screen dimensions and returning * an enum for Telemetry. */ function getScreenDimensions() { let width = {}; let height = {}; screenManager.primaryScreen.GetRect({}, {}, width, height); let dims = width.value + "x" + height.value; if (width.value < 800 || height.value < 600) { return 0; } if (dims === "800x600") { return 1; } if (dims === "1024x768") { return 2; } if (dims === "1280x800") { return 3; } if (dims === "1280x1024") { return 4; } if (dims === "1366x768") { return 5; } if (dims === "1440x900") { return 6; } if (dims === "1920x1080") { return 7; } if (dims === "2560×1440") { return 8; } if (dims === "2560×1600") { return 9; } if (dims === "2880x1800") { return 10; } if (width.value > 2880 || height.value > 1800) { return 12; } // Other dimension such as a VM. return 11; } /** * Function for fetching OS CPU and returning * an enum for Telemetry. */ function getOSCPU() { if (oscpu.includes("NT 5.1") || oscpu.includes("NT 5.2")) { return 0; } if (oscpu.includes("NT 6.0")) { return 1; } if (oscpu.includes("NT 6.1")) { return 2; } if (oscpu.includes("NT 6.2")) { return 3; } if (oscpu.includes("NT 6.3")) { return 4; } if (oscpu.includes("OS X")) { return 5; } if (oscpu.includes("Linux")) { return 6; } if (oscpu.includes("NT 10.")) { return 7; } // Other OS. return 12; } function getSetting(name) { let deferred = promise.defer(); if ("@mozilla.org/settingsService;1" in Cc) { let settingsService; // settingsService fails in b2g child processes // TODO bug 1205797, make this work in child processes. try { settingsService = Cc["@mozilla.org/settingsService;1"].getService(Ci.nsISettingsService); } catch (e) { return promise.reject(e); } let req = settingsService.createLock().get(name, { handle: (name, value) => deferred.resolve(value), handleError: (error) => deferred.reject(error), }); } else { deferred.reject(new Error("No settings service")); } return deferred.promise; } exports.is64Bit = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).is64Bit; exports.getSystemInfo = Task.async(getSystemInfo); exports.getAppIniString = getAppIniString; exports.getSetting = getSetting; exports.getScreenDimensions = getScreenDimensions; exports.getOSCPU = getOSCPU; exports.constants = AppConstants;