Title: [193870] trunk/Source/WebInspectorUI
Revision
193870
Author
bb...@apple.com
Date
2015-12-09 14:45:21 -0800 (Wed, 09 Dec 2015)

Log Message

Web Inspector: control whether to collect and dump protocol messages using a WebInspector.Setting
https://bugs.webkit.org/show_bug.cgi?id=151635

Reviewed by Timothy Hatcher.

When closing and reopening the inspector, the setting for whether
to dump protocol messages should be persisted. Otherwise, enabling
dumping from the debug-only UI will miss the initial flood of
messages that are processed when the Inspector loads initial data.

To support a persistent setting, and build some infrastructure for
more advanced uses of collected protocol messages, this patch adds
a new object to trace protocol events. It gets callbacks for each
and implements the console-dumping functionality previously baked in
to InspectorBackend.

In follow-up patches, other protocol tracers will be added to save
protocol data to disk, marshall it to a higher inspection level,
or provide more fine-grained control over what is logged.

This change moves Setting.js into the Base/ directory,
since it is used by Views, Models, and now Protocol classes.

* UserInterface/Base/Setting.js: Renamed from Source/WebInspectorUI/UserInterface/Models/Setting.js.
(WebInspector.Setting):
(WebInspector.Setting.prototype.get name):
(WebInspector.Setting.prototype.get value):
(WebInspector.Setting.prototype.set value):
* UserInterface/Main.html:
* UserInterface/Protocol/InspectorBackend.js:
(InspectorBackendClass):
(InspectorBackendClass.prototype.set dumpInspectorProtocolMessages):
(InspectorBackendClass.prototype.get dumpInspectorProtocolMessages):

    We still want to support the legacy way to enable dumping:
    `InspectorBackend.dumpInspectorProtocolMessages = true`. This
    is because some tests always use it, and it's easier to set this
    flag in a custom Bootstrap.js file than to configure the Setting.

(InspectorBackendClass.prototype.set dumpInspectorTimeStats):
(InspectorBackendClass.prototype.get dumpInspectorTimeStats):

    We still want to support the legacy way to enable dumping:
    `InspectorBackend.dumpInspectorTimeStats = true`. This is
    because MessageDispatcher checks this flag for its logging.

(InspectorBackendClass.prototype.set activeTracer):
(InspectorBackendClass.prototype.get activeTracer):

    Set the active tracer, finalizing and removing any active tracer
    if one exists. If removing a custom tracer (setting to null), then
    re-sync activeTracer with the automatic tracing Setting.

(InspectorBackendClass.prototype.dispatch):
(InspectorBackendClass.prototype._startOrStopAutomaticTracing):

    Sync the Setting with activeTracer. If an custom tracer is active,
    don't replace it with the automatic logging tracer.

(InspectorBackendClass.prototype._sendCommandToBackendWithCallback):
(InspectorBackendClass.prototype._sendCommandToBackendExpectingPromise):
(InspectorBackendClass.prototype._sendMessageToBackend):
(InspectorBackendClass.prototype._dispatchResponse):
(InspectorBackendClass.prototype._dispatchEvent):
(InspectorBackendClass.prototype._flushPendingScripts):
* UserInterface/Protocol/LoggingProtocolTracer.js: Added.
(WebInspector.LoggingProtocolTracer):
(WebInspector.LoggingProtocolTracer.prototype.set dumpMessagesToConsole):
(WebInspector.LoggingProtocolTracer.prototype.get dumpMessagesToConsole):
(WebInspector.LoggingProtocolTracer.prototype.set dumpTimingDataToConsole):
(WebInspector.LoggingProtocolTracer.prototype.get dumpTimingDataToConsole):
(WebInspector.LoggingProtocolTracer.prototype.logFrontendException):
(WebInspector.LoggingProtocolTracer.prototype.logProtocolError):
(WebInspector.LoggingProtocolTracer.prototype.logFrontendRequest):
(WebInspector.LoggingProtocolTracer.prototype.logWillHandleResponse):
(WebInspector.LoggingProtocolTracer.prototype.logDidHandleResponse):
(WebInspector.LoggingProtocolTracer.prototype.logWillHandleEvent):
(WebInspector.LoggingProtocolTracer.prototype.logDidHandleEvent):
(WebInspector.LoggingProtocolTracer.prototype._processEntry):
* UserInterface/Protocol/ProtocolTracer.js: Added.
(WebInspector.ProtocolTracer.prototype.logStarted):
(WebInspector.ProtocolTracer.prototype.logFrontendException):
(WebInspector.ProtocolTracer.prototype.logProtocolError):
(WebInspector.ProtocolTracer.prototype.logFrontendRequest):
(WebInspector.ProtocolTracer.prototype.logWillHandleResponse):
(WebInspector.ProtocolTracer.prototype.logDidHandleResponse):
(WebInspector.ProtocolTracer.prototype.logWillHandleEvent):
(WebInspector.ProtocolTracer.prototype.logDidHandleEvent):        (WebInspector.ProtocolTracer.prototype.logFinished):
(WebInspector.ProtocolTracer):
* UserInterface/Test.html:

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Source/WebInspectorUI/ChangeLog (193869 => 193870)


--- trunk/Source/WebInspectorUI/ChangeLog	2015-12-09 22:39:46 UTC (rev 193869)
+++ trunk/Source/WebInspectorUI/ChangeLog	2015-12-09 22:45:21 UTC (rev 193870)
@@ -1,5 +1,98 @@
 2015-12-09  Brian Burg  <bb...@apple.com>
 
+        Web Inspector: control whether to collect and dump protocol messages using a WebInspector.Setting
+        https://bugs.webkit.org/show_bug.cgi?id=151635
+
+        Reviewed by Timothy Hatcher.
+
+        When closing and reopening the inspector, the setting for whether
+        to dump protocol messages should be persisted. Otherwise, enabling
+        dumping from the debug-only UI will miss the initial flood of
+        messages that are processed when the Inspector loads initial data.
+
+        To support a persistent setting, and build some infrastructure for
+        more advanced uses of collected protocol messages, this patch adds
+        a new object to trace protocol events. It gets callbacks for each
+        and implements the console-dumping functionality previously baked in
+        to InspectorBackend.
+
+        In follow-up patches, other protocol tracers will be added to save
+        protocol data to disk, marshall it to a higher inspection level,
+        or provide more fine-grained control over what is logged.
+
+        This change moves Setting.js into the Base/ directory,
+        since it is used by Views, Models, and now Protocol classes.
+
+        * UserInterface/Base/Setting.js: Renamed from Source/WebInspectorUI/UserInterface/Models/Setting.js.
+        (WebInspector.Setting):
+        (WebInspector.Setting.prototype.get name):
+        (WebInspector.Setting.prototype.get value):
+        (WebInspector.Setting.prototype.set value):
+        * UserInterface/Main.html:
+        * UserInterface/Protocol/InspectorBackend.js:
+        (InspectorBackendClass):
+        (InspectorBackendClass.prototype.set dumpInspectorProtocolMessages):
+        (InspectorBackendClass.prototype.get dumpInspectorProtocolMessages):
+
+            We still want to support the legacy way to enable dumping:
+            `InspectorBackend.dumpInspectorProtocolMessages = true`. This
+            is because some tests always use it, and it's easier to set this
+            flag in a custom Bootstrap.js file than to configure the Setting.
+
+        (InspectorBackendClass.prototype.set dumpInspectorTimeStats):
+        (InspectorBackendClass.prototype.get dumpInspectorTimeStats):
+
+            We still want to support the legacy way to enable dumping:
+            `InspectorBackend.dumpInspectorTimeStats = true`. This is
+            because MessageDispatcher checks this flag for its logging.
+
+        (InspectorBackendClass.prototype.set activeTracer):
+        (InspectorBackendClass.prototype.get activeTracer):
+
+            Set the active tracer, finalizing and removing any active tracer
+            if one exists. If removing a custom tracer (setting to null), then
+            re-sync activeTracer with the automatic tracing Setting.
+
+        (InspectorBackendClass.prototype.dispatch):
+        (InspectorBackendClass.prototype._startOrStopAutomaticTracing):
+
+            Sync the Setting with activeTracer. If an custom tracer is active,
+            don't replace it with the automatic logging tracer.
+
+        (InspectorBackendClass.prototype._sendCommandToBackendWithCallback):
+        (InspectorBackendClass.prototype._sendCommandToBackendExpectingPromise):
+        (InspectorBackendClass.prototype._sendMessageToBackend):
+        (InspectorBackendClass.prototype._dispatchResponse):
+        (InspectorBackendClass.prototype._dispatchEvent):
+        (InspectorBackendClass.prototype._flushPendingScripts):
+        * UserInterface/Protocol/LoggingProtocolTracer.js: Added.
+        (WebInspector.LoggingProtocolTracer):
+        (WebInspector.LoggingProtocolTracer.prototype.set dumpMessagesToConsole):
+        (WebInspector.LoggingProtocolTracer.prototype.get dumpMessagesToConsole):
+        (WebInspector.LoggingProtocolTracer.prototype.set dumpTimingDataToConsole):
+        (WebInspector.LoggingProtocolTracer.prototype.get dumpTimingDataToConsole):
+        (WebInspector.LoggingProtocolTracer.prototype.logFrontendException):
+        (WebInspector.LoggingProtocolTracer.prototype.logProtocolError):
+        (WebInspector.LoggingProtocolTracer.prototype.logFrontendRequest):
+        (WebInspector.LoggingProtocolTracer.prototype.logWillHandleResponse):
+        (WebInspector.LoggingProtocolTracer.prototype.logDidHandleResponse):
+        (WebInspector.LoggingProtocolTracer.prototype.logWillHandleEvent):
+        (WebInspector.LoggingProtocolTracer.prototype.logDidHandleEvent):
+        (WebInspector.LoggingProtocolTracer.prototype._processEntry):
+        * UserInterface/Protocol/ProtocolTracer.js: Added.
+        (WebInspector.ProtocolTracer.prototype.logStarted):
+        (WebInspector.ProtocolTracer.prototype.logFrontendException):
+        (WebInspector.ProtocolTracer.prototype.logProtocolError):
+        (WebInspector.ProtocolTracer.prototype.logFrontendRequest):
+        (WebInspector.ProtocolTracer.prototype.logWillHandleResponse):
+        (WebInspector.ProtocolTracer.prototype.logDidHandleResponse):
+        (WebInspector.ProtocolTracer.prototype.logWillHandleEvent):
+        (WebInspector.ProtocolTracer.prototype.logDidHandleEvent):        (WebInspector.ProtocolTracer.prototype.logFinished):
+        (WebInspector.ProtocolTracer):
+        * UserInterface/Test.html:
+
+2015-12-09  Brian Burg  <bb...@apple.com>
+
         Web Inspector: zoom with Ctrl +/- doesn't work correctly when inspector is docked
         https://bugs.webkit.org/show_bug.cgi?id=152076
 

Copied: trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js (from rev 193867, trunk/Source/WebInspectorUI/UserInterface/Models/Setting.js) (0 => 193870)


--- trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js	2015-12-09 22:45:21 UTC (rev 193870)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Setting = class Setting extends WebInspector.Object
+{
+    constructor(name, defaultValue)
+    {
+        super();
+
+        this._name = name;
+
+        let inspectionLevel = InspectorFrontendHost ? InspectorFrontendHost.inspectionLevel() : 1;
+        let levelString = inspectionLevel > 1 ? "-" + inspectionLevel : "";
+        this._localStorageKey = `com.apple.WebInspector${levelString}.${name}`;
+        this._defaultValue = defaultValue;
+    }
+
+    // Public
+
+    get name()
+    {
+        return this._name;
+    }
+
+    get value()
+    {
+        if ("_value" in this)
+            return this._value;
+
+        // Make a copy of the default value so changes to object values don't modify the default value.
+        this._value = JSON.parse(JSON.stringify(this._defaultValue));
+
+        if (!window.InspectorTest && window.localStorage && this._localStorageKey in window.localStorage) {
+            try {
+                this._value = JSON.parse(window.localStorage[this._localStorageKey]);
+            } catch(e) {
+                delete window.localStorage[this._localStorageKey];
+            }
+        }
+
+        return this._value;
+    }
+
+    set value(value)
+    {
+        this._value = value;
+
+        if (!window.InspectorTest && window.localStorage) {
+            try {
+                // Use Object.shallowEqual to properly compare objects.
+                if (Object.shallowEqual(this._value, this._defaultValue))
+                    delete window.localStorage[this._localStorageKey];
+                else
+                    window.localStorage[this._localStorageKey] = JSON.stringify(this._value);
+            } catch(e) {
+                console.error("Error saving setting with name: " + this._name);
+            }
+        }
+
+        this.dispatchEventToListeners(WebInspector.Setting.Event.Changed, this._value, {name: this._name});
+    }
+};
+
+WebInspector.Setting.Event = {
+    Changed: "setting-changed"
+};

Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (193869 => 193870)


--- trunk/Source/WebInspectorUI/UserInterface/Main.html	2015-12-09 22:39:46 UTC (rev 193869)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html	2015-12-09 22:45:21 UTC (rev 193870)
@@ -224,7 +224,11 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
 
+    <script src=""
+    <script src=""
+
     <script src=""
     <script src=""
     <script src=""
@@ -328,7 +332,6 @@
     <script src=""
     <script src=""
     <script src=""
-    <script src=""
     <script src=""
     <script src=""
     <script src=""

Deleted: trunk/Source/WebInspectorUI/UserInterface/Models/Setting.js (193869 => 193870)


--- trunk/Source/WebInspectorUI/UserInterface/Models/Setting.js	2015-12-09 22:39:46 UTC (rev 193869)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/Setting.js	2015-12-09 22:45:21 UTC (rev 193870)
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- * Copyright (C) 2013 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WebInspector.Setting = class Setting extends WebInspector.Object
-{
-    constructor(name, defaultValue)
-    {
-        super();
-
-        this._name = name;
-
-        let inspectionLevel = InspectorFrontendHost.inspectionLevel();
-        let levelString = inspectionLevel > 1 ? "-" + inspectionLevel : "";
-        this._localStorageKey = `com.apple.WebInspector${levelString}.${name}`;
-        this._defaultValue = defaultValue;
-    }
-
-    // Public
-
-    get name()
-    {
-        return this._name;
-    }
-
-    get value()
-    {
-        if ("_value" in this)
-            return this._value;
-
-        // Make a copy of the default value so changes to object values don't modify the default value.
-        this._value = JSON.parse(JSON.stringify(this._defaultValue));
-
-        if (!window.InspectorTest && window.localStorage && this._localStorageKey in window.localStorage) {
-            try {
-                this._value = JSON.parse(window.localStorage[this._localStorageKey]);
-            } catch(e) {
-                delete window.localStorage[this._localStorageKey];
-            }
-        }
-
-        return this._value;
-    }
-
-    set value(value)
-    {
-        this._value = value;
-
-        if (!window.InspectorTest && window.localStorage) {
-            try {
-                // Use Object.shallowEqual to properly compare objects.
-                if (Object.shallowEqual(this._value, this._defaultValue))
-                    delete window.localStorage[this._localStorageKey];
-                else
-                    window.localStorage[this._localStorageKey] = JSON.stringify(this._value);
-            } catch(e) {
-                console.error("Error saving setting with name: " + this._name);
-            }
-        }
-
-        this.dispatchEventToListeners(WebInspector.Setting.Event.Changed, this._value, {name: this._name});
-    }
-};
-
-WebInspector.Setting.Event = {
-    Changed: "setting-changed"
-};

Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js (193869 => 193870)


--- trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js	2015-12-09 22:39:46 UTC (rev 193869)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js	2015-12-09 22:45:21 UTC (rev 193870)
@@ -38,17 +38,92 @@
         this._pendingResponses = new Map;
         this._agents = {};
         this._deferredScripts = [];
+        this._activeTracer = null;
+        this._automaticTracer = null;
 
-        this.dumpInspectorTimeStats = false;
-        this.dumpInspectorProtocolMessages = false;
-        this.warnForLongMessageHandling = false;
-        this.longMessageHandlingThreshold = 10; // milliseconds.
+        this._dumpInspectorTimeStats = false;
 
-        this._log = window.InspectorTest ? InspectorFrontendHost.unbufferedLog.bind(InspectorFrontendHost) : console.log.bind(console);
+        let setting = WebInspector.autoLogProtocolMessagesSetting = new WebInspector.Setting("auto-collect-protocol-messages", false);
+        setting.addEventListener(WebInspector.Setting.Event.Changed, this._startOrStopAutomaticTracing.bind(this))
+        this._startOrStopAutomaticTracing();
     }
 
     // Public
 
+    // It's still possible to set this flag on InspectorBackend to just
+    // dump protocol traffic as it happens. For more complex uses of
+    // protocol data, install a subclass of WebInspector.ProtocolTracer.
+    set dumpInspectorProtocolMessages(value)
+    {
+        // Implicitly cause automatic logging to start if it's allowed.
+        let setting = WebInspector.autoLogProtocolMessagesSetting;
+        setting.value = value;
+
+        if (this.activeTracer !== this._automaticTracer)
+            return;
+
+        if (this.activeTracer)
+            this.activeTracer.dumpMessagesToConsole = value;
+    }
+
+    get dumpInspectorProtocolMessages()
+    {
+        return !!this._automaticTracer;
+    }
+
+    set dumpInspectorTimeStats(value)
+    {
+        if (!this.dumpInspectorProtocolMessages)
+            this.dumpInspectorProtocolMessages = true;
+
+        if (this.activeTracer !== this._automaticTracer)
+            return;
+
+        if (this.activeTracer)
+            this.activeTracer.dumpTimingDataToConsole = value;
+    }
+
+    get dumpInspectorTimeStats()
+    {
+        return this._dumpInspectorTimeStats;
+    }
+
+    set activeTracer(tracer)
+    {
+        console.assert(!tracer || tracer instanceof WebInspector.ProtocolTracer);
+
+        // Bail early if no state change is to be made.
+        if (!tracer && !this._activeTracer)
+            return;
+
+        if (tracer === this._activeTracer)
+            return;
+
+        // Don't allow an automatic tracer to dislodge a custom tracer.
+        if (this._activeTracer && tracer === this._automaticTracer)
+            return;
+
+        if (this.activeTracer)
+            this.activeTracer.logFinished();
+
+        if (this._activeTracer === this._automaticTracer)
+            this._automaticTracer = null;
+
+        this._activeTracer = tracer;
+        if (this.activeTracer)
+            this.activeTracer.logStarted();
+        else {
+            // If the custom tracer was removed and automatic tracing is enabled,
+            // then create a new automatic tracer and install it in its place.
+            this._startOrStopAutomaticTracing();
+        }
+    }
+
+    get activeTracer()
+    {
+        return this._activeTracer || null;
+    }
+
     registerCommand(qualifiedName, callSignature, replySignature)
     {
         var [domainName, commandName] = qualifiedName.split(".");
@@ -78,11 +153,8 @@
 
     dispatch(message)
     {
-        if (this.dumpInspectorProtocolMessages)
-            this._log("backend: " + ((typeof message === "string") ? message : JSON.stringify(message)));
+        let messageObject = (typeof message === "string") ? JSON.parse(message) : message;
 
-        var messageObject = (typeof message === "string") ? JSON.parse(message) : message;
-
         if ("id" in messageObject)
             this._dispatchResponse(messageObject);
         else
@@ -113,6 +185,28 @@
 
     // Private
 
+    _startOrStopAutomaticTracing()
+    {
+        let setting = WebInspector.autoLogProtocolMessagesSetting;
+
+        // Bail if there is no state transition to be made.
+        if (!(setting.value ^ !!this.activeTracer))
+            return;
+
+        if (!setting.value) {
+            if (this.activeTracer === this._automaticTracer)
+                this.activeTracer = null;
+
+            this._automaticTracer = null;
+        } else {
+            this._automaticTracer = new WebInspector.LoggingProtocolTracer;
+            this._automaticTracer.dumpMessagesToConsole = this.dumpInspectorProtocolMessages;
+            this._automaticTracer.dumpTimingDataToConsole = this.dumpTimingDataToConsole;
+            // This will be ignored if a custom tracer is installed.
+            this.activeTracer = this._automaticTracer;
+        }
+    }
+
     _agentForDomain(domainName)
     {
         if (this._agents[domainName])
@@ -137,7 +231,7 @@
 
         let responseData = {command, callback};
 
-        if (this.dumpInspectorTimeStats)
+        if (this.activeTracer)
             responseData.sendRequestTimestamp = timestamp();
 
         this._pendingResponses.set(sequenceId, responseData);
@@ -158,7 +252,7 @@
 
         let responseData = {command};
 
-        if (this.dumpInspectorTimeStats)
+        if (this.activeTracer)
             responseData.sendRequestTimestamp = timestamp();
 
         let responsePromise = new Promise(function(resolve, reject) {
@@ -174,8 +268,8 @@
     _sendMessageToBackend(messageObject)
     {
         let stringifiedMessage = JSON.stringify(messageObject);
-        if (this.dumpInspectorProtocolMessages)
-            this._log("frontend: " + stringifiedMessage);
+        if (this.activeTracer)
+            this.activeTracer.logFrontendRequest(stringifiedMessage);
 
         InspectorFrontendHost.sendMessageToBackend(stringifiedMessage);
     }
@@ -195,9 +289,11 @@
         let responseData = this._pendingResponses.take(sequenceId);
         let {command, callback, promise} = responseData;
 
-        var processingStartTimestamp;
-        if (this.dumpInspectorTimeStats)
+        let processingStartTimestamp;
+        if (this.activeTracer) {
             processingStartTimestamp = timestamp();
+            this.activeTracer.logWillHandleResponse(JSON.stringify(messageObject));
+        }
 
         if (typeof callback === "function")
             this._dispatchResponseToCallback(command, messageObject, callback);
@@ -206,13 +302,10 @@
         else
             console.error("Received a command response without a corresponding callback or promise.", messageObject, command);
 
-        let processingDuration = (timestamp() - processingStartTimestamp).toFixed(3);
-        if (this.warnForLongMessageHandling && processingDuration > this.longMessageHandlingThreshold)
-            console.warn(`InspectorBackend: took ${processingDuration}ms to handle response for command: ${command.qualifiedName}`);
-
-        if (this.dumpInspectorTimeStats) {
-            let roundTripDuration = (processingStartTimestamp - responseData.sendRequestTimestamp).toFixed(3);
-            console.log(`time-stats: Handling: ${processingDuration}ms; RTT: ${roundTripDuration}ms; (command ${command.qualifiedName})`);
+        if (this.activeTracer) {
+            let processingTime = (timestamp() - processingStartTimestamp).toFixed(3);
+            let roundTripTime = (processingStartTimestamp - responseData.sendRequestTimestamp).toFixed(3);
+            this.activeTracer.logDidHandleResponse(JSON.stringify(messageObject), {rtt: roundTripTime, dispatch: processingTime});
         }
 
         if (this._deferredScripts.length && !this._pendingResponses.size)
@@ -247,48 +340,47 @@
 
     _dispatchEvent(messageObject)
     {
-        var qualifiedName = messageObject["method"];
-        var [domainName, eventName] = qualifiedName.split(".");
+        let qualifiedName = messageObject["method"];
+        let [domainName, eventName] = qualifiedName.split(".");
         if (!(domainName in this._agents)) {
             console.error("Protocol Error: Attempted to dispatch method '" + eventName + "' for non-existing domain '" + domainName + "'");
             return;
         }
 
-        var agent = this._agentForDomain(domainName);
+        let agent = this._agentForDomain(domainName);
         if (!agent.active) {
             console.error("Protocol Error: Attempted to dispatch method for domain '" + domainName + "' which exists but is not active.");
             return;
         }
 
-        var event = agent.getEvent(eventName);
+        let event = agent.getEvent(eventName);
         if (!event) {
             console.error("Protocol Error: Attempted to dispatch an unspecified method '" + qualifiedName + "'");
             return;
         }
 
-        var eventArguments = [];
-        if (messageObject["params"]) {
-            var parameterNames = event.parameterNames;
-            for (var i = 0; i < parameterNames.length; ++i)
-                eventArguments.push(messageObject["params"][parameterNames[i]]);
-        }
+        let eventArguments = [];
+        if (messageObject["params"])
+            eventArguments = event.parameterNames.map((name) => messageObject["params"][name]);
 
-        var processingStartTimestamp;
-        if (this.dumpInspectorTimeStats)
+        let processingStartTimestamp;
+        if (this.activeTracer) {
             processingStartTimestamp = timestamp();
+            this.activeTracer.logWillHandleEvent(JSON.stringify(messageObject));
+        }
 
         try {
             agent.dispatchEvent(eventName, eventArguments);
         } catch (e) {
             console.error("Uncaught exception in inspector page while handling event " + qualifiedName, e);
+            if (this.activeTracer)
+                this.activeTracer.logFrontendException(JSON.stringify(messageObject), e);
         }
 
-        let processingDuration = (timestamp() - processingStartTimestamp).toFixed(3);
-        if (this.warnForLongMessageHandling && processingDuration > this.longMessageHandlingThreshold)
-            console.warn(`InspectorBackend: took ${processingDuration}ms to handle event: ${messageObject.method}`);
-
-        if (this.dumpInspectorTimeStats)
-            console.log(`time-stats: Handling: ${processingDuration}ms (event ${messageObject.method})`);
+        if (this.activeTracer) {
+            let processingTime = (timestamp() - processingStartTimestamp).toFixed(3);
+            this.activeTracer.logDidHandleEvent(JSON.stringify(messageObject), {dispatch: processingTime});
+        }
     }
 
     _reportProtocolError(messageObject)
@@ -300,9 +392,9 @@
     {
         console.assert(this._pendingResponses.size === 0);
 
-        var scriptsToRun = this._deferredScripts;
+        let scriptsToRun = this._deferredScripts;
         this._deferredScripts = [];
-        for (var script of scriptsToRun)
+        for (let script of scriptsToRun)
             script.call(this);
     }
 };

Added: trunk/Source/WebInspectorUI/UserInterface/Protocol/LoggingProtocolTracer.js (0 => 193870)


--- trunk/Source/WebInspectorUI/UserInterface/Protocol/LoggingProtocolTracer.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/LoggingProtocolTracer.js	2015-12-09 22:45:21 UTC (rev 193870)
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.LoggingProtocolTracer = class LoggingProtocolTracer extends WebInspector.ProtocolTracer
+{
+    constructor()
+    {
+        super();
+
+        this._dumpMessagesToConsole = false;
+        this._dumpTimingDataToConsole = false;
+        this._logToConsole = window.InspectorTest ? InspectorFrontendHost.unbufferedLog.bind(InspectorFrontendHost) : console.log.bind(console);
+    }
+
+    // Public
+
+    set dumpMessagesToConsole(value)
+    {
+        this._dumpMessagesToConsole = !!value;
+    }
+
+    get dumpMessagesToConsole()
+    {
+        return this._dumpMessagesToConsole;
+    }
+
+    set dumpTimingDataToConsole(value)
+    {
+        this._dumpTimingDataToConsole = !!value;
+    }
+
+    get dumpTimingDataToConsole()
+    {
+        return this._dumpTimingDataToConsole;
+    }
+
+    logFrontendException(message, exception)
+    {
+        this._processEntry({type: "exception", message, exception});
+    }
+
+    logProtocolError(message, error)
+    {
+        this._processEntry({type: "error", message, error});
+    }
+
+    logFrontendRequest(message)
+    {
+        console.assert(typeof message === "string", "Must stringify messages to avoid leaking all JSON protocol messages.")
+
+        this._processEntry({type: "request", message});
+    }
+
+    logWillHandleResponse(message)
+    {
+        console.assert(typeof message === "string", "Must stringify messages to avoid leaking all JSON protocol messages.")
+
+        let entry = {type: "response", message};
+        this._processEntry(entry);
+    }
+
+    logDidHandleResponse(message, timings = null)
+    {
+        console.assert(typeof message === "string", "Must stringify messages to avoid leaking all JSON protocol messages.")
+
+        let entry = {type: "response", message};
+        if (timings)
+            entry.timings = Object.shallowCopy(timings);
+
+        this._processEntry(entry);
+    }
+
+    logWillHandleEvent(message)
+    {
+        console.assert(typeof message === "string", "Must stringify messages to avoid leaking all JSON protocol messages.")
+
+        let entry = {type: "event", message};
+        this._processEntry(entry);
+    }
+
+    logDidHandleEvent(message, timings = null)
+    {
+        console.assert(typeof message === "string", "Must stringify messages to avoid leaking all JSON protocol messages.")
+
+        let entry = {type: "event", message};
+        if (timings)
+            entry.timings = Object.shallowCopy(timings);
+
+        this._processEntry(entry);
+    }
+
+    _processEntry(entry)
+    {
+        if (this._dumpTimingDataToConsole && entry.timings) {
+            if (entry.timings.rtt && entry.timings.dispatch)
+                this._logToConsole(`time-stats: Handling: ${entry.timings.dispatch || NaN}ms; RTT: ${entry.timings.rtt}ms`);
+            else if (entry.timings.dispatch)
+                this._logToConsole(`time-stats: Handling: ${entry.timings.dispatch || NaN}ms`);
+        } else if (this._dumpMessagesToConsole)
+            this._logToConsole(`${entry.type}: ${entry.message}`);
+    }
+};

Added: trunk/Source/WebInspectorUI/UserInterface/Protocol/ProtocolTracer.js (0 => 193870)


--- trunk/Source/WebInspectorUI/UserInterface/Protocol/ProtocolTracer.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/ProtocolTracer.js	2015-12-09 22:45:21 UTC (rev 193870)
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ProtocolTracer = class ProtocolTracer extends WebInspector.Object
+{
+    // Public
+
+    logStarted()
+    {
+        // To be overridden by subclasses.
+    }
+
+    logFrontendException(message, exception)
+    {
+        console.assert(typeof message === "string", "Must stringify messages to avoid leaking all JSON protocol messages.")
+
+        // To be overridden by subclasses.
+    }
+
+    logProtocolError(message, error)
+    {
+        console.assert(typeof message === "string", "Must stringify messages to avoid leaking all JSON protocol messages.")
+
+        // To be overridden by subclasses.
+    }
+
+    logFrontendRequest(message)
+    {
+        console.assert(typeof message === "string", "Must stringify messages to avoid leaking all JSON protocol messages.")
+
+        // To be overridden by subclasses.
+    }
+
+    logWillHandleResponse(message)
+    {
+        console.assert(typeof message === "string", "Must stringify messages to avoid leaking all JSON protocol messages.")
+
+        // To be overridden by subclasses.
+    }
+
+    logDidHandleResponse(message, timings = null)
+    {
+        console.assert(typeof message === "string", "Must stringify messages to avoid leaking all JSON protocol messages.")
+
+        // To be overridden by subclasses.
+    }
+
+    logWillHandleEvent(message)
+    {
+        console.assert(typeof message === "string", "Must stringify messages to avoid leaking all JSON protocol messages.")
+
+        // To be overridden by subclasses.
+    }
+
+    logDidHandleEvent(message, timings = null)
+    {
+        console.assert(typeof message === "string", "Must stringify messages to avoid leaking all JSON protocol messages.")
+
+        // To be overridden by subclasses.
+    }
+
+    logFinished()
+    {
+        // To be overridden by subclasses.
+    }
+};

Modified: trunk/Source/WebInspectorUI/UserInterface/Test.html (193869 => 193870)


--- trunk/Source/WebInspectorUI/UserInterface/Test.html	2015-12-09 22:39:46 UTC (rev 193869)
+++ trunk/Source/WebInspectorUI/UserInterface/Test.html	2015-12-09 22:45:21 UTC (rev 193870)
@@ -49,7 +49,11 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
 
+    <script src=""
+    <script src=""
+
     <script src=""
     <script src=""
     <script src=""
@@ -135,7 +139,6 @@
     <script src=""
     <script src=""
     <script src=""
-    <script src=""
     <script src=""
     <script src=""
     <script src=""
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to