Bug 1321831 - Delay loading RDM devices to allow faster open. r=ochameau draft
authorJ. Ryan Stinnett <jryans@gmail.com>
Thu, 29 Dec 2016 11:59:09 -0600
changeset 456013 225dff89b143716460bc23d35120e5abf1255702
parent 454691 dd0de3c7ea4ff7d2ee268ad4ce4d704c92bcc069
child 541097 4cec884d5afc58a973c0356f6073a4aede932d7f
push id40353
push userbmo:jryans@gmail.com
push dateWed, 04 Jan 2017 18:04:25 +0000
reviewersochameau
bugs1321831
milestone53.0a1
Bug 1321831 - Delay loading RDM devices to allow faster open. r=ochameau MozReview-Commit-ID: 4UkW0qjSAmr
devtools/client/responsive.html/index.js
devtools/client/responsive.html/manager.js
devtools/client/responsive.html/test/browser/browser_device_modal_submit.js
devtools/client/responsive.html/test/browser/browser_mouse_resize.js
devtools/client/responsive.html/test/browser/head.js
--- a/devtools/client/responsive.html/index.js
+++ b/devtools/client/responsive.html/index.js
@@ -25,31 +25,33 @@ const { Provider } = require("devtools/c
 const message = require("./utils/message");
 const App = createFactory(require("./app"));
 const Store = require("./store");
 const { changeLocation } = require("./actions/location");
 const { changeDisplayPixelRatio } = require("./actions/display-pixel-ratio");
 const { addViewport, resizeViewport } = require("./actions/viewports");
 const { loadDevices } = require("./actions/devices");
 
+// Exposed for use by tests
+window.require = require;
+
 let bootstrap = {
 
   telemetry: new Telemetry(),
 
   store: null,
 
   init: Task.async(function* () {
     // Load a special UA stylesheet to reset certain styles such as dropdown
     // lists.
     loadSheet(window,
               "resource://devtools/client/responsive.html/responsive-ua.css",
               "agent");
     this.telemetry.toolOpened("responsive");
     let store = this.store = Store();
-    this.dispatch(loadDevices());
     let provider = createElement(Provider, { store }, App());
     ReactDOM.render(provider, document.querySelector("#root"));
     message.post(window, "init:done");
   }),
 
   destroy() {
     this.store = null;
     this.telemetry.toolClosed("responsive");
@@ -71,16 +73,20 @@ let bootstrap = {
     this.store.dispatch(action);
   },
 
 };
 
 // manager.js sends a message to signal init
 message.wait(window, "init").then(() => bootstrap.init());
 
+// manager.js sends a message to signal init is done, which can be used for delayed
+// startup work that shouldn't block initial load
+message.wait(window, "post-init").then(() => bootstrap.dispatch(loadDevices()));
+
 window.addEventListener("unload", function onUnload() {
   window.removeEventListener("unload", onUnload);
   bootstrap.destroy();
 });
 
 // Allows quick testing of actions from the console
 window.dispatch = action => bootstrap.dispatch(action);
 
--- a/devtools/client/responsive.html/manager.js
+++ b/devtools/client/responsive.html/manager.js
@@ -342,16 +342,19 @@ ResponsiveUI.prototype = {
 
     this.tab.addEventListener("BeforeTabRemotenessChange", this);
 
     // Notify the inner browser to start the frame script
     yield message.request(this.toolWindow, "start-frame-script");
 
     // Get the protocol ready to speak with emulation actor
     yield this.connectToServer();
+
+    // Non-blocking message to tool UI to start any delayed init activities
+    message.post(this.toolWindow, "post-init");
   }),
 
   /**
    * Close RDM and restore page content back into a regular tab.
    *
    * @param object
    *        Destroy options, which currently includes a `reason` string.
    * @return boolean
--- a/devtools/client/responsive.html/test/browser/browser_device_modal_submit.js
+++ b/devtools/client/responsive.html/test/browser/browser_device_modal_submit.js
@@ -109,18 +109,19 @@ addRDMTask(TEST_URL, function* ({ ui }) 
   // Let's add a dummy device to simulate featured flag changes for next test
   addDeviceForTest(addedDevice);
 });
 
 addRDMTask(TEST_URL, function* ({ ui }) {
   let { store, document } = ui.toolWindow;
   let select = document.querySelector(".viewport-device-selector");
 
-  // Wait until the viewport has been added
-  yield waitUntilState(store, state => state.viewports.length == 1);
+  // Wait until the viewport has been added and the device list has been loaded
+  yield waitUntilState(store, state => state.viewports.length == 1
+    && state.devices.listState == Types.deviceListState.LOADED);
 
   openDeviceModal(ui);
 
   let remoteList = yield getDevices();
   let featuredCount = remoteList.TYPES.reduce((total, type) => {
     return total + remoteList[type].reduce((subtotal, device) => {
       return subtotal + ((device.os != "fxos" && device.featured) ? 1 : 0);
     }, 0);
--- a/devtools/client/responsive.html/test/browser/browser_mouse_resize.js
+++ b/devtools/client/responsive.html/test/browser/browser_mouse_resize.js
@@ -1,17 +1,21 @@
 /* Any copyright is dedicated to the Public Domain.
 http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const TEST_URL = "data:text/html;charset=utf-8,";
 
 addRDMTask(TEST_URL, function* ({ ui, manager }) {
-  ok(ui, "An instance of the RDM should be attached to the tab.");
+  let store = ui.toolWindow.store;
+
+  // Wait until the viewport has been added
+  yield waitUntilState(store, state => state.viewports.length == 1);
+
   yield setViewportSize(ui, manager, 300, 300);
 
   // Do horizontal + vertical resize
   yield testViewportResize(ui, ".viewport-resize-handle",
     [10, 10], [320, 310], [10, 10]);
 
   // Do horizontal resize
   yield testViewportResize(ui, ".viewport-horizontal-resize-handle",
--- a/devtools/client/responsive.html/test/browser/head.js
+++ b/devtools/client/responsive.html/test/browser/head.js
@@ -211,36 +211,30 @@ function* testViewportResize(ui, selecto
 
   let endRect = getElRect(selector, win);
   is(endRect.left - startRect.left, expectedHandleMove[0],
     `The x move of ${selector} is as expected`);
   is(endRect.top - startRect.top, expectedHandleMove[1],
     `The y move of ${selector} is as expected`);
 }
 
-function openDeviceModal({toolWindow}) {
+function openDeviceModal({ toolWindow }) {
   let { document } = toolWindow;
+  let React = toolWindow.require("devtools/client/shared/vendor/react");
+  let { Simulate } = React.addons.TestUtils;
   let select = document.querySelector(".viewport-device-selector");
   let modal = document.querySelector("#device-modal-wrapper");
 
   info("Checking initial device modal state");
   ok(modal.classList.contains("closed") && !modal.classList.contains("opened"),
     "The device modal is closed by default.");
 
   info("Opening device modal through device selector.");
-
-  let event = new toolWindow.UIEvent("change", {
-    view: toolWindow,
-    bubbles: true,
-    cancelable: true
-  });
-
   select.value = OPEN_DEVICE_MODAL_VALUE;
-  select.dispatchEvent(event);
-
+  Simulate.change(select);
   ok(modal.classList.contains("opened") && !modal.classList.contains("closed"),
     "The device modal is displayed.");
 }
 
 function changeSelectValue({ toolWindow }, selector, value) {
   info(`Selecting ${value} in ${selector}.`);
 
   return new Promise(resolve => {