Bug 44174

Summary: Web Inspector: extract profiler-related code and data from InspectorController into ProfilerAgent
Product: WebKit Reporter: Mikhail Naganov <mnaganov>
Component: Web Inspector (Deprecated)Assignee: Nobody <webkit-unassigned>
Status: RESOLVED FIXED    
Severity: Normal CC: bweinstein, eric, joepeck, keishi, pfeldman, pmuellr, rik, timothy, yurys
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: All   
OS: All   
Attachments:
Description Flags
Proposed patch
none
Fix mac linking issue
pfeldman: review-
Comments addressed.
none
This time, interactive_ui_tests pass
pfeldman: review-
Comments addressed.
none
Comments addressed (forgot to mark the previous attachment as a patch.) pfeldman: review+, pfeldman: commit-queue-

Description Mikhail Naganov 2010-08-18 07:09:19 PDT
The same refactoring as was previously done for debugger-related stuff.
Comment 1 Mikhail Naganov 2010-08-18 07:18:16 PDT
Created attachment 64704 [details]
Proposed patch
Comment 2 Eric Seidel (no email) 2010-08-18 07:36:45 PDT
Attachment 64704 [details] did not build on mac:
Build output: http://queues.webkit.org/results/3703368
Comment 3 Mikhail Naganov 2010-08-18 08:04:02 PDT
Created attachment 64712 [details]
Fix mac linking issue
Comment 4 Pavel Feldman 2010-08-18 10:07:58 PDT
Comment on attachment 64712 [details]
Fix mac linking issue

WebCore/GNUmakefile.am:1628
 +  	WebCore/inspector/InspectorProfilerAgent.cpp \
Do not forget the CMakeLists.

WebCore/ChangeLog:5
 +          Extract profiler-related code and data from InspectorController into ProfilerAgent.
Web Inspector: Extract ... into InspectorProfilerAgent.

WebCore/inspector/InspectorController.cpp:1488
 +      if (profilerEnabled())
In the previous version, user initiated profiling could be started regardless of the profilerEnabled state. You should not change that. r- for that. Please make sure profiler tests are passing!
Comment 5 Mikhail Naganov 2010-08-19 05:56:54 PDT
Created attachment 64836 [details]
Comments addressed.
Comment 6 Mikhail Naganov 2010-08-19 07:12:10 PDT
Comment on attachment 64836 [details]
Comments addressed.

This breaks Chromium's interactive_ui_test for profiler. Holding this change back.

> diff --git a/WebCore/CMakeLists.txt b/WebCore/CMakeLists.txt
> index 3fe6c2c..4efd85c 100644
> --- a/WebCore/CMakeLists.txt
> +++ b/WebCore/CMakeLists.txt
> @@ -1074,6 +1074,7 @@ SET(WebCore_SOURCES
>      inspector/InspectorDebuggerAgent.cpp
>      inspector/InspectorFrontendClientLocal.cpp
>      inspector/InspectorFrontendHost.cpp
> +    inspector/InspectorProfilerAgent.cpp
>      inspector/InspectorResource.cpp
>      inspector/InspectorValues.cpp
>      inspector/InspectorStorageAgent.cpp
> diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
> index 9934fbf..ba704d5 100644
> --- a/WebCore/ChangeLog
> +++ b/WebCore/ChangeLog
> @@ -1,3 +1,69 @@
> +2010-08-19  Mikhail Naganov  <mnaganov@chromium.org>
> +
> +        Reviewed by NOBODY (OOPS!).
> +
> +        Extract profiler-related code and data from InspectorController into
> +        InspectorProfilerAgent.
> +
> +        https://bugs.webkit.org/show_bug.cgi?id=44174
> +
> +        * CMakeLists.txt:
> +        * GNUmakefile.am:
> +        * WebCore.exp.in:
> +        * WebCore.gypi:
> +        * WebCore.pro:
> +        * WebCore.vcproj/WebCore.vcproj:
> +        * WebCore.xcodeproj/project.pbxproj:
> +        * bindings/js/ScriptProfiler.cpp:
> +        (WebCore::ScriptProfiler::isProfilerAlwaysEnabled):
> +        * bindings/js/ScriptProfiler.h:
> +        * bindings/v8/ScriptProfiler.cpp:
> +        (WebCore::ScriptProfiler::isProfilerAlwaysEnabled):
> +        * bindings/v8/ScriptProfiler.h:
> +        * inspector/CodeGeneratorInspector.pm:
> +        * inspector/Inspector.idl:
> +        * inspector/InspectorController.cpp:
> +        (WebCore::InspectorController::InspectorController):
> +        (WebCore::InspectorController::inspectedPageDestroyed):
> +        (WebCore::InspectorController::connectFrontend):
> +        (WebCore::InspectorController::disconnectFrontend):
> +        (WebCore::InspectorController::populateScriptObjects):
> +        (WebCore::InspectorController::didCommitLoad):
> +        (WebCore::InspectorController::addProfile):
> +        (WebCore::InspectorController::addProfileFinishedMessageToConsole):
> +        (WebCore::InspectorController::addStartProfilingMessageToConsole):
> +        (WebCore::InspectorController::isRecordingUserInitiatedProfile):
> +        (WebCore::InspectorController::getCurrentUserInitiatedProfileName):
> +        (WebCore::InspectorController::startUserInitiatedProfiling):
> +        (WebCore::InspectorController::stopUserInitiatedProfiling):
> +        (WebCore::InspectorController::enableProfiler):
> +        (WebCore::InspectorController::disableProfiler):
> +        * inspector/InspectorController.h:
> +        (WebCore::InspectorController::profilerEnabled):
> +        (WebCore::InspectorController::profilerAgent):
> +        * inspector/InspectorProfilerAgent.cpp: Added.
> +        (WebCore::InspectorProfilerAgent::create):
> +        (WebCore::InspectorProfilerAgent::InspectorProfilerAgent):
> +        (WebCore::InspectorProfilerAgent::~InspectorProfilerAgent):
> +        (WebCore::InspectorProfilerAgent::addProfile):
> +        (WebCore::InspectorProfilerAgent::addProfileFinishedMessageToConsole):
> +        (WebCore::InspectorProfilerAgent::addStartProfilingMessageToConsole):
> +        (WebCore::InspectorProfilerAgent::createProfileHeader):
> +        (WebCore::InspectorProfilerAgent::getCurrentUserInitiatedProfileName):
> +        (WebCore::InspectorProfilerAgent::getProfileHeaders):
> +        (WebCore::InspectorProfilerAgent::getProfile):
> +        (WebCore::InspectorProfilerAgent::removeProfile):
> +        (WebCore::InspectorProfilerAgent::resetState):
> +        (WebCore::InspectorProfilerAgent::startUserInitiatedProfiling):
> +        (WebCore::InspectorProfilerAgent::stopUserInitiatedProfiling):
> +        (WebCore::InspectorProfilerAgent::toggleRecordButton):
> +        * inspector/InspectorProfilerAgent.h: Added.
> +        (WebCore::InspectorProfilerAgent::clearProfiles):
> +        (WebCore::InspectorProfilerAgent::isRecordingUserInitiatedProfile):
> +        (WebCore::InspectorProfilerAgent::setRemoteFrontend):
> +        (WebCore::InspectorProfilerAgent::startProfiling):
> +        (WebCore::InspectorProfilerAgent::stopProfiling):
> +
>  2010-08-19  Andreas Kling  <andreas.kling@nokia.com>
>  
>          Reviewed by Kenneth Rohde Christiansen.
> diff --git a/WebCore/GNUmakefile.am b/WebCore/GNUmakefile.am
> index 20baf0f..e4b660e 100644
> --- a/WebCore/GNUmakefile.am
> +++ b/WebCore/GNUmakefile.am
> @@ -1627,6 +1627,8 @@ webcore_sources += \
>  	WebCore/inspector/InspectorFrontendClientLocal.h \
>  	WebCore/inspector/InspectorFrontendHost.cpp \
>  	WebCore/inspector/InspectorFrontendHost.h \
> +	WebCore/inspector/InspectorProfilerAgent.cpp \
> +	WebCore/inspector/InspectorProfilerAgent.h \
>  	WebCore/inspector/InspectorResource.cpp \
>  	WebCore/inspector/InspectorResource.h \
>  	WebCore/inspector/InspectorStorageAgent.cpp \
> diff --git a/WebCore/WebCore.exp.in b/WebCore/WebCore.exp.in
> index 1369296..57b8440 100644
> --- a/WebCore/WebCore.exp.in
> +++ b/WebCore/WebCore.exp.in
> @@ -1189,10 +1189,11 @@ __ZN7WebCore19InspectorController20stopTimelineProfilerEv
>  __ZN7WebCore19InspectorController21startTimelineProfilerEv
>  __ZN7WebCore19InspectorController25evaluateForTestInFrontendElRKN3WTF6StringE
>  __ZN7WebCore19InspectorController26setInspectorFrontendClientEN3WTF10PassOwnPtrINS_23InspectorFrontendClientEEE
> +__ZN7WebCore19InspectorController27startUserInitiatedProfilingEv
>  __ZN7WebCore19InspectorController26stopUserInitiatedProfilingEv
> -__ZN7WebCore19InspectorController27startUserInitiatedProfilingEPNS_5TimerIS0_EE
>  __ZN7WebCore19InspectorController34inspectorStartsAttachedSettingNameEv
>  __ZN7WebCore19InspectorController34inspectorStartsAttachedSettingNameEv
> +__ZNK7WebCore19InspectorController31isRecordingUserInitiatedProfileEv
>  __ZN7WebCore19InspectorController4showEv
>  __ZN7WebCore19InspectorController5closeEv
>  __ZN7WebCore19InspectorController7inspectEPNS_4NodeE
> diff --git a/WebCore/WebCore.gypi b/WebCore/WebCore.gypi
> index 3dff25d..38504ad 100644
> --- a/WebCore/WebCore.gypi
> +++ b/WebCore/WebCore.gypi
> @@ -1769,6 +1769,8 @@
>              'inspector/InspectorFrontendClient.h',
>              'inspector/InspectorFrontendHost.cpp',
>              'inspector/InspectorFrontendHost.h',
> +            'inspector/InspectorProfilerAgent.cpp',
> +            'inspector/InspectorProfilerAgent.h',
>              'inspector/InspectorResource.cpp',
>              'inspector/InspectorResource.h',
>              'inspector/InspectorStorageAgent.cpp',
> diff --git a/WebCore/WebCore.pro b/WebCore/WebCore.pro
> index 37d4bd7..4555725 100644
> --- a/WebCore/WebCore.pro
> +++ b/WebCore/WebCore.pro
> @@ -753,6 +753,7 @@ SOURCES += \
>      inspector/InspectorDOMStorageResource.cpp \
>      inspector/InspectorFrontendClientLocal.cpp \
>      inspector/InspectorFrontendHost.cpp \
> +    inspector/InspectorProfilerAgent.cpp \
>      inspector/InspectorResource.cpp \
>      inspector/InspectorStorageAgent.cpp \
>      inspector/InspectorTimelineAgent.cpp \
> @@ -1522,6 +1523,7 @@ HEADERS += \
>      inspector/InspectorFrontendClient.h \
>      inspector/InspectorFrontendClientLocal.h \
>      inspector/InspectorFrontendHost.h \
> +    inspector/InspectorProfilerAgent.h \
>      inspector/InspectorResource.h \
>      inspector/InspectorStorageAgent.h \
>      inspector/InspectorTimelineAgent.h \
> diff --git a/WebCore/WebCore.vcproj/WebCore.vcproj b/WebCore/WebCore.vcproj/WebCore.vcproj
> index 18d4851..e4831f4 100644
> --- a/WebCore/WebCore.vcproj/WebCore.vcproj
> +++ b/WebCore/WebCore.vcproj/WebCore.vcproj
> @@ -51853,6 +51853,14 @@
>  				>
>  			</File>
>  			<File
> +				RelativePath="..\inspector\InspectorProfilerAgent.cpp"
> +				>
> +			</File>
> +			<File
> +				RelativePath="..\inspector\InspectorProfilerAgent.h"
> +				>
> +			</File>
> +			<File
>  				RelativePath="..\inspector\InspectorResource.cpp"
>  				>
>  			</File>
> diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj
> index 2435c61..6712582 100644
> --- a/WebCore/WebCore.xcodeproj/project.pbxproj
> +++ b/WebCore/WebCore.xcodeproj/project.pbxproj
> @@ -2742,6 +2742,8 @@
>  		97EF561011E40783007E026F /* HTMLConstructionSite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97EF560E11E40783007E026F /* HTMLConstructionSite.cpp */; };
>  		97EF561111E40783007E026F /* HTMLConstructionSite.h in Headers */ = {isa = PBXBuildFile; fileRef = 97EF560F11E40783007E026F /* HTMLConstructionSite.h */; };
>  		97EF7DFE107E55B700D7C49C /* ScriptControllerBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97EF7DFD107E55B700D7C49C /* ScriptControllerBase.cpp */; };
> +		9F0D6B2E121BFEBA006C0288 /* InspectorProfilerAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9F0D6B2C121BFEBA006C0288 /* InspectorProfilerAgent.cpp */; };
> +		9F0D6B2F121BFEBA006C0288 /* InspectorProfilerAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F0D6B2D121BFEBA006C0288 /* InspectorProfilerAgent.h */; };
>  		9F6FC1961122E82A00E80196 /* ScriptDebugServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9F6FC1941122E82A00E80196 /* ScriptDebugServer.cpp */; };
>  		9F6FC1971122E82A00E80196 /* ScriptDebugServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F6FC1951122E82A00E80196 /* ScriptDebugServer.h */; settings = {ATTRIBUTES = (Private, ); }; };
>  		9F72304F11184B4100AD0126 /* ScriptProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F72304C11184B4100AD0126 /* ScriptProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
> @@ -8597,6 +8599,8 @@
>  		97EF560E11E40783007E026F /* HTMLConstructionSite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLConstructionSite.cpp; sourceTree = "<group>"; };
>  		97EF560F11E40783007E026F /* HTMLConstructionSite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLConstructionSite.h; sourceTree = "<group>"; };
>  		97EF7DFD107E55B700D7C49C /* ScriptControllerBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptControllerBase.cpp; sourceTree = "<group>"; };
> +		9F0D6B2C121BFEBA006C0288 /* InspectorProfilerAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorProfilerAgent.cpp; sourceTree = "<group>"; };
> +		9F0D6B2D121BFEBA006C0288 /* InspectorProfilerAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorProfilerAgent.h; sourceTree = "<group>"; };
>  		9F6FC1941122E82A00E80196 /* ScriptDebugServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptDebugServer.cpp; sourceTree = "<group>"; };
>  		9F6FC1951122E82A00E80196 /* ScriptDebugServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptDebugServer.h; sourceTree = "<group>"; };
>  		9F72304C11184B4100AD0126 /* ScriptProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptProfile.h; sourceTree = "<group>"; };
> @@ -11787,6 +11791,8 @@
>  				7A0E770B10C00A8800A0276E /* InspectorFrontendHost.cpp */,
>  				7A0E770C10C00A8800A0276E /* InspectorFrontendHost.h */,
>  				7A0E770D10C00A8800A0276E /* InspectorFrontendHost.idl */,
> +				9F0D6B2C121BFEBA006C0288 /* InspectorProfilerAgent.cpp */,
> +				9F0D6B2D121BFEBA006C0288 /* InspectorProfilerAgent.h */,
>  				41F062000F5F0B6600A07EAC /* InspectorResource.cpp */,
>  				41F061FF0F5F0B6600A07EAC /* InspectorResource.h */,
>  				7AB0B1BE1211A62200A76940 /* InspectorStorageAgent.cpp */,
> @@ -20329,6 +20335,7 @@
>  				2EDEF1F8121B0EFC00726DB2 /* BlobStorageData.h in Headers */,
>  				2EF1BFEB121C9F4200C27627 /* FileStream.h in Headers */,
>  				46A26906121B6B4300C41F3A /* FileWriter.h in Headers */,
> +				9F0D6B2F121BFEBA006C0288 /* InspectorProfilerAgent.h in Headers */,
>  			);
>  			runOnlyForDeploymentPostprocessing = 0;
>  		};
> @@ -22780,6 +22787,7 @@
>  				2EDEF1F6121B0EFC00726DB2 /* BlobRegistryImpl.cpp in Sources */,
>  				2EF1BFEA121C9F4200C27627 /* FileStream.cpp in Sources */,
>  				46A26905121B6B4300C41F3A /* FileWriter.cpp in Sources */,
> +				9F0D6B2E121BFEBA006C0288 /* InspectorProfilerAgent.cpp in Sources */,
>  			);
>  			runOnlyForDeploymentPostprocessing = 0;
>  		};
> diff --git a/WebCore/bindings/js/ScriptProfiler.cpp b/WebCore/bindings/js/ScriptProfiler.cpp
> index f372c3c..62ae9ba 100644
> --- a/WebCore/bindings/js/ScriptProfiler.cpp
> +++ b/WebCore/bindings/js/ScriptProfiler.cpp
> @@ -46,6 +46,11 @@ PassRefPtr<ScriptProfile> ScriptProfiler::stop(ScriptState* state, const String&
>      return ScriptProfile::create(profile);
>  }
>  
> +bool ScriptProfiler::isProfilerAlwaysEnabled()
> +{
> +    return false;
> +}
> +
>  } // namespace WebCore
>  
>  #endif // ENABLE(JAVASCRIPT_DEBUGGER)
> diff --git a/WebCore/bindings/js/ScriptProfiler.h b/WebCore/bindings/js/ScriptProfiler.h
> index 4fa331c..180c49f 100644
> --- a/WebCore/bindings/js/ScriptProfiler.h
> +++ b/WebCore/bindings/js/ScriptProfiler.h
> @@ -41,6 +41,7 @@ public:
>      static PassRefPtr<ScriptProfile> stop(ScriptState* state, const String& title);
>      static void takeHeapSnapshot() { }
>      static long getProfilerLogLines(long, String*) { return 0; }
> +    static bool isProfilerAlwaysEnabled();
>  };
>  
>  } // namespace WebCore
> diff --git a/WebCore/bindings/v8/ScriptProfiler.cpp b/WebCore/bindings/v8/ScriptProfiler.cpp
> index 9213774..0de4a24 100644
> --- a/WebCore/bindings/v8/ScriptProfiler.cpp
> +++ b/WebCore/bindings/v8/ScriptProfiler.cpp
> @@ -69,4 +69,9 @@ long ScriptProfiler::getProfilerLogLines(long position, String* data)
>      return position;
>  }
>  
> +bool ScriptProfiler::isProfilerAlwaysEnabled()
> +{
> +    return true;
> +}
> +
>  } // namespace WebCore
> diff --git a/WebCore/bindings/v8/ScriptProfiler.h b/WebCore/bindings/v8/ScriptProfiler.h
> index 5c1054b..b1ab3b1 100644
> --- a/WebCore/bindings/v8/ScriptProfiler.h
> +++ b/WebCore/bindings/v8/ScriptProfiler.h
> @@ -45,6 +45,7 @@ public:
>      static PassRefPtr<ScriptProfile> stop(ScriptState* state, const String& title);
>      static void takeHeapSnapshot();
>      static long getProfilerLogLines(long position, String* data);
> +    static bool isProfilerAlwaysEnabled();
>  };
>  
>  } // namespace WebCore
> diff --git a/WebCore/inspector/CodeGeneratorInspector.pm b/WebCore/inspector/CodeGeneratorInspector.pm
> index cd9052a..e647c90 100644
> --- a/WebCore/inspector/CodeGeneratorInspector.pm
> +++ b/WebCore/inspector/CodeGeneratorInspector.pm
> @@ -38,6 +38,11 @@ $typeTransform{"ApplicationCache"} = {
>      "header" => "InspectorApplicationCacheAgent.h",
>      "handlerAccessor" => "m_inspectorController->applicationCacheAgent()",
>  };
> +$typeTransform{"Profiler"} = {
> +    "forward" => "InspectorProfilerAgent",
> +    "header" => "InspectorProfilerAgent.h",
> +    "handlerAccessor" => "m_inspectorController->profilerAgent()",
> +};
>  $typeTransform{"Frontend"} = {
>      "forward" => "RemoteInspectorFrontend",
>      "header" => "RemoteInspectorFrontend.h",
> diff --git a/WebCore/inspector/Inspector.idl b/WebCore/inspector/Inspector.idl
> index 1c66b59..4864842 100644
> --- a/WebCore/inspector/Inspector.idl
> +++ b/WebCore/inspector/Inspector.idl
> @@ -145,14 +145,14 @@ module core {
>          [handler=Controller] void enableProfiler(in boolean always);
>          [handler=Controller] void disableProfiler(in boolean always);
>  
> -        [handler=Controller] void startProfiling();
> -        [handler=Controller] void stopProfiling();
> +        [handler=Profiler] void startProfiling();
> +        [handler=Profiler] void stopProfiling();
>  
> -        [handler=Controller] void getProfileHeaders(in long callId, out Array headers);
> -        [handler=Controller] void getProfile(in long callId, in unsigned long uid, out Object profile);
> +        [handler=Profiler] void getProfileHeaders(in long callId, out Array headers);
> +        [handler=Profiler] void getProfile(in long callId, in unsigned long uid, out Object profile);
>  
> -        [handler=Controller] void removeProfile(in unsigned long uid);
> -        [handler=Controller] void clearProfiles();
> +        [handler=Profiler] void removeProfile(in unsigned long uid);
> +        [handler=Profiler] void clearProfiles();
>  
>          [handler=Backend] void takeHeapSnapshot();
>          [handler=Backend] void getProfilerLogLines(in long callId, in long inPosition, out long outPosition, out String log);
> diff --git a/WebCore/inspector/InspectorController.cpp b/WebCore/inspector/InspectorController.cpp
> index ac670cb..d6a3634 100644
> --- a/WebCore/inspector/InspectorController.cpp
> +++ b/WebCore/inspector/InspectorController.cpp
> @@ -63,6 +63,7 @@
>  #include "InspectorDOMStorageResource.h"
>  #include "InspectorDatabaseResource.h"
>  #include "InspectorDebuggerAgent.h"
> +#include "InspectorProfilerAgent.h"
>  #include "InspectorResource.h"
>  #include "InspectorStorageAgent.h"
>  #include "InspectorTimelineAgent.h"
> @@ -115,8 +116,6 @@ using namespace std;
>  
>  namespace WebCore {
>  
> -static const char* const UserInitiatedProfileName = "org.webkit.profiles.user-initiated";
> -static const char* const CPUProfileType = "CPU";
>  static const char* const resourceTrackingEnabledSettingName = "resourceTrackingEnabled";
>  static const char* const debuggerEnabledSettingName = "debuggerEnabled";
>  static const char* const profilerEnabledSettingName = "profilerEnabled";
> @@ -170,11 +169,6 @@ InspectorController::InspectorController(Page* page, InspectorClient* client)
>      , m_injectedScriptHost(InjectedScriptHost::create(this))
>  #if ENABLE(JAVASCRIPT_DEBUGGER)
>      , m_attachDebuggerWhenShown(false)
> -    , m_profilerEnabled(!WTF_USE_JSC)
> -    , m_recordingUserInitiatedProfile(false)
> -    , m_currentUserInitiatedProfileNumber(-1)
> -    , m_nextUserInitiatedProfileNumber(1)
> -    , m_startProfiling(this, &InspectorController::startUserInitiatedProfiling)
>  #endif
>  {
>      ASSERT_ARG(page, page);
> @@ -209,6 +203,7 @@ void InspectorController::inspectedPageDestroyed()
>  
>  #if ENABLE(JAVASCRIPT_DEBUGGER)
>      m_debuggerAgent.clear();
> +    m_profilerAgent.clear();
>  #endif
>      ASSERT(m_inspectedPage);
>      m_inspectedPage = 0;
> @@ -504,10 +499,16 @@ void InspectorController::connectFrontend()
>          String debuggerEnabled = setting(debuggerEnabledSettingName);
>          if (debuggerEnabled == "true" || m_attachDebuggerWhenShown)
>              enableDebugger();
> +    }
> +    if (ScriptProfiler::isProfilerAlwaysEnabled())
> +        enableProfiler(true, false);
> +    else {
>          String profilerEnabled = setting(profilerEnabledSettingName);
>          if (profilerEnabled == "true")
>              enableProfiler();
>      }
> +    if (profilerEnabled())
> +        m_profilerAgent->setRemoteFrontend(m_remoteFrontend.get());
>  #endif
>  
>      if (m_showAfterVisible == lastActivePanel)
> @@ -594,7 +595,10 @@ void InspectorController::disconnectFrontend()
>      hideHighlight();
>  
>  #if ENABLE(JAVASCRIPT_DEBUGGER)
> -    stopUserInitiatedProfiling();
> +    if (profilerEnabled()) {
> +        m_profilerAgent->setRemoteFrontend(0);
> +        stopUserInitiatedProfiling();
> +    }
>  #endif
>  
>      releaseFrontendLifetimeAgents();
> @@ -638,7 +642,7 @@ void InspectorController::populateScriptObjects()
>          m_remoteFrontend->monitoringXHRWasEnabled();
>  
>  #if ENABLE(JAVASCRIPT_DEBUGGER)
> -    if (m_profilerEnabled)
> +    if (profilerEnabled())
>          m_remoteFrontend->profilerWasEnabled();
>  #endif
>  
> @@ -745,11 +749,8 @@ void InspectorController::didCommitLoad(DocumentLoader* loader)
>              m_debuggerAgent->clearForPageNavigation();
>  #endif
>  #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
> -        m_profiles.clear();
> -        m_currentUserInitiatedProfileNumber = 1;
> -        m_nextUserInitiatedProfileNumber = 1;
> -        if (m_remoteFrontend)
> -            m_remoteFrontend->resetProfilesPanel();
> +        if (m_profilerAgent)
> +            m_profilerAgent->resetState();
>  #endif
>          // unbindAllResources should be called before database and DOM storage
>          // resources are cleared so that it has a chance to unbind them.
> @@ -1456,145 +1457,48 @@ InspectorDOMStorageResource* InspectorController::getDOMStorageResourceForId(lon
>  #if ENABLE(JAVASCRIPT_DEBUGGER)
>  void InspectorController::addProfile(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL)
>  {
> -    if (!enabled())
> -        return;
> -
> -    RefPtr<ScriptProfile> profile = prpProfile;
> -    m_profiles.add(profile->uid(), profile);
> -
> -    if (m_remoteFrontend) {
> -        m_remoteFrontend->addProfileHeader(createProfileHeader(*profile));
> -    }
> -
> -    addProfileFinishedMessageToConsole(profile, lineNumber, sourceURL);
> +    if (profilerEnabled())
> +        m_profilerAgent->addProfile(prpProfile, lineNumber, sourceURL);
>  }
>  
>  void InspectorController::addProfileFinishedMessageToConsole(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL)
>  {
> -    RefPtr<ScriptProfile> profile = prpProfile;
> -
> -    String title = profile->title();
> -    String message = String::format("Profile \"webkit-profile://%s/%s#%d\" finished.", CPUProfileType, encodeWithURLEscapeSequences(title).utf8().data(), profile->uid());
> -    addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
> +    if (profilerEnabled())
> +        m_profilerAgent->addProfileFinishedMessageToConsole(prpProfile, lineNumber, sourceURL);
>  }
>  
>  void InspectorController::addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL)
>  {
> -    String message = String::format("Profile \"webkit-profile://%s/%s#0\" started.", CPUProfileType, encodeWithURLEscapeSequences(title).utf8().data());
> -    addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
> -}
> -
> -void InspectorController::removeProfile(unsigned uid)
> -{
> -    if (!enabled())
> -        return;
> -
> -    if (m_profiles.contains(uid))
> -        m_profiles.remove(uid);
> +    if (profilerEnabled())
> +        m_profilerAgent->addStartProfilingMessageToConsole(title, lineNumber, sourceURL);
>  }
>  
> -void InspectorController::clearProfiles()
> -{
> -    if (!enabled())
> -        return;
> -
> -    m_profiles.clear();
> -    m_currentUserInitiatedProfileNumber = 1;
> -    m_nextUserInitiatedProfileNumber = 1;
> -}
>  
> -void InspectorController::getProfileHeaders(RefPtr<InspectorArray>* headers)
> +bool InspectorController::isRecordingUserInitiatedProfile() const
>  {
> -    ProfilesMap::iterator profilesEnd = m_profiles.end();
> -    for (ProfilesMap::iterator it = m_profiles.begin(); it != profilesEnd; ++it)
> -        (*headers)->pushObject(createProfileHeader(*it->second));
> +    return m_profilerAgent && m_profilerAgent->isRecordingUserInitiatedProfile();
>  }
>  
> -void InspectorController::getProfile(unsigned uid, RefPtr<InspectorObject>* profileObject)
> +String InspectorController::getCurrentUserInitiatedProfileName(bool incrementProfileNumber)
>  {
> -    ProfilesMap::iterator it = m_profiles.find(uid);
> -    if (it != m_profiles.end()) {
> -        *profileObject = createProfileHeader(*it->second);
> -        (*profileObject)->setObject("head", it->second->buildInspectorObjectForHead());
> -    }
> -}
> -
> -PassRefPtr<InspectorObject> InspectorController::createProfileHeader(const ScriptProfile& profile)
> -{
> -    RefPtr<InspectorObject> header = InspectorObject::create();
> -    header->setString("title", profile.title());
> -    header->setNumber("uid", profile.uid());
> -    header->setString("typeId", String(CPUProfileType));
> -    return header;
> +    if (profilerEnabled())
> +        return m_profilerAgent->getCurrentUserInitiatedProfileName(incrementProfileNumber);
> +    return "";
>  }
>  
> -String InspectorController::getCurrentUserInitiatedProfileName(bool incrementProfileNumber = false)
> +void InspectorController::startUserInitiatedProfiling()
>  {
> -    if (incrementProfileNumber)
> -        m_currentUserInitiatedProfileNumber = m_nextUserInitiatedProfileNumber++;
> -
> -    return String::format("%s.%d", UserInitiatedProfileName, m_currentUserInitiatedProfileNumber);
> -}
> -
> -void InspectorController::startUserInitiatedProfilingSoon()
> -{
> -    m_startProfiling.startOneShot(0);
> -}
> -
> -void InspectorController::startUserInitiatedProfiling(Timer<InspectorController>*)
> -{
> -    if (!enabled())
> -        return;
> -
>      if (!profilerEnabled()) {
>          enableProfiler(false, true);
>          ScriptDebugServer::shared().recompileAllJSFunctions();
>      }
> -
> -    m_recordingUserInitiatedProfile = true;
> -
> -    String title = getCurrentUserInitiatedProfileName(true);
> -
> -#if USE(JSC)
> -    JSC::ExecState* scriptState = toJSDOMWindow(m_inspectedPage->mainFrame(), debuggerWorld())->globalExec();
> -#else
> -    ScriptState* scriptState = 0;
> -#endif
> -    ScriptProfiler::start(scriptState, title);
> -
> -    addStartProfilingMessageToConsole(title, 0, String());
> -
> -    toggleRecordButton(true);
> +    m_profilerAgent->startUserInitiatedProfiling();
>  }
>  
>  void InspectorController::stopUserInitiatedProfiling()
>  {
> -    if (!enabled())
> -        return;
> -
> -    m_recordingUserInitiatedProfile = false;
> -
> -    String title = getCurrentUserInitiatedProfileName();
> -
> -#if USE(JSC)
> -    JSC::ExecState* scriptState = toJSDOMWindow(m_inspectedPage->mainFrame(), debuggerWorld())->globalExec();
> -#else
> -    // Use null script state to avoid filtering by context security token.
> -    // All functions from all iframes should be visible from Inspector UI.
> -    ScriptState* scriptState = 0;
> -#endif
> -    RefPtr<ScriptProfile> profile = ScriptProfiler::stop(scriptState, title);
> -    if (profile)
> -        addProfile(profile, 0, String());
> -
> -    toggleRecordButton(false);
> -}
> -
> -void InspectorController::toggleRecordButton(bool isProfiling)
> -{
> -    if (!m_remoteFrontend)
> -        return;
> -    m_remoteFrontend->setRecordingProfile(isProfiling);
> +    if (profilerEnabled())
> +        m_profilerAgent->stopUserInitiatedProfiling();
>  }
>  
>  void InspectorController::enableProfiler(bool always, bool skipRecompile)
> @@ -1602,14 +1506,14 @@ void InspectorController::enableProfiler(bool always, bool skipRecompile)
>      if (always)
>          setSetting(profilerEnabledSettingName, "true");
>  
> -    if (m_profilerEnabled)
> +    if (profilerEnabled())
>          return;
>  
> -    m_profilerEnabled = true;
> -
>      if (!skipRecompile)
>          ScriptDebugServer::shared().recompileAllJSFunctionsSoon();
>  
> +    m_profilerAgent = InspectorProfilerAgent::create(this, m_remoteFrontend.get());
> +
>      if (m_remoteFrontend)
>          m_remoteFrontend->profilerWasEnabled();
>  }
> @@ -1619,10 +1523,10 @@ void InspectorController::disableProfiler(bool always)
>      if (always)
>          setSetting(profilerEnabledSettingName, "false");
>  
> -    if (!m_profilerEnabled)
> +    if (!profilerEnabled())
>          return;
>  
> -    m_profilerEnabled = false;
> +    m_profilerAgent.clear();
>  
>      ScriptDebugServer::shared().recompileAllJSFunctionsSoon();
>  
> diff --git a/WebCore/inspector/InspectorController.h b/WebCore/inspector/InspectorController.h
> index 8d96005..672a7c1 100644
> --- a/WebCore/inspector/InspectorController.h
> +++ b/WebCore/inspector/InspectorController.h
> @@ -33,9 +33,7 @@
>  #include "Cookie.h"
>  #include "InspectorDOMAgent.h"
>  #include "PlatformString.h"
> -#include "ScriptProfile.h"
>  #include "ScriptState.h"
> -#include "Timer.h"
>  #include <wtf/HashMap.h>
>  #include <wtf/HashSet.h>
>  #include <wtf/ListHashSet.h>
> @@ -65,6 +63,7 @@ class InspectorDatabaseResource;
>  class InspectorDebuggerAgent;
>  class InspectorFrontendClient;
>  class InspectorObject;
> +class InspectorProfilerAgent;
>  class InspectorResource;
>  class InspectorStorageAgent;
>  class InspectorTimelineAgent;
> @@ -78,6 +77,7 @@ class ResourceRequest;
>  class ResourceResponse;
>  class ResourceError;
>  class ScriptCallStack;
> +class ScriptProfile;
>  class ScriptString;
>  class SharedBuffer;
>  class Storage;
> @@ -228,20 +228,14 @@ public:
>      void addProfile(PassRefPtr<ScriptProfile>, unsigned lineNumber, const String& sourceURL);
>      void addProfileFinishedMessageToConsole(PassRefPtr<ScriptProfile>, unsigned lineNumber, const String& sourceURL);
>      void addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL);
> -    void removeProfile(unsigned);
> -    void clearProfiles();
> -
> -    bool isRecordingUserInitiatedProfile() const { return m_recordingUserInitiatedProfile; }
> -
> -    String getCurrentUserInitiatedProfileName(bool incrementProfileNumber);
> -    void startUserInitiatedProfiling(Timer<InspectorController>* = 0);
> +    bool isRecordingUserInitiatedProfile() const;
> +    String getCurrentUserInitiatedProfileName(bool incrementProfileNumber = false);
> +    void startUserInitiatedProfiling();
>      void stopUserInitiatedProfiling();
> -    void startProfiling() { startUserInitiatedProfiling(); }
> -    void stopProfiling() { stopUserInitiatedProfiling(); }
> -
>      void enableProfiler(bool always = false, bool skipRecompile = false);
>      void disableProfiler(bool always = false);
> -    bool profilerEnabled() const { return enabled() && m_profilerEnabled; }
> +    bool profilerEnabled() const { return enabled() && m_profilerAgent; }
> +    InspectorProfilerAgent* profilerAgent() const { return m_profilerAgent.get(); }
>  
>      void enableDebugger();
>      void disableDebugger(bool always = false);
> @@ -283,14 +277,9 @@ private:
>      void releaseFrontendLifetimeAgents();
>  
>  #if ENABLE(JAVASCRIPT_DEBUGGER)
> -    typedef HashMap<unsigned int, RefPtr<ScriptProfile> > ProfilesMap;
>  
> -    void startUserInitiatedProfilingSoon();
>      void toggleRecordButton(bool);
>      void enableDebuggerFromFrontend(bool always);
> -    void getProfileHeaders(RefPtr<InspectorArray>* headers);
> -    void getProfile(unsigned uid, RefPtr<InspectorObject>* profileObject);
> -    PassRefPtr<InspectorObject> createProfileHeader(const ScriptProfile& profile);
>  #endif
>  #if ENABLE(DATABASE)
>      void selectDatabase(Database* database);
> @@ -380,12 +369,7 @@ private:
>      bool m_attachDebuggerWhenShown;
>      OwnPtr<InspectorDebuggerAgent> m_debuggerAgent;
>  
> -    bool m_profilerEnabled;
> -    bool m_recordingUserInitiatedProfile;
> -    int m_currentUserInitiatedProfileNumber;
> -    unsigned m_nextUserInitiatedProfileNumber;
> -    Timer<InspectorController> m_startProfiling;
> -    ProfilesMap m_profiles;
> +    OwnPtr<InspectorProfilerAgent> m_profilerAgent;
>  #endif
>  #if ENABLE(WORKERS)
>      typedef HashMap<intptr_t, RefPtr<InspectorWorkerResource> > WorkersMap;
> diff --git a/WebCore/inspector/InspectorProfilerAgent.cpp b/WebCore/inspector/InspectorProfilerAgent.cpp
> new file mode 100644
> index 0000000..3954194
> --- /dev/null
> +++ b/WebCore/inspector/InspectorProfilerAgent.cpp
> @@ -0,0 +1,184 @@
> +/*
> + * Copyright (C) 2010 Apple Inc. All rights reserved.
> + * Copyright (C) 2010 Google 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.
> + * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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.
> + */
> +
> +#include "config.h"
> +#include "InspectorProfilerAgent.h"
> +
> +#if ENABLE(JAVASCRIPT_DEBUGGER)
> +
> +#include "Console.h"
> +#include "InspectorController.h"
> +#include "InspectorValues.h"
> +#include "KURL.h"
> +#include "Page.h"
> +#include "RemoteInspectorFrontend.h"
> +#include "ScriptProfile.h"
> +#include "ScriptProfiler.h"
> +#include <wtf/OwnPtr.h>
> +
> +#if USE(JSC)
> +#include "JSDOMWindow.h"
> +#endif
> +
> +namespace WebCore {
> +
> +static const char* const UserInitiatedProfileName = "org.webkit.profiles.user-initiated";
> +static const char* const CPUProfileType = "CPU";
> +
> +PassOwnPtr<InspectorProfilerAgent> InspectorProfilerAgent::create(InspectorController* inspectorController, RemoteInspectorFrontend* remoteFrontend)
> +{
> +    OwnPtr<InspectorProfilerAgent> agent = adoptPtr(new InspectorProfilerAgent(inspectorController, remoteFrontend));
> +    return agent.release();
> +}
> +
> +InspectorProfilerAgent::InspectorProfilerAgent(InspectorController* inspectorController, RemoteInspectorFrontend* remoteFrontend)
> +        : m_inspectorController(inspectorController)
> +        , m_remoteFrontend(remoteFrontend)
> +        , m_recordingUserInitiatedProfile(false)
> +        , m_currentUserInitiatedProfileNumber(-1)
> +        , m_nextUserInitiatedProfileNumber(1)
> +{
> +}
> +
> +InspectorProfilerAgent::~InspectorProfilerAgent()
> +{
> +}
> +
> +void InspectorProfilerAgent::addProfile(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL)
> +{
> +    RefPtr<ScriptProfile> profile = prpProfile;
> +    m_profiles.add(profile->uid(), profile);
> +    if (m_remoteFrontend)
> +        m_remoteFrontend->addProfileHeader(createProfileHeader(*profile));
> +    addProfileFinishedMessageToConsole(profile, lineNumber, sourceURL);
> +}
> +
> +void InspectorProfilerAgent::addProfileFinishedMessageToConsole(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL)
> +{
> +    RefPtr<ScriptProfile> profile = prpProfile;
> +
> +    String title = profile->title();
> +    String message = String::format("Profile \"webkit-profile://%s/%s#%d\" finished.", CPUProfileType, encodeWithURLEscapeSequences(title).utf8().data(), profile->uid());
> +    m_inspectorController->addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
> +}
> +
> +void InspectorProfilerAgent::addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL)
> +{
> +    String message = String::format("Profile \"webkit-profile://%s/%s#0\" started.", CPUProfileType, encodeWithURLEscapeSequences(title).utf8().data());
> +    m_inspectorController->addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
> +}
> +
> +PassRefPtr<InspectorObject> InspectorProfilerAgent::createProfileHeader(const ScriptProfile& profile)
> +{
> +    RefPtr<InspectorObject> header = InspectorObject::create();
> +    header->setString("title", profile.title());
> +    header->setNumber("uid", profile.uid());
> +    header->setString("typeId", String(CPUProfileType));
> +    return header;
> +}
> +
> +String InspectorProfilerAgent::getCurrentUserInitiatedProfileName(bool incrementProfileNumber)
> +{
> +    if (incrementProfileNumber)
> +        m_currentUserInitiatedProfileNumber = m_nextUserInitiatedProfileNumber++;
> +
> +    return String::format("%s.%d", UserInitiatedProfileName, m_currentUserInitiatedProfileNumber);
> +}
> +
> +void InspectorProfilerAgent::getProfileHeaders(RefPtr<InspectorArray>* headers)
> +{
> +    ProfilesMap::iterator profilesEnd = m_profiles.end();
> +    for (ProfilesMap::iterator it = m_profiles.begin(); it != profilesEnd; ++it)
> +        (*headers)->pushObject(createProfileHeader(*it->second));
> +}
> +
> +void InspectorProfilerAgent::getProfile(unsigned uid, RefPtr<InspectorObject>* profileObject)
> +{
> +    ProfilesMap::iterator it = m_profiles.find(uid);
> +    if (it != m_profiles.end()) {
> +        *profileObject = createProfileHeader(*it->second);
> +        (*profileObject)->setObject("head", it->second->buildInspectorObjectForHead());
> +    }
> +}
> +
> +void InspectorProfilerAgent::removeProfile(unsigned uid)
> +{
> +    if (m_profiles.contains(uid))
> +        m_profiles.remove(uid);
> +}
> +
> +void InspectorProfilerAgent::resetState()
> +{
> +    m_profiles.clear();
> +    m_currentUserInitiatedProfileNumber = 1;
> +    m_nextUserInitiatedProfileNumber = 1;
> +    if (m_remoteFrontend)
> +        m_remoteFrontend->resetProfilesPanel();
> +}
> +
> +void InspectorProfilerAgent::startUserInitiatedProfiling()
> +{
> +    m_recordingUserInitiatedProfile = true;
> +    String title = getCurrentUserInitiatedProfileName(true);
> +#if USE(JSC)
> +    JSC::ExecState* scriptState = toJSDOMWindow(m_inspectorController->inspectedPage()->mainFrame(), debuggerWorld())->globalExec();
> +#else
> +    ScriptState* scriptState = 0;
> +#endif
> +    ScriptProfiler::start(scriptState, title);
> +    addStartProfilingMessageToConsole(title, 0, String());
> +    toggleRecordButton(true);
> +}
> +
> +void InspectorProfilerAgent::stopUserInitiatedProfiling()
> +{
> +    m_recordingUserInitiatedProfile = false;
> +    String title = getCurrentUserInitiatedProfileName();
> +#if USE(JSC)
> +    JSC::ExecState* scriptState = toJSDOMWindow(m_inspectorController->inspectedPage()->mainFrame(), debuggerWorld())->globalExec();
> +#else
> +    // Use null script state to avoid filtering by context security token.
> +    // All functions from all iframes should be visible from Inspector UI.
> +    ScriptState* scriptState = 0;
> +#endif
> +    RefPtr<ScriptProfile> profile = ScriptProfiler::stop(scriptState, title);
> +    if (profile)
> +        addProfile(profile, 0, String());
> +    toggleRecordButton(false);
> +}
> +
> +void InspectorProfilerAgent::toggleRecordButton(bool isProfiling)
> +{
> +    if (m_remoteFrontend)
> +        m_remoteFrontend->setRecordingProfile(isProfiling);
> +}
> +
> +} // namespace WebCore
> +
> +#endif // ENABLE(JAVASCRIPT_DEBUGGER)
> diff --git a/WebCore/inspector/InspectorProfilerAgent.h b/WebCore/inspector/InspectorProfilerAgent.h
> new file mode 100644
> index 0000000..2ce6549
> --- /dev/null
> +++ b/WebCore/inspector/InspectorProfilerAgent.h
> @@ -0,0 +1,89 @@
> +/*
> + * Copyright (C) 2010 Apple Inc. All rights reserved.
> + * Copyright (C) 2010 Google 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.
> + * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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.
> + */
> +
> +#ifndef InspectorProfilerAgent_h
> +#define InspectorProfilerAgent_h
> +
> +#if ENABLE(JAVASCRIPT_DEBUGGER)
> +
> +#include "PlatformString.h"
> +#include <wtf/Forward.h>
> +#include <wtf/HashMap.h>
> +#include <wtf/Noncopyable.h>
> +#include <wtf/PassOwnPtr.h>
> +
> +namespace WebCore {
> +
> +class InspectorArray;
> +class InspectorController;
> +class InspectorObject;
> +class ScriptProfile;
> +class RemoteInspectorFrontend;
> +
> +class InspectorProfilerAgent : public Noncopyable {
> +public:
> +    static PassOwnPtr<InspectorProfilerAgent> create(InspectorController*, RemoteInspectorFrontend*);
> +    virtual ~InspectorProfilerAgent();
> +
> +    void addProfile(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL);
> +    void addProfileFinishedMessageToConsole(PassRefPtr<ScriptProfile>, unsigned lineNumber, const String& sourceURL);
> +    void addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL);
> +    void clearProfiles() { resetState(); }
> +    String getCurrentUserInitiatedProfileName(bool incrementProfileNumber = false);
> +    void getProfileHeaders(RefPtr<InspectorArray>* headers);
> +    void getProfile(unsigned uid, RefPtr<InspectorObject>* profileObject);
> +    bool isRecordingUserInitiatedProfile() { return m_recordingUserInitiatedProfile; }
> +    void removeProfile(unsigned uid);
> +    void resetState();
> +    void setRemoteFrontend(RemoteInspectorFrontend* frontend) { m_remoteFrontend = frontend; }
> +    void startProfiling() { startUserInitiatedProfiling(); }
> +    void startUserInitiatedProfiling();
> +    void stopProfiling() { stopUserInitiatedProfiling(); }
> +    void stopUserInitiatedProfiling();
> +    void toggleRecordButton(bool isProfiling);
> +
> +private:
> +    typedef HashMap<unsigned int, RefPtr<ScriptProfile> > ProfilesMap;
> +
> +    InspectorProfilerAgent(InspectorController*, RemoteInspectorFrontend*);
> +    PassRefPtr<InspectorObject> createProfileHeader(const ScriptProfile& profile);
> +
> +    InspectorController* m_inspectorController;
> +    RemoteInspectorFrontend* m_remoteFrontend;
> +    bool m_recordingUserInitiatedProfile;
> +    int m_currentUserInitiatedProfileNumber;
> +    unsigned m_nextUserInitiatedProfileNumber;
> +    ProfilesMap m_profiles;
> +};
> +
> +} // namespace WebCore
> +
> +#endif // ENABLE(JAVASCRIPT_DEBUGGER)
> +
> +#endif // !defined(InspectorProfilerAgent_h)
Comment 7 Mikhail Naganov 2010-08-19 08:46:17 PDT
Created attachment 64857 [details]
This time, interactive_ui_tests pass
Comment 8 Pavel Feldman 2010-08-20 04:49:15 PDT
Comment on attachment 64857 [details]
This time, interactive_ui_tests pass

WebCore/inspector/InspectorController.cpp:177
 +      // Needed for 'console.profile' to work.
This seems wrong. JSC does not require this for console.profile to work?

WebCore/inspector/InspectorController.cpp:506
 +      String profilerEnabledSetting = setting(profilerEnabledSettingName);
we should not perform this check in case profiler is always enabled?

WebCore/inspector/InspectorProfilerAgent.h:64
 +      void setRemoteFrontend(RemoteInspectorFrontend* frontend) { m_remoteFrontend = frontend; }
By the nature of your agent, all the calls to it should be of query form (initiated from the front-end side). You should not need remoteFrontend reference for it to work.
Comment 9 Mikhail Naganov 2010-08-23 01:23:25 PDT
Created attachment 65086 [details]
Comments addressed.

As we had discussed offline, calls to InspectorProfilerAgent can't be fully converted into query form, e.g. starting and stopping profiling.
Comment 10 Mikhail Naganov 2010-08-23 01:24:59 PDT
Created attachment 65087 [details]
Comments addressed (forgot to mark the previous attachment as a patch.)

As we had discussed offline, calls to InspectorProfilerAgent can't be fully converted into query form, e.g. starting and stopping profiling.
Comment 11 Pavel Feldman 2010-08-23 01:49:07 PDT
Comment on attachment 65087 [details]
Comments addressed (forgot to mark the previous attachment as a patch.)

WebCore/inspector/InspectorController.cpp:1470
 +  bool InspectorController::isRecordingUserInitiatedProfile() const
I'd rather get rid of the usage in the WebKit layer. WebKit is starting and stopping it, why doesn't it track its own state? Also, I'd implement user initiated profiling in the WebKit layer as a whole...

WebCore/inspector/InspectorProfilerAgent.cpp:62
 +          : m_inspectorController(inspectorController)
Too many spaces.
Comment 12 Mikhail Naganov 2010-08-23 03:23:52 PDT
Committed as http://trac.webkit.org/changeset/65797:


2010-08-23  Mikhail Naganov  <mnaganov@chromium.org>

        Reviewed by Pavel Feldman.

        Extract profiler-related code and data from InspectorController into
        InspectorProfilerAgent.

        https://bugs.webkit.org/show_bug.cgi?id=44174