Title: [213691] trunk
Revision
213691
Author
[email protected]
Date
2017-03-09 16:53:48 -0800 (Thu, 09 Mar 2017)

Log Message

Web Inspector: Add XHR breakpoints UI
https://bugs.webkit.org/show_bug.cgi?id=168763
<rdar://problem/30952439>

Reviewed by Joseph Pecoraro.

Source/_javascript_Core:

* inspector/protocol/DOMDebugger.json:
Added clarifying comments to command descriptions.

Source/WebCore:

Test: inspector/dom-debugger/xhr-breakpoints.html

* inspector/InspectorDOMDebuggerAgent.cpp:
(WebCore::InspectorDOMDebuggerAgent::discardBindings):
(WebCore::InspectorDOMDebuggerAgent::willSendXMLHttpRequest):
Don't break for XHRs when breakpoints are disabled.

Source/WebInspectorUI:

* Localizations/en.lproj/localizedStrings.js:
New UI strings.

* UserInterface/Controllers/DOMDebuggerManager.js:
Plumbing for XHR breakpoints. Like DOM breakpoints, they are tracked
per-page. Unlike DOM breakpoints, they have no separate "resolved"
state, and are simply added/removed as the main frame changes.

(WebInspector.DOMDebuggerManager):
(WebInspector.DOMDebuggerManager.prototype.get allRequestsBreakpoint):
(WebInspector.DOMDebuggerManager.prototype.get xhrBreakpoints):
(WebInspector.DOMDebuggerManager.prototype.isBreakpointRemovable):
(WebInspector.DOMDebuggerManager.prototype.removeDOMBreakpoint):
(WebInspector.DOMDebuggerManager.prototype.addXHRBreakpoint):
(WebInspector.DOMDebuggerManager.prototype.removeXHRBreakpoint):
(WebInspector.DOMDebuggerManager.prototype._speculativelyResolveBreakpoints):
(WebInspector.DOMDebuggerManager.prototype._detachXHRBreakpoint):
(WebInspector.DOMDebuggerManager.prototype._updateXHRBreakpoint.breakpointUpdated):
(WebInspector.DOMDebuggerManager.prototype._updateXHRBreakpoint):
(WebInspector.DOMDebuggerManager.prototype._resolveXHRBreakpoint):
(WebInspector.DOMDebuggerManager.prototype._saveXHRBreakpoints):
(WebInspector.DOMDebuggerManager.prototype._domBreakpointDisabledStateDidChange):
(WebInspector.DOMDebuggerManager.prototype._xhrBreakpointDisabledStateDidChange):
(WebInspector.DOMDebuggerManager.prototype._mainResourceDidChange):
(WebInspector.DOMDebuggerManager.prototype._saveBreakpoints): Deleted.
Renamed `saveDOMBreakpoints`.

* UserInterface/Controllers/DebuggerManager.js:
(WebInspector.DebuggerManager.prototype._pauseReasonFromPayload):
Plumbing for XHR breakpoint pause reason.

* UserInterface/Controllers/XHRBreakpointTreeController.js: Added.
Creates the "All Requests" breakpoint, handles DOMDebuggerManager messages,
and updates an associated tree outline as XHR breakpoints are added and removed.

(WebInspector.XHRBreakpointTreeController):
(WebInspector.XHRBreakpointTreeController.prototype.revealAndSelect):
(WebInspector.XHRBreakpointTreeController.prototype.disconnect):
(WebInspector.XHRBreakpointTreeController.prototype._xhrBreakpointAdded):
(WebInspector.XHRBreakpointTreeController.prototype._xhrBreakpointRemoved):
(WebInspector.XHRBreakpointTreeController.prototype._mainResourceDidChange):
(WebInspector.XHRBreakpointTreeController.prototype._reset):

* UserInterface/Main.html:
New files.

* UserInterface/Models/XHRBreakpoint.js: Added.
New model class. XHR breakpoints have an associated URL, which is matched
against the request URL when deciding whether to break. An empty URL matches
all XMLHttpRequests.

(WebInspector.XHRBreakpoint):
(WebInspector.XHRBreakpoint.prototype.get documentURL):
(WebInspector.XHRBreakpoint.prototype.get url):
(WebInspector.XHRBreakpoint.prototype.get disabled):
(WebInspector.XHRBreakpoint.prototype.set disabled):
(WebInspector.XHRBreakpoint.prototype.get serializableInfo):
(WebInspector.XHRBreakpoint.prototype.saveIdentityToCookie):

* UserInterface/Test.html:
New files.

* UserInterface/Views/ContentView.js:
(WebInspector.ContentView.createFromRepresentedObject):
Plumbing for new represented object type, to prevent runtime assertion.

* UserInterface/Views/DOMBreakpointTreeElement.js:
(WebInspector.DOMBreakpointTreeElement):
Reuse BreakpointTreeElement styles.

* UserInterface/Views/DebuggerSidebarPanel.js:
(WebInspector.DebuggerSidebarPanel):
(WebInspector.DebuggerSidebarPanel.prototype.saveStateToCookie):
(WebInspector.DebuggerSidebarPanel.prototype.restoreStateFromCookie):
(WebInspector.DebuggerSidebarPanel.prototype._updatePauseReasonSection):
(WebInspector.DebuggerSidebarPanel.prototype._addXHRBreakpointButtonClicked):
(WebInspector.DebuggerSidebarPanel.prototype.willDismissPopover):

* UserInterface/Views/InputPopover.css: Added.
(.popover .input-popover-content):
(.popover .input-popover-content > .editor):
(.popover .input-popover-content > .editor > .CodeMirror):
(.popover .input-popover-content > .editor > .CodeMirror-scroll):

* UserInterface/Views/InputPopover.js: Added.
New general purpose popover class. Style and structure lifted from
the Popover implementation used by the Probe Expressions UI. A follow-up
has been filed to switch that UI over to this new class:
https://bugs.webkit.org/show_bug.cgi?id=169428.

(WebInspector.InputPopover):
(WebInspector.InputPopover.prototype.get value):
(WebInspector.InputPopover.prototype.get result):
(WebInspector.InputPopover.prototype.show):
(WebInspector.InputPopover.prototype._presentOverTargetElement):

* UserInterface/Views/XHRBreakpointTreeElement.js: Added.
Tree element class for XHR breakpoints. Behaves identically to
script and DOM breakpoint tree elements.

(WebInspector.XHRBreakpointTreeElement):
Reuse BreakpointTreeElement styles.
(WebInspector.XHRBreakpointTreeElement.prototype.onattach):
(WebInspector.XHRBreakpointTreeElement.prototype.ondetach):
(WebInspector.XHRBreakpointTreeElement.prototype.ondelete):
(WebInspector.XHRBreakpointTreeElement.prototype.onenter):
(WebInspector.XHRBreakpointTreeElement.prototype.onspace):
(WebInspector.XHRBreakpointTreeElement.prototype.populateContextMenu):
(WebInspector.XHRBreakpointTreeElement.prototype._statusImageElementClicked):
(WebInspector.XHRBreakpointTreeElement.prototype._statusImageElementFocused):
(WebInspector.XHRBreakpointTreeElement.prototype._statusImageElementMouseDown):
(WebInspector.XHRBreakpointTreeElement.prototype._toggleBreakpoint):
(WebInspector.XHRBreakpointTreeElement.prototype._updateStatus):

LayoutTests:

Tests for pausing on XMLHttpRequests using XHR breakpoints.

* inspector/dom-debugger/xhr-breakpoints-expected.txt: Added.
* inspector/dom-debugger/xhr-breakpoints.html: Added.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (213690 => 213691)


--- trunk/LayoutTests/ChangeLog	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/LayoutTests/ChangeLog	2017-03-10 00:53:48 UTC (rev 213691)
@@ -1,3 +1,16 @@
+2017-03-09  Matt Baker  <[email protected]>
+
+        Web Inspector: Add XHR breakpoints UI
+        https://bugs.webkit.org/show_bug.cgi?id=168763
+        <rdar://problem/30952439>
+
+        Reviewed by Joseph Pecoraro.
+
+        Tests for pausing on XMLHttpRequests using XHR breakpoints.
+
+        * inspector/dom-debugger/xhr-breakpoints-expected.txt: Added.
+        * inspector/dom-debugger/xhr-breakpoints.html: Added.
+
 2017-03-09  John Wilander  <[email protected]>
 
         Resource Load Statistics: Remove statistics data as part of full website data removal

Added: trunk/LayoutTests/inspector/dom-debugger/xhr-breakpoints-expected.txt (0 => 213691)


--- trunk/LayoutTests/inspector/dom-debugger/xhr-breakpoints-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/dom-debugger/xhr-breakpoints-expected.txt	2017-03-10 00:53:48 UTC (rev 213691)
@@ -0,0 +1,52 @@
+Tests for XHR breakpoints.
+
+
+== Running test suite: XHRBreakpoints
+-- Running test case: BreakOnAllXMLHttpRequests
+Set pause on all XMLHttpRequests.
+Sending XMLHttpRequest.
+PAUSED:
+PASS: Pause reason should be XHR.
+PASS: Pause data URL should be empty.
+CALL STACK:
+0: [F] loadResourceXHR
+1: [P] Global Code
+-- Running test teardown.
+
+-- Running test case: BreakOnXMLHttpRequestContainingURL
+PASS: Breakpoint should not be disabled initially.
+PASS: Added breakpoint for URL: data
+Sending XMLHttpRequest.
+PAUSED:
+PASS: Pause reason should be XHR.
+PASS: Pause data URL should match breakpoint URL.
+CALL STACK:
+0: [F] loadResourceXHR
+1: [P] Global Code
+-- Running test teardown.
+
+-- Running test case: ShouldNotPauseOnDisabledBreakpoint
+PASS: Breakpoint should not be disabled initially.
+Disabling breakpoint.
+PASS: Added breakpoint for URL: data
+Sending XMLHttpRequest.
+Wait for evaluate in page to return.
+PASS: Should not pause for disabled breakpoint.
+-- Running test teardown.
+
+-- Running test case: ShouldNotPauseOnXMLHttpRequestNotContainingURL
+PASS: Breakpoint should not be disabled initially.
+PASS: Added breakpoint for URL: nonexistant-url
+Sending XMLHttpRequest.
+Wait for evaluate in page to return.
+PASS: Should not pause for breakpoint with different URL.
+-- Running test teardown.
+
+-- Running test case: RemoveBreakpoint
+PASS: Breakpoint should not be disabled initially.
+PASS: Added breakpoint for URL: data
+Remove breakpoint.
+Wait for evaluate in page to return.
+PASS: Should not pause for removed breakpoint.
+-- Running test teardown.
+

Added: trunk/LayoutTests/inspector/dom-debugger/xhr-breakpoints.html (0 => 213691)


--- trunk/LayoutTests/inspector/dom-debugger/xhr-breakpoints.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/dom-debugger/xhr-breakpoints.html	2017-03-10 00:53:48 UTC (rev 213691)
@@ -0,0 +1,189 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<script src=""
+<script src=""
+<script>
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("XHRBreakpoints");
+
+    function teardown(resolve) {
+        let breakpoints = WebInspector.domDebuggerManager.xhrBreakpoints;
+        for (let breakpoint of breakpoints)
+            WebInspector.domDebuggerManager.removeXHRBreakpoint(breakpoint);
+
+        WebInspector.domDebuggerManager.allRequestsBreakpoint.disabled = true;
+        resolve();
+    }
+
+    function awaitEvaluateInPage(_expression_) {
+        return new Promise((resolve, reject) => {
+            InspectorTest.log("Wait for evaluate in page to return.");
+            InspectorTest.evaluateInPage(_expression_, (error) => {
+                if (error)
+                    reject(error);
+
+                resolve();
+            });
+        });
+    }
+
+    function rejectOnPause() {
+        return new Promise((resolve, reject) => {
+            WebInspector.debuggerManager.awaitEvent(WebInspector.DebuggerManager.Event.Paused)
+            .then((event) => {
+                WebInspector.debuggerManager.resume();
+                InspectorTest.fail("Should not pause.");
+                reject();
+            });
+        });
+    }
+
+    function addBreakpointForURL(url, disabled) {
+        return new Promise((resolve, reject) => {
+            let mainFrame = WebInspector.frameResourceManager.mainFrame;
+            InspectorTest.assert(mainFrame, "Missing main frame.");
+            if (!mainFrame)
+                reject();
+
+            let breakpoint = new WebInspector.XHRBreakpoint(mainFrame.url, url);
+            WebInspector.domDebuggerManager.awaitEvent(WebInspector.DOMDebuggerManager.Event.XHRBreakpointAdded)
+            .then(() => {
+                InspectorTest.expectFalse(breakpoint.disabled, "Breakpoint should not be disabled initially.");
+
+                if (disabled) {
+                    InspectorTest.log("Disabling breakpoint.");
+                    breakpoint.disabled = true;
+                }
+
+                InspectorTest.pass("Added breakpoint for URL: " + url);
+                resolve(breakpoint);
+            });
+
+            WebInspector.domDebuggerManager.addXHRBreakpoint(breakpoint);
+        });
+    }
+
+    suite.addTestCase({
+        name: "BreakOnAllXMLHttpRequests",
+        description: "Check that debugger pauses for all XMLHttpRequests.",
+        teardown,
+        test(resolve, reject) {
+            InspectorTest.log("Set pause on all XMLHttpRequests.");
+            WebInspector.domDebuggerManager.allRequestsBreakpoint.disabled = false;
+
+            InspectorTest.log("Sending XMLHttpRequest.");
+            InspectorTest.evaluateInPage("loadResourceXHR()");
+
+            WebInspector.debuggerManager.awaitEvent(WebInspector.DebuggerManager.Event.Paused)
+            .then(() => {
+                let targetData = WebInspector.debuggerManager.dataForTarget(WebInspector.debuggerManager.activeCallFrame.target);
+                InspectorTest.log("PAUSED:");
+                InspectorTest.expectEqual(targetData.pauseReason, WebInspector.DebuggerManager.PauseReason.XHR, "Pause reason should be XHR.");
+                InspectorTest.expectFalse(targetData.pauseData.breakpointURL, "Pause data URL should be empty.");
+
+                logActiveStackTrace();
+
+                return WebInspector.debuggerManager.resume();
+            })
+            .then(resolve, reject);
+        }
+    });
+
+    suite.addTestCase({
+        name: "BreakOnXMLHttpRequestContainingURL",
+        description: "Check that debugger pauses for XMLHttpRequests.",
+        teardown,
+        test(resolve, reject) {
+            let expectedBreakpointURL;
+            addBreakpointForURL("data")
+            .then((breakpoint) => {
+                expectedBreakpointURL = breakpoint.url;
+
+                InspectorTest.log("Sending XMLHttpRequest.");
+                InspectorTest.evaluateInPage("loadResourceXHR()");
+                return WebInspector.debuggerManager.awaitEvent(WebInspector.DebuggerManager.Event.Paused);
+            })
+            .then(() => {
+                let targetData = WebInspector.debuggerManager.dataForTarget(WebInspector.debuggerManager.activeCallFrame.target);
+                InspectorTest.log("PAUSED:");
+                InspectorTest.expectEqual(targetData.pauseReason, WebInspector.DebuggerManager.PauseReason.XHR, "Pause reason should be XHR.");
+                InspectorTest.expectEqual(targetData.pauseData.breakpointURL, expectedBreakpointURL, "Pause data URL should match breakpoint URL.");
+
+                logActiveStackTrace();
+
+                return WebInspector.debuggerManager.resume();
+            })
+            .then(resolve, reject);
+        }
+    });
+
+    suite.addTestCase({
+        name: "ShouldNotPauseOnDisabledBreakpoint",
+        description: "Check that debugger does not pause for disabled breakpoint.",
+        teardown,
+        test(resolve, reject) {
+            const disabled = true;
+            addBreakpointForURL("data", disabled)
+            .then((breakpoint) => {
+                InspectorTest.log("Sending XMLHttpRequest.");
+                return Promise.race([awaitEvaluateInPage("loadResourceXHR()"), rejectOnPause()]);
+            })
+            .then(() => {
+                InspectorTest.pass("Should not pause for disabled breakpoint.");
+                resolve();
+            })
+            .catch(reject);
+        }
+    });
+
+    suite.addTestCase({
+        name: "ShouldNotPauseOnXMLHttpRequestNotContainingURL",
+        description: "Check that debugger does not pause for breakpoint with different URL.",
+        teardown,
+        test(resolve, reject) {
+            addBreakpointForURL("nonexistant-url")
+            .then((breakpoint) => {
+                InspectorTest.log("Sending XMLHttpRequest.");
+                return Promise.race([awaitEvaluateInPage("loadResourceXHR()"), rejectOnPause()]);
+            })
+            .then(() => {
+                InspectorTest.pass("Should not pause for breakpoint with different URL.");
+                resolve();
+            })
+            .catch(reject);
+        }
+    });
+
+    suite.addTestCase({
+        name: "RemoveBreakpoint",
+        description: "Check that debugger does not pause for removed breakpoint.",
+        teardown,
+        test(resolve, reject) {
+            addBreakpointForURL("data")
+            .then((breakpoint) => {
+                let promise = WebInspector.domDebuggerManager.awaitEvent(WebInspector.DOMDebuggerManager.Event.XHRBreakpointRemoved);
+
+                InspectorTest.log("Remove breakpoint.");
+                WebInspector.domDebuggerManager.removeXHRBreakpoint(breakpoint);
+                return promise;
+            })
+            .then(() => Promise.race([awaitEvaluateInPage("loadResourceXHR()"), rejectOnPause()]))
+            .then(() => {
+                InspectorTest.pass("Should not pause for removed breakpoint.");
+                resolve();
+            })
+            .catch(reject);
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onload_="runTest()">
+<p>Tests for XHR breakpoints.</p>
+</body>
+</html>

Modified: trunk/Source/_javascript_Core/ChangeLog (213690 => 213691)


--- trunk/Source/_javascript_Core/ChangeLog	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-03-10 00:53:48 UTC (rev 213691)
@@ -1,3 +1,14 @@
+2017-03-09  Matt Baker  <[email protected]>
+
+        Web Inspector: Add XHR breakpoints UI
+        https://bugs.webkit.org/show_bug.cgi?id=168763
+        <rdar://problem/30952439>
+
+        Reviewed by Joseph Pecoraro.
+
+        * inspector/protocol/DOMDebugger.json:
+        Added clarifying comments to command descriptions.
+
 2017-03-09  Michael Saboff  <[email protected]>
 
         Add plumbing to WebProcess to enable _javascript_Core configuration and logging

Modified: trunk/Source/_javascript_Core/inspector/protocol/DOMDebugger.json (213690 => 213691)


--- trunk/Source/_javascript_Core/inspector/protocol/DOMDebugger.json	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/_javascript_Core/inspector/protocol/DOMDebugger.json	2017-03-10 00:53:48 UTC (rev 213691)
@@ -58,7 +58,7 @@
         {
             "name": "setXHRBreakpoint",
             "parameters": [
-                { "name": "url", "type": "string", "description": "Resource URL substring. All XHRs having this substring in the URL will get stopped upon." }
+                { "name": "url", "type": "string", "description": "Resource URL substring. All XHRs having this substring in the URL will get stopped upon. An empty string will pause on all XHRs." }
             ],
             "description": "Sets breakpoint on XMLHttpRequest."
         },
@@ -65,7 +65,7 @@
         {
             "name": "removeXHRBreakpoint",
             "parameters": [
-                { "name": "url", "type": "string", "description": "Resource URL substring." }
+                { "name": "url", "type": "string", "description": "Resource URL substring. An empty string will stop pausing on all XHRs." }
             ],
             "description": "Removes breakpoint from XMLHttpRequest."
         }

Modified: trunk/Source/WebCore/ChangeLog (213690 => 213691)


--- trunk/Source/WebCore/ChangeLog	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/WebCore/ChangeLog	2017-03-10 00:53:48 UTC (rev 213691)
@@ -1,3 +1,18 @@
+2017-03-09  Matt Baker  <[email protected]>
+
+        Web Inspector: Add XHR breakpoints UI
+        https://bugs.webkit.org/show_bug.cgi?id=168763
+        <rdar://problem/30952439>
+
+        Reviewed by Joseph Pecoraro.
+
+        Test: inspector/dom-debugger/xhr-breakpoints.html
+
+        * inspector/InspectorDOMDebuggerAgent.cpp:
+        (WebCore::InspectorDOMDebuggerAgent::discardBindings):
+        (WebCore::InspectorDOMDebuggerAgent::willSendXMLHttpRequest):
+        Don't break for XHRs when breakpoints are disabled.
+
 2017-03-09  Michael Saboff  <[email protected]>
 
         Add plumbing to WebProcess to enable _javascript_Core configuration and logging

Modified: trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.cpp (213690 => 213691)


--- trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.cpp	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.cpp	2017-03-10 00:53:48 UTC (rev 213691)
@@ -114,6 +114,7 @@
 void InspectorDOMDebuggerAgent::discardBindings()
 {
     m_domBreakpoints.clear();
+    m_xhrBreakpoints.clear();
 }
 
 void InspectorDOMDebuggerAgent::setEventListenerBreakpoint(ErrorString& error, const String& eventName)
@@ -393,6 +394,9 @@
 
 void InspectorDOMDebuggerAgent::willSendXMLHttpRequest(const String& url)
 {
+    if (!m_debuggerAgent->breakpointsActive())
+        return;
+
     String breakpointURL;
     if (m_pauseOnAllXHRsEnabled)
         breakpointURL = emptyString();

Modified: trunk/Source/WebInspectorUI/ChangeLog (213690 => 213691)


--- trunk/Source/WebInspectorUI/ChangeLog	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/WebInspectorUI/ChangeLog	2017-03-10 00:53:48 UTC (rev 213691)
@@ -1,5 +1,127 @@
 2017-03-09  Matt Baker  <[email protected]>
 
+        Web Inspector: Add XHR breakpoints UI
+        https://bugs.webkit.org/show_bug.cgi?id=168763
+        <rdar://problem/30952439>
+
+        Reviewed by Joseph Pecoraro.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        New UI strings.
+
+        * UserInterface/Controllers/DOMDebuggerManager.js:
+        Plumbing for XHR breakpoints. Like DOM breakpoints, they are tracked
+        per-page. Unlike DOM breakpoints, they have no separate "resolved"
+        state, and are simply added/removed as the main frame changes.
+
+        (WebInspector.DOMDebuggerManager):
+        (WebInspector.DOMDebuggerManager.prototype.get allRequestsBreakpoint):
+        (WebInspector.DOMDebuggerManager.prototype.get xhrBreakpoints):
+        (WebInspector.DOMDebuggerManager.prototype.isBreakpointRemovable):
+        (WebInspector.DOMDebuggerManager.prototype.removeDOMBreakpoint):
+        (WebInspector.DOMDebuggerManager.prototype.addXHRBreakpoint):
+        (WebInspector.DOMDebuggerManager.prototype.removeXHRBreakpoint):
+        (WebInspector.DOMDebuggerManager.prototype._speculativelyResolveBreakpoints):
+        (WebInspector.DOMDebuggerManager.prototype._detachXHRBreakpoint):
+        (WebInspector.DOMDebuggerManager.prototype._updateXHRBreakpoint.breakpointUpdated):
+        (WebInspector.DOMDebuggerManager.prototype._updateXHRBreakpoint):
+        (WebInspector.DOMDebuggerManager.prototype._resolveXHRBreakpoint):
+        (WebInspector.DOMDebuggerManager.prototype._saveXHRBreakpoints):
+        (WebInspector.DOMDebuggerManager.prototype._domBreakpointDisabledStateDidChange):
+        (WebInspector.DOMDebuggerManager.prototype._xhrBreakpointDisabledStateDidChange):
+        (WebInspector.DOMDebuggerManager.prototype._mainResourceDidChange):
+        (WebInspector.DOMDebuggerManager.prototype._saveBreakpoints): Deleted.
+        Renamed `saveDOMBreakpoints`.
+
+        * UserInterface/Controllers/DebuggerManager.js:
+        (WebInspector.DebuggerManager.prototype._pauseReasonFromPayload):
+        Plumbing for XHR breakpoint pause reason.
+
+        * UserInterface/Controllers/XHRBreakpointTreeController.js: Added.
+        Creates the "All Requests" breakpoint, handles DOMDebuggerManager messages,
+        and updates an associated tree outline as XHR breakpoints are added and removed.
+
+        (WebInspector.XHRBreakpointTreeController):
+        (WebInspector.XHRBreakpointTreeController.prototype.revealAndSelect):
+        (WebInspector.XHRBreakpointTreeController.prototype.disconnect):
+        (WebInspector.XHRBreakpointTreeController.prototype._xhrBreakpointAdded):
+        (WebInspector.XHRBreakpointTreeController.prototype._xhrBreakpointRemoved):
+        (WebInspector.XHRBreakpointTreeController.prototype._mainResourceDidChange):
+        (WebInspector.XHRBreakpointTreeController.prototype._reset):
+
+        * UserInterface/Main.html:
+        New files.
+
+        * UserInterface/Models/XHRBreakpoint.js: Added.
+        New model class. XHR breakpoints have an associated URL, which is matched
+        against the request URL when deciding whether to break. An empty URL matches
+        all XMLHttpRequests.
+
+        (WebInspector.XHRBreakpoint):
+        (WebInspector.XHRBreakpoint.prototype.get documentURL):
+        (WebInspector.XHRBreakpoint.prototype.get url):
+        (WebInspector.XHRBreakpoint.prototype.get disabled):
+        (WebInspector.XHRBreakpoint.prototype.set disabled):
+        (WebInspector.XHRBreakpoint.prototype.get serializableInfo):
+        (WebInspector.XHRBreakpoint.prototype.saveIdentityToCookie):
+
+        * UserInterface/Test.html:
+        New files.
+
+        * UserInterface/Views/ContentView.js:
+        (WebInspector.ContentView.createFromRepresentedObject):
+        Plumbing for new represented object type, to prevent runtime assertion.
+
+        * UserInterface/Views/DOMBreakpointTreeElement.js:
+        (WebInspector.DOMBreakpointTreeElement):
+        Reuse BreakpointTreeElement styles.
+
+        * UserInterface/Views/DebuggerSidebarPanel.js:
+        (WebInspector.DebuggerSidebarPanel):
+        (WebInspector.DebuggerSidebarPanel.prototype.saveStateToCookie):
+        (WebInspector.DebuggerSidebarPanel.prototype.restoreStateFromCookie):
+        (WebInspector.DebuggerSidebarPanel.prototype._updatePauseReasonSection):
+        (WebInspector.DebuggerSidebarPanel.prototype._addXHRBreakpointButtonClicked):
+        (WebInspector.DebuggerSidebarPanel.prototype.willDismissPopover):
+
+        * UserInterface/Views/InputPopover.css: Added.
+        (.popover .input-popover-content):
+        (.popover .input-popover-content > .editor):
+        (.popover .input-popover-content > .editor > .CodeMirror):
+        (.popover .input-popover-content > .editor > .CodeMirror-scroll):
+
+        * UserInterface/Views/InputPopover.js: Added.
+        New general purpose popover class. Style and structure lifted from
+        the Popover implementation used by the Probe Expressions UI. A follow-up
+        has been filed to switch that UI over to this new class:
+        https://bugs.webkit.org/show_bug.cgi?id=169428.
+
+        (WebInspector.InputPopover):
+        (WebInspector.InputPopover.prototype.get value):
+        (WebInspector.InputPopover.prototype.get result):
+        (WebInspector.InputPopover.prototype.show):
+        (WebInspector.InputPopover.prototype._presentOverTargetElement):
+
+        * UserInterface/Views/XHRBreakpointTreeElement.js: Added.
+        Tree element class for XHR breakpoints. Behaves identically to
+        script and DOM breakpoint tree elements.
+
+        (WebInspector.XHRBreakpointTreeElement):
+        Reuse BreakpointTreeElement styles.
+        (WebInspector.XHRBreakpointTreeElement.prototype.onattach):
+        (WebInspector.XHRBreakpointTreeElement.prototype.ondetach):
+        (WebInspector.XHRBreakpointTreeElement.prototype.ondelete):
+        (WebInspector.XHRBreakpointTreeElement.prototype.onenter):
+        (WebInspector.XHRBreakpointTreeElement.prototype.onspace):
+        (WebInspector.XHRBreakpointTreeElement.prototype.populateContextMenu):
+        (WebInspector.XHRBreakpointTreeElement.prototype._statusImageElementClicked):
+        (WebInspector.XHRBreakpointTreeElement.prototype._statusImageElementFocused):
+        (WebInspector.XHRBreakpointTreeElement.prototype._statusImageElementMouseDown):
+        (WebInspector.XHRBreakpointTreeElement.prototype._toggleBreakpoint):
+        (WebInspector.XHRBreakpointTreeElement.prototype._updateStatus):
+
+2017-03-09  Matt Baker  <[email protected]>
+
         REGRESSION (r196271): Web Inspector: DOM element loses focus/active selection after committing an inline attribute editor in DOMTreeOutline
         https://bugs.webkit.org/show_bug.cgi?id=168119
         <rdar://problem/30466013>

Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (213690 => 213691)


--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2017-03-10 00:53:48 UTC (rev 213691)
@@ -64,6 +64,7 @@
 localizedStrings["Add New"] = "Add New";
 localizedStrings["Add New Probe _expression_"] = "Add New Probe _expression_";
 localizedStrings["Add New Watch _expression_"] = "Add New Watch _expression_";
+localizedStrings["Add XHR Breakpoint"] = "Add XHR Breakpoint";
 localizedStrings["Add a Class"] = "Add a Class";
 localizedStrings["Add new breakpoint action after this action"] = "Add new breakpoint action after this action";
 localizedStrings["Add new rule"] = "Add new rule";
@@ -75,6 +76,7 @@
 localizedStrings["All"] = "All";
 localizedStrings["All Changes"] = "All Changes";
 localizedStrings["All Exceptions"] = "All Exceptions";
+localizedStrings["All Requests"] = "All Requests";
 localizedStrings["All Resources"] = "All Resources";
 localizedStrings["All Storage"] = "All Storage";
 localizedStrings["Alternates"] = "Alternates";
@@ -124,6 +126,7 @@
 localizedStrings["Box Model"] = "Box Model";
 localizedStrings["Box Shadow"] = "Box Shadow";
 localizedStrings["Break on…"] = "Break on…";
+localizedStrings["Break when URL contains:"] = "Break when URL contains:";
 localizedStrings["Breakdown"] = "Breakdown";
 localizedStrings["Breakdown of each memory category at the end of the selected time range"] = "Breakdown of each memory category at the end of the selected time range";
 localizedStrings["Breakpoints"] = "Breakpoints";
@@ -834,10 +837,12 @@
 localizedStrings["Transition"] = "Transition";
 localizedStrings["Triggered Breakpoint"] = "Triggered Breakpoint";
 localizedStrings["Triggered DOM Breakpoint"] = "Triggered DOM Breakpoint";
+localizedStrings["Triggered XHR Breakpoint"] = "Triggered XHR Breakpoint";
 localizedStrings["True"] = "True";
 localizedStrings["Type"] = "Type";
 localizedStrings["Type Issue"] = "Type Issue";
 localizedStrings["Type information for variable: %s"] = "Type information for variable: %s";
+localizedStrings["URL contains:"] = "URL contains:";
 localizedStrings["Unable to determine path to property from root"] = "Unable to determine path to property from root";
 localizedStrings["Uncaught Exceptions"] = "Uncaught Exceptions";
 localizedStrings["Unchanged"] = "Unchanged";
@@ -881,6 +886,7 @@
 localizedStrings["X1"] = "X1";
 localizedStrings["X2"] = "X2";
 localizedStrings["XHR"] = "XHR";
+localizedStrings["XHR Breakpoints"] = "XHR Breakpoints";
 localizedStrings["XHRs"] = "XHRs";
 localizedStrings["Y"] = "Y";
 localizedStrings["Y1"] = "Y1";

Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js (213690 => 213691)


--- trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js	2017-03-10 00:53:48 UTC (rev 213691)
@@ -33,7 +33,15 @@
         this._domBreakpointURLMap = new Map;
         this._domBreakpointFrameIdentifierMap = new Map;
 
+        this._xhrBreakpointsSetting = new WebInspector.Setting("xhr-breakpoints", []);
+        this._xhrBreakpointURLMap = new Map;
+        this._allRequestsBreakpointEnabledSetting = new WebInspector.Setting("break-on-all-requests", false);
+
+        const emptyURL = "";
+        this._allRequestsBreakpoint = new WebInspector.XHRBreakpoint(null, emptyURL, !this._allRequestsBreakpointEnabledSetting.value);
+
         WebInspector.DOMBreakpoint.addEventListener(WebInspector.DOMBreakpoint.Event.DisabledStateDidChange, this._domBreakpointDisabledStateDidChange, this);
+        WebInspector.XHRBreakpoint.addEventListener(WebInspector.XHRBreakpoint.Event.DisabledStateDidChange, this._xhrBreakpointDisabledStateDidChange, this);
 
         WebInspector.domTreeManager.addEventListener(WebInspector.DOMTreeManager.Event.NodeRemoved, this._nodeRemoved, this);
         WebInspector.domTreeManager.addEventListener(WebInspector.DOMTreeManager.Event.NodeInserted, this._nodeInserted, this);
@@ -51,6 +59,11 @@
                 this.addDOMBreakpoint(breakpoint);
             }
 
+            for (let cookie of this._xhrBreakpointsSetting.value) {
+                let breakpoint = new WebInspector.XHRBreakpoint(cookie.documentURL, cookie.url, cookie.disabled);
+                this.addXHRBreakpoint(breakpoint);
+            }
+
             this._restoringBreakpoints = false;
             this._speculativelyResolveBreakpoints();
         }
@@ -63,6 +76,8 @@
         return !!window.DOMDebuggerAgent;
     }
 
+    get allRequestsBreakpoint() { return this._allRequestsBreakpoint; }
+
     get domBreakpoints()
     {
         let mainFrame = WebInspector.frameResourceManager.mainFrame;
@@ -85,6 +100,24 @@
         return resolvedBreakpoints;
     }
 
+    get xhrBreakpoints()
+    {
+        let mainFrame = WebInspector.frameResourceManager.mainFrame;
+        if (!mainFrame)
+            return [];
+
+        let breakpoints = this._xhrBreakpointURLMap.get(mainFrame.url)
+        if (!breakpoints)
+            return [];
+
+        return breakpoints.slice();
+    }
+
+    isBreakpointRemovable(breakpoint)
+    {
+        return breakpoint !== this._allRequestsBreakpoint;
+    }
+
     domBreakpointsForNode(node)
     {
         console.assert(node instanceof WebInspector.DOMNode);
@@ -148,9 +181,47 @@
 
         breakpoint.domNodeIdentifier = null;
 
-        this._saveBreakpoints();
+        this._saveDOMBreakpoints();
     }
 
+    addXHRBreakpoint(breakpoint)
+    {
+        console.assert(breakpoint instanceof WebInspector.XHRBreakpoint);
+        if (!breakpoint || !breakpoint.documentURL)
+            return;
+
+        let url = ""
+        let breakpoints = this._xhrBreakpointURLMap.get(url);
+        if (!breakpoints) {
+            breakpoints = [breakpoint];
+            this._xhrBreakpointURLMap.set(url, breakpoints);
+        } else
+            breakpoints.push(breakpoint);
+
+        this._resolveXHRBreakpoint(breakpoint);
+        this._saveXHRBreakpoints();
+    }
+
+    removeXHRBreakpoint(breakpoint)
+    {
+        console.assert(breakpoint instanceof WebInspector.XHRBreakpoint);
+        if (!breakpoint)
+            return;
+
+        let url = ""
+        let breakpoints = this._xhrBreakpointURLMap.get(url);
+        breakpoints.remove(breakpoint, true);
+
+        this._detachXHRBreakpoint(breakpoint);
+
+        if (!breakpoints.length)
+            this._xhrBreakpointURLMap.delete(url);
+
+        this.dispatchEventToListeners(WebInspector.DOMDebuggerManager.Event.DOMBreakpointRemoved, {breakpoint});
+
+        this._saveXHRBreakpoints();
+    }
+
     // Private
 
     _detachDOMBreakpoint(breakpoint)
@@ -203,20 +274,25 @@
         if (!mainFrame)
             return;
 
-        let breakpoints = this._domBreakpointURLMap.get(mainFrame.url);
-        if (!breakpoints)
-            return;
+        let domBreakpoints = this._domBreakpointURLMap.get(mainFrame.url);
+        if (domBreakpoints) {
+            for (let breakpoint of domBreakpoints) {
+                if (breakpoint.domNodeIdentifier)
+                    continue;
 
-        for (let breakpoint of breakpoints) {
-            if (breakpoint.domNodeIdentifier)
-                continue;
+                WebInspector.domTreeManager.pushNodeByPathToFrontend(breakpoint.path, (nodeIdentifier) => {
+                    if (!nodeIdentifier)
+                        return;
 
-            WebInspector.domTreeManager.pushNodeByPathToFrontend(breakpoint.path, (nodeIdentifier) => {
-                if (!nodeIdentifier)
-                    return;
+                    this._resolveDOMBreakpoint(breakpoint, nodeIdentifier);
+                });
+            }
+        }
 
-                this._resolveDOMBreakpoint(breakpoint, nodeIdentifier);
-            });
+        let xhrBreakpoints = this._xhrBreakpointURLMap.get(mainFrame.url);
+        if (xhrBreakpoints) {
+            for (let breakpoint of xhrBreakpoints)
+                this._resolveXHRBreakpoint(breakpoint);
         }
     }
 
@@ -263,8 +339,48 @@
             DOMDebuggerAgent.setDOMBreakpoint(nodeIdentifier, breakpoint.type, breakpointUpdated);
     }
 
-    _saveBreakpoints()
+    _detachXHRBreakpoint(breakpoint)
     {
+        if (breakpoint.disabled)
+            return;
+
+        DOMDebuggerAgent.removeXHRBreakpoint(breakpoint.url, (error) => {
+            if (error)
+                console.error(error);
+
+            this.dispatchEventToListeners(WebInspector.DOMDebuggerManager.Event.XHRBreakpointRemoved, {breakpoint});
+        });
+    }
+
+    _updateXHRBreakpoint(breakpoint, callback)
+    {
+        function breakpointUpdated(error)
+        {
+            if (error)
+                console.error(error);
+
+            if (callback && typeof callback === "function")
+                callback(error);
+        }
+
+        if (breakpoint.disabled)
+            DOMDebuggerAgent.removeXHRBreakpoint(breakpoint.url, breakpointUpdated);
+        else
+            DOMDebuggerAgent.setXHRBreakpoint(breakpoint.url, breakpointUpdated);
+    }
+
+    _resolveXHRBreakpoint(breakpoint)
+    {
+        if (breakpoint.disabled)
+            return;
+
+        this._updateXHRBreakpoint(breakpoint, () => {
+            this.dispatchEventToListeners(WebInspector.DOMDebuggerManager.Event.XHRBreakpointAdded, {breakpoint});
+        });
+    }
+
+    _saveDOMBreakpoints()
+    {
         if (this._restoringBreakpoints)
             return;
 
@@ -275,13 +391,36 @@
         this._domBreakpointsSetting.value = breakpointsToSave.map((breakpoint) => breakpoint.serializableInfo);
     }
 
+    _saveXHRBreakpoints()
+    {
+        if (this._restoringBreakpoints)
+            return;
+
+        let breakpointsToSave = [];
+        for (let breakpoints of this._xhrBreakpointURLMap.values())
+            breakpointsToSave = breakpointsToSave.concat(breakpoints);
+
+        this._xhrBreakpointsSetting.value = breakpointsToSave.map((breakpoint) => breakpoint.serializableInfo);
+    }
+
     _domBreakpointDisabledStateDidChange(event)
     {
         let breakpoint = event.target;
         this._updateDOMBreakpoint(breakpoint);
-        this._saveBreakpoints();
+        this._saveDOMBreakpoints();
     }
 
+    _xhrBreakpointDisabledStateDidChange(event)
+    {
+        let breakpoint = event.target;
+
+        if (breakpoint === this._allRequestsBreakpoint)
+            this._allRequestsBreakpointEnabledSetting.value = !breakpoint.disabled;
+
+        this._updateXHRBreakpoint(breakpoint);
+        this._saveXHRBreakpoints();
+    }
+
     _childFrameWasRemoved(event)
     {
         let frame = event.data.childFrame;
@@ -301,6 +440,12 @@
                 breakpoints.forEach((breakpoint) => { breakpoint.domNodeIdentifier = null; });
 
             this._domBreakpointFrameIdentifierMap.clear();
+
+            let xhrBreakpoints = this._xhrBreakpointURLMap.get(frame.url);
+            if (xhrBreakpoints) {
+                for (let breakpoint of xhrBreakpoints)
+                    this._detachXHRBreakpoint(breakpoint);
+            }
         } else
             this._detachBreakpointsForFrame(frame);
 
@@ -356,4 +501,6 @@
 WebInspector.DOMDebuggerManager.Event = {
     DOMBreakpointAdded: "dom-debugger-manager-dom-breakpoint-added",
     DOMBreakpointRemoved: "dom-debugger-manager-dom-breakpoint-removed",
+    XHRBreakpointAdded: "dom-debugger-manager-xhr-breakpoint-added",
+    XHRBreakpointRemoved: "dom-debugger-manager-xhr-breakpoint-removed",
 };

Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js (213690 => 213691)


--- trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js	2017-03-10 00:53:48 UTC (rev 213691)
@@ -815,6 +815,8 @@
             return WebInspector.DebuggerManager.PauseReason.Exception;
         case DebuggerAgent.PausedReason.PauseOnNextStatement:
             return WebInspector.DebuggerManager.PauseReason.PauseOnNextStatement;
+        case DebuggerAgent.PausedReason.XHR:
+            return WebInspector.DebuggerManager.PauseReason.XHR;
         default:
             return WebInspector.DebuggerManager.PauseReason.Other;
         }
@@ -1228,5 +1230,6 @@
     DOM: "DOM",
     Exception: "exception",
     PauseOnNextStatement: "pause-on-next-statement",
+    XHR: "xhr",
     Other: "other",
 };

Added: trunk/Source/WebInspectorUI/UserInterface/Controllers/XHRBreakpointTreeController.js (0 => 213691)


--- trunk/Source/WebInspectorUI/UserInterface/Controllers/XHRBreakpointTreeController.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/XHRBreakpointTreeController.js	2017-03-10 00:53:48 UTC (rev 213691)
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.XHRBreakpointTreeController = class XHRBreakpointsTreeController extends WebInspector.Object
+{
+    constructor(treeOutline)
+    {
+        super();
+
+        this._treeOutline = treeOutline;
+
+        WebInspector.Frame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
+
+        WebInspector.domDebuggerManager.addEventListener(WebInspector.DOMDebuggerManager.Event.XHRBreakpointAdded, this._xhrBreakpointAdded, this);
+        WebInspector.domDebuggerManager.addEventListener(WebInspector.DOMDebuggerManager.Event.XHRBreakpointRemoved, this._xhrBreakpointRemoved, this);
+
+        this._allReqestsBreakpointTreeElement = new WebInspector.XHRBreakpointTreeElement(WebInspector.domDebuggerManager.allRequestsBreakpoint, WebInspector.DebuggerSidebarPanel.AssertionIconStyleClassName, WebInspector.UIString("All Requests"));
+
+        this._treeOutline.appendChild(this._allReqestsBreakpointTreeElement);
+    }
+
+    // Public
+
+    revealAndSelect(breakpoint)
+    {
+        let treeElement = this._treeOutline.findTreeElement(breakpoint);
+        if (!treeElement)
+            return;
+
+        treeElement.revealAndSelect();
+    }
+
+    disconnect()
+    {
+        WebInspector.Frame.removeEventListener(null, null, this);
+        WebInspector.domDebuggerManager.removeEventListener(null, null, this);
+    }
+
+    // Private
+
+    _xhrBreakpointAdded(event)
+    {
+        let breakpoint = event.data.breakpoint;
+        let treeElement = this._treeOutline.findTreeElement(breakpoint);
+        console.assert(!treeElement);
+        if (treeElement)
+            return;
+
+        this._treeOutline.appendChild(new WebInspector.XHRBreakpointTreeElement(breakpoint));
+    }
+
+    _xhrBreakpointRemoved(event)
+    {
+        let breakpoint = event.data.breakpoint;
+        let treeElement = this._treeOutline.findTreeElement(breakpoint);
+        if (!treeElement)
+            return;
+
+        this._treeOutline.removeChild(treeElement);
+    }
+
+    _mainResourceDidChange(event)
+    {
+        if (!event.target.isMainFrame())
+            return;
+
+        while (this._treeOutline.children.length > 1)
+            this._treeOutline.removeChild(this._treeOutline.children.lastValue);
+    }
+};

Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (213690 => 213691)


--- trunk/Source/WebInspectorUI/UserInterface/Main.html	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html	2017-03-10 00:53:48 UTC (rev 213691)
@@ -64,7 +64,6 @@
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
-    <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
@@ -103,6 +102,7 @@
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
+    <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
@@ -402,6 +402,7 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
 
     <script src=""
     <script src=""
@@ -421,6 +422,7 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
     <script src=""
     <script src=""
     <script src=""
@@ -582,6 +584,7 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
     <script src=""
     <script src=""
     <script src=""
@@ -610,7 +613,6 @@
     <script src=""
     <script src=""
     <script src=""
-    <script src=""
     <script src=""
     <script src=""
     <script src=""
@@ -681,6 +683,7 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
 
     <script src=""
     <script src=""
@@ -750,6 +753,7 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
 
     <script src=""
 

Added: trunk/Source/WebInspectorUI/UserInterface/Models/XHRBreakpoint.js (0 => 213691)


--- trunk/Source/WebInspectorUI/UserInterface/Models/XHRBreakpoint.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/XHRBreakpoint.js	2017-03-10 00:53:48 UTC (rev 213691)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.XHRBreakpoint = class XHRBreakpoint extends WebInspector.Object
+{
+    constructor(documentURL, url, disabled)
+    {
+        super();
+
+        this._documentURL = documentURL;
+        this._url = url;
+        this._disabled = disabled || false;
+    }
+
+    // Public
+
+    get documentURL() { return this._documentURL; }
+    get url() { return this._url; }
+
+    get disabled()
+    {
+        return this._disabled;
+    }
+
+    set disabled(disabled)
+    {
+        if (this._disabled === disabled)
+            return;
+
+        this._disabled = disabled;
+
+        this.dispatchEventToListeners(WebInspector.XHRBreakpoint.Event.DisabledStateDidChange);
+    }
+
+    get serializableInfo()
+    {
+        let info = {documentURL: this._documentURL, url: this._url};
+        if (this._disabled)
+            info.disabled = true;
+
+        return info;
+    }
+
+    saveIdentityToCookie(cookie)
+    {
+        cookie[WebInspector.XHRBreakpoint.DocumentURLCookieKey] = this._documentURL;
+        cookie[WebInspector.XHRBreakpoint.URLCookieKey] = this._url;
+    }
+};
+
+WebInspector.XHRBreakpoint.DocumentURLCookieKey = "xhr-breakpoint-document-url";
+WebInspector.XHRBreakpoint.URLCookieKey = "xhr-breakpoint-url";
+
+WebInspector.XHRBreakpoint.Event = {
+    DisabledStateDidChange: "xhr-breakpoint-disabled-state-did-change",
+    ResolvedStateDidChange: "xhr-breakpoint-resolved-state-did-change",
+};

Modified: trunk/Source/WebInspectorUI/UserInterface/Test.html (213690 => 213691)


--- trunk/Source/WebInspectorUI/UserInterface/Test.html	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/WebInspectorUI/UserInterface/Test.html	2017-03-10 00:53:48 UTC (rev 213691)
@@ -174,6 +174,7 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
 
     <script src=""
     <script src=""

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ContentView.js (213690 => 213691)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ContentView.js	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ContentView.js	2017-03-10 00:53:48 UTC (rev 213691)
@@ -126,6 +126,9 @@
                 return WebInspector.ContentView.createFromRepresentedObject(representedObject.domNode, extraArguments);
         }
 
+        if (representedObject instanceof WebInspector.XHRBreakpoint)
+            return WebInspector.ContentView.createFromRepresentedObject(WebInspector.frameResourceManager.mainFrame.domTree, extraArguments);
+
         if (representedObject instanceof WebInspector.SourceCodeSearchMatchObject) {
             var resultView;
             if (representedObject.sourceCode instanceof WebInspector.Resource)

Deleted: trunk/Source/WebInspectorUI/UserInterface/Views/DOMBreakpointTreeElement.css (213690 => 213691)


--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMBreakpointTreeElement.css	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMBreakpointTreeElement.css	2017-03-10 00:53:48 UTC (rev 213691)
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-.item.dom-breakpoint .icon {
-    content: url(../Images/ResultLine.svg);
-}
-
-.item.dom-breakpoint.breakpoint-paused-icon .icon {
-    content: url(../Images/PausedBreakpoint.svg);
-}
-
-.item.dom-breakpoint .status img {
-    content: url(../Images/BreakpointButton.svg);
-    width: 21px;
-    height: 12px;
-    margin-top: 3px;
-}
-
-.item.dom-breakpoint .status > img.disabled {
-    opacity: 0.35;
-}

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMBreakpointTreeElement.js (213690 => 213691)


--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMBreakpointTreeElement.js	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMBreakpointTreeElement.js	2017-03-10 00:53:48 UTC (rev 213691)
@@ -35,10 +35,10 @@
         if (!title)
             title = WebInspector.DOMBreakpointTreeElement.displayNameForType(breakpoint.type);
 
-        super(["dom-breakpoint", className], title, null, breakpoint);
+        super(["breakpoint", className], title, null, breakpoint);
 
         this._statusImageElement = document.createElement("img");
-        this._statusImageElement.classList.add("status-image");
+        this._statusImageElement.classList.add("status-image", "resolved");
         this.status = this._statusImageElement;
 
         breakpoint.addEventListener(WebInspector.DOMBreakpoint.Event.DisabledStateDidChange, this._updateStatus, this);

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.css (213690 => 213691)


--- trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.css	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.css	2017-03-10 00:53:48 UTC (rev 213691)
@@ -103,3 +103,22 @@
 .sidebar > .panel.navigation.debugger .details-section.dom-breakpoints .item.dom-node .icon {
     content: url(../Images/DOMElement.svg);
 }
+
+.sidebar > .panel.navigation.debugger .details-section.xhr-breakpoints .item.breakpoint .subtitle:before {
+    content: "";
+}
+
+.sidebar > .panel.navigation.debugger .details-section.xhr-breakpoints .item.breakpoint .subtitle {
+    padding-left: 5px;
+    font-family: Menlo, monospace;
+
+    --subtitle-padding-start: 6px;
+}
+
+body[dir=ltr] .sidebar > .panel.navigation.debugger .details-section.xhr-breakpoints .item.breakpoint .subtitle {
+    padding-left: var(--subtitle-padding-start);
+}
+
+body[dir=rtl] .sidebar > .panel.navigation.debugger .details-section.xhr-breakpoints .item.breakpoint .subtitle {
+    padding-right: var(--subtitle-padding-start);
+}

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js (213690 => 213691)


--- trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js	2017-03-10 00:53:09 UTC (rev 213690)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js	2017-03-10 00:53:48 UTC (rev 213691)
@@ -179,6 +179,24 @@
             let domBreakpointsGroup = new WebInspector.DetailsSectionGroup([this._domBreakpointsRow]);
             let domBreakpointsSection = new WebInspector.DetailsSection("dom-breakpoints", WebInspector.UIString("DOM Breakpoints"), [domBreakpointsGroup]);
             this.contentView.element.appendChild(domBreakpointsSection.element);
+
+            this._xhrBreakpointsContentTreeOutline = this.createContentTreeOutline(true);
+            this._xhrBreakpointTreeController = new WebInspector.XHRBreakpointTreeController(this._xhrBreakpointsContentTreeOutline);
+
+            this._xhrBreakpointsRow = new WebInspector.DetailsSectionRow;
+            this._xhrBreakpointsRow.element.appendChild(this._xhrBreakpointsContentTreeOutline.element);
+
+            let navigationBar = new WebInspector.NavigationBar;
+            let navigationBarWrapper = document.createElement("div");
+            navigationBarWrapper.appendChild(navigationBar.element);
+
+            let addXHRBreakpointButton = new WebInspector.ButtonNavigationItem("add-xhr-breakpoint", WebInspector.UIString("Add XHR Breakpoint"), "Images/Plus13.svg", 13, 13);
+            addXHRBreakpointButton.addEventListener(WebInspector.ButtonNavigationItem.Event.Clicked, this._addXHRBreakpointButtonClicked, this);
+            navigationBar.addNavigationItem(addXHRBreakpointButton);
+
+            let xhrBreakpointsGroup = new WebInspector.DetailsSectionGroup([this._xhrBreakpointsRow]);
+            let xhrBreakpointsSection = new WebInspector.DetailsSection("xhr-breakpoints", WebInspector.UIString("XHR Breakpoints"), [xhrBreakpointsGroup], navigationBarWrapper);
+            this.contentView.element.appendChild(xhrBreakpointsSection.element);
         }
 
         this._scriptsContentTreeOutline = this.createContentTreeOutline();
@@ -329,6 +347,11 @@
             return;
         }
 
+        if (representedObject === WebInspector.domDebuggerManager.allRequestsBreakpoint) {
+            cookie[WebInspector.DebuggerSidebarPanel.SelectedAllRequestsCookieKey] = true;
+            return;
+        }
+
         super.saveStateToCookie(cookie);
     }
 
@@ -343,6 +366,8 @@
             this._allUncaughtExceptionsBreakpointTreeElement.revealAndSelect();
         else if (cookie[WebInspector.DebuggerSidebarPanel.SelectedAssertionsCookieKey])
             this._assertionsBreakpointTreeElement.revealAndSelect();
+        else if (cookie[WebInspector.DebuggerSidebarPanel.SelectedAllRequestsCookieKey])
+            this._xhrBreakpointTreeController.revealAndSelect(WebInspector.domDebuggerManager.allRequestsBreakpoint);
         else
             super.restoreStateFromCookie(cookie, relaxedMatchDelay);
     }
@@ -975,6 +1000,36 @@
             this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
             return true;
 
+        case WebInspector.DebuggerManager.PauseReason.XHR:
+            console.assert(WebInspector.domDebuggerManager.supported);
+            console.assert(pauseData, "Expected XHR breakpoint data, but found none.");
+            if (pauseData && pauseData.breakpointURL) {
+                let xhrBreakpoints = WebInspector.domDebuggerManager.xhrBreakpoints;
+                let xhrBreakpoint;
+                for (let breakpoint of xhrBreakpoints) {
+                    if (breakpoint.url ="" pauseData.breakpointURL) {
+                        xhrBreakpoint = breakpoint;
+                        break;
+                    }
+                }
+
+                if (!xhrBreakpoint)
+                    return;
+
+                this._pauseReasonTreeOutline = this.createContentTreeOutline(true, true);
+
+                let xhrBreakpointTreeElement = new WebInspector.XHRBreakpointTreeElement(xhrBreakpoint, WebInspector.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName, WebInspector.UIString("Triggered XHR Breakpoint"));
+                let xhrBreakpointRow = new WebInspector.DetailsSectionRow;
+                this._pauseReasonTreeOutline.appendChild(xhrBreakpointTreeElement);
+                xhrBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);
+
+                this._pauseReasonTextRow.text = pauseData.url;
+                this._pauseReasonGroup.rows = [xhrBreakpointRow, this._pauseReasonTextRow];
+
+                return true;
+            }
+            break;
+
         case WebInspector.DebuggerManager.PauseReason.Other:
             console.error("Paused for unknown reason. We should always have a reason.");
             break;
@@ -1067,6 +1122,27 @@
         this._domBreakpointsRow.hideEmptyMessage();
         this._domBreakpointsRow.element.append(this._domBreakpointsContentTreeOutline.element);
     }
+
+    _addXHRBreakpointButtonClicked(event)
+    {
+        let popover = new WebInspector.InputPopover(WebInspector.UIString("Break when URL contains:"), this);
+        popover.show(event.target.element, [WebInspector.RectEdge.MAX_Y, WebInspector.RectEdge.MIN_Y, WebInspector.RectEdge.MAX_X]);
+    }
+
+    // Popover delegate
+
+    willDismissPopover(popover)
+    {
+        if (popover.result !== WebInspector.InputPopover.Result.Committed)
+            return;
+
+        let url = ""
+        if (!url)
+            return;
+
+        let documentURL = WebInspector.frameResourceManager.mainFrame.url;
+        WebInspector.domDebuggerManager.addXHRBreakpoint(new WebInspector.XHRBreakpoint(documentURL, url));
+    }
 };
 
 WebInspector.DebuggerSidebarPanel.DebuggerPausedStyleClassName = "paused";
@@ -1077,3 +1153,4 @@
 WebInspector.DebuggerSidebarPanel.SelectedAllExceptionsCookieKey = "debugger-sidebar-panel-all-exceptions-breakpoint";
 WebInspector.DebuggerSidebarPanel.SelectedAllUncaughtExceptionsCookieKey = "debugger-sidebar-panel-all-uncaught-exceptions-breakpoint";
 WebInspector.DebuggerSidebarPanel.SelectedAssertionsCookieKey = "debugger-sidebar-panel-assertions-breakpoint";
+WebInspector.DebuggerSidebarPanel.SelectedAllRequestsCookieKey = "debugger-sidebar-panel-all-requests-breakpoint";

Copied: trunk/Source/WebInspectorUI/UserInterface/Views/InputPopover.css (from rev 213690, trunk/Source/WebInspectorUI/UserInterface/Views/DOMBreakpointTreeElement.css) (0 => 213691)


--- trunk/Source/WebInspectorUI/UserInterface/Views/InputPopover.css	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/InputPopover.css	2017-03-10 00:53:48 UTC (rev 213691)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.popover .input-popover-content {
+    padding: 5px;
+    margin: 2px;
+}
+
+.popover .input-popover-content > .editor {
+    width: 200px;
+    margin-top: 5px;
+    padding: 4px 0 2px 0;
+    -webkit-appearance: textfield;
+    border: 1px solid hsl(0, 0%, 78%);
+    background: white;
+}
+
+.popover .input-popover-content > .editor > .CodeMirror {
+    width: calc(100% - 2px);
+    height: auto;
+}
+
+.popover .input-popover-content > .editor > .CodeMirror-scroll {
+    width: calc(100% - 2px);
+    overflow: hidden;
+}

Added: trunk/Source/WebInspectorUI/UserInterface/Views/InputPopover.js (0 => 213691)


--- trunk/Source/WebInspectorUI/UserInterface/Views/InputPopover.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/InputPopover.js	2017-03-10 00:53:48 UTC (rev 213691)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.InputPopover = class InputPopover extends WebInspector.Popover
+{
+    constructor(message, delegate)
+    {
+        super(delegate);
+
+        this._message = message;
+        this._value = null;
+        this._result = WebInspector.InputPopover.Result.None;
+
+        this._targetElement = null;
+        this._preferredEdges = null;
+
+        this.windowResizeHandler = this._presentOverTargetElement.bind(this);
+    }
+
+    get value() { return this._value; }
+    get result() { return this._result; }
+
+    show(targetElement, preferredEdges)
+    {
+        this._targetElement = targetElement;
+        this._preferredEdges = preferredEdges;
+
+        let contentElement = document.createElement("div");
+        contentElement.classList.add("input-popover-content");
+
+        if (this._message) {
+            let label = document.createElement("div");
+            label.classList.add("label");
+            label.textContent = this._message;
+            contentElement.appendChild(label);
+        }
+
+        this._inputElement = document.createElement("input");
+        this._inputElement.type = "text";
+
+        this._inputElement.addEventListener("keydown", (event) => {
+            if (!isEnterKey(event))
+                return;
+
+            this._result = WebInspector.InputPopover.Result.Committed;
+            this._value = event.target.value;
+
+            this.dismiss();
+        });
+
+        contentElement.appendChild(this._inputElement);
+        this.content = contentElement;
+
+        this._presentOverTargetElement();
+    }
+
+    // Private
+
+    _presentOverTargetElement()
+    {
+        if (!this._targetElement)
+            return;
+
+        let targetFrame = WebInspector.Rect.rectFromClientRect(this._targetElement.getBoundingClientRect());
+        this.present(targetFrame, this._preferredEdges);
+
+        this._inputElement.select();
+    }
+};
+
+WebInspector.InputPopover.Result = {
+    None: Symbol("result-none"),
+    Cancelled: Symbol("result-cancelled"),
+    Committed: Symbol("result-committed"),
+};

Copied: trunk/Source/WebInspectorUI/UserInterface/Views/XHRBreakpointTreeElement.js (from rev 213690, trunk/Source/WebInspectorUI/UserInterface/Views/DOMBreakpointTreeElement.js) (0 => 213691)


--- trunk/Source/WebInspectorUI/UserInterface/Views/XHRBreakpointTreeElement.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/XHRBreakpointTreeElement.js	2017-03-10 00:53:48 UTC (rev 213691)
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.XHRBreakpointTreeElement = class XHRBreakpointTreeElement extends WebInspector.GeneralTreeElement
+{
+    constructor(breakpoint, className, title)
+    {
+        console.assert(breakpoint instanceof WebInspector.XHRBreakpoint);
+
+        if (!className)
+            className = WebInspector.BreakpointTreeElement.GenericLineIconStyleClassName;
+
+        let subtitle;
+        if (!title) {
+            title = WebInspector.UIString("URL contains:");
+            subtitle = breakpoint.url;
+        }
+
+        super(["breakpoint", className], title, subtitle, breakpoint);
+
+        this._statusImageElement = document.createElement("img");
+        this._statusImageElement.classList.add("status-image", "resolved");
+        this.status = this._statusImageElement;
+
+        breakpoint.addEventListener(WebInspector.XHRBreakpoint.Event.DisabledStateDidChange, this._updateStatus, this);
+
+        this._updateStatus();
+    }
+
+    // Protected
+
+    onattach()
+    {
+        super.onattach();
+
+        this._boundStatusImageElementClicked = this._statusImageElementClicked.bind(this);
+        this._boundStatusImageElementFocused = this._statusImageElementFocused.bind(this);
+        this._boundStatusImageElementMouseDown = this._statusImageElementMouseDown.bind(this);
+
+        this._statusImageElement.addEventListener("click", this._boundStatusImageElementClicked);
+        this._statusImageElement.addEventListener("focus", this._boundStatusImageElementFocused);
+        this._statusImageElement.addEventListener("mousedown", this._boundStatusImageElementMouseDown);
+    }
+
+    ondetach()
+    {
+        this._statusImageElement.removeEventListener("click", this._boundStatusImageElementClicked);
+        this._statusImageElement.removeEventListener("focus", this._boundStatusImageElementFocused);
+        this._statusImageElement.removeEventListener("mousedown", this._boundStatusImageElementMouseDown);
+
+        this._boundStatusImageElementClicked = null;
+        this._boundStatusImageElementFocused = null;
+        this._boundStatusImageElementMouseDown = null;
+    }
+
+    ondelete()
+    {
+        WebInspector.domDebuggerManager.removeXHRBreakpoint(this.representedObject);
+        return true;
+    }
+
+    onenter()
+    {
+        this._toggleBreakpoint();
+        return true;
+    }
+
+    onspace()
+    {
+        this._toggleBreakpoint();
+        return true;
+    }
+
+    populateContextMenu(contextMenu, event)
+    {
+        let breakpoint = this.representedObject;
+        let label = breakpoint.disabled ? WebInspector.UIString("Enable Breakpoint") : WebInspector.UIString("Disable Breakpoint");
+        contextMenu.appendItem(label, this._toggleBreakpoint.bind(this));
+
+        if (WebInspector.domDebuggerManager.isBreakpointRemovable(breakpoint)) {
+            contextMenu.appendSeparator();
+            contextMenu.appendItem(WebInspector.UIString("Delete Breakpoint"), function() {
+                WebInspector.domDebuggerManager.removeXHRBreakpoint(breakpoint);
+            });
+        }
+    }
+
+    // Private
+
+    _statusImageElementClicked(event)
+    {
+        this._toggleBreakpoint();
+    }
+
+    _statusImageElementFocused(event)
+    {
+        // Prevent tree outline focus.
+        event.stopPropagation();
+    }
+
+    _statusImageElementMouseDown(event)
+    {
+        // Prevent tree element selection.
+        event.stopPropagation();
+    }
+
+    _toggleBreakpoint()
+    {
+        this.representedObject.disabled = !this.representedObject.disabled;
+    }
+
+    _updateStatus()
+    {
+        this._statusImageElement.classList.toggle("disabled", this.representedObject.disabled);
+    }
+};
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to