<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[158976] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/158976">158976</a></dd>
<dt>Author</dt> <dd>achicu@adobe.com</dd>
<dt>Date</dt> <dd>2013-11-08 16:39:31 -0800 (Fri, 08 Nov 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: It should be possible to debug the Inspector code
https://bugs.webkit.org/show_bug.cgi?id=124065

Reviewed by Timothy Hatcher.

Source/WebKit2:

When the script is paused, the debugger will pause all the pages in the same PageGroup.
All the Inspector windows were created in the same PageGroup, so pausing one debugger
would stop the other too.

Added WebInspectorPageGroups to manage the PageGroups created for the Inspectors.
The WebInspectors will now use the inspection &quot;level&quot; to figure out which PageGroup to use.
The inspector that debugs the main page will use &quot;__WebInspectorPageGroupLevel1__&quot;,
the second inspector (that debugs the first inspector) will use &quot;__WebInspectorPageGroupLevel2__&quot; ...

* UIProcess/WebInspectorProxy.cpp:
(WebKit::WebInspectorPageGroups::shared):
(WebKit::WebInspectorPageGroups::inspectorLevel):
(WebKit::WebInspectorPageGroups::isInspectorPageGroup):
(WebKit::WebInspectorPageGroups::inspectorPageGroupLevel):
(WebKit::WebInspectorPageGroups::inspectorPageGroupForLevel):
(WebKit::WebInspectorPageGroups::createInspectorPageGroup):
(WebKit::WebInspectorProxy::WebInspectorProxy):
(WebKit::WebInspectorProxy::inspectorPageGroup):
(WebKit::WebInspectorProxy::isInspectorPage):
(WebKit::WebInspectorProxy::canAttach):
* UIProcess/WebInspectorProxy.h:

LayoutTests:

Added test to check that a second inspector window can be used to debug the first one.

* inspector-protocol/debugger/nested-inspectors-expected.txt: Added.
* inspector-protocol/debugger/nested-inspectors.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebInspectorProxycpp">trunk/Source/WebKit2/UIProcess/WebInspectorProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebInspectorProxyh">trunk/Source/WebKit2/UIProcess/WebInspectorProxy.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsinspectorprotocoldebuggernestedinspectorsexpectedtxt">trunk/LayoutTests/inspector-protocol/debugger/nested-inspectors-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectorprotocoldebuggernestedinspectorshtml">trunk/LayoutTests/inspector-protocol/debugger/nested-inspectors.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (158975 => 158976)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2013-11-09 00:39:03 UTC (rev 158975)
+++ trunk/LayoutTests/ChangeLog        2013-11-09 00:39:31 UTC (rev 158976)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2013-11-08  Alexandru Chiculita  &lt;achicu@adobe.com&gt;
+
+        Web Inspector: It should be possible to debug the Inspector code
+        https://bugs.webkit.org/show_bug.cgi?id=124065
+
+        Reviewed by Timothy Hatcher.
+
+        Added test to check that a second inspector window can be used to debug the first one.
+
+        * inspector-protocol/debugger/nested-inspectors-expected.txt: Added.
+        * inspector-protocol/debugger/nested-inspectors.html: Added.
+
</ins><span class="cx"> 2013-11-08  Hans Muller  &lt;hmuller@adobe.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [CSS Shapes] Image valued shape-outside that extends vertically into the margin-box is top-clipped
</span></span></pre></div>
<a id="trunkLayoutTestsinspectorprotocoldebuggernestedinspectorsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector-protocol/debugger/nested-inspectors-expected.txt (0 => 158976)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector-protocol/debugger/nested-inspectors-expected.txt                                (rev 0)
+++ trunk/LayoutTests/inspector-protocol/debugger/nested-inspectors-expected.txt        2013-11-09 00:39:31 UTC (rev 158976)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+CONSOLE MESSAGE: line 1: Error: PASS: Expected exception
+Checking that the inspector code can be debugged using a second inspector window.
+
+Breakpoints Enabled
+Debugger.setPauseOnExceptions - all
+PASS: Paused!
+PASS: Resumed!
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectorprotocoldebuggernestedinspectorshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector-protocol/debugger/nested-inspectors.html (0 => 158976)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector-protocol/debugger/nested-inspectors.html                                (rev 0)
+++ trunk/LayoutTests/inspector-protocol/debugger/nested-inspectors.html        2013-11-09 00:39:31 UTC (rev 158976)
</span><span class="lines">@@ -0,0 +1,57 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../http/tests/inspector-protocol/resources/protocol-test.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;resources/exception.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+function test()
+{
+    function testFunction() {
+        // This function runs in the second inspector window. We can use this one to debug the first inspector.
+
+        InspectorTest.sendCommand(&quot;Debugger.enable&quot;, {});
+        InspectorTest.sendCommand(&quot;Debugger.setBreakpointsActive&quot;, {active: true}, function() {
+            InspectorTest.log(&quot;Breakpoints Enabled&quot;);
+            InspectorTest.sendCommand(&quot;Debugger.setPauseOnExceptions&quot;, {state: &quot;all&quot;}, function(responseObject) {
+                InspectorTest.checkForError(responseObject);
+                InspectorTest.log(&quot;Debugger.setPauseOnExceptions - all&quot;);
+
+                // Trigger an exception in the main inspector.
+                InspectorTest.sendCommand(&quot;Runtime.evaluate&quot;, {expression: &quot;setTimeout(function() { throw new Error('PASS: Expected exception') }, 0);&quot;});
+            });
+        });
+
+        InspectorTest.eventHandler[&quot;Debugger.paused&quot;] = function(messageObject)
+        {
+            InspectorTest.log(&quot;PASS: Paused!&quot;);
+            InspectorTest.sendCommand(&quot;Debugger.resume&quot;, {});
+        }
+
+        InspectorTest.eventHandler[&quot;Debugger.resumed&quot;] = function(messageObject)
+        {
+            InspectorTest.log(&quot;PASS: Resumed!&quot;);
+
+            // Revert Debugger.setPauseOnExceptions as it can have an impact on the following tests.
+            InspectorTest.sendCommand(&quot;Debugger.setPauseOnExceptions&quot;, {state: &quot;none&quot;}, function(responseObject) {
+                InspectorTest.completeTest();
+            });
+        }
+    };
+
+    window.log = InspectorTest.log.bind(InspectorTest);
+    window.closeTest = function()
+    {
+        window.internals.closeDummyInspectorFrontend();
+        InspectorTest.completeTest();
+    }
+
+    var secondInspectorFrontend = window.internals.openDummyInspectorFrontend(&quot;protocol-test.html&quot;);
+    secondInspectorFrontend.addEventListener(&quot;load&quot;, function(event) {
+        secondInspectorFrontend.postMessage(&quot;(&quot; + testFunction.toString() +&quot;)();&quot;, &quot;*&quot;);
+    });
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+&lt;p&gt;Checking that the inspector code can be debugged using a second inspector window.&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (158975 => 158976)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2013-11-09 00:39:03 UTC (rev 158975)
+++ trunk/Source/WebKit2/ChangeLog        2013-11-09 00:39:31 UTC (rev 158976)
</span><span class="lines">@@ -1,3 +1,32 @@
</span><ins>+2013-11-08  Alexandru Chiculita  &lt;achicu@adobe.com&gt;
+
+        Web Inspector: It should be possible to debug the Inspector code
+        https://bugs.webkit.org/show_bug.cgi?id=124065
+
+        Reviewed by Timothy Hatcher.
+
+        When the script is paused, the debugger will pause all the pages in the same PageGroup.
+        All the Inspector windows were created in the same PageGroup, so pausing one debugger
+        would stop the other too.
+
+        Added WebInspectorPageGroups to manage the PageGroups created for the Inspectors.
+        The WebInspectors will now use the inspection &quot;level&quot; to figure out which PageGroup to use.
+        The inspector that debugs the main page will use &quot;__WebInspectorPageGroupLevel1__&quot;,
+        the second inspector (that debugs the first inspector) will use &quot;__WebInspectorPageGroupLevel2__&quot; ...
+
+        * UIProcess/WebInspectorProxy.cpp:
+        (WebKit::WebInspectorPageGroups::shared):
+        (WebKit::WebInspectorPageGroups::inspectorLevel):
+        (WebKit::WebInspectorPageGroups::isInspectorPageGroup):
+        (WebKit::WebInspectorPageGroups::inspectorPageGroupLevel):
+        (WebKit::WebInspectorPageGroups::inspectorPageGroupForLevel):
+        (WebKit::WebInspectorPageGroups::createInspectorPageGroup):
+        (WebKit::WebInspectorProxy::WebInspectorProxy):
+        (WebKit::WebInspectorProxy::inspectorPageGroup):
+        (WebKit::WebInspectorProxy::isInspectorPage):
+        (WebKit::WebInspectorProxy::canAttach):
+        * UIProcess/WebInspectorProxy.h:
+
</ins><span class="cx"> 2013-11-08  Anders Carlsson  &lt;andersca@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Begin stubbing out a KeyedEncoder class in WebCore
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebInspectorProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebInspectorProxy.cpp (158975 => 158976)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebInspectorProxy.cpp        2013-11-09 00:39:03 UTC (rev 158975)
+++ trunk/Source/WebKit2/UIProcess/WebInspectorProxy.cpp        2013-11-09 00:39:31 UTC (rev 158976)
</span><span class="lines">@@ -58,27 +58,68 @@
</span><span class="cx"> const unsigned WebInspectorProxy::minimumAttachedWidth = 750;
</span><span class="cx"> const unsigned WebInspectorProxy::minimumAttachedHeight = 250;
</span><span class="cx"> 
</span><del>-static PassRefPtr&lt;WebPageGroup&gt; createInspectorPageGroup()
-{
-    RefPtr&lt;WebPageGroup&gt; pageGroup = WebPageGroup::create(&quot;__WebInspectorPageGroup__&quot;, false, false);
</del><ins>+class WebInspectorPageGroups {
+public:
+    static WebInspectorPageGroups&amp; shared()
+    {
+        DEFINE_STATIC_LOCAL(WebInspectorPageGroups, instance, ());
+        return instance;
+    }
</ins><span class="cx"> 
</span><ins>+    unsigned inspectorLevel(WebPageGroup* inspectedPageGroup)
+    {
+        return isInspectorPageGroup(inspectedPageGroup) ? inspectorPageGroupLevel(inspectedPageGroup) + 1 : 1;
+    }
+
+    bool isInspectorPageGroup(WebPageGroup* group)
+    {
+        return m_pageGroupLevel.contains(group);
+    }
+
+    unsigned inspectorPageGroupLevel(WebPageGroup* group)
+    {
+        ASSERT(isInspectorPageGroup(group));
+        return m_pageGroupLevel.get(group);
+    }
+
+    WebPageGroup* inspectorPageGroupForLevel(unsigned level)
+    {
+        // The level is the key of the HashMap, so it cannot be 0.
+        ASSERT(level);
+
+        auto iterator = m_pageGroupByLevel.find(level);
+        if (iterator != m_pageGroupByLevel.end())
+            return iterator-&gt;value.get();
+
+        RefPtr&lt;WebPageGroup&gt; group = createInspectorPageGroup(level);
+        m_pageGroupByLevel.set(level, group.get());
+        m_pageGroupLevel.set(group.get(), level);
+        return group.get();
+    }
+
+private:
+    static PassRefPtr&lt;WebPageGroup&gt; createInspectorPageGroup(unsigned level)
+    {
+        RefPtr&lt;WebPageGroup&gt; pageGroup = WebPageGroup::create(String::format(&quot;__WebInspectorPageGroupLevel%u__&quot;, level), false, false);
+
</ins><span class="cx"> #ifndef NDEBUG
</span><del>-    // Allow developers to inspect the Web Inspector in debug builds.
-    pageGroup-&gt;preferences()-&gt;setDeveloperExtrasEnabled(true);
-    pageGroup-&gt;preferences()-&gt;setLogsPageMessagesToSystemConsoleEnabled(true);
</del><ins>+        // Allow developers to inspect the Web Inspector in debug builds.
+        pageGroup-&gt;preferences()-&gt;setDeveloperExtrasEnabled(true);
+        pageGroup-&gt;preferences()-&gt;setLogsPageMessagesToSystemConsoleEnabled(true);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    pageGroup-&gt;preferences()-&gt;setApplicationChromeModeEnabled(true);
</del><ins>+        pageGroup-&gt;preferences()-&gt;setApplicationChromeModeEnabled(true);
</ins><span class="cx"> 
</span><del>-    return pageGroup.release();
-}
</del><ins>+        return pageGroup.release();
+    }
</ins><span class="cx"> 
</span><del>-WebPageGroup* WebInspectorProxy::inspectorPageGroup()
-{
-    static WebPageGroup* pageGroup = createInspectorPageGroup().leakRef();
-    return pageGroup;
-}
</del><ins>+    typedef HashMap&lt;unsigned, RefPtr&lt;WebPageGroup&gt; &gt; PageGroupByLevelMap;
+    typedef HashMap&lt;WebPageGroup*, unsigned&gt; PageGroupLevelMap;
</ins><span class="cx"> 
</span><ins>+    PageGroupByLevelMap m_pageGroupByLevel;
+    PageGroupLevelMap m_pageGroupLevel;
+};
+
</ins><span class="cx"> WebInspectorProxy::WebInspectorProxy(WebPageProxy* page)
</span><span class="cx">     : m_page(page)
</span><span class="cx">     , m_isVisible(false)
</span><span class="lines">@@ -98,6 +139,7 @@
</span><span class="cx">     , m_remoteInspectionPageId(0)
</span><span class="cx"> #endif
</span><span class="cx"> {
</span><ins>+    m_level = WebInspectorPageGroups::shared().inspectorLevel(m_page-&gt;pageGroup());
</ins><span class="cx">     m_page-&gt;process()-&gt;addMessageReceiver(Messages::WebInspectorProxy::messageReceiverName(), m_page-&gt;pageID(), this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -105,6 +147,11 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+WebPageGroup* WebInspectorProxy::inspectorPageGroup() const
+{
+    return WebInspectorPageGroups::shared().inspectorPageGroupForLevel(m_level);
+}
+
</ins><span class="cx"> void WebInspectorProxy::invalidate()
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(INSPECTOR_SERVER)
</span><span class="lines">@@ -311,7 +358,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool WebInspectorProxy::isInspectorPage(WebPageProxy* page)
</span><span class="cx"> {
</span><del>-    return page-&gt;pageGroup() == inspectorPageGroup();
</del><ins>+    return WebInspectorPageGroups::shared().isInspectorPageGroup(page-&gt;pageGroup());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static bool isMainInspectorPage(const WebInspectorProxy* webInspectorProxy, WKURLRequestRef requestRef)
</span><span class="lines">@@ -502,8 +549,7 @@
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><span class="cx">     // Don't allow attaching to another inspector -- two inspectors in one window is too much!
</span><del>-    bool isInspectorPage = m_page-&gt;pageGroup() == inspectorPageGroup();
-    if (isInspectorPage)
</del><ins>+    if (m_level &gt; 0)
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     // Don't allow the attach if the window would be too small to accommodate the minimum inspector height.
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebInspectorProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebInspectorProxy.h (158975 => 158976)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebInspectorProxy.h        2013-11-09 00:39:03 UTC (rev 158975)
+++ trunk/Source/WebKit2/UIProcess/WebInspectorProxy.h        2013-11-09 00:39:31 UTC (rev 158976)
</span><span class="lines">@@ -190,7 +190,7 @@
</span><span class="cx"> 
</span><span class="cx">     void open();
</span><span class="cx"> 
</span><del>-    static WebPageGroup* inspectorPageGroup();
</del><ins>+    WebPageGroup* inspectorPageGroup() const;
</ins><span class="cx"> 
</span><span class="cx"> #if PLATFORM(GTK) || PLATFORM(EFL)
</span><span class="cx">     void createInspectorWindow();
</span><span class="lines">@@ -217,6 +217,11 @@
</span><span class="cx">     bool m_createdInspectorPage;
</span><span class="cx">     bool m_ignoreFirstBringToFront;
</span><span class="cx"> 
</span><ins>+    // The debugger stops all the pages in the same PageGroup. Having
+    // all the inspectors in the same group will make it impossible to debug
+    // the inspector code, so we use the level to make different page groups.
+    unsigned m_level;
+
</ins><span class="cx">     AttachmentSide m_attachmentSide;
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(MAC)
</span></span></pre>
</div>
</div>

</body>
</html>