Bug 1297758 - Make the inspector self-loadable. r=bgrins draft
authorAlexandre Poirot <poirot.alex@gmail.com>
Mon, 26 Sep 2016 06:20:58 -0700
changeset 418993 e0b5958693934aae92797a604cc90e811f05fe31
parent 418992 f7d5008ee2ab9200052e45ad6ecc3f3a348f7f86
child 418994 1041ec9ec4d34eb973c3ba097257f7320b71276d
push id30810
push userbmo:poirot.alex@gmail.com
push dateThu, 29 Sep 2016 10:31:35 +0000
reviewersbgrins
bugs1297758
milestone52.0a1
Bug 1297758 - Make the inspector self-loadable. r=bgrins MozReview-Commit-ID: GsmNhW7CbNX
devtools/client/definitions.js
devtools/client/inspector/inspector-panel.js
devtools/client/inspector/inspector.xhtml
devtools/client/inspector/moz.build
devtools/client/inspector/panel.js
devtools/client/jar.mn
--- a/devtools/client/definitions.js
+++ b/devtools/client/definitions.js
@@ -4,17 +4,17 @@
 
 "use strict";
 
 const Services = require("Services");
 const osString = Services.appinfo.OS;
 
 // Panels
 loader.lazyGetter(this, "OptionsPanel", () => require("devtools/client/framework/toolbox-options").OptionsPanel);
-loader.lazyGetter(this, "InspectorPanel", () => require("devtools/client/inspector/inspector-panel").InspectorPanel);
+loader.lazyGetter(this, "InspectorPanel", () => require("devtools/client/inspector/panel").InspectorPanel);
 loader.lazyGetter(this, "WebConsolePanel", () => require("devtools/client/webconsole/panel").WebConsolePanel);
 loader.lazyGetter(this, "DebuggerPanel", () => require("devtools/client/debugger/panel").DebuggerPanel);
 loader.lazyGetter(this, "StyleEditorPanel", () => require("devtools/client/styleeditor/styleeditor-panel").StyleEditorPanel);
 loader.lazyGetter(this, "ShaderEditorPanel", () => require("devtools/client/shadereditor/panel").ShaderEditorPanel);
 loader.lazyGetter(this, "CanvasDebuggerPanel", () => require("devtools/client/canvasdebugger/panel").CanvasDebuggerPanel);
 loader.lazyGetter(this, "WebAudioEditorPanel", () => require("devtools/client/webaudioeditor/panel").WebAudioEditorPanel);
 loader.lazyGetter(this, "MemoryPanel", () => require("devtools/client/memory/panel").MemoryPanel);
 loader.lazyGetter(this, "PerformancePanel", () => require("devtools/client/performance/panel").PerformancePanel);
--- a/devtools/client/inspector/inspector-panel.js
+++ b/devtools/client/inspector/inspector-panel.js
@@ -1,16 +1,20 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* 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/. */
 
+/* global window */
+
 "use strict";
 
+var Cu = Components.utils;
+var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 var Services = require("Services");
 var promise = require("promise");
 var defer = require("devtools/shared/defer");
 var EventEmitter = require("devtools/shared/event-emitter");
 const {executeSoon} = require("devtools/shared/DevToolsUtils");
 var {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
 var {Task} = require("devtools/shared/task");
 const {initCssProperties} = require("devtools/shared/fronts/css-properties");
@@ -76,21 +80,21 @@ const PORTRAIT_MODE_WIDTH = 700;
  * - computed-view-filtered
  *      Fired when the computed rules view is filtered
  * - rule-view-refreshed
  *      Fired when the rule view updates to a new node
  * - rule-view-sourcelinks-updated
  *      Fired when the stylesheet source links have been updated (when switching
  *      to source-mapped files)
  */
-function InspectorPanel(iframeWindow, toolbox) {
+function Inspector(toolbox) {
   this._toolbox = toolbox;
   this._target = toolbox.target;
-  this.panelDoc = iframeWindow.document;
-  this.panelWin = iframeWindow;
+  this.panelDoc = window.document;
+  this.panelWin = window;
   this.panelWin.inspector = this;
 
   this.telemetry = new Telemetry();
 
   this.nodeMenuTriggerInfo = null;
 
   this._handleRejectionIfNotDestroyed = this._handleRejectionIfNotDestroyed.bind(this);
   this._onBeforeNavigate = this._onBeforeNavigate.bind(this);
@@ -107,23 +111,21 @@ function InspectorPanel(iframeWindow, to
   this.onSidebarHidden = this.onSidebarHidden.bind(this);
 
   this._target.on("will-navigate", this._onBeforeNavigate);
   this._detectingActorFeatures = this._detectActorFeatures();
 
   EventEmitter.decorate(this);
 }
 
-exports.InspectorPanel = InspectorPanel;
-
-InspectorPanel.prototype = {
+Inspector.prototype = {
   /**
    * open is effectively an asynchronous constructor
    */
-  open: Task.async(function* () {
+  init: Task.async(function* () {
     // Localize all the nodes containing a data-localization attribute.
     localizeMarkup(this.panelDoc);
 
     this._cssPropertiesLoaded = initCssProperties(this.toolbox);
     yield this._cssPropertiesLoaded;
     yield this.target.makeRemote();
     yield this._getPageStyle();
     let defaultSelection = yield this._getDefaultNodeForSelection();
@@ -141,16 +143,20 @@ InspectorPanel.prototype = {
   get walker() {
     return this._toolbox.walker;
   },
 
   get selection() {
     return this._toolbox.selection;
   },
 
+  get highlighter() {
+    return this._toolbox.highlighter;
+  },
+
   get isOuterHTMLEditable() {
     return this._target.client.traits.editOuterHTML;
   },
 
   get hasUrlToImageDataResolver() {
     return this._target.client.traits.urlToImageDataResolver;
   },
 
@@ -270,17 +276,17 @@ InspectorPanel.prototype = {
     this._defaultNode = null;
     this.selection.setNodeFront(null);
     this._destroyMarkup();
     this.isDirty = false;
     this._pendingSelection = null;
   },
 
   _getPageStyle: function () {
-    return this._toolbox.inspector.getPageStyle().then(pageStyle => {
+    return this.inspector.getPageStyle().then(pageStyle => {
       this.pageStyle = pageStyle;
     }, this._handleRejectionIfNotDestroyed);
   },
 
   /**
    * Return a promise that will resolve to the default node for selection.
    */
   _getDefaultNodeForSelection: function () {
@@ -1811,8 +1817,77 @@ InspectorPanel.prototype = {
   copyAttributeLink: function (link) {
     // When the inspector menu was setup on click (see _getNodeLinkMenuItems), we
     // already checked that resolveRelativeURL existed.
     this.inspector.resolveRelativeURL(link, this.selection.nodeFront).then(url => {
       clipboardHelper.copyString(url);
     }, console.error);
   }
 };
+
+// URL constructor doesn't support chrome: scheme
+let href = window.location.href.replace(/chrome:/, "http://");
+let url = new window.URL(href);
+
+// Only use this method to attach the toolbox if some query parameters are given
+if (url.search.length > 1) {
+  const { targetFromURL } = require("devtools/client/framework/target-from-url");
+  const { attachThread } = require("devtools/client/framework/attach-thread");
+  const { BrowserLoader } =
+    Cu.import("resource://devtools/client/shared/browser-loader.js", {});
+
+  const { Selection } = require("devtools/client/framework/selection");
+  const { InspectorFront } = require("devtools/shared/fronts/inspector");
+  const { getHighlighterUtils } = require("devtools/client/framework/toolbox-highlighter-utils");
+
+  Task.spawn(function* () {
+    let target = yield targetFromURL(url);
+
+    let fakeToolbox = {
+      target,
+      hostType: "bottom",
+      doc: window.document,
+      win: window,
+      on() {}, emit() {}, off() {},
+      initInspector() {},
+      browserRequire: BrowserLoader({
+        window: window,
+        useOnlyShared: true
+      }).require,
+      get React() {
+        return this.browserRequire("devtools/client/shared/vendor/react");
+      },
+      get ReactDOM() {
+        return this.browserRequire("devtools/client/shared/vendor/react-dom");
+      },
+      isToolRegistered() {
+        return false;
+      },
+      // For attachThread:
+      highlightTool() {},
+      unhighlightTool() {},
+      selectTool() {},
+      raise() {},
+      getNotificationBox() {}
+    };
+
+    // attachThread also expect a toolbox as argument
+    fakeToolbox.threadClient = yield attachThread(fakeToolbox);
+
+    let inspector = InspectorFront(target.client, target.form);
+    let showAllAnonymousContent =
+      Services.prefs.getBoolPref("devtools.inspector.showAllAnonymousContent");
+    let walker = yield inspector.getWalker({ showAllAnonymousContent });
+    let selection = new Selection(walker);
+    let highlighter = yield inspector.getHighlighter(false);
+
+    fakeToolbox.inspector = inspector;
+    fakeToolbox.walker = walker;
+    fakeToolbox.selection = selection;
+    fakeToolbox.highlighter = highlighter;
+    fakeToolbox.highlighterUtils = getHighlighterUtils(fakeToolbox);
+
+    let inspectorUI = new Inspector(fakeToolbox);
+    inspectorUI.init();
+  }).then(null, e => {
+    window.alert("Unable to start the inspector:" + e.message + "\n" + e.stack);
+  });
+}
--- a/devtools/client/inspector/inspector.xhtml
+++ b/devtools/client/inspector/inspector.xhtml
@@ -20,16 +20,17 @@
 
 <!DOCTYPE html>
 
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
   <script type="application/javascript;version=1.8"
           src="chrome://devtools/content/shared/theme-switching.js"></script>
+  <script type="application/javascript;version=1.8" src="inspector-panel.js" defer="true"></script>
 </head>
 <body class="theme-body" role="application">
   <div class="inspector-responsive-container theme-body inspector">
 
     <!-- Main Panel Content -->
     <div id="inspector-main-content" class="devtools-main-content">
       <div id="inspector-toolbar" class="devtools-toolbar" nowindowdrag="true"
                 data-localization-bundle="devtools/locale/inspector.properties">
--- a/devtools/client/inspector/moz.build
+++ b/devtools/client/inspector/moz.build
@@ -9,15 +9,15 @@ DIRS += [
     'markup',
     'rules',
     'shared'
 ]
 
 DevToolsModules(
     'breadcrumbs.js',
     'inspector-commands.js',
-    'inspector-panel.js',
     'inspector-search.js',
     'inspector.xhtml',
+    'panel.js',
     'toolsidebar.js',
 )
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/panel.js
@@ -0,0 +1,19 @@
+/* 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";
+
+function InspectorPanel(iframeWindow, toolbox) {
+  this._inspector = new iframeWindow.Inspector(toolbox);
+}
+InspectorPanel.prototype = {
+  open() {
+    return this._inspector.init();
+  },
+
+  destroy() {
+    return this._inspector.destroy();
+  }
+};
+exports.InspectorPanel = InspectorPanel;
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -20,16 +20,17 @@ devtools.jar:
     content/webconsole/webconsole.xul (webconsole/webconsole.xul)
 *   content/scratchpad/scratchpad.xul (scratchpad/scratchpad.xul)
     content/scratchpad/scratchpad.js (scratchpad/scratchpad.js)
     content/shared/splitview.css (shared/splitview.css)
     content/shared/theme-switching.js (shared/theme-switching.js)
     content/shared/frame-script-utils.js (shared/frame-script-utils.js)
     content/styleeditor/styleeditor.xul (styleeditor/styleeditor.xul)
     content/storage/storage.xul (storage/storage.xul)
+    content/inspector/inspector-panel.js (inspector/inspector-panel.js)
     content/inspector/fonts/fonts.js (inspector/fonts/fonts.js)
     content/inspector/markup/markup.xhtml (inspector/markup/markup.xhtml)
     content/animationinspector/animation-controller.js (animationinspector/animation-controller.js)
     content/animationinspector/animation-panel.js (animationinspector/animation-panel.js)
     content/animationinspector/animation-inspector.xhtml (animationinspector/animation-inspector.xhtml)
     content/sourceeditor/codemirror/addon/dialog/dialog.css (sourceeditor/codemirror/addon/dialog/dialog.css)
     content/sourceeditor/codemirror/addon/hint/show-hint.js (sourceeditor/codemirror/addon/hint/show-hint.js)
     content/sourceeditor/codemirror/addon/tern/tern.js (sourceeditor/codemirror/addon/tern/tern.js)