Web Inspector: Add message loop instrumentation to public API and timeline agent
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 9 Jun 2012 10:16:10 +0000 (10:16 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 9 Jun 2012 10:16:10 +0000 (10:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=88639

Patch by Eugene Klyuchnikov <eustas.bug@gmail.com> on 2012-06-09
Reviewed by Vsevolod Vlasov.

Message loop instrumentation will show when the render thread is busy.
That way developer can discover if a render thread business causes low fps, or not.

Source/WebCore:

* inspector/InspectorClient.h:
(WebCore::InspectorClient::startMessageLoopMonitoring): Starts observer.
(WebCore::InspectorClient::stopMessageLoopMonitoring): Stops observer.
* inspector/InspectorController.cpp:
(WebCore::InspectorController::InspectorController):
Changed timeline agent constructor parameters.
* inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::willProcessTaskImpl):
Forwards observer notification.
(WebCore):
(WebCore::InspectorInstrumentation::didProcessTaskImpl):
Ditto.
* inspector/InspectorInstrumentation.h:
(InspectorInstrumentation):
(WebCore::InspectorInstrumentation::willProcessTask):
Ditto.
(WebCore):
(WebCore::InspectorInstrumentation::didProcessTask):
Ditto.
* inspector/InspectorTimelineAgent.cpp:
(WebCore::InspectorTimelineAgent::start):
Starts observer.
(WebCore::InspectorTimelineAgent::stop):
Stops observer.
(WebCore::InspectorTimelineAgent::supportsFrameInstrumentation):
Changed result origin.
(WebCore::InspectorTimelineAgent::willProcessTask):
Noop implementqation.
(WebCore):
(WebCore::InspectorTimelineAgent::didProcessTask):
Noop implementqation.
(WebCore::InspectorTimelineAgent::InspectorTimelineAgent):
Changed constructor parameters.
* inspector/InspectorTimelineAgent.h:
(WebCore::InspectorTimelineAgent::create):
Ditto.
(InspectorTimelineAgent):
* inspector/WorkerInspectorController.cpp:
(WebCore::WorkerInspectorController::WorkerInspectorController):
Changed timeline agent constructor parameters.

Source/WebKit/chromium:

* public/WebDevToolsAgent.h:
(WebDevToolsAgent):
* public/WebDevToolsAgentClient.h:
(WebDevToolsAgentClient):
(WebKit::WebDevToolsAgentClient::startMessageLoopMonitoring):
Request message loop notifications.
(WebKit::WebDevToolsAgentClient::stopMessageLoopMonitoring):
Cancel message loop notifications.
* src/InspectorClientImpl.cpp:
(WebKit::InspectorClientImpl::startMessageLoopMonitoring):
Request message loop notifications.
(WebKit):
(WebKit::InspectorClientImpl::stopMessageLoopMonitoring):
Cancel message loop notifications.
* src/InspectorClientImpl.h:
(InspectorClientImpl):
* src/WebDevToolsAgentImpl.cpp:
(WebKit::WebDevToolsAgentImpl::startMessageLoopMonitoring):
Request message loop notifications.
(WebKit):
(WebKit::WebDevToolsAgentImpl::stopMessageLoopMonitoring):
Cancel message loop notifications.
(WebKit::WebDevToolsAgentImpl::instrumentWillProcessTask):
Message loop notification.
(WebKit::WebDevToolsAgentImpl::instrumentDidProcessTask):
Ditto.
* src/WebDevToolsAgentImpl.h:
(WebDevToolsAgentImpl):

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

15 files changed:
Source/WebCore/ChangeLog
Source/WebCore/inspector/InspectorClient.h
Source/WebCore/inspector/InspectorController.cpp
Source/WebCore/inspector/InspectorInstrumentation.cpp
Source/WebCore/inspector/InspectorInstrumentation.h
Source/WebCore/inspector/InspectorTimelineAgent.cpp
Source/WebCore/inspector/InspectorTimelineAgent.h
Source/WebCore/inspector/WorkerInspectorController.cpp
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/public/WebDevToolsAgent.h
Source/WebKit/chromium/public/WebDevToolsAgentClient.h
Source/WebKit/chromium/src/InspectorClientImpl.cpp
Source/WebKit/chromium/src/InspectorClientImpl.h
Source/WebKit/chromium/src/WebDevToolsAgentImpl.cpp
Source/WebKit/chromium/src/WebDevToolsAgentImpl.h

index c727c0f..8cc7e3d 100644 (file)
@@ -1,3 +1,54 @@
+2012-06-09  Eugene Klyuchnikov  <eustas.bug@gmail.com>
+
+        Web Inspector: Add message loop instrumentation to public API and timeline agent
+        https://bugs.webkit.org/show_bug.cgi?id=88639
+
+        Reviewed by Vsevolod Vlasov.
+
+        Message loop instrumentation will show when the render thread is busy.
+        That way developer can discover if a render thread business causes low fps, or not.
+
+        * inspector/InspectorClient.h:
+        (WebCore::InspectorClient::startMessageLoopMonitoring): Starts observer.
+        (WebCore::InspectorClient::stopMessageLoopMonitoring): Stops observer.
+        * inspector/InspectorController.cpp:
+        (WebCore::InspectorController::InspectorController):
+        Changed timeline agent constructor parameters.
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore::InspectorInstrumentation::willProcessTaskImpl):
+        Forwards observer notification.
+        (WebCore):
+        (WebCore::InspectorInstrumentation::didProcessTaskImpl):
+        Ditto.
+        * inspector/InspectorInstrumentation.h:
+        (InspectorInstrumentation):
+        (WebCore::InspectorInstrumentation::willProcessTask):
+        Ditto.
+        (WebCore):
+        (WebCore::InspectorInstrumentation::didProcessTask):
+        Ditto.
+        * inspector/InspectorTimelineAgent.cpp:
+        (WebCore::InspectorTimelineAgent::start):
+        Starts observer.
+        (WebCore::InspectorTimelineAgent::stop):
+        Stops observer.
+        (WebCore::InspectorTimelineAgent::supportsFrameInstrumentation):
+        Changed result origin.
+        (WebCore::InspectorTimelineAgent::willProcessTask):
+        Noop implementqation.
+        (WebCore):
+        (WebCore::InspectorTimelineAgent::didProcessTask):
+        Noop implementqation.
+        (WebCore::InspectorTimelineAgent::InspectorTimelineAgent):
+        Changed constructor parameters.
+        * inspector/InspectorTimelineAgent.h:
+        (WebCore::InspectorTimelineAgent::create):
+        Ditto.
+        (InspectorTimelineAgent):
+        * inspector/WorkerInspectorController.cpp:
+        (WebCore::WorkerInspectorController::WorkerInspectorController):
+        Changed timeline agent constructor parameters.
+
 2012-06-08  Andrey Kosyakov  <caseq@chromium.org>
 
         Web Inspector: optimize timeline's frame mode overview appearance for 30fps
index f7a9dab..4eef0d6 100644 (file)
@@ -55,6 +55,8 @@ public:
     virtual void clearBrowserCache() { }
     virtual bool canClearBrowserCookies() { return false; }
     virtual void clearBrowserCookies() { }
+    virtual void startMessageLoopMonitoring() { }
+    virtual void stopMessageLoopMonitoring() { }
 
     virtual bool canOverrideDeviceMetrics() { return false; }
 
index d2c81b7..f9f4e62 100644 (file)
@@ -114,7 +114,7 @@ InspectorController::InspectorController(Page* page, InspectorClient* inspectorC
     m_agents.append(domStorageAgentPtr.release());
     m_agents.append(InspectorMemoryAgent::create(m_instrumentingAgents.get(), m_state.get(), m_page, m_domAgent));
     m_agents.append(InspectorTimelineAgent::create(m_instrumentingAgents.get(), pageAgent, m_state.get(), InspectorTimelineAgent::PageInspector,
-       inspectorClient->supportsFrameInstrumentation() ? InspectorTimelineAgent::FrameInstrumentationSupported : InspectorTimelineAgent::FrameInstrumentationNotSupported));
+       inspectorClient));
     m_agents.append(InspectorApplicationCacheAgent::create(m_instrumentingAgents.get(), m_state.get(), pageAgent));
 
     OwnPtr<InspectorResourceAgent> resourceAgentPtr(InspectorResourceAgent::create(m_instrumentingAgents.get(), pageAgent, inspectorClient, m_state.get()));
index fbea180..a65ff7e 100644 (file)
@@ -551,6 +551,18 @@ void InspectorInstrumentation::didProcessRuleImpl(const InspectorInstrumentation
         cssAgent->didProcessRule();
 }
 
+void InspectorInstrumentation::willProcessTaskImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->willProcessTask();
+}
+
+void InspectorInstrumentation::didProcessTaskImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didProcessTask();
+}
+
 void InspectorInstrumentation::applyUserAgentOverrideImpl(InstrumentingAgents* instrumentingAgents, String* userAgent)
 {
     if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
index 5076949..1d79f24 100644 (file)
@@ -153,6 +153,8 @@ public:
     static void didMatchRule(const InspectorInstrumentationCookie&, bool matched);
     static InspectorInstrumentationCookie willProcessRule(Document*, const StyleRule*);
     static void didProcessRule(const InspectorInstrumentationCookie&);
+    static void willProcessTask(Page*);
+    static void didProcessTask(Page*);
 
     static void applyUserAgentOverride(Frame*, String*);
     static void applyScreenWidthOverride(Frame*, long*);
@@ -316,6 +318,8 @@ private:
     static void didMatchRuleImpl(const InspectorInstrumentationCookie&, bool matched);
     static InspectorInstrumentationCookie willProcessRuleImpl(InstrumentingAgents*, const StyleRule*);
     static void didProcessRuleImpl(const InspectorInstrumentationCookie&);
+    static void willProcessTaskImpl(InstrumentingAgents*);
+    static void didProcessTaskImpl(InstrumentingAgents*);
 
     static void applyUserAgentOverrideImpl(InstrumentingAgents*, String*);
     static void applyScreenWidthOverrideImpl(InstrumentingAgents*, long*);
@@ -913,6 +917,24 @@ inline void InspectorInstrumentation::didProcessRule(const InspectorInstrumentat
 #endif
 }
 
+inline void InspectorInstrumentation::willProcessTask(Page* page)
+{
+#if ENABLE(INSPECTOR)
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        willProcessTaskImpl(instrumentingAgents);
+#endif
+}
+
+inline void InspectorInstrumentation::didProcessTask(Page* page)
+{
+#if ENABLE(INSPECTOR)
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        didProcessTaskImpl(instrumentingAgents);
+#endif
+}
+
 inline void InspectorInstrumentation::applyUserAgentOverride(Frame* frame, String* userAgent)
 {
 #if ENABLE(INSPECTOR)
index b865233..c3f90c8 100644 (file)
@@ -154,6 +154,10 @@ void InspectorTimelineAgent::start(ErrorString*, const int* maxCallStackDepth)
         m_maxCallStackDepth = 5;
     m_state->setLong(TimelineAgentState::timelineMaxCallStackDepth, m_maxCallStackDepth);
     m_timestampOffset = currentTime() - monotonicallyIncreasingTime();
+
+    if (m_client)
+        m_client->startMessageLoopMonitoring();
+
     m_instrumentingAgents->setInspectorTimelineAgent(this);
     ScriptGCEvent::addEventListener(this);
     m_state->setBoolean(TimelineAgentState::timelineAgentEnabled, true);
@@ -163,6 +167,10 @@ void InspectorTimelineAgent::stop(ErrorString*)
 {
     if (!m_state->getBoolean(TimelineAgentState::timelineAgentEnabled))
         return;
+
+    if (m_client)
+        m_client->stopMessageLoopMonitoring();
+
     m_instrumentingAgents->setInspectorTimelineAgent(0);
     ScriptGCEvent::removeEventListener(this);
 
@@ -179,7 +187,7 @@ void InspectorTimelineAgent::setIncludeMemoryDetails(ErrorString*, bool value)
 
 void InspectorTimelineAgent::supportsFrameInstrumentation(ErrorString*, bool* result)
 {
-    *result = m_frameInstrumentationSupport == FrameInstrumentationSupported;
+    *result = m_client && m_client->supportsFrameInstrumentation();
 }
 
 void InspectorTimelineAgent::didBeginFrame()
@@ -405,6 +413,16 @@ void InspectorTimelineAgent::didFireAnimationFrame()
     didCompleteCurrentRecord(TimelineRecordType::FireAnimationFrame);
 }
 
+void InspectorTimelineAgent::willProcessTask()
+{
+    // TODO: Record task processing start time.
+}
+
+void InspectorTimelineAgent::didProcessTask()
+{
+    // TODO: Record task processing end time.
+}
+
 void InspectorTimelineAgent::addRecordToTimeline(PassRefPtr<InspectorObject> record, const String& type, const String& frameId)
 {
     commitCancelableRecords();
@@ -462,7 +480,7 @@ void InspectorTimelineAgent::didCompleteCurrentRecord(const String& type)
     }
 }
 
-InspectorTimelineAgent::InspectorTimelineAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorState* state, InspectorType type, FrameInstrumentationSupport frameInstrumentationSupport)
+InspectorTimelineAgent::InspectorTimelineAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorState* state, InspectorType type, InspectorClient* client)
     : InspectorBaseAgent<InspectorTimelineAgent>("Timeline", instrumentingAgents, state)
     , m_pageAgent(pageAgent)
     , m_frontend(0)
@@ -470,7 +488,7 @@ InspectorTimelineAgent::InspectorTimelineAgent(InstrumentingAgents* instrumentin
     , m_id(1)
     , m_maxCallStackDepth(5)
     , m_inspectorType(type)
-    , m_frameInstrumentationSupport(frameInstrumentationSupport)
+    , m_client(client)
 {
 }
 
index d19a76b..94c7fca 100644 (file)
@@ -60,11 +60,10 @@ class InspectorTimelineAgent : public InspectorBaseAgent<InspectorTimelineAgent>
     WTF_MAKE_NONCOPYABLE(InspectorTimelineAgent);
 public:
     enum InspectorType { PageInspector, WorkerInspector };
-    enum FrameInstrumentationSupport { FrameInstrumentationNotSupported, FrameInstrumentationSupported };
 
-    static PassOwnPtr<InspectorTimelineAgent> create(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorState* state, InspectorType type, FrameInstrumentationSupport frameInstrumentationSupport)
+    static PassOwnPtr<InspectorTimelineAgent> create(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorState* state, InspectorType type, InspectorClient* client)
     {
-        return adoptPtr(new InspectorTimelineAgent(instrumentingAgents, pageAgent, state, type, frameInstrumentationSupport));
+        return adoptPtr(new InspectorTimelineAgent(instrumentingAgents, pageAgent, state, type, client));
     }
 
     ~InspectorTimelineAgent();
@@ -141,6 +140,9 @@ public:
 
     virtual void didGC(double, double, size_t);
 
+    void willProcessTask();
+    void didProcessTask();
+
 private:
     struct TimelineRecordEntry {
         TimelineRecordEntry(PassRefPtr<InspectorObject> record, PassRefPtr<InspectorObject> data, PassRefPtr<InspectorArray> children, const String& type, const String& frameId, bool cancelable = false)
@@ -155,7 +157,7 @@ private:
         bool cancelable;
     };
         
-    InspectorTimelineAgent(InstrumentingAgents*, InspectorPageAgent*, InspectorState*, InspectorType, FrameInstrumentationSupport);
+    InspectorTimelineAgent(InstrumentingAgents*, InspectorPageAgent*, InspectorState*, InspectorType, InspectorClient*);
 
     void pushCurrentRecord(PassRefPtr<InspectorObject>, const String& type, bool captureCallStack, Frame*);
     void setHeapSizeStatistic(InspectorObject* record);
@@ -195,7 +197,7 @@ private:
     GCEvents m_gcEvents;
     int m_maxCallStackDepth;
     InspectorType m_inspectorType;
-    FrameInstrumentationSupport m_frameInstrumentationSupport;
+    InspectorClient* m_client;
 };
 
 } // namespace WebCore
index 87dbbf2..4d16eb6 100644 (file)
@@ -102,7 +102,7 @@ WorkerInspectorController::WorkerInspectorController(WorkerContext* workerContex
     m_debuggerAgent = WorkerDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), workerContext, m_injectedScriptManager.get());
     m_profilerAgent = InspectorProfilerAgent::create(m_instrumentingAgents.get(), m_consoleAgent.get(), workerContext, m_state.get(), m_injectedScriptManager.get());
 #endif
-    m_timelineAgent = InspectorTimelineAgent::create(m_instrumentingAgents.get(), 0, m_state.get(), InspectorTimelineAgent::WorkerInspector, InspectorTimelineAgent::FrameInstrumentationNotSupported);
+    m_timelineAgent = InspectorTimelineAgent::create(m_instrumentingAgents.get(), 0, m_state.get(), InspectorTimelineAgent::WorkerInspector, 0);
 
     m_injectedScriptManager->injectedScriptHost()->init(0
         , 0
index 3a6ea38..f021a1e 100644 (file)
@@ -1,3 +1,42 @@
+2012-06-09  Eugene Klyuchnikov  <eustas.bug@gmail.com>
+
+        Web Inspector: Add message loop instrumentation to public API and timeline agent
+        https://bugs.webkit.org/show_bug.cgi?id=88639
+
+        Reviewed by Vsevolod Vlasov.
+
+        Message loop instrumentation will show when the render thread is busy.
+        That way developer can discover if a render thread business causes low fps, or not.
+
+        * public/WebDevToolsAgent.h:
+        (WebDevToolsAgent):
+        * public/WebDevToolsAgentClient.h:
+        (WebDevToolsAgentClient):
+        (WebKit::WebDevToolsAgentClient::startMessageLoopMonitoring):
+        Request message loop notifications.
+        (WebKit::WebDevToolsAgentClient::stopMessageLoopMonitoring):
+        Cancel message loop notifications.
+        * src/InspectorClientImpl.cpp:
+        (WebKit::InspectorClientImpl::startMessageLoopMonitoring):
+        Request message loop notifications.
+        (WebKit):
+        (WebKit::InspectorClientImpl::stopMessageLoopMonitoring):
+        Cancel message loop notifications.
+        * src/InspectorClientImpl.h:
+        (InspectorClientImpl):
+        * src/WebDevToolsAgentImpl.cpp:
+        (WebKit::WebDevToolsAgentImpl::startMessageLoopMonitoring):
+        Request message loop notifications.
+        (WebKit):
+        (WebKit::WebDevToolsAgentImpl::stopMessageLoopMonitoring):
+        Cancel message loop notifications.
+        (WebKit::WebDevToolsAgentImpl::instrumentWillProcessTask):
+        Message loop notification.
+        (WebKit::WebDevToolsAgentImpl::instrumentDidProcessTask):
+        Ditto.
+        * src/WebDevToolsAgentImpl.h:
+        (WebDevToolsAgentImpl):
+
 2012-06-08  David Reveman  <reveman@chromium.org>
 
         [Chromium] Compositor doesn't support translucent root layers.
index 9f1d53f..8af43bc 100644 (file)
@@ -69,6 +69,14 @@ public:
     // Exposed for LayoutTestController.
     virtual void evaluateInWebInspector(long callId, const WebString& script) = 0;
 
+    // Instrumentation method that marks beginning of task processing
+    // in renderer message loop.
+    virtual void instrumentWillProcessTask() = 0;
+
+    // Instrumentation method that marks end of task processing
+    // in renderer message loop.
+    virtual void instrumentDidProcessTask() = 0;
+
     class MessageDescriptor {
     public:
         virtual ~MessageDescriptor() { }
index 9c63b11..7fd217f 100644 (file)
@@ -58,6 +58,14 @@ public:
     };
     virtual WebKitClientMessageLoop* createClientMessageLoop() { return 0; }
 
+    // Add task observer to message loop that is responsible for rendering
+    // of instrumented page. Corresponding WebDevToolsAgent should be notified
+    // about beginning and finishing of task processing in message loop.
+    virtual void startMessageLoopMonitoring() { }
+
+    // Remove task observer added by "startMessageLoopMonitoring".
+    virtual void stopMessageLoopMonitoring() { }
+
     virtual void clearBrowserCache() { }
     virtual void clearBrowserCookies() { }
 
index 17bd161..96f4dd7 100644 (file)
@@ -128,6 +128,18 @@ void InspectorClientImpl::clearBrowserCookies()
         agent->clearBrowserCookies();
 }
 
+void InspectorClientImpl::startMessageLoopMonitoring()
+{
+    if (WebDevToolsAgentImpl* agent = devToolsAgent())
+        agent->startMessageLoopMonitoring();
+}
+
+void InspectorClientImpl::stopMessageLoopMonitoring()
+{
+    if (WebDevToolsAgentImpl* agent = devToolsAgent())
+        agent->stopMessageLoopMonitoring();
+}
+
 bool InspectorClientImpl::canOverrideDeviceMetrics()
 {
     return true;
index bdb9b33..d9415e4 100644 (file)
@@ -64,6 +64,9 @@ public:
     virtual bool canClearBrowserCookies();
     virtual void clearBrowserCookies();
 
+    virtual void startMessageLoopMonitoring();
+    virtual void stopMessageLoopMonitoring();
+
     virtual bool canOverrideDeviceMetrics();
     virtual void overrideDeviceMetrics(int, int, float, bool);
     virtual void autoZoomPageToFitWidth();
index 6f72f13..70fddf1 100644 (file)
@@ -549,6 +549,28 @@ void WebDevToolsAgentImpl::clearBrowserCookies()
     m_client->clearBrowserCookies();
 }
 
+void WebDevToolsAgentImpl::startMessageLoopMonitoring()
+{
+    m_client->startMessageLoopMonitoring();
+}
+
+void WebDevToolsAgentImpl::stopMessageLoopMonitoring()
+{
+    m_client->stopMessageLoopMonitoring();
+}
+
+void WebDevToolsAgentImpl::instrumentWillProcessTask()
+{
+    if (Page* page = m_webViewImpl->page())
+        InspectorInstrumentation::willProcessTask(page);
+}
+
+void WebDevToolsAgentImpl::instrumentDidProcessTask()
+{
+    if (Page* page = m_webViewImpl->page())
+        InspectorInstrumentation::didProcessTask(page);
+}
+
 void WebDevToolsAgentImpl::setProcessId(long processId)
 {
     inspectorController()->setProcessId(processId);
index edbee14..181881d 100644 (file)
@@ -85,6 +85,8 @@ public:
     virtual void inspectElementAt(const WebPoint& point);
     virtual void evaluateInWebInspector(long callId, const WebString& script);
     virtual void setProcessId(long);
+    virtual void instrumentWillProcessTask();
+    virtual void instrumentDidProcessTask();
 
     // InspectorClient implementation.
     virtual void inspectorDestroyed();
@@ -100,6 +102,9 @@ public:
     virtual void clearBrowserCache();
     virtual void clearBrowserCookies();
 
+    virtual void startMessageLoopMonitoring();
+    virtual void stopMessageLoopMonitoring();
+
     virtual void overrideDeviceMetrics(int width, int height, float fontScaleFactor, bool fitWindow);
     virtual void autoZoomPageToFitWidth();