toolkit/devtools/server/actors/device.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 const {Cc, Ci, Cu, CC} = require("chrome");
     6 const Services = require("Services");
     7 const protocol = require("devtools/server/protocol");
     8 const {method, RetVal} = protocol;
     9 const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
    10 const {LongStringActor} = require("devtools/server/actors/string");
    11 const {DebuggerServer} = require("devtools/server/main");
    13 Cu.import("resource://gre/modules/PermissionsTable.jsm")
    15 const APP_MAP = {
    16   '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}': 'firefox',
    17   '{3550f703-e582-4d05-9a08-453d09bdfdc6}': 'thunderbird',
    18   '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}': 'seamonkey',
    19   '{718e30fb-e89b-41dd-9da7-e25a45638b28}': 'sunbird',
    20   '{3c2e2abc-06d4-11e1-ac3b-374f68613e61}': 'b2g',
    21   '{aa3c5121-dab2-40e2-81ca-7ea25febc110}': 'mobile/android',
    22   '{a23983c0-fd0e-11dc-95ff-0800200c9a66}': 'mobile/xul'
    23 }
    25 exports.register = function(handle) {
    26   handle.addGlobalActor(DeviceActor, "deviceActor");
    27 };
    29 exports.unregister = function(handle) {
    30 };
    32 let DeviceActor = protocol.ActorClass({
    33   typeName: "device",
    35   _desc: null,
    37   _getAppIniString : function(section, key) {
    38     let inifile = Services.dirsvc.get("GreD", Ci.nsIFile);
    39     inifile.append("application.ini");
    41     if (!inifile.exists()) {
    42       inifile = Services.dirsvc.get("CurProcD", Ci.nsIFile);
    43       inifile.append("application.ini");
    44     }
    46     if (!inifile.exists()) {
    47       return undefined;
    48     }
    50     let iniParser = Cc["@mozilla.org/xpcom/ini-parser-factory;1"].getService(Ci.nsIINIParserFactory).createINIParser(inifile);
    51     try {
    52       return iniParser.getString(section, key);
    53     } catch (e) {
    54       return undefined;
    55     }
    56   },
    58   _getSetting: function(name) {
    59     let deferred = promise.defer();
    61     if ("@mozilla.org/settingsService;1" in Cc) {
    62       let settingsService = Cc["@mozilla.org/settingsService;1"].getService(Ci.nsISettingsService);
    63       let req = settingsService.createLock().get(name, {
    64         handle: (name, value) => deferred.resolve(value),
    65         handleError: (error) => deferred.reject(error),
    66       });
    67     } else {
    68       deferred.reject(new Error("No settings service"));
    69     }
    70     return deferred.promise;
    71   },
    73   getDescription: method(function() {
    74     // Most of this code is inspired from Nightly Tester Tools:
    75     // https://wiki.mozilla.org/Auto-tools/Projects/NightlyTesterTools
    77     let appInfo = Services.appinfo;
    78     let win = Services.wm.getMostRecentWindow(DebuggerServer.chromeWindowType);
    79     let utils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
    81     desc = {
    82       appid: appInfo.ID,
    83       apptype: APP_MAP[appInfo.ID],
    84       vendor: appInfo.vendor,
    85       name: appInfo.name,
    86       version: appInfo.version,
    87       appbuildid: appInfo.appBuildID,
    88       platformbuildid: appInfo.platformBuildID,
    89       platformversion: appInfo.platformVersion,
    90       geckobuildid: appInfo.platformBuildID,
    91       geckoversion: appInfo.platformVersion,
    92       changeset: this._getAppIniString("App", "SourceStamp"),
    93       useragent: win.navigator.userAgent,
    94       locale: Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry).getSelectedLocale("global"),
    95       os: null,
    96       hardware: "unknown",
    97       processor: appInfo.XPCOMABI.split("-")[0],
    98       compiler: appInfo.XPCOMABI.split("-")[1],
    99       dpi: utils.displayDPI,
   100       brandName: null,
   101       channel: null,
   102       profile: null,
   103       width: win.screen.width,
   104       height: win.screen.height
   105     };
   107     // Profile
   108     let profd = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
   109     let profservice = Cc["@mozilla.org/toolkit/profile-service;1"].getService(Ci.nsIToolkitProfileService);
   110     var profiles = profservice.profiles;
   111     while (profiles.hasMoreElements()) {
   112       let profile = profiles.getNext().QueryInterface(Ci.nsIToolkitProfile);
   113       if (profile.rootDir.path == profd.path) {
   114         desc.profile = profile.name;
   115         break;
   116       }
   117     }
   119     if (!desc.profile) {
   120       desc.profile = profd.leafName;
   121     }
   123     // Channel
   124     try {
   125       desc.channel = Services.prefs.getCharPref('app.update.channel');
   126     } catch(e) {}
   128     if (desc.apptype == "b2g") {
   129       // B2G specific
   130       desc.os = "B2G";
   132       return this._getSetting('deviceinfo.hardware')
   133       .then(value => desc.hardware = value)
   134       .then(() => this._getSetting('deviceinfo.os'))
   135       .then(value => desc.version = value)
   136       .then(() => desc);
   137     }
   139     // Not B2G
   140     desc.os = appInfo.OS;
   141     let bundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
   142     if (bundle) {
   143       desc.brandName = bundle.GetStringFromName("brandFullName");
   144     }
   146     return desc;
   148   }, {request: {},response: { value: RetVal("json")}}),
   150   getWallpaper: method(function() {
   151     let deferred = promise.defer();
   152     this._getSetting("wallpaper.image").then((blob) => {
   153       let FileReader = CC("@mozilla.org/files/filereader;1");
   154       let reader = new FileReader();
   155       let conn = this.conn;
   156       reader.addEventListener("load", function() {
   157         let str = new LongStringActor(conn, reader.result);
   158         deferred.resolve(str);
   159       });
   160       reader.addEventListener("error", function() {
   161         deferred.reject(reader.error);
   162       });
   163       reader.readAsDataURL(blob);
   164     });
   165     return deferred.promise;
   166   }, {request: {},response: { value: RetVal("longstring")}}),
   168   screenshotToDataURL: method(function() {
   169     let window = Services.wm.getMostRecentWindow(DebuggerServer.chromeWindowType);
   170     let canvas = window.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
   171     let width = window.innerWidth;
   172     let height = window.innerHeight;
   173     canvas.setAttribute('width', width);
   174     canvas.setAttribute('height', height);
   175     let context = canvas.getContext('2d');
   176     let flags =
   177           context.DRAWWINDOW_DRAW_CARET |
   178           context.DRAWWINDOW_DRAW_VIEW |
   179           context.DRAWWINDOW_USE_WIDGET_LAYERS;
   180     context.drawWindow(window, 0, 0, width, height, 'rgb(255,255,255)', flags);
   181     let dataURL = canvas.toDataURL('image/png')
   182     return new LongStringActor(this.conn, dataURL);
   183   }, {request: {},response: { value: RetVal("longstring")}}),
   185   getRawPermissionsTable: method(function() {
   186     return {
   187       rawPermissionsTable: PermissionsTable,
   188       UNKNOWN_ACTION: Ci.nsIPermissionManager.UNKNOWN_ACTION,
   189       ALLOW_ACTION: Ci.nsIPermissionManager.ALLOW_ACTION,
   190       DENY_ACTION: Ci.nsIPermissionManager.DENY_ACTION,
   191       PROMPT_ACTION: Ci.nsIPermissionManager.PROMPT_ACTION
   192     };
   193   }, {request: {},response: { value: RetVal("json")}})
   194 });
   196 let DeviceFront = protocol.FrontClass(DeviceActor, {
   197   initialize: function(client, form) {
   198     protocol.Front.prototype.initialize.call(this, client);
   199     this.actorID = form.deviceActor;
   200     client.addActorPool(this);
   201     this.manage(this);
   202   },
   204   screenshotToBlob: function() {
   205     return this.screenshotToDataURL().then(longstr => {
   206       return longstr.string().then(dataURL => {
   207         let deferred = promise.defer();
   208         longstr.release().then(null, Cu.reportError);
   209         let req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
   210         req.open("GET", dataURL, true);
   211         req.responseType = "blob";
   212         req.onload = () => {
   213           deferred.resolve(req.response);
   214         };
   215         req.onerror = () => {
   216           deferred.reject(req.status);
   217         }
   218         req.send();
   219         return deferred.promise;
   220       });
   221     });
   222   },
   223 });
   225 const _knownDeviceFronts = new WeakMap();
   227 exports.getDeviceFront = function(client, form) {
   228   if (_knownDeviceFronts.has(client))
   229     return _knownDeviceFronts.get(client);
   231   let front = new DeviceFront(client, form);
   232   _knownDeviceFronts.set(client, front);
   233   return front;
   234 }

mercurial