Bug 1578753: Reflect the switching of the top-level target. r=jdescottes,ochameau
authorDaisuke Akatsuka <daisuke@birchill.co.jp>
Mon, 16 Dec 2019 10:16:05 +0000
changeset 507066 2297b54080b13fca7094c25373ecb5a4e5925e87
parent 507065 b0b6c99e9cf0df9f6f0b0fd96f04671887b46c7c
child 507067 3cff413b1897dbc48924cae9435dde5015f2a68b
push id36922
push userncsoregi@mozilla.com
push dateMon, 16 Dec 2019 17:21:47 +0000
treeherdermozilla-central@27d0d6cc2131 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes, ochameau
bugs1578753
milestone73.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 1578753: Reflect the switching of the top-level target. r=jdescottes,ochameau Differential Revision: https://phabricator.services.mozilla.com/D56704
devtools/client/styleeditor/StyleEditorUI.jsm
devtools/client/styleeditor/panel.js
--- a/devtools/client/styleeditor/StyleEditorUI.jsm
+++ b/devtools/client/styleeditor/StyleEditorUI.jsm
@@ -66,27 +66,24 @@ const HTML_NS = "http://www.w3.org/1999/
  * maintaining a list of editors for each stylesheet on a debuggee.
  *
  * Emits events:
  *   'editor-added': A new editor was added to the UI
  *   'editor-selected': An editor was selected
  *   'error': An error occured
  *
  * @param {Toolbox} toolbox
- * @param {StyleEditorFront} debuggee
- *        Client-side front for interacting with the page's stylesheets
  * @param {Document} panelDoc
  *        Document of the toolbox panel to populate UI in.
  * @param {CssProperties} A css properties database.
  */
-function StyleEditorUI(toolbox, debuggee, panelDoc, cssProperties) {
+function StyleEditorUI(toolbox, panelDoc, cssProperties) {
   EventEmitter.decorate(this);
 
   this._toolbox = toolbox;
-  this._debuggee = debuggee;
   this._panelDoc = panelDoc;
   this._cssProperties = cssProperties;
   this._window = this._panelDoc.defaultView;
   this._root = this._panelDoc.getElementById("style-editor-chrome");
 
   this.editors = [];
   this.selectedEditor = null;
   this.savedLocations = {};
@@ -105,25 +102,25 @@ function StyleEditorUI(toolbox, debuggee
   this._onMediaPrefChanged = this._onMediaPrefChanged.bind(this);
   this._updateMediaList = this._updateMediaList.bind(this);
   this._clear = this._clear.bind(this);
   this._onError = this._onError.bind(this);
   this._updateContextMenuItems = this._updateContextMenuItems.bind(this);
   this._openLinkNewTab = this._openLinkNewTab.bind(this);
   this._copyUrl = this._copyUrl.bind(this);
   this._addStyleSheet = this._addStyleSheet.bind(this);
+  this._onTargetAvailable = this._onTargetAvailable.bind(this);
+  this._onTargetDestroyed = this._onTargetDestroyed.bind(this);
 
   this._prefObserver = new PrefObserver("devtools.styleeditor.");
   this._prefObserver.on(PREF_MEDIA_SIDEBAR, this._onMediaPrefChanged);
   this._sourceMapPrefObserver = new PrefObserver(
     "devtools.source-map.client-service."
   );
   this._sourceMapPrefObserver.on(PREF_ORIG_SOURCES, this._onNewDocument);
-
-  this._debuggee.on("stylesheet-added", this._addStyleSheet);
 }
 this.StyleEditorUI = StyleEditorUI;
 
 StyleEditorUI.prototype = {
   get currentTarget() {
     return this._toolbox.targetList.targetFront;
   },
 
@@ -132,33 +129,30 @@ StyleEditorUI.prototype = {
    */
   get selectedStyleSheetIndex() {
     return this.selectedEditor
       ? this.selectedEditor.styleSheet.styleSheetIndex
       : -1;
   },
 
   /**
-   * Initiates the style editor ui creation, the inspector front to get
-   * reference to the walker and the selector highlighter if available
+   * Initiates the style editor ui creation, and start to track TargetList updates.
    */
   async initialize() {
-    await this.initializeHighlighter();
-
     this.createUI();
 
-    const styleSheets = await this._debuggee.getStyleSheets();
-    await this._resetStyleSheetList(styleSheets);
-
-    this.currentTarget.on("will-navigate", this._clear);
-    this.currentTarget.on("navigate", this._onNewDocument);
+    await this._toolbox.targetList.watchTargets(
+      [this._toolbox.targetList.TYPES.FRAME],
+      this._onTargetAvailable,
+      this._onTargetDestroyed
+    );
   },
 
-  async initializeHighlighter() {
-    const inspectorFront = await this.currentTarget.getFront("inspector");
+  async initializeHighlighter(targetFront) {
+    const inspectorFront = await targetFront.getFront("inspector");
     this._walker = inspectorFront.walker;
 
     try {
       this._highlighter = await inspectorFront.getHighlighterByType(
         SELECTOR_HIGHLIGHTER_TYPE
       );
     } catch (e) {
       // The selectorHighlighter can't always be instantiated, for example
@@ -172,18 +166,19 @@ StyleEditorUI.prototype = {
   },
 
   /**
    * Build the initial UI and wire buttons with event handlers.
    */
   createUI: function() {
     this._view = new SplitView(this._root);
 
-    wire(this._view.rootElement, ".style-editor-newButton", () => {
-      this._debuggee.addStyleSheet(null);
+    wire(this._view.rootElement, ".style-editor-newButton", async () => {
+      const stylesheetsFront = await this.currentTarget.getFront("stylesheets");
+      stylesheetsFront.addStyleSheet(null);
     });
 
     wire(this._view.rootElement, ".style-editor-importButton", () => {
       this._importFromFile(this._mockImportFile || null, this._window);
     });
 
     wire(this._view.rootElement, "#style-editor-options", event => {
       this._onOptionsButtonClick(event);
@@ -237,30 +232,26 @@ StyleEditorUI.prototype = {
       this._optionsButton.removeAttribute("open");
     });
 
     this._optionsMenu.popup(screenX, screenY, this._toolbox.doc);
   },
 
   /**
    * Refresh editors to reflect the stylesheets in the document.
-   *
-   * @param {string} event
-   *        Event name
-   * @param {StyleSheet} styleSheet
-   *        StyleSheet object for new sheet
    */
-  _onNewDocument: function() {
+  async _onNewDocument() {
     this._suppressAdd = true;
-    this._debuggee
-      .getStyleSheets()
-      .then(styleSheets => {
-        return this._resetStyleSheetList(styleSheets);
-      })
-      .catch(console.error);
+    try {
+      const stylesheetsFront = await this.currentTarget.getFront("stylesheets");
+      const styleSheets = await stylesheetsFront.getStyleSheets();
+      await this._resetStyleSheetList(styleSheets);
+    } catch (e) {
+      console.error(e);
+    }
   },
 
   /**
    * Add editors for all the given stylesheets to the UI.
    *
    * @param  {array} styleSheets
    *         Array of StyleSheetFront
    */
@@ -446,38 +437,39 @@ StyleEditorUI.prototype = {
       }
       NetUtil.asyncFetch(
         {
           uri: NetUtil.newURI(selectedFile),
           loadingNode: this._window.document,
           securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS,
           contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER,
         },
-        (stream, status) => {
+        async (stream, status) => {
           if (!Components.isSuccessCode(status)) {
             this.emit("error", { key: LOAD_ERROR, level: "warning" });
             return;
           }
           const source = NetUtil.readInputStreamToString(
             stream,
             stream.available()
           );
           stream.close();
 
           this._suppressAdd = true;
-          this._debuggee.addStyleSheet(source).then(styleSheet => {
-            this._suppressAdd = false;
-            this._addStyleSheet(styleSheet, true).then(editor => {
-              if (editor) {
-                editor.savedFile = selectedFile;
-              }
-              // Just for testing purposes.
-              this.emit("test:editor-updated", editor);
-            });
-          });
+          const stylesheetsFront = await this.currentTarget.getFront(
+            "stylesheets"
+          );
+          const styleSheet = await stylesheetsFront.addStyleSheet(source);
+          this._suppressAdd = false;
+          const editor = await this._addStyleSheet(styleSheet, true);
+          if (editor) {
+            editor.savedFile = selectedFile;
+          }
+          // Just for testing purposes.
+          this.emit("test:editor-updated", editor);
         }
       );
     };
 
     showFilePicker(file, false, parentWindow, onFileSelected);
   },
 
   /**
@@ -1094,26 +1086,57 @@ StyleEditorUI.prototype = {
    * @param  {object} location
    *         Location object with 'line', 'column', and 'source' properties.
    */
   _jumpToLocation: function(location) {
     const source = location.styleSheet || location.source;
     this.selectStyleSheet(source, location.line - 1, location.column - 1);
   },
 
+  async _onTargetAvailable({ targetFront, isTopLevel }) {
+    if (isTopLevel) {
+      await this.initializeHighlighter(targetFront);
+
+      const stylesheetsFront = await targetFront.getFront("stylesheets");
+      stylesheetsFront.on("stylesheet-added", this._addStyleSheet);
+      targetFront.on("will-navigate", this._clear);
+      targetFront.on("navigate", this._onNewDocument);
+
+      await this._onNewDocument();
+    }
+  },
+
+  async _onTargetDestroyed({ isTopLevel }) {
+    if (isTopLevel) {
+      this._clear();
+    }
+  },
+
   destroy: function() {
+    this._toolbox.targetList.unwatchTargets(
+      [this._toolbox.targetList.TYPES.FRAME],
+      this._onTargetAvailable,
+      this._onTargetDestroyed
+    );
+
+    this.currentTarget.off("will-navigate", this._clear);
+    this.currentTarget.off("navigate", this._onNewDocument);
+
+    const stylesheetsFront = this.currentTarget.getCachedFront("stylesheets");
+    if (stylesheetsFront) {
+      stylesheetsFront.off("stylesheet-added", this._addStyleSheet);
+    }
+
     this._clearStyleSheetEditors();
 
     this._seenSheets = null;
     this._suppressAdd = false;
 
     const sidebar = this._panelDoc.querySelector(".splitview-controller");
     const sidebarWidth = sidebar.getAttribute("width");
     Services.prefs.setIntPref(PREF_NAV_WIDTH, sidebarWidth);
 
     this._sourceMapPrefObserver.off(PREF_ORIG_SOURCES, this._onNewDocument);
     this._sourceMapPrefObserver.destroy();
     this._prefObserver.off(PREF_MEDIA_SIDEBAR, this._onMediaPrefChanged);
     this._prefObserver.destroy();
-
-    this._debuggee.off("stylesheet-added", this._addStyleSheet);
   },
 };
--- a/devtools/client/styleeditor/panel.js
+++ b/devtools/client/styleeditor/panel.js
@@ -25,42 +25,29 @@ var StyleEditorPanel = function StyleEdi
 
   this.destroy = this.destroy.bind(this);
   this._showError = this._showError.bind(this);
 };
 
 exports.StyleEditorPanel = StyleEditorPanel;
 
 StyleEditorPanel.prototype = {
-  get currentTarget() {
-    return this._toolbox.targetList.targetFront;
-  },
-
   get panelWindow() {
     return this._panelWin;
   },
 
   /**
    * open is effectively an asynchronous constructor
    */
   async open() {
-    this.currentTarget.on("close", this.destroy);
-
-    this._debuggee = await this.currentTarget.getFront("stylesheets");
-
     // Initialize the CSS properties database.
     const { cssProperties } = await initCssProperties(this._toolbox);
 
     // Initialize the UI
-    this.UI = new StyleEditorUI(
-      this._toolbox,
-      this._debuggee,
-      this._panelDoc,
-      cssProperties
-    );
+    this.UI = new StyleEditorUI(this._toolbox, this._panelDoc, cssProperties);
     this.UI.on("error", this._showError);
     await this.UI.initialize();
 
     this.isReady = true;
 
     return this;
   },
 
@@ -113,37 +100,34 @@ StyleEditorPanel.prototype = {
    *        Line number to jump to after selecting. One-indexed
    * @param {number} col
    *        Column number to jump to after selecting. One-indexed
    * @return {Promise}
    *         Promise that will resolve when the editor is selected and ready
    *         to be used.
    */
   selectStyleSheet: function(href, line, col) {
-    if (!this._debuggee || !this.UI) {
+    if (!this.UI) {
       return null;
     }
     return this.UI.selectStyleSheet(href, line - 1, col ? col - 1 : 0);
   },
 
   /**
    * Destroy the style editor.
    */
   destroy: function() {
     if (this._destroyed) {
       return;
     }
     this._destroyed = true;
 
-    this.currentTarget.off("close", this.destroy);
     this._toolbox = null;
     this._panelWin = null;
     this._panelDoc = null;
-    this._debuggee.destroy();
-    this._debuggee = null;
 
     this.UI.destroy();
     this.UI = null;
   },
 };
 
 XPCOMUtils.defineLazyGetter(StyleEditorPanel.prototype, "strings", function() {
   return Services.strings.createBundle(