Bug 1135018 - Make devices.js use a CDN. r=ochameau
authorJan Keromnes <janx@linux.com>
Sat, 21 Mar 2015 04:02:00 -0400
changeset 265598 d462c69631569305ef3046275dc1d232cf04107f
parent 265597 1e547a8615b4ca828ea1b854dd8c30d3075328d3
child 265599 3ec9f77647f6116c1720bb5f9367b36e7c61eab2
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersochameau
bugs1135018
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1135018 - Make devices.js use a CDN. r=ochameau
browser/devtools/shared/devices.js
browser/devtools/shared/test/browser.ini
browser/devtools/shared/test/browser_devices.js
browser/devtools/shared/test/browser_devices.json
browser/locales/en-US/chrome/browser/devtools/device.properties
modules/libpref/init/all.js
--- a/browser/devtools/shared/devices.js
+++ b/browser/devtools/shared/devices.js
@@ -1,603 +1,74 @@
 /* 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 { Ci, Cc } = require("chrome");
+const { getJSON } = require("devtools/shared/getjson");
 const { Services } = require("resource://gre/modules/Services.jsm");
+const promise = require("promise");
+
+const DEVICES_URL = "devtools.devices.url";
 const Strings = Services.strings.createBundle("chrome://browser/locale/devtools/device.properties");
 
-/* `Devices` is a catalog of existing devices and their properties, intended
- * for (mobile) device emulation tools and features.
+/* This is a catalog of common web-enabled devices and their properties,
+ * intended for (mobile) device emulation.
  *
  * The properties of a device are:
- * - name: Device brand and model(s).
- * - width: Viewport width.
- * - height: Viewport height.
- * - pixelRatio: Screen pixel ratio to viewport.
- * - userAgent: Device UserAgent string.
- * - touch: Whether the screen is touch-enabled.
+ * - name: brand and model(s).
+ * - width: viewport width.
+ * - height: viewport height.
+ * - pixelRatio: ratio from viewport to physical screen pixels.
+ * - userAgent: UA string of the device's browser.
+ * - touch: whether it has a touch screen.
+ * - firefoxOS: whether Firefox OS is supported.
  *
- * To add more devices to this catalog, either patch this file, or push new
- * device descriptions from your own code (e.g. an addon) like so:
+ * The device types are:
+ *   ["phones", "tablets", "laptops", "televisions", "consoles", "watches"].
+ *
+ * You can easily add more devices to this catalog from your own code (e.g. an
+ * addon) like so:
  *
  *   var myPhone = { name: "My Phone", ... };
- *   require("devtools/shared/devices").Devices.Others.phones.push(myPhone);
+ *   require("devtools/shared/devices").AddDevice(myPhone, "phones");
  */
 
-let Devices = {
-  Types: ["phones", "tablets", "notebooks", "televisions", "watches"],
-
-  // Get the localized string of a device type.
-  GetString(deviceType) {
-    return Strings.GetStringFromName("device." + deviceType);
-  },
-};
-exports.Devices = Devices;
-
+// Local devices catalog that addons can add to.
+let localDevices = {};
 
-// The `Devices.FirefoxOS` list was put together from various sources online.
-Devices.FirefoxOS = {
-  phones: [
-    {
-      name: "Firefox OS Flame",
-      width: 320,
-      height: 570,
-      pixelRatio: 1.5,
-      userAgent: "Mozilla/5.0 (Mobile; rv:28.0) Gecko/28.0 Firefox/28.0",
-      touch: true,
-    },
-    {
-      name: "Alcatel One Touch Fire, Fire C",
-      width: 320,
-      height: 480,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Mobile; ALCATELOneTouch4012X; rv:28.0) Gecko/28.0 Firefox/28.0",
-      touch: true,
-    },
-    {
-      name: "Alcatel Fire E",
-      width: 320,
-      height: 480,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (Mobile; ALCATELOneTouch4012X; rv:28.0) Gecko/28.0 Firefox/28.0",
-      touch: true,
-    },
-    {
-      name: "Geeksphone Keon",
-      width: 320,
-      height: 480,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Mobile; rv:28.0) Gecko/28.0 Firefox/28.0",
-      touch: true,
-    },
-    {
-      name: "Geeksphone Peak, Revolution",
-      width: 360,
-      height: 640,
-      pixelRatio: 1.5,
-      userAgent: "Mozilla/5.0 (Mobile; rv:28.0) Gecko/28.0 Firefox/28.0",
-      touch: true,
-    },
-    {
-      name: "Intex Cloud Fx",
-      width: 320,
-      height: 480,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Mobile; rv:28.0) Gecko/28.0 Firefox/28.0",
-      touch: true,
-    },
-    {
-      name: "LG Fireweb",
-      width: 320,
-      height: 480,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Mobile; LG-D300; rv:28.0) Gecko/28.0 Firefox/28.0",
-      touch: true,
-    },
-    {
-      name: "Spice Fire One Mi-FX1",
-      width: 320,
-      height: 480,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Mobile; rv:28.0) Gecko/28.0 Firefox/28.0",
-      touch: true,
-    },
-    {
-      name: "Symphony GoFox F15",
-      width: 320,
-      height: 480,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Mobile; rv:28.0) Gecko/28.0 Firefox/28.0",
-      touch: true,
-    },
-    {
-      name: "Zen Fire 105",
-      width: 320,
-      height: 480,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Mobile; rv:28.0) Gecko/28.0 Firefox/28.0",
-      touch: true,
-    },
-    {
-      name: "ZTE Open",
-      width: 320,
-      height: 480,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Mobile; ZTEOPEN; rv:28.0) Gecko/28.0 Firefox/28.0",
-      touch: true,
-    },
-    {
-      name: "ZTE Open C",
-      width: 320,
-      height: 450,
-      pixelRatio: 1.5,
-      userAgent: "Mozilla/5.0 (Mobile; OPENC; rv:28.0) Gecko/28.0 Firefox/28.0",
-      touch: true,
-    },
-  ],
-  tablets: [
-    {
-      name: "Foxconn InFocus",
-      width: 1280,
-      height: 800,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Mobile; rv:28.0) Gecko/28.0 Firefox/28.0",
-      touch: true,
-    },
-    {
-      name: "VIA Vixen",
-      width: 1024,
-      height: 600,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Mobile; rv:28.0) Gecko/28.0 Firefox/28.0",
-      touch: true,
-    },
-  ],
-  notebooks: [
-  ],
-  televisions: [
-    {
-      name: "720p HD Television",
-      width: 1280,
-      height: 720,
-      pixelRatio: 1,
-      userAgent: "",
-      touch: false,
-    },
-    {
-      name: "1080p Full HD Television",
-      width: 1920,
-      height: 1080,
-      pixelRatio: 1,
-      userAgent: "",
-      touch: false,
-    },
-    {
-      name: "4K Ultra HD Television",
-      width: 3840,
-      height: 2160,
-      pixelRatio: 1,
-      userAgent: "",
-      touch: false,
-    },
-  ],
-  watches: [
-    {
-      name: "LG G Watch",
-      width: 280,
-      height: 280,
-      pixelRatio: 1,
-      userAgent: "",
-      touch: true,
-    },
-    {
-      name: "LG G Watch R",
-      width: 320,
-      height: 320,
-      pixelRatio: 1,
-      userAgent: "",
-      touch: true,
-    },
-    {
-      name: "Moto 360",
-      width: 320,
-      height: 290,
-      pixelRatio: 1,
-      userAgent: "",
-      touch: true,
-    },
-    {
-      name: "Samsung Gear Live",
-      width: 320,
-      height: 320,
-      pixelRatio: 1,
-      userAgent: "",
-      touch: true,
-    },
-  ],
-};
+// Add a device to the local catalog.
+function AddDevice(device, type = "phones") {
+  let list = localDevices[type];
+  if (!list) {
+    list = localDevices[type] = [];
+  }
+  list.push(device);
+}
+exports.AddDevice = AddDevice;
+
+// Get the complete devices catalog.
+function GetDevices(bypassCache = false) {
+  let deferred = promise.defer();
 
-// `Devices.Others` was derived from the Chromium source code:
-// - chromium/src/third_party/WebKit/Source/devtools/front_end/toolbox/OverridesUI.js
-Devices.Others = {
-  phones: [
-    {
-      name: "Apple iPhone 3GS",
-      width: 320,
-      height: 480,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5",
-      touch: true,
-    },
-    {
-      name: "Apple iPhone 4",
-      width: 320,
-      height: 480,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5",
-      touch: true,
-    },
-    {
-      name: "Apple iPhone 5",
-      width: 320,
-      height: 568,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53",
-      touch: true,
-    },
-    {
-      name: "Apple iPhone 6",
-      width: 375,
-      height: 667,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4",
-      touch: true,
-    },
-    {
-      name: "Apple iPhone 6 Plus",
-      width: 414,
-      height: 736,
-      pixelRatio: 3,
-      userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4",
-      touch: true,
-    },
-    {
-      name: "BlackBerry Z10",
-      width: 384,
-      height: 640,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+",
-      touch: true,
-    },
-    {
-      name: "BlackBerry Z30",
-      width: 360,
-      height: 640,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+",
-      touch: true,
-    },
-    {
-      name: "Google Nexus 4",
-      width: 384,
-      height: 640,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 4 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19",
-      touch: true,
-    },
-    {
-      name: "Google Nexus 5",
-      width: 360,
-      height: 640,
-      pixelRatio: 3,
-      userAgent: "Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19",
-      touch: true,
-    },
-    {
-      name: "Google Nexus S",
-      width: 320,
-      height: 533,
-      pixelRatio: 1.5,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Nexus S Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
-      touch: true,
-    },
-    {
-      name: "HTC Evo, Touch HD, Desire HD, Desire",
-      width: 320,
-      height: 533,
-      pixelRatio: 1.5,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Sprint APA9292KT Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
-      touch: true,
-    },
-    {
-      name: "HTC One X, EVO LTE",
-      width: 360,
-      height: 640,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (Linux; Android 4.0.3; HTC One X Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
-      touch: true,
-    },
-    {
-      name: "HTC Sensation, Evo 3D",
-      width: 360,
-      height: 640,
-      pixelRatio: 1.5,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
-      touch: true,
-    },
-    {
-      name: "LG Optimus 2X, Optimus 3D, Optimus Black",
-      width: 320,
-      height: 533,
-      pixelRatio: 1.5,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 2.2; en-us; LG-P990/V08c Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MMS/LG-Android-MMS-V1.0/1.2",
-      touch: true,
-    },
-    {
-      name: "LG Optimus G",
-      width: 384,
-      height: 640,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (Linux; Android 4.0; LG-E975 Build/IMM76L) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19",
-      touch: true,
-    },
-    {
-      name: "LG Optimus LTE, Optimus 4X HD",
-      width: 424,
-      height: 753,
-      pixelRatio: 1.7,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 2.3; en-us; LG-P930 Build/GRJ90) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
-      touch: true,
-    },
-    {
-      name: "LG Optimus One",
-      width: 213,
-      height: 320,
-      pixelRatio: 1.5,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; LG-MS690 Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
-      touch: true,
-    },
-    {
-      name: "Motorola Defy, Droid, Droid X, Milestone",
-      width: 320,
-      height: 569,
-      pixelRatio: 1.5,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Milestone Build/ SHOLS_U2_01.03.1) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",
-      touch: true,
-    },
-    {
-      name: "Motorola Droid 3, Droid 4, Droid Razr, Atrix 4G, Atrix 2",
-      width: 540,
-      height: 960,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Droid Build/FRG22D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
-      touch: true,
-    },
-    {
-      name: "Motorola Droid Razr HD",
-      width: 720,
-      height: 1280,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 2.3; en-us; DROID RAZR 4G Build/6.5.1-73_DHD-11_M1-29) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
-      touch: true,
-    },
-    {
-      name: "Nokia C5, C6, C7, N97, N8, X7",
-      width: 360,
-      height: 640,
-      pixelRatio: 1,
-      userAgent: "NokiaN97/21.1.107 (SymbianOS/9.4; Series60/5.0 Mozilla/5.0; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebkit/525 (KHTML, like Gecko) BrowserNG/7.1.4",
-      touch: true,
-    },
-    {
-      name: "Nokia Lumia 7X0, Lumia 8XX, Lumia 900, N800, N810, N900",
-      width: 320,
-      height: 533,
-      pixelRatio: 1.5,
-      userAgent: "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 820)",
-      touch: true,
-    },
-    {
-      name: "Samsung Galaxy Note 3",
-      width: 360,
-      height: 640,
-      pixelRatio: 3,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
-      touch: true,
-    },
-    {
-      name: "Samsung Galaxy Note II",
-      width: 360,
-      height: 640,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
-      touch: true,
-    },
-    {
-      name: "Samsung Galaxy Note",
-      width: 400,
-      height: 640,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 2.3; en-us; SAMSUNG-SGH-I717 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
-      touch: true,
-    },
-    {
-      name: "Samsung Galaxy S III, Galaxy Nexus",
-      width: 360,
-      height: 640,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
-      touch: true,
-    },
-    {
-      name: "Samsung Galaxy S, S II, W",
-      width: 320,
-      height: 533,
-      pixelRatio: 1.5,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 2.1; en-us; GT-I9000 Build/ECLAIR) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
-      touch: true,
-    },
-    {
-      name: "Samsung Galaxy S4",
-      width: 360,
-      height: 640,
-      pixelRatio: 3,
-      userAgent: "Mozilla/5.0 (Linux; Android 4.2.2; GT-I9505 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36",
-      touch: true,
-    },
-    {
-      name: "Sony Xperia S, Ion",
-      width: 360,
-      height: 640,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 4.0; en-us; LT28at Build/6.1.C.1.111) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
-      touch: true,
-    },
-    {
-      name: "Sony Xperia Sola, U",
-      width: 480,
-      height: 854,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 2.3; en-us; SonyEricssonST25i Build/6.0.B.1.564) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
-      touch: true,
-    },
-    {
-      name: "Sony Xperia Z, Z1",
-      width: 360,
-      height: 640,
-      pixelRatio: 3,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 4.2; en-us; SonyC6903 Build/14.1.G.1.518) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
-      touch: true,
-    },
-  ],
-  tablets: [
-    {
-      name: "Amazon Kindle Fire HDX 7″",
-      width: 1920,
-      height: 1200,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (Linux; U; en-us; KFTHWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true",
-      touch: true,
-    },
-    {
-      name: "Amazon Kindle Fire HDX 8.9″",
-      width: 2560,
-      height: 1600,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true",
-      touch: true,
-    },
-    {
-      name: "Amazon Kindle Fire (First Generation)",
-      width: 1024,
-      height: 600,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.0.141.16-Gen4_11004310) AppleWebkit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true",
-      touch: true,
-    },
-    {
-      name: "Apple iPad 1 / 2 / iPad Mini",
-      width: 1024,
-      height: 768,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (iPad; CPU OS 4_3_5 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8L1 Safari/6533.18.5",
-      touch: true,
-    },
-    {
-      name: "Apple iPad 3 / 4",
-      width: 1024,
-      height: 768,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53",
-      touch: true,
-    },
-    {
-      name: "BlackBerry PlayBook",
-      width: 1024,
-      height: 600,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+",
-      touch: true,
-    },
-    {
-      name: "Google Nexus 10",
-      width: 1280,
-      height: 800,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (Linux; Android 4.3; Nexus 10 Build/JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.72 Safari/537.36",
-      touch: true,
-    },
-    {
-      name: "Google Nexus 7 2",
-      width: 960,
-      height: 600,
-      pixelRatio: 2,
-      userAgent: "Mozilla/5.0 (Linux; Android 4.3; Nexus 7 Build/JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.72 Safari/537.36",
-      touch: true,
-    },
-    {
-      name: "Google Nexus 7",
-      width: 966,
-      height: 604,
-      pixelRatio: 1.325,
-      userAgent: "Mozilla/5.0 (Linux; Android 4.3; Nexus 7 Build/JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.72 Safari/537.36",
-      touch: true,
-    },
-    {
-      name: "Motorola Xoom, Xyboard",
-      width: 1280,
-      height: 800,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
-      touch: true,
-    },
-    {
-      name: "Samsung Galaxy Tab 7.7, 8.9, 10.1",
-      width: 1280,
-      height: 800,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
-      touch: true,
-    },
-    {
-      name: "Samsung Galaxy Tab",
-      width: 1024,
-      height: 600,
-      pixelRatio: 1,
-      userAgent: "Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
-      touch: true,
-    },
-  ],
-  notebooks: [
-    {
-      name: "Notebook with touch",
-      width: 1280,
-      height: 950,
-      pixelRatio: 1,
-      userAgent: "",
-      touch: true,
-    },
-    {
-      name: "Notebook with HiDPI screen",
-      width: 1440,
-      height: 900,
-      pixelRatio: 2,
-      userAgent: "",
-      touch: false,
-    },
-    {
-      name: "Generic notebook",
-      width: 1280,
-      height: 800,
-      pixelRatio: 1,
-      userAgent: "",
-      touch: false,
-    },
-  ],
-  televisions: [
-  ],
-  watches: [
-  ],
-};
+  // Fetch common devices from Mozilla's CDN.
+  getJSON(DEVICES_URL, bypassCache).then(devices => {
+    for (let type in localDevices) {
+      if (!devices[type]) {
+        devices.TYPES.push(type);
+        devices[type] = [];
+      }
+      devices[type] = localDevices[type].concat(devices[type]);
+    }
+    deferred.resolve(devices);
+  });
+
+  return deferred.promise;
+}
+exports.GetDevices = GetDevices;
+
+// Get the localized string for a device type.
+function GetDeviceString(deviceType) {
+  return Strings.GetStringFromName("device." + deviceType);
+}
+exports.GetDeviceString = GetDeviceString;
--- a/browser/devtools/shared/test/browser.ini
+++ b/browser/devtools/shared/test/browser.ini
@@ -2,16 +2,17 @@
 subsuite = devtools
 support-files =
   browser_layoutHelpers.html
   browser_layoutHelpers-getBoxQuads.html
   browser_layoutHelpers_iframe.html
   browser_templater_basic.html
   browser_toolbar_basic.html
   browser_toolbar_webconsole_errors_count.html
+  browser_devices.json
   doc_options-view.xul
   head.js
   leakhunt.js
 
 [browser_css_color.js]
 [browser_cubic-bezier-01.js]
 [browser_cubic-bezier-02.js]
 [browser_cubic-bezier-03.js]
@@ -96,8 +97,9 @@ skip-if = e10s # Bug 1086492 - Disable t
 [browser_templater_basic.js]
 [browser_toolbar_basic.js]
 [browser_toolbar_tooltip.js]
 [browser_toolbar_webconsole_errors_count.js]
 skip-if = buildapp == 'mulet' || e10s # The developertoolbar error count isn't correct with e10s
 [browser_treeWidget_basic.js]
 [browser_treeWidget_keyboard_interaction.js]
 [browser_treeWidget_mouse_interaction.js]
+[browser_devices.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/shared/test/browser_devices.js
@@ -0,0 +1,50 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let { GetDevices, GetDeviceString, AddDevice } = devtools.require("devtools/shared/devices");
+
+add_task(function*() {
+  Services.prefs.setCharPref("devtools.devices.url", TEST_URI_ROOT + "browser_devices.json");
+
+  let devices = yield GetDevices();
+
+  is(devices.TYPES.length, 1, "Found 1 device type.");
+
+  let type1 = devices.TYPES[0];
+
+  is(devices[type1].length, 2, "Found 2 devices of type #1.");
+
+  let string = GetDeviceString(type1);
+  ok(typeof string === "string" && string.length > 0, "Able to localize type #1.");
+
+  let device1 = {
+    name: "SquarePhone",
+    width: 320,
+    height: 320,
+    pixelRatio: 2,
+    userAgent: "Mozilla/5.0 (Mobile; rv:42.0)",
+    touch: true,
+    firefoxOS: true
+  };
+  AddDevice(device1, type1);
+  devices = yield GetDevices();
+
+  is(devices[type1].length, 3, "Added new device of type #1.");
+  ok(devices[type1].filter(d => d.name === device1.name), "Found the new device.");
+
+  let type2 = "appliances";
+  let device2 = {
+    name: "Mr Freezer",
+    width: 800,
+    height: 600,
+    pixelRatio: 5,
+    userAgent: "Mozilla/5.0 (Appliance; rv:42.0)",
+    touch: true,
+    firefoxOS: true
+  };
+  AddDevice(device2, type2);
+  devices = yield GetDevices();
+
+  is(devices.TYPES.length, 2, "Added device type #2.");
+  is(devices[type2].length, 1, "Added new device of type #2.");
+});
new file mode 100644
--- /dev/null
+++ b/browser/devtools/shared/test/browser_devices.json
@@ -0,0 +1,23 @@
+{
+  "TYPES": [ "phones" ],
+  "phones": [
+    {
+      "name": "Small Phone",
+      "width": 320,
+      "height": 480,
+      "pixelRatio": 1,
+      "userAgent": "Mozilla/5.0 (Mobile; rv:39.0) Gecko/39.0 Firefox/39.0",
+      "touch": true,
+      "firefoxOS": true
+    },
+    {
+      "name": "Big Phone",
+      "width": 360,
+      "height": 640,
+      "pixelRatio": 3,
+      "userAgent": "Mozilla/5.0 (Mobile; rv:39.0) Gecko/39.0 Firefox/39.0",
+      "touch": true,
+      "firefoxOS": true
+    }
+  ]
+}
--- a/browser/locales/en-US/chrome/browser/devtools/device.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/device.properties
@@ -9,11 +9,12 @@
 # language in which you'd find the best documentation on web development on the
 # web.
 
 # LOCALIZATION NOTE:
 # These strings are category names in a list of devices that a user can choose
 # to simulate (e.g. "ZTE Open C", "VIA Vixen", "720p HD Television", etc).
 device.phones=Phones
 device.tablets=Tablets
-device.notebooks=Notebooks
+device.laptops=Laptops
 device.televisions=TVs
+device.consoles=Gaming consoles
 device.watches=Watches
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -832,16 +832,19 @@ pref("devtools.discovery.log", false);
 pref("devtools.remote.wifi.scan", false);
 // Hide UI options for controlling device visibility over WiFi
 // N.B.: This does not set whether the device can be discovered via WiFi, only
 // whether the UI control to make such a choice is shown to the user
 pref("devtools.remote.wifi.visible", false);
 // Client must complete TLS handshake within this window (ms)
 pref("devtools.remote.tls-handshake-timeout", 10000);
 
+// URL of the remote JSON catalog used for device simulation
+pref("devtools.devices.url", "https://code.cdn.mozilla.net/devices/devices.json");
+
 // view source
 pref("view_source.syntax_highlight", true);
 pref("view_source.wrap_long_lines", false);
 pref("view_source.editor.external", false);
 pref("view_source.editor.path", "");
 // allows to add further arguments to the editor; use the %LINE% placeholder
 // for jumping to a specific line (e.g. "/line:%LINE%" or "--goto %LINE%")
 pref("view_source.editor.args", "");