Web Inspector: Embeddable Web Inspector
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Aug 2012 23:30:25 +0000 (23:30 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Aug 2012 23:30:25 +0000 (23:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=91528

Patch by Gabriel Peal <gpeal@google.com> on 2012-08-21
Reviewed by Pavel Feldman.

Adds functionality to the inspector such that it is better suited to run embedded in another webpage. It adds the ability to prepopulate the timeline panel with an existing recording among other controls.

* English.lproj/localizedStrings.js:
* inspector/front-end/InspectorFrontendAPI.js:
(InspectorFrontendAPI.dispatchQueryParameters):
(InspectorFrontendAPI.loadTimelineFromURL):
* inspector/front-end/InspectorFrontendHostStub.js:
(.WebInspector.InspectorFrontendHostStub.prototype.hiddenPanels):
(.WebInspector.InspectorFrontendHostStub.prototype.loadResourceSynchronously):
* inspector/front-end/InspectorView.js:
* inspector/front-end/TimelineModel.js:
(WebInspector.TimelineModel.prototype.loadFromURL.onDataReceived):
(WebInspector.TimelineModel.prototype.loadFromURL.parseAndImportData):
(WebInspector.TimelineModel.prototype.loadFromURL.onLoad):
(WebInspector.TimelineModel.prototype.loadFromURL):
* inspector/front-end/TimelinePanel.js:
(WebInspector.TimelinePanel.prototype.loadFromURL):
* inspector/front-end/inspector.js:
(WebInspector._createPanels):
(WebInspector.loaded):
* inspector/front-end/utilities.js:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@126215 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/English.lproj/localizedStrings.js
Source/WebCore/inspector/front-end/InspectorFrontendAPI.js
Source/WebCore/inspector/front-end/InspectorFrontendHostStub.js
Source/WebCore/inspector/front-end/InspectorView.js
Source/WebCore/inspector/front-end/JavaScriptSourceFrame.js
Source/WebCore/inspector/front-end/TimelineModel.js
Source/WebCore/inspector/front-end/TimelinePanel.js
Source/WebCore/inspector/front-end/externs.js
Source/WebCore/inspector/front-end/inspector.js
Source/WebCore/inspector/front-end/utilities.js

index 43bafcc..feb0e5e 100644 (file)
@@ -1,3 +1,32 @@
+2012-08-21  Gabriel Peal  <gpeal@google.com>
+
+        Web Inspector: Embeddable Web Inspector
+        https://bugs.webkit.org/show_bug.cgi?id=91528
+
+        Reviewed by Pavel Feldman.
+
+        Adds functionality to the inspector such that it is better suited to run embedded in another webpage. It adds the ability to prepopulate the timeline panel with an existing recording among other controls.
+
+        * English.lproj/localizedStrings.js:
+        * inspector/front-end/InspectorFrontendAPI.js:
+        (InspectorFrontendAPI.dispatchQueryParameters):
+        (InspectorFrontendAPI.loadTimelineFromURL):
+        * inspector/front-end/InspectorFrontendHostStub.js:
+        (.WebInspector.InspectorFrontendHostStub.prototype.hiddenPanels):
+        (.WebInspector.InspectorFrontendHostStub.prototype.loadResourceSynchronously):
+        * inspector/front-end/InspectorView.js:
+        * inspector/front-end/TimelineModel.js:
+        (WebInspector.TimelineModel.prototype.loadFromURL.onDataReceived):
+        (WebInspector.TimelineModel.prototype.loadFromURL.parseAndImportData):
+        (WebInspector.TimelineModel.prototype.loadFromURL.onLoad):
+        (WebInspector.TimelineModel.prototype.loadFromURL):
+        * inspector/front-end/TimelinePanel.js:
+        (WebInspector.TimelinePanel.prototype.loadFromURL):
+        * inspector/front-end/inspector.js:
+        (WebInspector._createPanels):
+        (WebInspector.loaded):
+        * inspector/front-end/utilities.js:
+
 2012-08-21  Robin Cao  <robin.cao@torchmobile.com.cn>
 
         [BlackBerry] Add support for getUserMedia
index 95742fe..752cb9e 100644 (file)
@@ -582,9 +582,9 @@ localizedStrings["Load timeline data\u2026"] = "Load Timeline data\u2026";
 localizedStrings["Save timeline data\u2026"] = "Save Timeline data\u2026";
 localizedStrings["Load timeline data"] = "Load Timeline data";
 localizedStrings["Save timeline data"] = "Save Timeline data";
-localizedStrings["Timeline.loadFromFile: An error occurred reading the file \"%s\""] = "Timeline.loadFromFile: An error occurred while reading the file \"%s\"";
-localizedStrings["Timeline.loadFromFile: File \"%s\" is not readable"] = "Timeline.loadFromFile: File \"%s\" is not readable";
-localizedStrings["Timeline.loadFromFile: File \"%s\" not found."] = "Timeline.loadFromFile: File \"%s\" not found.";
+localizedStrings["An error occurred reading the file \"%s\""] = "An error occurred while reading the file \"%s\"";
+localizedStrings["File \"%s\" is not readable"] = "File \"%s\" is not readable";
+localizedStrings["File \"%s\" not found."] = "File \"%s\" not found.";
 localizedStrings["Filter out records shorter than %s"] = "Filter out records shorter than %s";
 localizedStrings["Show user agent styles"] = "Show user agent styles";
 localizedStrings["Show script folders"] = "Show script folders";
index 90a254a..bab529e 100644 (file)
@@ -52,7 +52,7 @@ InspectorFrontendAPI = {
 
     setTimelineProfilingEnabled: function(enabled)
     {
-        WebInspector.panel("timeline").setTimelineProfilingEnabled(enabled);
+        WebInspector.showPanel("timeline").setTimelineProfilingEnabled(enabled);
     },
 
     isProfilingJavaScript: function()
@@ -133,6 +133,20 @@ InspectorFrontendAPI = {
         InspectorFrontendAPI._pendingCommands.push(signature);
     },
 
+    dispatchQueryParameters: function()
+    {
+        if ("dispatch" in WebInspector.queryParamsObject)
+            InspectorFrontendAPI.dispatch(JSON.parse(window.decodeURI(WebInspector.queryParamsObject["dispatch"])));
+    },
+
+    /**
+     * @param {string} url
+     */
+    loadTimelineFromURL: function(url) 
+    {
+        WebInspector.showPanel("timeline").loadFromURL(url);
+    },
+
     loadCompleted: function()
     {
         InspectorFrontendAPI._isLoaded = true;
index 0b4eaa6..61d8ae8 100644 (file)
@@ -102,7 +102,7 @@ WebInspector.InspectorFrontendHostStub.prototype = {
 
     hiddenPanels: function()
     {
-        return "";
+        return WebInspector.queryParamsObject["hiddenPanels"] || "";
     },
 
     inspectedURLChanged: function(url)
@@ -179,7 +179,7 @@ WebInspector.InspectorFrontendHostStub.prototype = {
 
     loadResourceSynchronously: function(url)
     {
-        return "";
+        return loadXHR(url);
     },
 
     setZoomFactor: function(zoom)
index d49b04e..e5799ba 100644 (file)
@@ -95,7 +95,10 @@ WebInspector.InspectorView.prototype = {
     {
         return this._currentPanel;
     },
-
+    
+    /**
+     * @param {WebInspector.Panel} x
+     */
     setCurrentPanel: function(x)
     {
         if (this._currentPanel === x)
index ae12bae..fdd730a 100644 (file)
@@ -160,7 +160,7 @@ WebInspector.JavaScriptSourceFrame.prototype = {
     _didEditContent: function(error)
     {
         if (error) {
-            WebInspector.log(error, WebInspector.ConsoleMessage.MessageLevel.Error, true);
+            WebInspector.showErrorMessage(error);
             return;
         }
         if (!this._javaScriptSource.supportsEnabledBreakpointsWhileEditing())
index 77a5b39..dff3044 100644 (file)
@@ -197,11 +197,16 @@ WebInspector.TimelineModel.prototype = {
 
         function parseAndImportData(data)
         {
-            var records = JSON.parse(data);
-            parsingProgress.done();
-            this.reset();
-            processingProgress.setTotalWork(records.length);
-            this._loadNextChunk(processingProgress, records, 1);
+            try {
+                var records = JSON.parse(data);
+                parsingProgress.done();
+                this.reset();
+                processingProgress.setTotalWork(records.length);
+                this._loadNextChunk(processingProgress, records, 1);
+            } catch (e) {
+                WebInspector.showErrorMessage("Malformed timeline data.");
+                progress.done();
+            }
         }
 
         function onLoad(e)
@@ -216,15 +221,15 @@ WebInspector.TimelineModel.prototype = {
             progress.done();
             switch(e.target.error.code) {
             case e.target.error.NOT_FOUND_ERR:
-                WebInspector.log(WebInspector.UIString('Timeline.loadFromFile: File "%s" not found.', file.name));
+                WebInspector.showErrorMessage(WebInspector.UIString("File \"%s\" not found.", file.name));
             break;
             case e.target.error.NOT_READABLE_ERR:
-                WebInspector.log(WebInspector.UIString('Timeline.loadFromFile: File "%s" is not readable', file.name));
+                WebInspector.showErrorMessage(WebInspector.UIString("File \"%s\" is not readable", file.name));
             break;
             case e.target.error.ABORT_ERR:
                 break;
             default:
-                WebInspector.log(WebInspector.UIString('Timeline.loadFromFile: An error occurred while reading the file "%s"', file.name));
+                WebInspector.showErrorMessage(WebInspector.UIString("An error occurred while reading the file \"%s\"", file.name));
             }
         }
 
@@ -243,6 +248,39 @@ WebInspector.TimelineModel.prototype = {
         reader.readAsText(file);
     },
 
+    /**
+     * @param {string} url
+     */
+    loadFromURL: function(url, progress)
+    {
+        var compositeProgress = new WebInspector.CompositeProgress(progress);
+        var loadingProgress = compositeProgress.createSubProgress(1);
+        var parsingProgress = compositeProgress.createSubProgress(1);
+        var processingProgress = compositeProgress.createSubProgress(1);
+
+        // FIXME: extract parsing routines so that they did not require too many progress objects.
+        function parseAndImportData(data)
+        {
+            try {
+                var records = JSON.parse(data);
+                parsingProgress.done();
+                this.reset();
+                processingProgress.setTotalWork(records.length);
+                this._loadNextChunk(processingProgress, records, 1);
+            } catch (e) {
+                WebInspector.showErrorMessage("Malformed timeline data.");
+                progress.done();
+            }
+        }
+
+        var responseText = loadXHR(url);
+        if (responseText) {
+            loadingProgress.done();
+            parsingProgress.setTotalWork(1);
+            setTimeout(parseAndImportData.bind(this, responseText), 0);
+        }
+    },
+
     saveToFile: function()
     {
         var records = ['[' + JSON.stringify(new String(window.navigator.appVersion))];
index b6ec0dd..661d6bb 100644 (file)
@@ -349,8 +349,31 @@ WebInspector.TimelinePanel.prototype = {
 
     _loadFromFile: function()
     {
-        if (this._operationInProgress)
+        var progressIndicator = this._prepareToLoadTimeline();
+        if (!progressIndicator)
+            return;
+        this._model.loadFromFile(this._fileSelectorElement.files[0], progressIndicator);
+        this._createFileSelector();
+    },
+
+    /**
+     * @param {string} url
+     */
+    loadFromURL: function(url)
+    {
+        var progressIndicator = this._prepareToLoadTimeline();
+        if (!progressIndicator)
             return;
+        this._model.loadFromURL(url, progressIndicator);
+    },
+
+    /**
+     * @return {?WebInspector.ProgressIndicator}
+     */
+    _prepareToLoadTimeline: function()
+    {
+        if (this._operationInProgress)
+            return null;
         if (this.toggleTimelineButton.toggled) {
             this.toggleTimelineButton.toggled = false;
             this._model.stopRecord();
@@ -358,8 +381,7 @@ WebInspector.TimelinePanel.prototype = {
         var progressIndicator = new WebInspector.ProgressIndicator();
         progressIndicator.addEventListener(WebInspector.ProgressIndicator.Events.Done, this._setOperationInProgress.bind(this, null));
         this._setOperationInProgress(progressIndicator);
-        this._model.loadFromFile(this._fileSelectorElement.files[0], progressIndicator);
-        this._createFileSelector();
+        return progressIndicator;
     },
 
     _rootRecord: function()
index ac508bf..92b877e 100644 (file)
@@ -142,6 +142,8 @@ WebInspector.closeViewInDrawer = function() {}
  */
 WebInspector.log = function(message, messageLevel, showConsole) {}
 
+WebInspector.showErrorMessage = function(error) {}
+
 WebInspector.addMainEventListeners = function(doc) {}
 
 WebInspector.openResource = function(url, external) {}
index 91ee54f..b3319c1 100644 (file)
@@ -56,7 +56,7 @@ var WebInspector = {
             return panelDescriptors;
         }
         var allDescriptors = [elements, resources, network, scripts, timeline, profiles, audits, console];
-        var hiddenPanels = (InspectorFrontendHost.hiddenPanels() || "").split(',');
+        var hiddenPanels = InspectorFrontendHost.hiddenPanels();
         for (var i = 0; i < allDescriptors.length; ++i) {
             if (hiddenPanels.indexOf(allDescriptors[i].name) === -1)
                 panelDescriptors.push(allDescriptors[i]);
@@ -433,7 +433,14 @@ WebInspector.loaded = function()
         }
         return;
     }
+
     WebInspector.doLoadedDone();
+
+    // In case of loading as a web page with no bindings / harness, kick off initialization manually.
+    if (InspectorFrontendHost.isStub) {
+        InspectorFrontendAPI.dispatchQueryParameters();
+        WebInspector._doLoadedDoneWithCapabilities();
+    }
 }
 
 WebInspector.doLoadedDone = function()
@@ -458,8 +465,6 @@ WebInspector.doLoadedDone = function()
     PageAgent.canOverrideDeviceMetrics(WebInspector._initializeCapability.bind(WebInspector, "canOverrideDeviceMetrics", null));
     PageAgent.canOverrideGeolocation(WebInspector._initializeCapability.bind(WebInspector, "canOverrideGeolocation", null));
     PageAgent.canOverrideDeviceOrientation(WebInspector._initializeCapability.bind(WebInspector, "canOverrideDeviceOrientation", WebInspector._doLoadedDoneWithCapabilities.bind(WebInspector)));
-    if ("debugLoad" in WebInspector.queryParamsObject)
-        WebInspector._doLoadedDoneWithCapabilities();
 }
 
 WebInspector._doLoadedDoneWithCapabilities = function()
@@ -993,6 +998,11 @@ WebInspector.log = function(message, messageLevel, showConsole)
     logMessage(message);
 }
 
+WebInspector.showErrorMessage = function(error)
+{
+    WebInspector.log(error, WebInspector.ConsoleMessage.MessageLevel.Error, true);
+}
+
 WebInspector.inspect = function(payload, hints)
 {
     var object = WebInspector.RemoteObject.fromPayload(payload);
index f215ce1..d9fa794 100644 (file)
@@ -726,6 +726,40 @@ Map.prototype = {
     }
 };
 
+/**
+ * @param {string} url
+ * @param {boolean=} async
+ * @param {function(?string)=} callback
+ * @return {?string}
+ */
+function loadXHR(url, async, callback) 
+{
+    function onReadyStateChanged() 
+    {
+        if (xhr.readyState !== XMLHttpRequest.DONE)
+            return;
+
+        if (xhr.status === 200) {
+            callback(xhr.responseText);
+            return;
+        }
+
+        callback(null); 
+   }
+
+    var xhr = new XMLHttpRequest();
+    xhr.open("GET", url, async);
+    if (async)
+        xhr.onreadystatechange = onReadyStateChanged;        
+    xhr.send(null);
+
+    if (!async) {
+        if (xhr.status === 200) 
+            return xhr.responseText;
+        return null;
+    }
+    return null;
+}
 
 /**
  * @constructor