Make console.profile record to the Timeline.
authortimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Jul 2014 21:16:46 +0000 (21:16 +0000)
committertimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Jul 2014 21:16:46 +0000 (21:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=134643

Reviewed by Joseph Pecoraro.

Source/WebCore:
Passes existing profiler tests in fast/profiler.

* bindings/js/ScriptState.cpp:
(WebCore::domWindowFromExecState):
(WebCore::frameFromExecState):
(WebCore::scriptExecutionContextFromExecState):
(WebCore::mainWorldExecState):
(WebCore::execStateFromNode):
* bindings/js/ScriptState.h:
* inspector/InspectorController.cpp:
(WebCore::InspectorController::InspectorController):
(WebCore::InspectorController::profilerEnabled):
(WebCore::InspectorController::setProfilerEnabled):
* inspector/InspectorController.h:
* inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::startProfilingImpl):
(WebCore::InspectorInstrumentation::stopProfilingImpl):
* inspector/InspectorTimelineAgent.cpp:
(WebCore::InspectorTimelineAgent::didCreateFrontendAndBackend):
(WebCore::InspectorTimelineAgent::willDestroyFrontendAndBackend):
(WebCore::InspectorTimelineAgent::start):
(WebCore::InspectorTimelineAgent::stop):
(WebCore::startProfiling):
(WebCore::stopProfiling):
(WebCore::InspectorTimelineAgent::startFromConsole):
(WebCore::InspectorTimelineAgent::stopFromConsole):
(WebCore::InspectorTimelineAgent::didWriteHTML):
(WebCore::InspectorTimelineAgent::breakpointActionProbe):
(WebCore::toProtocol):
(WebCore::InspectorTimelineAgent::addRecordToTimeline):
(WebCore::InspectorTimelineAgent::didCompleteRecordEntry):
(WebCore::InspectorTimelineAgent::didCompleteCurrentRecord):
(WebCore::InspectorTimelineAgent::InspectorTimelineAgent):
(WebCore::InspectorTimelineAgent::sendEvent):
(WebCore::InspectorTimelineAgent::createRecordEntry):
(WebCore::InspectorTimelineAgent::pushCurrentRecord):
* inspector/InspectorTimelineAgent.h:
(WebCore::InspectorTimelineAgent::TimelineRecordEntry::TimelineRecordEntry):
(WebCore::InspectorTimelineAgent::pushCurrentRecord):
* inspector/InstrumentingAgents.cpp:
(WebCore::InstrumentingAgents::InstrumentingAgents):
(WebCore::InstrumentingAgents::reset):
* inspector/InstrumentingAgents.h:
(WebCore::InstrumentingAgents::persistentInspectorTimelineAgent):
(WebCore::InstrumentingAgents::setPersistentInspectorTimelineAgent):
* inspector/TimelineRecordFactory.cpp:
(WebCore::TimelineRecordFactory::createConsoleProfileData):
* inspector/TimelineRecordFactory.h:
* inspector/protocol/Timeline.json:
* page/PageConsole.cpp:
(WebCore::PageConsole::profileEnd):

Source/WebInspectorUI:
* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Controllers/TimelineManager.js:
(WebInspector.TimelineManager.prototype.startCapturing):
(WebInspector.TimelineManager.prototype.stopCapturing):
(WebInspector.TimelineManager.prototype.capturingStarted):
(WebInspector.TimelineManager.prototype.capturingStopped):
(WebInspector.TimelineManager.prototype.eventRecorded.processRecord):
(WebInspector.TimelineManager.prototype.eventRecorded):
* UserInterface/Images/TimelineRecordConsoleProfile.svg: Added.
* UserInterface/Models/ScriptTimelineRecord.js:
* UserInterface/Protocol/TimelineObserver.js:
(WebInspector.TimelineObserver.prototype.eventRecorded):
(WebInspector.TimelineObserver.prototype.recordingStarted):
(WebInspector.TimelineObserver.prototype.recordingStopped):
* UserInterface/Views/TimelineIcons.css:
(.console-profile-record .icon):
* UserInterface/Views/TimelineRecordTreeElement.js:
(WebInspector.TimelineRecordTreeElement):

Source/WebKit/mac:
* WebInspector/WebInspector.mm:
(-[WebInspector isProfilingJavaScript]):
(-[WebInspector toggleProfilingJavaScript:]):
(-[WebInspector startProfilingJavaScript:]):
(-[WebInspector stopProfilingJavaScript:]):
(-[WebInspector isJavaScriptProfilingEnabled]):
(-[WebInspector setJavaScriptProfilingEnabled:]):

Source/WebKit2:
* WebProcess/WebPage/WebInspector.cpp:
(WebKit::WebInspector::setJavaScriptProfilingEnabled):
(WebKit::WebInspector::startJavaScriptProfiling):
(WebKit::WebInspector::stopJavaScriptProfiling):

LayoutTests:
* fast/profiler/profile-with-no-title-expected.txt:

* inspector-protocol/profiler/console-profile-expected.txt: Removed.
* inspector-protocol/profiler/console-profile.html: Removed.
* inspector-protocol/profiler/console-profileEnd-parameterless-expected.txt: Removed.
* inspector-protocol/profiler/console-profileEnd-parameterless.html: Removed.
Removed because console.profile does not go through the profiler protocol now.

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

32 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/profiler/profile-with-no-title-expected.txt
LayoutTests/inspector-protocol/profiler/console-profile-expected.txt [deleted file]
LayoutTests/inspector-protocol/profiler/console-profile.html [deleted file]
LayoutTests/inspector-protocol/profiler/console-profileEnd-parameterless-expected.txt [deleted file]
LayoutTests/inspector-protocol/profiler/console-profileEnd-parameterless.html [deleted file]
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/ScriptState.cpp
Source/WebCore/bindings/js/ScriptState.h
Source/WebCore/inspector/InspectorController.cpp
Source/WebCore/inspector/InspectorController.h
Source/WebCore/inspector/InspectorInstrumentation.cpp
Source/WebCore/inspector/InspectorTimelineAgent.cpp
Source/WebCore/inspector/InspectorTimelineAgent.h
Source/WebCore/inspector/InstrumentingAgents.cpp
Source/WebCore/inspector/InstrumentingAgents.h
Source/WebCore/inspector/TimelineRecordFactory.cpp
Source/WebCore/inspector/TimelineRecordFactory.h
Source/WebCore/inspector/protocol/Timeline.json
Source/WebCore/page/PageConsole.cpp
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js
Source/WebInspectorUI/UserInterface/Images/TimelineRecordConsoleProfile.svg [new file with mode: 0644]
Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js
Source/WebInspectorUI/UserInterface/Protocol/TimelineObserver.js
Source/WebInspectorUI/UserInterface/Views/TimelineIcons.css
Source/WebInspectorUI/UserInterface/Views/TimelineRecordTreeElement.js
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/WebInspector/WebInspector.mm
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/WebPage/WebInspector.cpp

index 9b6e48d..0beadd6 100644 (file)
@@ -1,3 +1,19 @@
+2014-07-17  Timothy Hatcher  <timothy@apple.com>
+
+        Make console.profile record to the Timeline.
+
+        https://bugs.webkit.org/show_bug.cgi?id=134643
+
+        Reviewed by Joseph Pecoraro.
+
+        * fast/profiler/profile-with-no-title-expected.txt:
+
+        * inspector-protocol/profiler/console-profile-expected.txt: Removed.
+        * inspector-protocol/profiler/console-profile.html: Removed.
+        * inspector-protocol/profiler/console-profileEnd-parameterless-expected.txt: Removed.
+        * inspector-protocol/profiler/console-profileEnd-parameterless.html: Removed.
+        Removed because console.profile does not go through the profiler protocol now.
+
 2014-07-16  Roger Fong  <roger_fong@apple.com>
 
         Add test for r169820.
index a519622..2fab800 100644 (file)
@@ -2,7 +2,7 @@ This page creates a profile without a title.
 
 To run this test manually, load it in the browser then load the WebInspector and look at the profile. If there is a profile that is sufficient for this test.
 
-Profile title: org.webkit.profiles.user-initiated.1
+Profile title: 
 Thread_1 (no file) (line 0:0)
    startTest profile-with-no-title.html (line 11:1)
       endTest profiler-test-JS-resources.js (line 1:20)
diff --git a/LayoutTests/inspector-protocol/profiler/console-profile-expected.txt b/LayoutTests/inspector-protocol/profiler/console-profile-expected.txt
deleted file mode 100644 (file)
index a4ca88f..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-Tests that console.profile/profileEnd will record CPU profile when inspector front-end is connected.
-SUCCESS: retrieved 'inner' profile
-SUCCESS: found 'collectProfiles' function in the profile
-
diff --git a/LayoutTests/inspector-protocol/profiler/console-profile.html b/LayoutTests/inspector-protocol/profiler/console-profile.html
deleted file mode 100644 (file)
index 4d69da4..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-<html>
-<head>
-<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/protocol-test.js"></script>
-<script>
-function collectProfiles()
-{
-    console.profile("outer");
-    console.profile("inner");
-    console.profileEnd("outer");
-    console.profileEnd("inner");
-}
-
-function test()
-{
-    function fail(message)
-    {
-        InspectorTest.log("FAIL: " + message);
-        InspectorTest.completeTest();
-    }
-
-    InspectorTest.sendCommand("Profiler.enable", {});
-    InspectorTest.sendCommand("Runtime.evaluate", {expression: "collectProfiles()"}, didCollectProfiles);
-
-    InspectorTest.eventHandler["Profiler.addProfileHeader"] = function(messageObject)
-    {
-        InspectorTest.log("FAIL: unexpected header = " + JSON.stringify(messageObject, null, 4));
-    }
-
-    function didCollectProfiles(messageObject)
-    {
-        InspectorTest.checkForError(messageObject);
-        InspectorTest.sendCommand("Profiler.getProfileHeaders", {}, didReceiveProfileHeaders);
-    }
-
-    function didReceiveProfileHeaders(messageObject)
-    {
-        InspectorTest.checkForError(messageObject);
-
-        var headers = messageObject["result"]["headers"];
-        if (!headers || headers.length !== 2) {
-            fail("Cannot retrive headers: " + JSON.stringify(messageObject, null, 4));
-            return;
-        }
-
-        for (var i = 0; i < headers.length; i++) {
-            if (headers[i].title === "inner") {
-                InspectorTest.sendCommand("Profiler.getCPUProfile", { uid: headers[i].uid }, didGetProfile);
-                return;
-            }
-        }
-
-        fail("Cannot find 'inner' profile header");
-    }
-
-    function didGetProfile(messageObject)
-    {
-        InspectorTest.checkForError(messageObject);
-        InspectorTest.log("SUCCESS: retrieved 'inner' profile");
-
-        var rootNodes = messageObject.result.profile.rootNodes;
-        if (!findFunctionInProfile(rootNodes, "collectProfiles")) {
-            fail("collectProfiles function not found in the profile: " + JSON.stringify(messageObject, null, 4));
-            return;
-        }
-
-        InspectorTest.log("SUCCESS: found 'collectProfiles' function in the profile");
-        InspectorTest.sendCommand("Profiler.clearProfiles", {});
-        InspectorTest.completeTest();
-    }
-
-    function findFunctionInProfile(rootNodes, functionName)
-    {
-        for (var i = 0; i < rootNodes.length; ++i)
-            if (rootNodes[i].functionName === functionName)
-                return true;
-
-        return false;
-    }
-}
-</script>
-</head>
-<body onload="runTest()">
-<p>
-Tests that console.profile/profileEnd will record CPU profile when inspector front-end is connected.<br>
-</p>
-</body>
-</html>
diff --git a/LayoutTests/inspector-protocol/profiler/console-profileEnd-parameterless-expected.txt b/LayoutTests/inspector-protocol/profiler/console-profileEnd-parameterless-expected.txt
deleted file mode 100644 (file)
index a346d38..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-Tests that "console.profileEnd()" does not cause crash.
-Bug 105759.
-SUCCESS: found 2 profile headers
-SUCCESS: titled profile found
-
diff --git a/LayoutTests/inspector-protocol/profiler/console-profileEnd-parameterless.html b/LayoutTests/inspector-protocol/profiler/console-profileEnd-parameterless.html
deleted file mode 100644 (file)
index 3107d93..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<html>
-<head>
-<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/protocol-test.js"></script>
-<script>
-function collectProfiles()
-{
-    console.profile();
-    console.profile("titled");
-    console.profileEnd();
-    console.profileEnd();
-}
-
-function test()
-{
-    function fail(message)
-    {
-        InspectorTest.log("FAIL: " + message);
-        InspectorTest.completeTest();
-    }
-
-    InspectorTest.sendCommand("Profiler.enable", {});
-    InspectorTest.sendCommand("Runtime.evaluate", {expression: "collectProfiles()"}, didCollectProfiles);
-
-    InspectorTest.eventHandler["Profiler.addProfileHeader"] = function(messageObject)
-    {
-        InspectorTest.log("FAIL: unexpected header = " + JSON.stringify(messageObject, null, 4));
-    }
-
-    function didCollectProfiles(messageObject)
-    {
-        InspectorTest.checkForError(messageObject);
-        InspectorTest.sendCommand("Profiler.getProfileHeaders", {}, didReceiveProfileHeaders);
-    }
-
-    function didReceiveProfileHeaders(messageObject)
-    {
-        InspectorTest.checkForError(messageObject);
-
-        var headers = messageObject["result"]["headers"];
-        if (!headers || headers.length !== 2) {
-            fail("Cannot retrive headers: " + JSON.stringify(messageObject, null, 4));
-            return;
-        }
-
-        InspectorTest.log("SUCCESS: found 2 profile headers");
-        for (var i = 0; i < headers.length; i++) {
-            if (headers[i].title === "titled") {
-                InspectorTest.log("SUCCESS: titled profile found");
-                InspectorTest.sendCommand("Profiler.clearProfiles", {});
-                InspectorTest.completeTest();
-                return;
-            }
-        }
-
-        fail("Cannot find titled profile");
-    }
-}
-</script>
-</head>
-<body onload="runTest()">
-<p>
-Tests that "console.profileEnd()" does not cause crash.<br>
-<a href="https://bugs.webkit.org/show_bug.cgi?id=105759">Bug 105759.</a><br>
-</p>
-</body>
-</html>
index 8fc981f..61ae7c1 100644 (file)
@@ -1,3 +1,63 @@
+2014-07-17  Timothy Hatcher  <timothy@apple.com>
+
+        Make console.profile record to the Timeline.
+
+        https://bugs.webkit.org/show_bug.cgi?id=134643
+
+        Reviewed by Joseph Pecoraro.
+
+        Passes existing profiler tests in fast/profiler.
+
+        * bindings/js/ScriptState.cpp:
+        (WebCore::domWindowFromExecState):
+        (WebCore::frameFromExecState):
+        (WebCore::scriptExecutionContextFromExecState):
+        (WebCore::mainWorldExecState):
+        (WebCore::execStateFromNode):
+        * bindings/js/ScriptState.h:
+        * inspector/InspectorController.cpp:
+        (WebCore::InspectorController::InspectorController):
+        (WebCore::InspectorController::profilerEnabled):
+        (WebCore::InspectorController::setProfilerEnabled):
+        * inspector/InspectorController.h:
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore::InspectorInstrumentation::startProfilingImpl):
+        (WebCore::InspectorInstrumentation::stopProfilingImpl):
+        * inspector/InspectorTimelineAgent.cpp:
+        (WebCore::InspectorTimelineAgent::didCreateFrontendAndBackend):
+        (WebCore::InspectorTimelineAgent::willDestroyFrontendAndBackend):
+        (WebCore::InspectorTimelineAgent::start):
+        (WebCore::InspectorTimelineAgent::stop):
+        (WebCore::startProfiling):
+        (WebCore::stopProfiling):
+        (WebCore::InspectorTimelineAgent::startFromConsole):
+        (WebCore::InspectorTimelineAgent::stopFromConsole):
+        (WebCore::InspectorTimelineAgent::didWriteHTML):
+        (WebCore::InspectorTimelineAgent::breakpointActionProbe):
+        (WebCore::toProtocol):
+        (WebCore::InspectorTimelineAgent::addRecordToTimeline):
+        (WebCore::InspectorTimelineAgent::didCompleteRecordEntry):
+        (WebCore::InspectorTimelineAgent::didCompleteCurrentRecord):
+        (WebCore::InspectorTimelineAgent::InspectorTimelineAgent):
+        (WebCore::InspectorTimelineAgent::sendEvent):
+        (WebCore::InspectorTimelineAgent::createRecordEntry):
+        (WebCore::InspectorTimelineAgent::pushCurrentRecord):
+        * inspector/InspectorTimelineAgent.h:
+        (WebCore::InspectorTimelineAgent::TimelineRecordEntry::TimelineRecordEntry):
+        (WebCore::InspectorTimelineAgent::pushCurrentRecord):
+        * inspector/InstrumentingAgents.cpp:
+        (WebCore::InstrumentingAgents::InstrumentingAgents):
+        (WebCore::InstrumentingAgents::reset):
+        * inspector/InstrumentingAgents.h:
+        (WebCore::InstrumentingAgents::persistentInspectorTimelineAgent):
+        (WebCore::InstrumentingAgents::setPersistentInspectorTimelineAgent):
+        * inspector/TimelineRecordFactory.cpp:
+        (WebCore::TimelineRecordFactory::createConsoleProfileData):
+        * inspector/TimelineRecordFactory.h:
+        * inspector/protocol/Timeline.json:
+        * page/PageConsole.cpp:
+        (WebCore::PageConsole::profileEnd):
+
 2014-07-16  Sam Weinig  <sam@webkit.org>
 
         Don't send geolocation permission requests when the page is not visible
index af1048d..70dfd16 100644 (file)
@@ -51,22 +51,29 @@ DOMWindow* domWindowFromExecState(JSC::ExecState* scriptState)
 {
     JSC::JSGlobalObject* globalObject = scriptState->lexicalGlobalObject();
     if (!globalObject->inherits(JSDOMWindowBase::info()))
-        return 0;
+        return nullptr;
     return &JSC::jsCast<JSDOMWindowBase*>(globalObject)->impl();
 }
 
+Frame* frameFromExecState(JSC::ExecState* scriptState)
+{
+    ScriptExecutionContext* context = scriptExecutionContextFromExecState(scriptState);
+    Document* document = context && context->isDocument() ? toDocument(context) : nullptr;
+    return document ? document->frame() : nullptr;
+}
+
 ScriptExecutionContext* scriptExecutionContextFromExecState(JSC::ExecState* scriptState)
 {
     JSC::JSGlobalObject* globalObject = scriptState->lexicalGlobalObject();
     if (!globalObject->inherits(JSDOMGlobalObject::info()))
-        return 0;
+        return nullptr;
     return JSC::jsCast<JSDOMGlobalObject*>(globalObject)->scriptExecutionContext();
 }
 
 JSC::ExecState* mainWorldExecState(Frame* frame)
 {
     if (!frame)
-        return 0;
+        return nullptr;
     JSDOMWindowShell* shell = frame->script().windowShell(mainThreadNormalWorld());
     return shell->window()->globalExec();
 }
@@ -74,12 +81,12 @@ JSC::ExecState* mainWorldExecState(Frame* frame)
 JSC::ExecState* execStateFromNode(DOMWrapperWorld& world, Node* node)
 {
     if (!node)
-        return 0;
+        return nullptr;
     Frame* frame = node->document().frame();
     if (!frame)
-        return 0;
+        return nullptr;
     if (!frame->script().canExecuteScripts(NotAboutToExecuteScript))
-        return 0;
+        return nullptr;
     return frame->script().globalObject(world)->globalExec();
 }
 
index 70d14c7..8a82cab 100644 (file)
@@ -52,6 +52,7 @@ class WorkerGlobalScope;
 typedef JSC::ExecState ScriptState;
 
 DOMWindow* domWindowFromExecState(JSC::ExecState*);
+Frame* frameFromExecState(JSC::ExecState*);
 ScriptExecutionContext* scriptExecutionContextFromExecState(JSC::ExecState*);
 
 JSC::ExecState* mainWorldExecState(Frame*);
index c64f31e..f2c4a82 100644 (file)
@@ -134,7 +134,7 @@ InspectorController::InspectorController(Page& page, InspectorClient* inspectorC
     m_agents.append(WTF::move(domStorageAgentPtr));
 
     auto timelineAgentPtr = std::make_unique<InspectorTimelineAgent>(m_instrumentingAgents.get(), pageAgent, InspectorTimelineAgent::PageInspector, inspectorClient);
-    InspectorTimelineAgent* timelineAgent = timelineAgentPtr.get();
+    m_timelineAgent = timelineAgentPtr.get();
     m_agents.append(WTF::move(timelineAgentPtr));
 
     auto resourceAgentPtr = std::make_unique<InspectorResourceAgent>(m_instrumentingAgents.get(), pageAgent, inspectorClient);
@@ -175,7 +175,7 @@ InspectorController::InspectorController(Page& page, InspectorClient* inspectorC
     }
 
     runtimeAgent->setScriptDebugServer(&m_debuggerAgent->scriptDebugServer());
-    timelineAgent->setPageScriptDebugServer(&m_debuggerAgent->scriptDebugServer());
+    m_timelineAgent->setPageScriptDebugServer(&m_debuggerAgent->scriptDebugServer());
     m_profilerAgent->setScriptDebugServer(&m_debuggerAgent->scriptDebugServer());
 }
 
@@ -380,16 +380,18 @@ void InspectorController::setIndicating(bool indicating)
 
 bool InspectorController::profilerEnabled() const
 {
-    return m_profilerAgent->enabled();
+    return m_instrumentingAgents->inspectorTimelineAgent();
 }
 
 void InspectorController::setProfilerEnabled(bool enable)
 {
-    ErrorString error;
-    if (enable)
-        m_profilerAgent->enable(&error);
-    else
-        m_profilerAgent->disable(&error);
+    if (enable) {
+        m_instrumentingAgents->setPersistentInspectorTimelineAgent(m_timelineAgent);
+        m_timelineAgent->start();
+    } else {
+        m_instrumentingAgents->setPersistentInspectorTimelineAgent(nullptr);
+        m_timelineAgent->stop();
+    }
 }
 
 void InspectorController::resume()
index c288661..e9844f0 100644 (file)
@@ -62,6 +62,7 @@ class InspectorDOMDebuggerAgent;
 class InspectorFrontendClient;
 class InspectorPageAgent;
 class InspectorResourceAgent;
+class InspectorTimelineAgent;
 class InstrumentingAgents;
 class Node;
 class Page;
@@ -144,6 +145,7 @@ private:
     PageDebuggerAgent* m_debuggerAgent;
     InspectorDOMDebuggerAgent* m_domDebuggerAgent;
     Inspector::InspectorProfilerAgent* m_profilerAgent;
+    InspectorTimelineAgent* m_timelineAgent;
 
     RefPtr<Inspector::InspectorBackendDispatcher> m_inspectorBackendDispatcher;
     std::unique_ptr<InspectorFrontendClient> m_inspectorFrontendClient;
index f151abe..692a47e 100644 (file)
@@ -945,14 +945,14 @@ void InspectorInstrumentation::consoleTimeStampImpl(InstrumentingAgents* instrum
 
 void InspectorInstrumentation::startProfilingImpl(InstrumentingAgents* instrumentingAgents, JSC::ExecState* exec, const String& title)
 {
-    if (InspectorProfilerAgent* profilerAgent = instrumentingAgents->inspectorProfilerAgent())
-        profilerAgent->startProfiling(title, exec);
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->persistentInspectorTimelineAgent())
+        timelineAgent->startFromConsole(exec, title);
 }
 
 PassRefPtr<JSC::Profile> InspectorInstrumentation::stopProfilingImpl(InstrumentingAgents* instrumentingAgents, JSC::ExecState* exec, const String& title)
 {
-    if (InspectorProfilerAgent* profilerAgent = instrumentingAgents->inspectorProfilerAgent())
-        return profilerAgent->stopProfiling(title, exec);
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->persistentInspectorTimelineAgent())
+        return timelineAgent->stopFromConsole(exec, title);
     return nullptr;
 }
 
index dddc1c6..2d12ffd 100644 (file)
@@ -74,6 +74,8 @@ void InspectorTimelineAgent::didCreateFrontendAndBackend(Inspector::InspectorFro
 {
     m_frontendDispatcher = std::make_unique<InspectorTimelineFrontendDispatcher>(frontendChannel);
     m_backendDispatcher = InspectorTimelineBackendDispatcher::create(backendDispatcher, this);
+
+    m_instrumentingAgents->setPersistentInspectorTimelineAgent(this);
 }
 
 void InspectorTimelineAgent::willDestroyFrontendAndBackend(InspectorDisconnectReason)
@@ -81,15 +83,14 @@ void InspectorTimelineAgent::willDestroyFrontendAndBackend(InspectorDisconnectRe
     m_frontendDispatcher = nullptr;
     m_backendDispatcher.clear();
 
+    m_instrumentingAgents->setPersistentInspectorTimelineAgent(nullptr);
+
     ErrorString error;
     stop(&error);
 }
 
 void InspectorTimelineAgent::start(ErrorString*, const int* maxCallStackDepth)
 {
-    if (!m_frontendDispatcher)
-        return;
-
     if (maxCallStackDepth && *maxCallStackDepth > 0)
         m_maxCallStackDepth = *maxCallStackDepth;
     else
@@ -103,6 +104,9 @@ void InspectorTimelineAgent::start(ErrorString*, const int* maxCallStackDepth)
         m_scriptDebugServer->addListener(this);
 
     m_enabled = true;
+
+    if (m_frontendDispatcher)
+        m_frontendDispatcher->recordingStarted();
 }
 
 void InspectorTimelineAgent::stop(ErrorString*)
@@ -110,7 +114,6 @@ void InspectorTimelineAgent::stop(ErrorString*)
     if (!m_enabled)
         return;
 
-    m_weakFactory.revokeAll();
     m_instrumentingAgents->setInspectorTimelineAgent(nullptr);
 
     if (m_scriptDebugServer)
@@ -119,6 +122,9 @@ void InspectorTimelineAgent::stop(ErrorString*)
     clearRecordStack();
 
     m_enabled = false;
+
+    if (m_frontendDispatcher)
+        m_frontendDispatcher->recordingStopped();
 }
 
 void InspectorTimelineAgent::setPageScriptDebugServer(PageScriptDebugServer* scriptDebugServer)
@@ -129,14 +135,74 @@ void InspectorTimelineAgent::setPageScriptDebugServer(PageScriptDebugServer* scr
     m_scriptDebugServer = scriptDebugServer;
 }
 
+static inline void startProfiling(JSC::ExecState* exec, const String& title)
+{
+    JSC::LegacyProfiler::profiler()->startProfiling(exec, title);
+}
+
+static inline PassRefPtr<JSC::Profile> stopProfiling(JSC::ExecState* exec, const String& title)
+{
+    return JSC::LegacyProfiler::profiler()->stopProfiling(exec, title);
+}
+
 static inline void startProfiling(Frame* frame, const String& title)
 {
-    JSC::LegacyProfiler::profiler()->startProfiling(toJSDOMWindow(frame, debuggerWorld())->globalExec(), title);
+    startProfiling(toJSDOMWindow(frame, debuggerWorld())->globalExec(), title);
 }
 
 static inline PassRefPtr<JSC::Profile> stopProfiling(Frame* frame, const String& title)
 {
-    return JSC::LegacyProfiler::profiler()->stopProfiling(toJSDOMWindow(frame, debuggerWorld())->globalExec(), title);
+    return stopProfiling(toJSDOMWindow(frame, debuggerWorld())->globalExec(), title);
+}
+
+void InspectorTimelineAgent::startFromConsole(JSC::ExecState* exec, const String &title)
+{
+    // Only allow recording of a profile if it is anonymous (empty title) or does not match
+    // the title of an already recording profile.
+    if (!title.isEmpty()) {
+        for (const TimelineRecordEntry& record : m_pendingConsoleProfileRecords) {
+            String recordTitle;
+            record.data->getString(ASCIILiteral("title"), &recordTitle);
+            if (recordTitle == title)
+                return;
+        }
+    }
+
+    if (m_pendingConsoleProfileRecords.isEmpty())
+        start();
+
+    startProfiling(exec, title);
+
+    m_pendingConsoleProfileRecords.append(createRecordEntry(TimelineRecordFactory::createConsoleProfileData(title), TimelineRecordType::ConsoleProfile, true, frameFromExecState(exec)));
+}
+
+PassRefPtr<JSC::Profile> InspectorTimelineAgent::stopFromConsole(JSC::ExecState* exec, const String& title)
+{
+    // Stop profiles in reverse order. If the title is empty, then stop the last profile.
+    // Otherwise, match the title of the profile to stop.
+    for (ptrdiff_t i = m_pendingConsoleProfileRecords.size() - 1; i >= 0; --i) {
+        const TimelineRecordEntry& record = m_pendingConsoleProfileRecords[i];
+
+        String recordTitle;
+        record.data->getString(ASCIILiteral("title"), &recordTitle);
+
+        if (title.isEmpty() || recordTitle == title) {
+            RefPtr<JSC::Profile> profile = stopProfiling(exec, title);
+            if (profile)
+                TimelineRecordFactory::appendProfile(record.data.get(), profile);
+
+            didCompleteRecordEntry(record);
+
+            m_pendingConsoleProfileRecords.remove(i);
+
+            if (m_pendingConsoleProfileRecords.isEmpty())
+                stop();
+
+            return profile.release();
+        }
+    }
+
+    return nullptr;
 }
 
 void InspectorTimelineAgent::willCallFunction(const String& scriptName, int scriptLine, Frame* frame)
@@ -264,7 +330,7 @@ void InspectorTimelineAgent::willWriteHTML(unsigned startLine, Frame* frame)
 void InspectorTimelineAgent::didWriteHTML(unsigned endLine)
 {
     if (!m_recordStack.isEmpty()) {
-        TimelineRecordEntry entry = m_recordStack.last();
+        const TimelineRecordEntry& entry = m_recordStack.last();
         entry.data->setNumber("endLine", endLine);
         didCompleteCurrentRecord(TimelineRecordType::ParseHTML);
     }
@@ -457,10 +523,7 @@ void InspectorTimelineAgent::breakpointActionProbe(JSC::ExecState* exec, const I
 {
     ASSERT(exec);
 
-    ScriptExecutionContext* context = scriptExecutionContextFromExecState(exec);
-    Document* document = (context && context->isDocument()) ? toDocument(context) : nullptr;
-    Frame* frame = document ? document->frame() : nullptr;
-    appendRecord(TimelineRecordFactory::createProbeSampleData(action, hitCount), TimelineRecordType::ProbeSample, false, frame);
+    appendRecord(TimelineRecordFactory::createProbeSampleData(action, hitCount), TimelineRecordType::ProbeSample, false, frameFromExecState(exec));
 }
 
 static Inspector::TypeBuilder::Timeline::EventType::Enum toProtocol(TimelineRecordType type)
@@ -528,6 +591,8 @@ static Inspector::TypeBuilder::Timeline::EventType::Enum toProtocol(TimelineReco
         return Inspector::TypeBuilder::Timeline::EventType::FunctionCall;
     case TimelineRecordType::ProbeSample:
         return Inspector::TypeBuilder::Timeline::EventType::ProbeSample;
+    case TimelineRecordType::ConsoleProfile:
+        return Inspector::TypeBuilder::Timeline::EventType::ConsoleProfile;
 
     case TimelineRecordType::RequestAnimationFrame:
         return Inspector::TypeBuilder::Timeline::EventType::RequestAnimationFrame;
@@ -558,7 +623,7 @@ void InspectorTimelineAgent::addRecordToTimeline(PassRefPtr<InspectorObject> prp
     if (m_recordStack.isEmpty())
         sendEvent(record.release());
     else {
-        TimelineRecordEntry parent = m_recordStack.last();
+        const TimelineRecordEntry& parent = m_recordStack.last();
         parent.children->pushObject(record.release());
     }
 }
@@ -573,6 +638,14 @@ void InspectorTimelineAgent::setFrameIdentifier(InspectorObject* record, Frame*
     record->setString("frameId", frameId);
 }
 
+void InspectorTimelineAgent::didCompleteRecordEntry(const TimelineRecordEntry& entry)
+{
+    entry.record->setObject(ASCIILiteral("data"), entry.data);
+    entry.record->setArray(ASCIILiteral("children"), entry.children);
+    entry.record->setNumber(ASCIILiteral("endTime"), timestamp());
+    addRecordToTimeline(entry.record, entry.type);
+}
+
 void InspectorTimelineAgent::didCompleteCurrentRecord(TimelineRecordType type)
 {
     // An empty stack could merely mean that the timeline agent was turned on in the middle of
@@ -580,11 +653,8 @@ void InspectorTimelineAgent::didCompleteCurrentRecord(TimelineRecordType type)
     if (!m_recordStack.isEmpty()) {
         TimelineRecordEntry entry = m_recordStack.last();
         m_recordStack.removeLast();
-        ASSERT(entry.type == type);
-        entry.record->setObject("data", entry.data);
-        entry.record->setArray("children", entry.children);
-        entry.record->setNumber("endTime", timestamp());
-        addRecordToTimeline(entry.record, type);
+        ASSERT_UNUSED(type, entry.type == type);
+        didCompleteRecordEntry(entry);
     }
 }
 
@@ -596,7 +666,6 @@ InspectorTimelineAgent::InspectorTimelineAgent(InstrumentingAgents* instrumentin
     , m_maxCallStackDepth(5)
     , m_inspectorType(type)
     , m_client(client)
-    , m_weakFactory(this)
     , m_enabled(false)
     , m_recordingProfile(false)
 {
@@ -612,16 +681,24 @@ void InspectorTimelineAgent::appendRecord(PassRefPtr<InspectorObject> data, Time
 
 void InspectorTimelineAgent::sendEvent(PassRefPtr<InspectorObject> event)
 {
+    if (!m_frontendDispatcher)
+        return;
+
     // FIXME: runtimeCast is a hack. We do it because we can't build TimelineEvent directly now.
     RefPtr<Inspector::TypeBuilder::Timeline::TimelineEvent> recordChecked = Inspector::TypeBuilder::Timeline::TimelineEvent::runtimeCast(event);
     m_frontendDispatcher->eventRecorded(recordChecked.release());
 }
 
-void InspectorTimelineAgent::pushCurrentRecord(PassRefPtr<InspectorObject> data, TimelineRecordType type, bool captureCallStack, Frame* frame)
+InspectorTimelineAgent::TimelineRecordEntry InspectorTimelineAgent::createRecordEntry(PassRefPtr<InspectorObject> data, TimelineRecordType type, bool captureCallStack, Frame* frame)
 {
     RefPtr<InspectorObject> record = TimelineRecordFactory::createGenericRecord(timestamp(), captureCallStack ? m_maxCallStackDepth : 0);
     setFrameIdentifier(record.get(), frame);
-    m_recordStack.append(TimelineRecordEntry(record.release(), data, InspectorArray::create(), type));
+    return TimelineRecordEntry(record.release(), data, InspectorArray::create(), type);
+}
+
+void InspectorTimelineAgent::pushCurrentRecord(PassRefPtr<InspectorObject> data, TimelineRecordType type, bool captureCallStack, Frame* frame)
+{
+    pushCurrentRecord(createRecordEntry(data, type, captureCallStack, frame));
 }
 
 void InspectorTimelineAgent::clearRecordStack()
index f863b15..2060704 100644 (file)
 #include <wtf/Vector.h>
 #include <wtf/WeakPtr.h>
 
+namespace JSC {
+class Profile;
+}
+
 namespace WebCore {
 
 class Event;
@@ -97,6 +101,7 @@ enum class TimelineRecordType {
 
     FunctionCall,
     ProbeSample,
+    ConsoleProfile,
 
     RequestAnimationFrame,
     CancelAnimationFrame,
@@ -136,8 +141,8 @@ public:
     virtual void didCreateFrontendAndBackend(Inspector::InspectorFrontendChannel*, Inspector::InspectorBackendDispatcher*) override;
     virtual void willDestroyFrontendAndBackend(Inspector::InspectorDisconnectReason) override;
 
-    virtual void start(ErrorString*, const int* maxCallStackDepth) override;
-    virtual void stop(ErrorString*) override;
+    virtual void start(ErrorString* = nullptr, const int* maxCallStackDepth = nullptr) override;
+    virtual void stop(ErrorString* = nullptr) override;
 
     int id() const { return m_id; }
 
@@ -146,6 +151,9 @@ public:
     void didCommitLoad();
 
     // Methods called from WebCore.
+    void startFromConsole(JSC::ExecState*, const String &title);
+    PassRefPtr<JSC::Profile> stopFromConsole(JSC::ExecState*, const String& title);
+
     void willCallFunction(const String& scriptName, int scriptLine, Frame*);
     void didCallFunction(Frame*);
 
@@ -224,10 +232,13 @@ private:
     friend class TimelineRecordStack;
 
     struct TimelineRecordEntry {
+        TimelineRecordEntry()
+            : type(TimelineRecordType::EventDispatch) { }
         TimelineRecordEntry(PassRefPtr<Inspector::InspectorObject> record, PassRefPtr<Inspector::InspectorObject> data, PassRefPtr<Inspector::InspectorArray> children, TimelineRecordType type)
             : record(record), data(data), children(children), type(type)
         {
         }
+
         RefPtr<Inspector::InspectorObject> record;
         RefPtr<Inspector::InspectorObject> data;
         RefPtr<Inspector::InspectorArray> children;
@@ -237,9 +248,13 @@ private:
     void sendEvent(PassRefPtr<Inspector::InspectorObject>);
     void appendRecord(PassRefPtr<Inspector::InspectorObject> data, TimelineRecordType, bool captureCallStack, Frame*);
     void pushCurrentRecord(PassRefPtr<Inspector::InspectorObject>, TimelineRecordType, bool captureCallStack, Frame*);
+    void pushCurrentRecord(const TimelineRecordEntry& record) { m_recordStack.append(record); }
+
+    TimelineRecordEntry createRecordEntry(PassRefPtr<Inspector::InspectorObject> data, TimelineRecordType, bool captureCallStack, Frame*);
 
     void setFrameIdentifier(Inspector::InspectorObject* record, Frame*);
 
+    void didCompleteRecordEntry(const TimelineRecordEntry&);
     void didCompleteCurrentRecord(TimelineRecordType);
 
     void addRecordToTimeline(PassRefPtr<Inspector::InspectorObject>, TimelineRecordType);
@@ -264,7 +279,8 @@ private:
     int m_maxCallStackDepth;
     InspectorType m_inspectorType;
     InspectorClient* m_client;
-    WeakPtrFactory<InspectorTimelineAgent> m_weakFactory;
+
+    Vector<TimelineRecordEntry> m_pendingConsoleProfileRecords;
 
     bool m_enabled;
     bool m_recordingProfile;
index bd0a4ea..75437e4 100644 (file)
@@ -56,6 +56,7 @@ InstrumentingAgents::InstrumentingAgents(InspectorEnvironment& environment)
     , m_pageRuntimeAgent(nullptr)
     , m_workerRuntimeAgent(nullptr)
     , m_inspectorTimelineAgent(nullptr)
+    , m_persistentInspectorTimelineAgent(nullptr)
     , m_inspectorDOMStorageAgent(nullptr)
 #if ENABLE(WEB_REPLAY)
     , m_inspectorReplayAgent(nullptr)
@@ -84,6 +85,7 @@ void InstrumentingAgents::reset()
     m_pageRuntimeAgent = nullptr;
     m_workerRuntimeAgent = nullptr;
     m_inspectorTimelineAgent = nullptr;
+    m_persistentInspectorTimelineAgent = nullptr;
     m_inspectorDOMStorageAgent = nullptr;
 #if ENABLE(WEB_REPLAY)
     m_inspectorReplayAgent = nullptr;
index 8e7c9e4..0d990aa 100644 (file)
@@ -105,6 +105,9 @@ public:
     InspectorTimelineAgent* inspectorTimelineAgent() const { return m_inspectorTimelineAgent; }
     void setInspectorTimelineAgent(InspectorTimelineAgent* agent) { m_inspectorTimelineAgent = agent; }
 
+    InspectorTimelineAgent* persistentInspectorTimelineAgent() const { return m_persistentInspectorTimelineAgent; }
+    void setPersistentInspectorTimelineAgent(InspectorTimelineAgent* agent) { m_persistentInspectorTimelineAgent = agent; }
+
     InspectorDOMStorageAgent* inspectorDOMStorageAgent() const { return m_inspectorDOMStorageAgent; }
     void setInspectorDOMStorageAgent(InspectorDOMStorageAgent* agent) { m_inspectorDOMStorageAgent = agent; }
 
@@ -154,6 +157,7 @@ private:
     PageRuntimeAgent* m_pageRuntimeAgent;
     WorkerRuntimeAgent* m_workerRuntimeAgent;
     InspectorTimelineAgent* m_inspectorTimelineAgent;
+    InspectorTimelineAgent* m_persistentInspectorTimelineAgent;
     InspectorDOMStorageAgent* m_inspectorDOMStorageAgent;
 #if ENABLE(WEB_REPLAY)
     InspectorReplayAgent* m_inspectorReplayAgent;
index 8629c8b..2c43280 100644 (file)
@@ -90,6 +90,13 @@ PassRefPtr<InspectorObject> TimelineRecordFactory::createFunctionCallData(const
     return data.release();
 }
 
+PassRefPtr<InspectorObject> TimelineRecordFactory::createConsoleProfileData(const String& title)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setString("title", title);
+    return data.release();
+}
+
 PassRefPtr<InspectorObject> TimelineRecordFactory::createProbeSampleData(const ScriptBreakpointAction& action, int hitCount)
 {
     RefPtr<InspectorObject> data = InspectorObject::create();
index 05ae729..6e1f656 100644 (file)
@@ -61,6 +61,7 @@ namespace WebCore {
         static PassRefPtr<Inspector::InspectorObject> createGCEventData(const size_t usedHeapSizeDelta);
 
         static PassRefPtr<Inspector::InspectorObject> createFunctionCallData(const String& scriptName, int scriptLine);
+        static PassRefPtr<Inspector::InspectorObject> createConsoleProfileData(const String& title);
 
         static PassRefPtr<Inspector::InspectorObject> createProbeSampleData(const Inspector::ScriptBreakpointAction&, int hitCount);
 
index c9ef2bb..aaec504 100644 (file)
@@ -5,7 +5,7 @@
         {
             "id": "EventType",
             "type": "string",
-            "enum": ["EventDispatch", "ScheduleStyleRecalculation", "RecalculateStyles", "InvalidateLayout", "Layout", "Paint", "ScrollLayer", "ResizeImage", "ParseHTML", "TimerInstall", "TimerRemove", "TimerFire", "EvaluateScript", "MarkLoad", "MarkDOMContent", "TimeStamp", "Time", "TimeEnd", "ScheduleResourceRequest", "ResourceSendRequest", "ResourceReceiveResponse", "ResourceReceivedData", "ResourceFinish", "XHRReadyStateChange", "XHRLoad", "FunctionCall", "ProbeSample", "GCEvent", "RequestAnimationFrame", "CancelAnimationFrame", "FireAnimationFrame", "WebSocketCreate", "WebSocketSendHandshakeRequest", "WebSocketReceiveHandshakeResponse", "WebSocketDestroy"],
+            "enum": ["EventDispatch", "ScheduleStyleRecalculation", "RecalculateStyles", "InvalidateLayout", "Layout", "Paint", "ScrollLayer", "ResizeImage", "ParseHTML", "TimerInstall", "TimerRemove", "TimerFire", "EvaluateScript", "MarkLoad", "MarkDOMContent", "TimeStamp", "Time", "TimeEnd", "ScheduleResourceRequest", "ResourceSendRequest", "ResourceReceiveResponse", "ResourceReceivedData", "ResourceFinish", "XHRReadyStateChange", "XHRLoad", "FunctionCall", "ProbeSample", "ConsoleProfile", "GCEvent", "RequestAnimationFrame", "CancelAnimationFrame", "FireAnimationFrame", "WebSocketCreate", "WebSocketSendHandshakeRequest", "WebSocketReceiveHandshakeResponse", "WebSocketDestroy"],
             "description": "Timeline record type."
         },
         {
                 { "name": "record", "$ref": "TimelineEvent", "description": "Timeline event record data." }
             ],
             "description": "Fired for every instrumentation event while timeline is started."
+        },
+        {
+            "name": "recordingStarted",
+            "description": "Fired when recording has started."
+        },
+        {
+            "name": "recordingStopped",
+            "description": "Fired when recording has stopped."
         }
     ]
 }
index 363cd9e..29537ad 100644 (file)
@@ -170,8 +170,7 @@ void PageConsole::profile(JSC::ExecState* exec, const String& title)
 
 void PageConsole::profileEnd(JSC::ExecState* exec, const String& title)
 {
-    RefPtr<JSC::Profile> profile = InspectorInstrumentation::stopProfiling(&m_page, exec, title);
-    if (profile)
+    if (RefPtr<JSC::Profile> profile = InspectorInstrumentation::stopProfiling(&m_page, exec, title))
         m_profiles.append(profile.release());
 }
 
index 02d389e..2aec8a3 100644 (file)
@@ -1,3 +1,30 @@
+2014-07-17  Timothy Hatcher  <timothy@apple.com>
+
+        Make console.profile record to the Timeline.
+
+        https://bugs.webkit.org/show_bug.cgi?id=134643
+
+        Reviewed by Joseph Pecoraro.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Controllers/TimelineManager.js:
+        (WebInspector.TimelineManager.prototype.startCapturing):
+        (WebInspector.TimelineManager.prototype.stopCapturing):
+        (WebInspector.TimelineManager.prototype.capturingStarted):
+        (WebInspector.TimelineManager.prototype.capturingStopped):
+        (WebInspector.TimelineManager.prototype.eventRecorded.processRecord):
+        (WebInspector.TimelineManager.prototype.eventRecorded):
+        * UserInterface/Images/TimelineRecordConsoleProfile.svg: Added.
+        * UserInterface/Models/ScriptTimelineRecord.js:
+        * UserInterface/Protocol/TimelineObserver.js:
+        (WebInspector.TimelineObserver.prototype.eventRecorded):
+        (WebInspector.TimelineObserver.prototype.recordingStarted):
+        (WebInspector.TimelineObserver.prototype.recordingStopped):
+        * UserInterface/Views/TimelineIcons.css:
+        (.console-profile-record .icon):
+        * UserInterface/Views/TimelineRecordTreeElement.js:
+        (WebInspector.TimelineRecordTreeElement):
+
 2014-07-16  Saam Barati  <sbarati@apple.com>
 
         Web Inspector: TextContentView calls the wrong super function in shown()
index eaabc23..2147e8a 100644 (file)
Binary files a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js and b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js differ
index 59e5a63..887f86b 100644 (file)
@@ -61,17 +61,25 @@ WebInspector.TimelineManager.prototype = {
 
     startCapturing: function()
     {
+        TimelineAgent.start();
+    },
+
+    stopCapturing: function()
+    {
+        TimelineAgent.stop();
+    },
+
+    capturingStarted: function()
+    {
         if (this._isCapturing)
             return;
 
         this._isCapturing = true;
 
-        TimelineAgent.start();
-
         this.dispatchEventToListeners(WebInspector.TimelineManager.Event.CapturingStarted);
     },
 
-    stopCapturing: function()
+    capturingStopped: function()
     {
         if (!this._isCapturing)
             return;
@@ -86,8 +94,6 @@ WebInspector.TimelineManager.prototype = {
             delete this._deadTimeTimeout;
         }
 
-        TimelineAgent.stop();
-
         this._isCapturing = false;
         this._autoCapturingMainResource = null;
 
@@ -229,6 +235,12 @@ WebInspector.TimelineManager.prototype = {
                 this._activeRecording.addEventMarker(eventMarker);
                 break;
 
+            case TimelineAgent.EventType.ConsoleProfile:
+                var profile = this._profileFromPayload(recordPayload.data.profile);
+                console.assert(profile);
+                this._addRecord(new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.ConsoleProfileRecorded, startTime, endTime, callFrames, sourceCodeLocation, recordPayload.data.title, profile));
+                break;
+
             case TimelineAgent.EventType.FunctionCall:
                 // FunctionCall always happens as a child of another record, and since the FunctionCall record
                 // has useful info we just make the timeline record here (combining the data from both records).
diff --git a/Source/WebInspectorUI/UserInterface/Images/TimelineRecordConsoleProfile.svg b/Source/WebInspectorUI/UserInterface/Images/TimelineRecordConsoleProfile.svg
new file mode 100644 (file)
index 0000000..728648e
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2013 Apple Inc. All rights reserved. -->
+<svg viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg">
+    <path fill="rgb(190, 165, 202)" d="M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 Z"/>
+    <path fill="rgb(141, 118, 153)" d="M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 M 13 2 C 13.550781 2 14 2.449219 14 3 L 14 13 C 14 13.550781 13.550781 14 13 14 L 3 14 C 2.449219 14 2 13.550781 2 13 L 2 3 C 2 2.449219 2.449219 2 3 2 L 13 2"/>
+    <path fill="rgb(153, 127, 166)" d="M 7.09187665 9.86486483 L 8.09187665 9.86486483 L 8.09187675 12 L 8.09187675 13 L 7.09187675 13 L 5.4 13 L 4.4 13 L 4.4 12 L 4.4 4 L 4.4 3 L 5.4 3 L 8.2907563 3 C 9.49663194 3 10.4135483 3.20769232 11.0534889 3.69149996 C 11.7636984 4.22843229 12.097479 5.0719049 12.097479 6.12432432 C 12.097479 7.27475638 11.6870881 8.23200847 10.8722916 8.91131913 C 10.0975424 9.55724163 9.06464428 9.86486486 7.80896359 9.86486486 L 7.09187675 9.86486486 L 7.09187675 9.36486486 L 7.09187675 8.86486486 L 7.80896359 8.86486486 C 8.11369101 8.86486486 8.39855198 8.84414571 8.66354709 8.80270722 C 9.30146061 8.70295376 9.82425299 8.48313329 10.2319328 8.14324324 C 10.8089665 7.66215976 11.097479 6.98919351 11.097479 6.12432432 C 11.097479 5.36035654 10.8817949 4.81531695 10.4504202 4.48918919 C 10.0190455 4.16306143 9.29916471 4 8.2907563 4 L 5.4 4 L 5.4 12 L 7.09187675 12 L 7.09187675 9.36486486 L 7.09187665 9.86486483 Z M 7.09187675 7.76756757 L 7.4280112 7.76756757 C 8.01811686 7.76756757 8.4840319 7.63513646 8.82577031 7.37027027 C 9.16750871 7.10540408 9.33837535 6.74594822 9.33837535 6.29189189 C 9.33837535 5.49549151 8.81363737 5.0972973 7.76414566 5.0972973 L 7.09187675 5.0972973 L 7.09187675 7.76756757 Z M 7.09187675 7.76756757"/>
+    <path fill="white" d="M 5.4 12 L 5.4 4 L 8.2907563 4 C 9.29916471 4 10.0190455 4.16306143 10.4504202 4.48918919 C 10.8817949 4.81531695 11.097479 5.36035654 11.097479 6.12432432 C 11.097479 6.98919351 10.8089665 7.66215976 10.2319328 8.14324324 C 9.65489908 8.62432673 8.84725076 8.86486486 7.80896359 8.86486486 L 7.09187675 8.86486486 L 7.09187675 12 L 5.4 12 Z M 7.09187675 7.76756757 L 7.4280112 7.76756757 C 8.01811686 7.76756757 8.4840319 7.63513646 8.82577031 7.37027027 C 9.16750871 7.10540408 9.33837535 6.74594822 9.33837535 6.29189189 C 9.33837535 5.49549151 8.81363737 5.0972973 7.76414566 5.0972973 L 7.09187675 5.0972973 L 7.09187675 7.76756757 Z M 7.09187675 7.76756757"/>
+</svg>
index 0ef7d45..0e70fca 100644 (file)
@@ -46,7 +46,8 @@ WebInspector.ScriptTimelineRecord.EventType = {
     TimerRemoved: "script-timeline-record-timer-removed",
     AnimationFrameFired: "script-timeline-record-animation-frame-fired",
     AnimationFrameRequested: "script-timeline-record-animation-frame-requested",
-    AnimationFrameCanceled: "script-timeline-record-animation-frame-canceled"
+    AnimationFrameCanceled: "script-timeline-record-animation-frame-canceled",
+    ConsoleProfileRecorded: "script-timeline-record-console-profile-recorded"
 };
 
 WebInspector.ScriptTimelineRecord.EventType.displayName = function(eventType, details, includeTimerIdentifierInMainTitle)
@@ -216,6 +217,10 @@ WebInspector.ScriptTimelineRecord.EventType.displayName = function(eventType, de
         return WebInspector.UIString("Event Dispatched");
     case WebInspector.ScriptTimelineRecord.EventType.ProbeSampleRecorded:
         return WebInspector.UIString("Probe Sample Recorded");
+    case WebInspector.ScriptTimelineRecord.EventType.ConsoleProfileRecorded:
+        if (details && (details instanceof String || typeof details === "string"))
+            return WebInspector.UIString("“%s” Profile Recorded").format(details);
+        return WebInspector.UIString("Console Profile Recorded");
     case WebInspector.ScriptTimelineRecord.EventType.TimerFired:
         if (details && includeTimerIdentifierInMainTitle)
             return WebInspector.UIString("Timer %s Fired").format(details);
index 1c7e043..bd887c2 100644 (file)
@@ -36,6 +36,16 @@ WebInspector.TimelineObserver.prototype = {
     eventRecorded: function(record)
     {
         WebInspector.timelineManager.eventRecorded(record);
+    },
+
+    recordingStarted: function()
+    {
+        WebInspector.timelineManager.capturingStarted();
+    },
+
+    recordingStopped: function()
+    {
+        WebInspector.timelineManager.capturingStopped();
     }
 };
 
index 51ad31e..1552de2 100644 (file)
     content: url(../Images/TimelineRecordProbeSampled.svg);
 }
 
+.console-profile-record .icon {
+    content: url(../Images/TimelineRecordConsoleProfile.svg);
+}
+
 .timer-record .icon {
     content: url(../Images/TimelineRecordTimer.svg);
 }
index 40d1abc..f2261e6 100644 (file)
@@ -80,6 +80,9 @@ WebInspector.TimelineRecordTreeElement = function(timelineRecord, subtitleNameSt
         case WebInspector.ScriptTimelineRecord.EventType.ProbeSampleRecorded:
             iconStyleClass = WebInspector.TimelineRecordTreeElement.ProbeRecordIconStyleClass;
             break;
+        case WebInspector.ScriptTimelineRecord.EventType.ConsoleProfileRecorded:
+            iconStyleClass = WebInspector.TimelineRecordTreeElement.ConsoleProfileIconStyleClass;
+            break;
         case WebInspector.ScriptTimelineRecord.EventType.TimerFired:
         case WebInspector.ScriptTimelineRecord.EventType.TimerInstalled:
         case WebInspector.ScriptTimelineRecord.EventType.TimerRemoved:
@@ -116,6 +119,7 @@ WebInspector.TimelineRecordTreeElement.EventRecordIconStyleClass = "event-record
 WebInspector.TimelineRecordTreeElement.TimerRecordIconStyleClass = "timer-record";
 WebInspector.TimelineRecordTreeElement.AnimationRecordIconStyleClass = "animation-record";
 WebInspector.TimelineRecordTreeElement.ProbeRecordIconStyleClass = "probe-record";
+WebInspector.TimelineRecordTreeElement.ConsoleProfileIconStyleClass = "console-profile-record";
 
 WebInspector.TimelineRecordTreeElement.prototype = {
     constructor: WebInspector.TimelineRecordTreeElement,
index c8cb8a0..5c7c770 100644 (file)
@@ -1,3 +1,19 @@
+2014-07-17  Timothy Hatcher  <timothy@apple.com>
+
+        Make console.profile record to the Timeline.
+
+        https://bugs.webkit.org/show_bug.cgi?id=134643
+
+        Reviewed by Joseph Pecoraro.
+
+        * WebInspector/WebInspector.mm:
+        (-[WebInspector isProfilingJavaScript]):
+        (-[WebInspector toggleProfilingJavaScript:]):
+        (-[WebInspector startProfilingJavaScript:]):
+        (-[WebInspector stopProfilingJavaScript:]):
+        (-[WebInspector isJavaScriptProfilingEnabled]):
+        (-[WebInspector setJavaScriptProfilingEnabled:]):
+
 2014-07-16  David Kilzer  <ddkilzer@apple.com>
 
         [iOS] Update order file paths for WebKit and WebKit2
index f1ecc62..113b7a3 100644 (file)
@@ -109,45 +109,34 @@ NSString *WebInspectorDidStopSearchingForNode = @"WebInspectorDidStopSearchingFo
 
 - (BOOL)isProfilingJavaScript
 {
-    return _frontend && [_frontend isProfilingJavaScript];
+    // No longer supported.
+    return NO;
 }
 
 - (void)toggleProfilingJavaScript:(id)sender
 {
-    [self showWindow];
-
-    if ([self isProfilingJavaScript])
-        [_frontend stopProfilingJavaScript];
-    else
-        [_frontend startProfilingJavaScript];
+    // No longer supported.
 }
 
 - (void)startProfilingJavaScript:(id)sender
 {
-    if (_frontend)
-        [_frontend startProfilingJavaScript];
+    // No longer supported.
 }
 
 - (void)stopProfilingJavaScript:(id)sender
 {
-    if (_frontend)
-        [_frontend stopProfilingJavaScript];
+    // No longer supported.
 }
 
 - (BOOL)isJavaScriptProfilingEnabled
 {
-    if (Page* page = core(_webView))
-        return page->inspectorController().profilerEnabled();
+    // No longer supported.
     return NO;
 }
 
 - (void)setJavaScriptProfilingEnabled:(BOOL)enabled
 {
-    Page* page = core(_webView);
-    if (!page)
-        return;
-
-    page->inspectorController().setProfilerEnabled(enabled);
+    // No longer supported.
 }
 
 - (BOOL)isTimelineProfilingEnabled
index ed3d392..ea514de 100644 (file)
@@ -1,3 +1,16 @@
+2014-07-17  Timothy Hatcher  <timothy@apple.com>
+
+        Make console.profile record to the Timeline.
+
+        https://bugs.webkit.org/show_bug.cgi?id=134643
+
+        Reviewed by Joseph Pecoraro.
+
+        * WebProcess/WebPage/WebInspector.cpp:
+        (WebKit::WebInspector::setJavaScriptProfilingEnabled):
+        (WebKit::WebInspector::startJavaScriptProfiling):
+        (WebKit::WebInspector::stopJavaScriptProfiling):
+
 2014-07-17  Brady Eidson  <beidson@apple.com>
 
         Crash in ServicesOverlayController::~ServicesOverlayController.
index 864c08e..f070e57 100644 (file)
@@ -277,25 +277,17 @@ void WebInspector::stopJavaScriptDebugging()
 
 void WebInspector::setJavaScriptProfilingEnabled(bool enabled)
 {
-    m_page->corePage()->inspectorController().show();
-    if (!m_frontendClient)
-        return;
-
-    m_page->corePage()->inspectorController().setProfilerEnabled(enabled);
+    // No longer supported.
 }
 
 void WebInspector::startJavaScriptProfiling()
 {
-    m_page->corePage()->inspectorController().show();
-    if (m_frontendClient)
-        m_frontendClient->startProfilingJavaScript();
+    // No longer supported.
 }
 
 void WebInspector::stopJavaScriptProfiling()
 {
-    m_page->corePage()->inspectorController().show();
-    if (m_frontendClient)
-        m_frontendClient->stopProfilingJavaScript();
+    // No longer supported.
 }
 
 void WebInspector::startPageProfiling()