<!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>[189104] 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/189104">189104</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2015-08-28 10:59:27 -0700 (Fri, 28 Aug 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Web Inspector: Separate creating a style sheet from adding a new rule in the protocol
https://bugs.webkit.org/show_bug.cgi?id=148502
Patch by Joseph Pecoraro <pecoraro@apple.com> on 2015-08-28
Reviewed by Timothy Hatcher.
Source/JavaScriptCore:
* inspector/protocol/CSS.json:
Add CSS.createStyleSheet. Modify CSS.addRule.
Source/WebCore:
Tests: inspector/css/createStyleSheet.html
inspector/css/manager-preferredInspectorStyleSheetForFrame.html
* inspector/InspectorCSSAgent.h:
Allow for multiple inspector style sheets per document.
* inspector/InspectorCSSAgent.cpp:
(WebCore::InspectorCSSAgent::createStyleSheet):
(WebCore::InspectorCSSAgent::createInspectorStyleSheetForDocument): Added.
(WebCore::InspectorCSSAgent::viaInspectorStyleSheet): Deleted.
Extract and generalize creating a via-inspector stylesheet here.
(WebCore::InspectorCSSAgent::addRule):
Lookup stylesheet to add a rule to via the provided stylesheet id.
(WebCore::InspectorCSSAgent::bindStyleSheet):
(WebCore::InspectorCSSAgent::detectOrigin):
Update to account for a list of stylesheets per document instead of one.
* inspector/InspectorStyleSheet.cpp:
(WebCore::InspectorStyleSheet::addRule):
(WebCore::InspectorStyleSheetForInlineStyle::setStyleText):
Source/WebInspectorUI:
The backend allows creating multiple stylesheets. This patch makes
the frontend have a preferred InspectorStyleSheet per-frame.
* UserInterface/Base/Object.js:
(WebInspector.Object.singleFireEventListener):
Return the wrapped listener so it can be removed if needed.
* UserInterface/Models/CSSStyleSheet.js:
(WebInspector.CSSStyleSheet.prototype.isInspectorStyleSheet):
Helper to check if the current stylesheet is an inspector created stylesheet.
* UserInterface/Controllers/CSSStyleManager.js:
(WebInspector.CSSStyleManager.prototype.preferredInspectorStyleSheetForFrame):
(WebInspector.CSSStyleManager.prototype.preferredInspectorStyleSheetForFrame.documentNodeAvailable):
(WebInspector.CSSStyleManager.prototype.preferredInspectorStyleSheetForFrame.bodyNodeAvailable):
(WebInspector.CSSStyleManager.prototype.preferredInspectorStyleSheetForFrame.cssRuleAvailable):
(WebInspector.CSSStyleManager.prototype._inspectorStyleSheetsForFrame):
Lookup the inspector stylesheet for a particular frame. If one doesn't exist create it.
For legacy backends, exploit "addRule" to create the inspector stylesheet.
* UserInterface/Models/DOMNode.js:
* UserInterface/Models/DOMNodeStyles.js:
(WebInspector.DOMNodeStyles.prototype.addEmptyRule.inspectorStyleSheetAvailable):
(WebInspector.DOMNodeStyles.prototype.addEmptyRule):
Currently add all new rules to the inspector stylesheet.
LayoutTests:
* inspector/css/createStyleSheet-expected.txt: Added.
* inspector/css/createStyleSheet.html: Added.
* inspector/css/manager-preferredInspectorStyleSheetForFrame-expected.txt: Added.
* inspector/css/manager-preferredInspectorStyleSheetForFrame.html: Added.
* inspector/css/stylesheet-events-inspector-stylesheet-expected.txt:
* inspector/css/stylesheet-events-inspector-stylesheet.html:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsinspectorcssstylesheeteventsinspectorstylesheetexpectedtxt">trunk/LayoutTests/inspector/css/stylesheet-events-inspector-stylesheet-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectorcssstylesheeteventsinspectorstylesheethtml">trunk/LayoutTests/inspector/css/stylesheet-events-inspector-stylesheet.html</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorprotocolCSSjson">trunk/Source/JavaScriptCore/inspector/protocol/CSS.json</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreinspectorInspectorCSSAgentcpp">trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp</a></li>
<li><a href="#trunkSourceWebCoreinspectorInspectorCSSAgenth">trunk/Source/WebCore/inspector/InspectorCSSAgent.h</a></li>
<li><a href="#trunkSourceWebCoreinspectorInspectorStyleSheetcpp">trunk/Source/WebCore/inspector/InspectorStyleSheet.cpp</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceBaseObjectjs">trunk/Source/WebInspectorUI/UserInterface/Base/Object.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceControllersCSSStyleManagerjs">trunk/Source/WebInspectorUI/UserInterface/Controllers/CSSStyleManager.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsCSSStyleSheetjs">trunk/Source/WebInspectorUI/UserInterface/Models/CSSStyleSheet.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsDOMNodejs">trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsDOMNodeStylesjs">trunk/Source/WebInspectorUI/UserInterface/Models/DOMNodeStyles.js</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsinspectorcsscreateStyleSheetexpectedtxt">trunk/LayoutTests/inspector/css/createStyleSheet-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectorcsscreateStyleSheethtml">trunk/LayoutTests/inspector/css/createStyleSheet.html</a></li>
<li><a href="#trunkLayoutTestsinspectorcssmanagerpreferredInspectorStyleSheetForFrameexpectedtxt">trunk/LayoutTests/inspector/css/manager-preferredInspectorStyleSheetForFrame-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectorcssmanagerpreferredInspectorStyleSheetForFramehtml">trunk/LayoutTests/inspector/css/manager-preferredInspectorStyleSheetForFrame.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/LayoutTests/ChangeLog        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2015-08-28 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Separate creating a style sheet from adding a new rule in the protocol
+ https://bugs.webkit.org/show_bug.cgi?id=148502
+
+ Reviewed by Timothy Hatcher.
+
+ * inspector/css/createStyleSheet-expected.txt: Added.
+ * inspector/css/createStyleSheet.html: Added.
+ * inspector/css/manager-preferredInspectorStyleSheetForFrame-expected.txt: Added.
+ * inspector/css/manager-preferredInspectorStyleSheetForFrame.html: Added.
+ * inspector/css/stylesheet-events-inspector-stylesheet-expected.txt:
+ * inspector/css/stylesheet-events-inspector-stylesheet.html:
+
</ins><span class="cx"> 2015-08-28 Xabier Rodriguez Calvar <calvaris@igalia.com>
</span><span class="cx">
</span><span class="cx"> Layout Test streams/reference-implementation/readable-stream.html is flaky
</span></span></pre></div>
<a id="trunkLayoutTestsinspectorcsscreateStyleSheetexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/css/createStyleSheet-expected.txt (0 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/css/createStyleSheet-expected.txt         (rev 0)
+++ trunk/LayoutTests/inspector/css/createStyleSheet-expected.txt        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+Test CSS.createStyleSheet.
+
+
+== Running test suite: CSS.createStyleSheet
+-- Running test case: CheckNoStyleSheets
+PASS: Should be no stylesheets.
+
+-- Running test case: CreateInspectorStyleSheetCall1
+PASS: Should increase the list of stylesheets.
+PASS: Added StyleSheet origin should be 'inspector'.
+PASS: StyleSheet.isInspectorStyleSheet() should be true.
+PASS: Added StyleSheet frame should be the main frame.
+
+-- Running test case: CreateInspectorStyleSheetCall2
+PASS: Should increase the list of stylesheets.
+PASS: Added StyleSheet origin should be 'inspector'.
+PASS: StyleSheet.isInspectorStyleSheet() should be true.
+PASS: Added StyleSheet frame should be the main frame.
+PASS: Added StyleSheet should be different from the last added stylesheet.
+
+-- Running test case: CreateInspectorStyleSheetCall3
+PASS: Should increase the list of stylesheets.
+PASS: Added StyleSheet origin should be 'inspector'.
+PASS: StyleSheet.isInspectorStyleSheet() should be true.
+PASS: Added StyleSheet frame should be the main frame.
+PASS: Added StyleSheet should be different from the last added stylesheet.
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectorcsscreateStyleSheethtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/css/createStyleSheet.html (0 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/css/createStyleSheet.html         (rev 0)
+++ trunk/LayoutTests/inspector/css/createStyleSheet.html        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script>
+function test()
+{
+ let addedStyleSheet;
+ let mainFrame = WebInspector.frameResourceManager.mainFrame;
+
+ let suite = InspectorTest.createAsyncSuite("CSS.createStyleSheet");
+
+ suite.addTestCase({
+ name: "CheckNoStyleSheets",
+ description: "Ensure there are no stylesheets.",
+ test: (resolve, reject) => {
+ InspectorTest.expectThat(WebInspector.cssStyleManager.styleSheets.length === 0, "Should be no stylesheets.");
+ resolve();
+ }
+ });
+
+ for (let i = 1; i <= 3; ++i) {
+ suite.addTestCase({
+ name: "CreateInspectorStyleSheetCall" + i,
+ description: "Should create a new inspector stylesheet.",
+ test: (resolve, reject) => {
+ CSSAgent.createStyleSheet(mainFrame.id);
+ WebInspector.cssStyleManager.singleFireEventListener(WebInspector.CSSStyleManager.Event.StyleSheetAdded, function(event) {
+ InspectorTest.expectThat(WebInspector.cssStyleManager.styleSheets.length === i, "Should increase the list of stylesheets.");
+ InspectorTest.expectThat(event.data.styleSheet.origin === WebInspector.CSSStyleSheet.Type.Inspector, "Added StyleSheet origin should be 'inspector'.");
+ InspectorTest.expectThat(event.data.styleSheet.isInspectorStyleSheet(), "StyleSheet.isInspectorStyleSheet() should be true.");
+ InspectorTest.expectThat(event.data.styleSheet.parentFrame === mainFrame, "Added StyleSheet frame should be the main frame.");
+ if (addedStyleSheet)
+ InspectorTest.expectThat(event.data.styleSheet !== addedStyleSheet, "Added StyleSheet should be different from the last added stylesheet.");
+ addedStyleSheet = event.data.styleSheet;
+ resolve();
+ });
+ }
+ });
+ }
+
+ WebInspector.cssStyleManager.singleFireEventListener(WebInspector.CSSStyleManager.Event.StyleSheetRemoved, function(event) {
+ InspectorTest.assert(false, "Should not be removing any StyleSheets in this test.");
+ });
+
+ suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="runTest()">
+ <p>Test CSS.createStyleSheet.</p>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectorcssmanagerpreferredInspectorStyleSheetForFrameexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/css/manager-preferredInspectorStyleSheetForFrame-expected.txt (0 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/css/manager-preferredInspectorStyleSheetForFrame-expected.txt         (rev 0)
+++ trunk/LayoutTests/inspector/css/manager-preferredInspectorStyleSheetForFrame-expected.txt        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -0,0 +1,34 @@
</span><ins>+Test CSSManager.preferredInspectorStyleSheetForFrame.
+
+
+
+== Running test suite: CSSManager.preferredInspectorStyleSheetForFrame
+-- Running test case: CheckNoStyleSheets
+PASS: Should be no stylesheets.
+
+-- Running test case: CreateMainFrameInspectorStyleSheet
+PASS: Added StyleSheet origin should be 'inspector'.
+PASS: StyleSheet.isInspectorStyleSheet() should be true.
+PASS: Added StyleSheet frame should be the main frame.
+PASS: Should be one stylesheet.
+PASS: StyleSheet origin is inspector.
+PASS: StyleSheet.isInspectorStyleSheet() should be true.
+
+-- Running test case: AnotherMainFrameRequestDoesNothing
+PASS: Should still be one stylesheet.
+PASS: StyleSheet origin should be 'inspector'.
+PASS: StyleSheet.isInspectorStyleSheet() should be true.
+
+-- Running test case: CreateSubFrameInspectorStyleSheet
+PASS: Added StyleSheet origin should be 'inspector'.
+PASS: StyleSheet.isInspectorStyleSheet() should be true.
+PASS: Added StyleSheet frame should be a child frame.
+PASS: Should be two stylesheets.
+PASS: StyleSheet origin should be 'inspector'.
+PASS: StyleSheet.isInspectorStyleSheet() should be true.
+
+-- Running test case: AnotherSubFrameRequestDoesNothing
+PASS: Should be two stylesheets.
+PASS: StyleSheet origin should be 'inspector'.
+PASS: StyleSheet.isInspectorStyleSheet() should be true.
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectorcssmanagerpreferredInspectorStyleSheetForFramehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/css/manager-preferredInspectorStyleSheetForFrame.html (0 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/css/manager-preferredInspectorStyleSheetForFrame.html         (rev 0)
+++ trunk/LayoutTests/inspector/css/manager-preferredInspectorStyleSheetForFrame.html        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -0,0 +1,104 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script>
+function test()
+{
+ let mainFrame = WebInspector.frameResourceManager.mainFrame;
+ let childFrame = mainFrame.childFrames[0];
+
+ let suite = InspectorTest.createAsyncSuite("CSSManager.preferredInspectorStyleSheetForFrame");
+
+ suite.addTestCase({
+ name: "CheckNoStyleSheets",
+ description: "Ensure there are no stylesheets.",
+ test: (resolve, reject) => {
+ InspectorTest.expectThat(WebInspector.cssStyleManager.styleSheets.length === 0, "Should be no stylesheets.");
+ resolve();
+ }
+ });
+
+ suite.addTestCase({
+ name: "CreateMainFrameInspectorStyleSheet",
+ description: "First request for main frame should create inspector stylesheet.",
+ test: (resolve, reject) => {
+ WebInspector.cssStyleManager.singleFireEventListener(WebInspector.CSSStyleManager.Event.StyleSheetAdded, function(event) {
+ InspectorTest.expectThat(event.data.styleSheet.origin === WebInspector.CSSStyleSheet.Type.Inspector, "Added StyleSheet origin should be 'inspector'.");
+ InspectorTest.expectThat(event.data.styleSheet.isInspectorStyleSheet(), "StyleSheet.isInspectorStyleSheet() should be true.");
+ InspectorTest.expectThat(event.data.styleSheet.parentFrame === mainFrame, "Added StyleSheet frame should be the main frame.");
+ });
+ WebInspector.cssStyleManager.preferredInspectorStyleSheetForFrame(mainFrame, function(styleSheet) {
+ InspectorTest.expectThat(WebInspector.cssStyleManager.styleSheets.length === 1, "Should be one stylesheet.");
+ InspectorTest.expectThat(styleSheet.origin === WebInspector.CSSStyleSheet.Type.Inspector, "StyleSheet origin is inspector.");
+ InspectorTest.expectThat(styleSheet.isInspectorStyleSheet(), "StyleSheet.isInspectorStyleSheet() should be true.");
+ resolve();
+ });
+ }
+ });
+
+ suite.addTestCase({
+ name: "AnotherMainFrameRequestDoesNothing",
+ description: "Second request for main frame should not create a new stylesheet.",
+ test: (resolve, reject) => {
+ let listener = WebInspector.cssStyleManager.singleFireEventListener(WebInspector.CSSStyleManager.Event.StyleSheetAdded, function(event) {
+ InspectorTest.assert(false, "Should not create a new StyleSheet, should reuse the existing one");
+ });
+ WebInspector.cssStyleManager.preferredInspectorStyleSheetForFrame(mainFrame, function(styleSheet) {
+ InspectorTest.expectThat(WebInspector.cssStyleManager.styleSheets.length === 1, "Should still be one stylesheet.");
+ InspectorTest.expectThat(styleSheet.origin === WebInspector.CSSStyleSheet.Type.Inspector, "StyleSheet origin should be 'inspector'.");
+ InspectorTest.expectThat(styleSheet.isInspectorStyleSheet(), "StyleSheet.isInspectorStyleSheet() should be true.");
+ WebInspector.cssStyleManager.removeEventListener(WebInspector.CSSStyleManager.Event.StyleSheetAdded, listener, null);
+ resolve();
+ });
+ }
+ });
+
+ suite.addTestCase({
+ name: "CreateSubFrameInspectorStyleSheet",
+ description: "First request for subframe should create inspector stylesheet.",
+ test: (resolve, reject) => {
+ WebInspector.cssStyleManager.singleFireEventListener(WebInspector.CSSStyleManager.Event.StyleSheetAdded, function(event) {
+ InspectorTest.expectThat(event.data.styleSheet.origin === WebInspector.CSSStyleSheet.Type.Inspector, "Added StyleSheet origin should be 'inspector'.");
+ InspectorTest.expectThat(event.data.styleSheet.isInspectorStyleSheet(), "StyleSheet.isInspectorStyleSheet() should be true.");
+ InspectorTest.expectThat(event.data.styleSheet.parentFrame === childFrame, "Added StyleSheet frame should be a child frame.");
+ });
+ WebInspector.cssStyleManager.preferredInspectorStyleSheetForFrame(childFrame, function(styleSheet) {
+ InspectorTest.expectThat(WebInspector.cssStyleManager.styleSheets.length === 2, "Should be two stylesheets.");
+ InspectorTest.expectThat(styleSheet.origin === WebInspector.CSSStyleSheet.Type.Inspector, "StyleSheet origin should be 'inspector'.");
+ InspectorTest.expectThat(styleSheet.isInspectorStyleSheet(), "StyleSheet.isInspectorStyleSheet() should be true.");
+ resolve();
+ });
+ }
+ });
+
+ suite.addTestCase({
+ name: "AnotherSubFrameRequestDoesNothing",
+ description: "Second request for main frame should not create a new stylesheet.",
+ test: (resolve, reject) => {
+ let listener = WebInspector.cssStyleManager.singleFireEventListener(WebInspector.CSSStyleManager.Event.StyleSheetAdded, function(event) {
+ InspectorTest.assert(false, "Should not create a new StyleSheet, should reuse the existing one");
+ });
+ WebInspector.cssStyleManager.preferredInspectorStyleSheetForFrame(childFrame, function(styleSheet) {
+ InspectorTest.expectThat(WebInspector.cssStyleManager.styleSheets.length === 2, "Should be two stylesheets.");
+ InspectorTest.expectThat(styleSheet.origin === WebInspector.CSSStyleSheet.Type.Inspector, "StyleSheet origin should be 'inspector'.");
+ InspectorTest.expectThat(styleSheet.isInspectorStyleSheet(), "StyleSheet.isInspectorStyleSheet() should be true.");
+ WebInspector.cssStyleManager.removeEventListener(WebInspector.CSSStyleManager.Event.StyleSheetAdded, listener, null);
+ resolve();
+ });
+ }
+ });
+
+ WebInspector.cssStyleManager.singleFireEventListener(WebInspector.CSSStyleManager.Event.StyleSheetRemoved, function(event) {
+ InspectorTest.assert(false, "Should not be removing any StyleSheets in this test.");
+ });
+
+ suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="runTest()">
+ <p>Test CSSManager.preferredInspectorStyleSheetForFrame.</p>
+ <iframe src="about:blank"></iframe>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectorcssstylesheeteventsinspectorstylesheetexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/css/stylesheet-events-inspector-stylesheet-expected.txt (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/css/stylesheet-events-inspector-stylesheet-expected.txt        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/LayoutTests/inspector/css/stylesheet-events-inspector-stylesheet-expected.txt        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -7,5 +7,5 @@
</span><span class="cx">
</span><span class="cx"> -- Running test case: CreateInspectorStyleSheet
</span><span class="cx"> PASS: Should be one stylesheet.
</span><del>-PASS: StyleSheet origin is inspector.
</del><ins>+PASS: StyleSheet origin should be 'inspector'.
</ins><span class="cx">
</span></span></pre></div>
<a id="trunkLayoutTestsinspectorcssstylesheeteventsinspectorstylesheethtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/css/stylesheet-events-inspector-stylesheet.html (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/css/stylesheet-events-inspector-stylesheet.html        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/LayoutTests/inspector/css/stylesheet-events-inspector-stylesheet.html        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -7,8 +7,6 @@
</span><span class="cx"> {
</span><span class="cx"> let suite = InspectorTest.createAsyncSuite("CSS.StyleSheetEvents.InspectorStyleSheet");
</span><span class="cx">
</span><del>- let bodyNodeId;
-
</del><span class="cx"> suite.addTestCase({
</span><span class="cx"> name: "CheckNoStyleSheets",
</span><span class="cx"> description: "Ensure there are currently no stylesheets.",
</span><span class="lines">@@ -22,24 +20,17 @@
</span><span class="cx"> name: "CreateInspectorStyleSheet",
</span><span class="cx"> description: "Creating an inspector stylesheet adds a stylesheet.",
</span><span class="cx"> test: (resolve, reject) => {
</span><ins>+ CSSAgent.createStyleSheet(WebInspector.frameResourceManager.mainFrame.id);
</ins><span class="cx"> WebInspector.cssStyleManager.singleFireEventListener(WebInspector.CSSStyleManager.Event.StyleSheetAdded, function(event) {
</span><span class="cx"> InspectorTest.expectThat(WebInspector.cssStyleManager.styleSheets.length === 1, "Should be one stylesheet.");
</span><span class="cx"> InspectorTest.assert(event.data.styleSheet instanceof WebInspector.CSSStyleSheet, "Event data should be a CSSStyleSheet");
</span><del>- InspectorTest.expectThat(event.data.styleSheet.origin === WebInspector.CSSStyleSheet.Type.Inspector, "StyleSheet origin is inspector.");
</del><ins>+ InspectorTest.expectThat(event.data.styleSheet.origin === WebInspector.CSSStyleSheet.Type.Inspector, "StyleSheet origin should be 'inspector'.");
</ins><span class="cx"> resolve();
</span><span class="cx"> });
</span><del>-
- // FIXME: Currently the only way to create an inspector stylesheet is through `CSS.addRule`.
- CSSAgent.addRule(bodyNodeId, "body");
</del><span class="cx"> }
</span><span class="cx"> });
</span><span class="cx">
</span><del>- WebInspector.domTreeManager.requestDocument(function(documentNode) {
- WebInspector.domTreeManager.querySelector(documentNode.id, "body", function(contentNodeId) {
- bodyNodeId = contentNodeId;
- suite.runTestCasesAndFinish();
- });
- });
</del><ins>+ suite.runTestCasesAndFinish();
</ins><span class="cx"> }
</span><span class="cx"> </script>
</span><span class="cx"> </head>
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2015-08-28 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Separate creating a style sheet from adding a new rule in the protocol
+ https://bugs.webkit.org/show_bug.cgi?id=148502
+
+ Reviewed by Timothy Hatcher.
+
+ * inspector/protocol/CSS.json:
+ Add CSS.createStyleSheet. Modify CSS.addRule.
+
</ins><span class="cx"> 2015-08-28 Mark Lam <mark.lam@apple.com>
</span><span class="cx">
</span><span class="cx"> ScratchRegisterAllocator::preserveReusedRegistersByPushing() should allow room for C helper calls and keep sp properly aligned.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorprotocolCSSjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/protocol/CSS.json (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/protocol/CSS.json        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/Source/JavaScriptCore/inspector/protocol/CSS.json        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -333,15 +333,25 @@
</span><span class="cx"> "description": "Modifies the rule selector."
</span><span class="cx"> },
</span><span class="cx"> {
</span><ins>+ "name": "createStyleSheet",
+ "parameters": [
+ { "name": "frameId", "$ref": "Network.FrameId", "description": "Identifier of the frame where the new \"inspector\" stylesheet should be created." }
+ ],
+ "returns": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "Identifier of the created \"inspector\" stylesheet." }
+ ],
+ "description": "Creates a new special \"inspector\" stylesheet in the frame with given <code>frameId</code>."
+ },
+ {
</ins><span class="cx"> "name": "addRule",
</span><span class="cx"> "parameters": [
</span><del>- { "name": "contextNodeId", "$ref": "DOM.NodeId" },
</del><ins>+ { "name": "styleSheetId", "$ref": "StyleSheetId" },
</ins><span class="cx"> { "name": "selector", "type": "string" }
</span><span class="cx"> ],
</span><span class="cx"> "returns": [
</span><span class="cx"> { "name": "rule", "$ref": "CSSRule", "description": "The newly created rule." }
</span><span class="cx"> ],
</span><del>- "description": "Creates a new empty rule with the given <code>selector</code> in a special \"inspector\" stylesheet in the owner document of the context node."
</del><ins>+ "description": "Creates a new empty rule with the given <code>selector</code> in a stylesheet with given <code>styleSheetId</code>."
</ins><span class="cx"> },
</span><span class="cx"> {
</span><span class="cx"> "name": "getSupportedCSSProperties",
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/Source/WebCore/ChangeLog        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -1,3 +1,33 @@
</span><ins>+2015-08-28 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Separate creating a style sheet from adding a new rule in the protocol
+ https://bugs.webkit.org/show_bug.cgi?id=148502
+
+ Reviewed by Timothy Hatcher.
+
+ Tests: inspector/css/createStyleSheet.html
+ inspector/css/manager-preferredInspectorStyleSheetForFrame.html
+
+ * inspector/InspectorCSSAgent.h:
+ Allow for multiple inspector style sheets per document.
+
+ * inspector/InspectorCSSAgent.cpp:
+ (WebCore::InspectorCSSAgent::createStyleSheet):
+ (WebCore::InspectorCSSAgent::createInspectorStyleSheetForDocument): Added.
+ (WebCore::InspectorCSSAgent::viaInspectorStyleSheet): Deleted.
+ Extract and generalize creating a via-inspector stylesheet here.
+
+ (WebCore::InspectorCSSAgent::addRule):
+ Lookup stylesheet to add a rule to via the provided stylesheet id.
+
+ (WebCore::InspectorCSSAgent::bindStyleSheet):
+ (WebCore::InspectorCSSAgent::detectOrigin):
+ Update to account for a list of stylesheets per document instead of one.
+
+ * inspector/InspectorStyleSheet.cpp:
+ (WebCore::InspectorStyleSheet::addRule):
+ (WebCore::InspectorStyleSheetForInlineStyle::setStyleText):
+
</ins><span class="cx"> 2015-08-28 Timothy Horton <timothy_horton@apple.com>
</span><span class="cx">
</span><span class="cx"> [Mac] Right-clicking on GIFs spins the UI process for a while
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorInspectorCSSAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> #include "HTMLStyleElement.h"
</span><span class="cx"> #include "InspectorDOMAgent.h"
</span><span class="cx"> #include "InspectorHistory.h"
</span><ins>+#include "InspectorPageAgent.h"
</ins><span class="cx"> #include "InstrumentingAgents.h"
</span><span class="cx"> #include "NamedFlowCollection.h"
</span><span class="cx"> #include "Node.h"
</span><span class="lines">@@ -747,14 +748,79 @@
</span><span class="cx"> errorString = InspectorDOMAgent::toErrorString(ec);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void InspectorCSSAgent::addRule(ErrorString& errorString, const int contextNodeId, const String& selector, RefPtr<Inspector::Protocol::CSS::CSSRule>& result)
</del><ins>+void InspectorCSSAgent::createStyleSheet(ErrorString& errorString, const String& frameId, String* styleSheetId)
</ins><span class="cx"> {
</span><del>- Node* node = m_domAgent->assertNode(errorString, contextNodeId);
- if (!node)
</del><ins>+ Frame* frame = m_domAgent->pageAgent()->frameForId(frameId);
+ if (!frame) {
+ errorString = ASCIILiteral("No frame for given id found");
</ins><span class="cx"> return;
</span><ins>+ }
</ins><span class="cx">
</span><del>- InspectorStyleSheet* inspectorStyleSheet = viaInspectorStyleSheet(&node->document(), true);
</del><ins>+ Document* document = frame->document();
+ if (!document) {
+ errorString = ASCIILiteral("No document for frame");
+ return;
+ }
+
+ InspectorStyleSheet* inspectorStyleSheet = createInspectorStyleSheetForDocument(*document);
</ins><span class="cx"> if (!inspectorStyleSheet) {
</span><ins>+ errorString = ASCIILiteral("Could not create stylesheet for the frame.");
+ return;
+ }
+
+ *styleSheetId = inspectorStyleSheet->id();
+}
+
+InspectorStyleSheet* InspectorCSSAgent::createInspectorStyleSheetForDocument(Document& document)
+{
+ if (!document.isHTMLDocument() && !document.isSVGDocument())
+ return nullptr;
+
+ ExceptionCode ec = 0;
+ RefPtr<Element> styleElement = document.createElement("style", ec);
+ if (ec)
+ return nullptr;
+
+ styleElement->setAttribute("type", "text/css", ec);
+ if (ec)
+ return nullptr;
+
+ ContainerNode* targetNode;
+ // HEAD is absent in ImageDocuments, for example.
+ if (auto* head = document.head())
+ targetNode = head;
+ else if (auto* body = document.bodyOrFrameset())
+ targetNode = body;
+ else
+ return nullptr;
+
+ // Inserting this <style> into the document will trigger activeStyleSheetsUpdated
+ // and we will create an InspectorStyleSheet for this <style>'s CSSStyleSheet.
+ // Set this flag, so when we create it, we put it into the via inspector map.
+ m_creatingViaInspectorStyleSheet = true;
+ InlineStyleOverrideScope overrideScope(document);
+ targetNode->appendChild(styleElement, ec);
+ m_creatingViaInspectorStyleSheet = false;
+ if (ec)
+ return nullptr;
+
+ auto iterator = m_documentToInspectorStyleSheet.find(&document);
+ ASSERT(iterator != m_documentToInspectorStyleSheet.end());
+ if (iterator == m_documentToInspectorStyleSheet.end())
+ return nullptr;
+
+ auto& inspectorStyleSheetsForDocument = iterator->value;
+ ASSERT(!inspectorStyleSheetsForDocument.isEmpty());
+ if (inspectorStyleSheetsForDocument.isEmpty())
+ return nullptr;
+
+ return inspectorStyleSheetsForDocument.last().get();
+}
+
+void InspectorCSSAgent::addRule(ErrorString& errorString, const String& styleSheetId, const String& selector, RefPtr<Inspector::Protocol::CSS::CSSRule>& result)
+{
+ InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
+ if (!inspectorStyleSheet) {
</ins><span class="cx"> errorString = ASCIILiteral("No target stylesheet found");
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="lines">@@ -905,59 +971,19 @@
</span><span class="cx"> inspectorStyleSheet = InspectorStyleSheet::create(m_domAgent->pageAgent(), id, styleSheet, detectOrigin(styleSheet, document), InspectorDOMAgent::documentURLString(document), this);
</span><span class="cx"> m_idToInspectorStyleSheet.set(id, inspectorStyleSheet);
</span><span class="cx"> m_cssStyleSheetToInspectorStyleSheet.set(styleSheet, inspectorStyleSheet);
</span><del>- if (m_creatingViaInspectorStyleSheet)
- m_documentToInspectorStyleSheet.add(document, inspectorStyleSheet);
</del><ins>+ if (m_creatingViaInspectorStyleSheet) {
+ auto& inspectorStyleSheetsForDocument = m_documentToInspectorStyleSheet.add(document, Vector<RefPtr<InspectorStyleSheet>>()).iterator->value;
+ inspectorStyleSheetsForDocument.append(inspectorStyleSheet);
+ }
</ins><span class="cx"> }
</span><span class="cx"> return inspectorStyleSheet.get();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-InspectorStyleSheet* InspectorCSSAgent::viaInspectorStyleSheet(Document* document, bool createIfAbsent)
-{
- if (!document) {
- ASSERT(!createIfAbsent);
- return nullptr;
- }
-
- if (!document->isHTMLDocument() && !document->isSVGDocument())
- return nullptr;
-
- RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_documentToInspectorStyleSheet.get(document);
- if (inspectorStyleSheet || !createIfAbsent)
- return inspectorStyleSheet.get();
-
- ExceptionCode ec = 0;
- RefPtr<Element> styleElement = document->createElement("style", ec);
- if (!ec)
- styleElement->setAttribute("type", "text/css", ec);
- if (!ec) {
- ContainerNode* targetNode;
- // HEAD is absent in ImageDocuments, for example.
- if (auto* head = document->head())
- targetNode = head;
- else if (auto* body = document->bodyOrFrameset())
- targetNode = body;
- else
- return nullptr;
-
- // Inserting this <style> into the document will trigger activeStyleSheetsUpdated
- // and we will create an InspectorStyleSheet for this <style>'s CSSStyleSheet.
- // Set this flag, so when we create it, we put it into the via inspector hash map.
- m_creatingViaInspectorStyleSheet = true;
- InlineStyleOverrideScope overrideScope(document);
- targetNode->appendChild(styleElement, ec);
- m_creatingViaInspectorStyleSheet = false;
- }
- if (ec)
- return nullptr;
-
- return m_documentToInspectorStyleSheet.get(document);
-}
-
</del><span class="cx"> InspectorStyleSheet* InspectorCSSAgent::assertStyleSheetForId(ErrorString& errorString, const String& styleSheetId)
</span><span class="cx"> {
</span><span class="cx"> IdToInspectorStyleSheet::iterator it = m_idToInspectorStyleSheet.find(styleSheetId);
</span><span class="cx"> if (it == m_idToInspectorStyleSheet.end()) {
</span><del>- errorString = ASCIILiteral("No style sheet with given id found");
</del><ins>+ errorString = ASCIILiteral("No stylesheet with given id found");
</ins><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><span class="cx"> return it->value.get();
</span><span class="lines">@@ -970,13 +996,17 @@
</span><span class="cx">
</span><span class="cx"> if (pageStyleSheet && !pageStyleSheet->ownerNode() && pageStyleSheet->href().isEmpty())
</span><span class="cx"> return Inspector::Protocol::CSS::StyleSheetOrigin::UserAgent;
</span><del>-
</del><ins>+
</ins><span class="cx"> if (pageStyleSheet && pageStyleSheet->ownerNode() && pageStyleSheet->ownerNode()->nodeName() == "#document")
</span><span class="cx"> return Inspector::Protocol::CSS::StyleSheetOrigin::User;
</span><span class="cx">
</span><del>- InspectorStyleSheet* viaInspectorStyleSheetForOwner = viaInspectorStyleSheet(ownerDocument, false);
- if (viaInspectorStyleSheetForOwner && pageStyleSheet == viaInspectorStyleSheetForOwner->pageStyleSheet())
- return Inspector::Protocol::CSS::StyleSheetOrigin::Inspector;
</del><ins>+ auto iterator = m_documentToInspectorStyleSheet.find(ownerDocument);
+ if (iterator != m_documentToInspectorStyleSheet.end()) {
+ for (auto& inspectorStyleSheet : iterator->value) {
+ if (pageStyleSheet == inspectorStyleSheet->pageStyleSheet())
+ return Inspector::Protocol::CSS::StyleSheetOrigin::Inspector;
+ }
+ }
</ins><span class="cx">
</span><span class="cx"> return Inspector::Protocol::CSS::StyleSheetOrigin::Regular;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorInspectorCSSAgenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/InspectorCSSAgent.h (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/InspectorCSSAgent.h        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/Source/WebCore/inspector/InspectorCSSAgent.h        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -45,21 +45,16 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><span class="cx"> class CSSRule;
</span><del>-class CSSRuleList;
-class CSSStyleDeclaration;
</del><span class="cx"> class CSSStyleRule;
</span><span class="cx"> class CSSStyleSheet;
</span><ins>+class ChangeRegionOversetTask;
</ins><span class="cx"> class Document;
</span><del>-class DocumentStyleSheetCollection;
</del><span class="cx"> class Element;
</span><del>-class InspectorCSSOMWrappers;
</del><span class="cx"> class InstrumentingAgents;
</span><del>-class NameNodeMap;
</del><span class="cx"> class Node;
</span><span class="cx"> class NodeList;
</span><span class="cx"> class StyleResolver;
</span><span class="cx"> class StyleRule;
</span><del>-class ChangeRegionOversetTask;
</del><span class="cx">
</span><span class="cx"> class InspectorCSSAgent final
</span><span class="cx"> : public InspectorAgentBase
</span><span class="lines">@@ -71,8 +66,8 @@
</span><span class="cx"> public:
</span><span class="cx"> class InlineStyleOverrideScope {
</span><span class="cx"> public:
</span><del>- InlineStyleOverrideScope(SecurityContext* context)
- : m_contentSecurityPolicy(context->contentSecurityPolicy())
</del><ins>+ InlineStyleOverrideScope(SecurityContext& context)
+ : m_contentSecurityPolicy(context.contentSecurityPolicy())
</ins><span class="cx"> {
</span><span class="cx"> m_contentSecurityPolicy->setOverrideAllowInlineStyle(true);
</span><span class="cx"> }
</span><span class="lines">@@ -119,7 +114,8 @@
</span><span class="cx"> virtual void setStyleSheetText(ErrorString&, const String& styleSheetId, const String& text) override;
</span><span class="cx"> virtual void setStyleText(ErrorString&, const Inspector::InspectorObject& styleId, const String& text, RefPtr<Inspector::Protocol::CSS::CSSStyle>& result) override;
</span><span class="cx"> virtual void setRuleSelector(ErrorString&, const Inspector::InspectorObject& ruleId, const String& selector, RefPtr<Inspector::Protocol::CSS::CSSRule>& result) override;
</span><del>- virtual void addRule(ErrorString&, int contextNodeId, const String& selector, RefPtr<Inspector::Protocol::CSS::CSSRule>& result) override;
</del><ins>+ virtual void createStyleSheet(ErrorString&, const String& frameId, String* styleSheetId) override;
+ virtual void addRule(ErrorString&, const String& styleSheetId, const String& selector, RefPtr<Inspector::Protocol::CSS::CSSRule>& result) override;
</ins><span class="cx"> virtual void getSupportedCSSProperties(ErrorString&, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSPropertyInfo>>& result) override;
</span><span class="cx"> virtual void getSupportedSystemFontFamilyNames(ErrorString&, RefPtr<Inspector::Protocol::Array<String>>& result) override;
</span><span class="cx"> virtual void forcePseudoState(ErrorString&, int nodeId, const Inspector::InspectorArray& forcedPseudoClasses) override;
</span><span class="lines">@@ -135,7 +131,7 @@
</span><span class="cx"> typedef HashMap<String, RefPtr<InspectorStyleSheet>> IdToInspectorStyleSheet;
</span><span class="cx"> typedef HashMap<CSSStyleSheet*, RefPtr<InspectorStyleSheet>> CSSStyleSheetToInspectorStyleSheet;
</span><span class="cx"> typedef HashMap<Node*, RefPtr<InspectorStyleSheetForInlineStyle>> NodeToInspectorStyleSheet; // bogus "stylesheets" with elements' inline styles
</span><del>- typedef HashMap<RefPtr<Document>, RefPtr<InspectorStyleSheet>> DocumentToViaInspectorStyleSheet; // "via inspector" stylesheets
</del><ins>+ typedef HashMap<RefPtr<Document>, Vector<RefPtr<InspectorStyleSheet>>> DocumentToViaInspectorStyleSheet; // "via inspector" stylesheets
</ins><span class="cx"> typedef HashMap<int, unsigned> NodeIdToForcedPseudoState;
</span><span class="cx">
</span><span class="cx"> void resetNonPersistentData();
</span><span class="lines">@@ -150,8 +146,8 @@
</span><span class="cx">
</span><span class="cx"> String unbindStyleSheet(InspectorStyleSheet*);
</span><span class="cx"> InspectorStyleSheet* bindStyleSheet(CSSStyleSheet*);
</span><del>- InspectorStyleSheet* viaInspectorStyleSheet(Document*, bool createIfAbsent);
</del><span class="cx"> InspectorStyleSheet* assertStyleSheetForId(ErrorString&, const String&);
</span><ins>+ InspectorStyleSheet* createInspectorStyleSheetForDocument(Document&);
</ins><span class="cx"> Inspector::Protocol::CSS::StyleSheetOrigin detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument);
</span><span class="cx">
</span><span class="cx"> RefPtr<Inspector::Protocol::CSS::CSSRule> buildObjectForRule(StyleRule*, StyleResolver&, Element*);
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorInspectorStyleSheetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/InspectorStyleSheet.cpp (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/InspectorStyleSheet.cpp        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/Source/WebCore/inspector/InspectorStyleSheet.cpp        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -726,7 +726,7 @@
</span><span class="cx">
</span><span class="cx"> styleSheetText.append(selector);
</span><span class="cx"> styleSheetText.appendLiteral(" {}");
</span><del>- // Using setText() as this operation changes the style sheet rule set.
</del><ins>+ // Using setText() as this operation changes the stylesheet rule set.
</ins><span class="cx"> setText(styleSheetText.toString(), ASSERT_NO_EXCEPTION);
</span><span class="cx">
</span><span class="cx"> fireStyleSheetChanged();
</span><span class="lines">@@ -1295,7 +1295,7 @@
</span><span class="cx"> ASSERT_UNUSED(style, style == inlineStyle());
</span><span class="cx">
</span><span class="cx"> {
</span><del>- InspectorCSSAgent::InlineStyleOverrideScope overrideScope(&m_element->document());
</del><ins>+ InspectorCSSAgent::InlineStyleOverrideScope overrideScope(m_element->document());
</ins><span class="cx"> m_element->setAttribute("style", text, ec);
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/Source/WebInspectorUI/ChangeLog        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -1,5 +1,38 @@
</span><span class="cx"> 2015-08-28 Joseph Pecoraro <pecoraro@apple.com>
</span><span class="cx">
</span><ins>+ Web Inspector: Separate creating a style sheet from adding a new rule in the protocol
+ https://bugs.webkit.org/show_bug.cgi?id=148502
+
+ Reviewed by Timothy Hatcher.
+
+ The backend allows creating multiple stylesheets. This patch makes
+ the frontend have a preferred InspectorStyleSheet per-frame.
+
+ * UserInterface/Base/Object.js:
+ (WebInspector.Object.singleFireEventListener):
+ Return the wrapped listener so it can be removed if needed.
+
+ * UserInterface/Models/CSSStyleSheet.js:
+ (WebInspector.CSSStyleSheet.prototype.isInspectorStyleSheet):
+ Helper to check if the current stylesheet is an inspector created stylesheet.
+
+ * UserInterface/Controllers/CSSStyleManager.js:
+ (WebInspector.CSSStyleManager.prototype.preferredInspectorStyleSheetForFrame):
+ (WebInspector.CSSStyleManager.prototype.preferredInspectorStyleSheetForFrame.documentNodeAvailable):
+ (WebInspector.CSSStyleManager.prototype.preferredInspectorStyleSheetForFrame.bodyNodeAvailable):
+ (WebInspector.CSSStyleManager.prototype.preferredInspectorStyleSheetForFrame.cssRuleAvailable):
+ (WebInspector.CSSStyleManager.prototype._inspectorStyleSheetsForFrame):
+ Lookup the inspector stylesheet for a particular frame. If one doesn't exist create it.
+ For legacy backends, exploit "addRule" to create the inspector stylesheet.
+
+ * UserInterface/Models/DOMNode.js:
+ * UserInterface/Models/DOMNodeStyles.js:
+ (WebInspector.DOMNodeStyles.prototype.addEmptyRule.inspectorStyleSheetAvailable):
+ (WebInspector.DOMNodeStyles.prototype.addEmptyRule):
+ Currently add all new rules to the inspector stylesheet.
+
+2015-08-28 Joseph Pecoraro <pecoraro@apple.com>
+
</ins><span class="cx"> Web Inspector: Type Profiler does not understand Functions within Default Argument Expressions
</span><span class="cx"> https://bugs.webkit.org/show_bug.cgi?id=148557
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceBaseObjectjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Object.js (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Base/Object.js        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Object.js        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -63,6 +63,7 @@
</span><span class="cx"> }.bind(this);
</span><span class="cx">
</span><span class="cx"> this.addEventListener(eventType, wrappedCallback, null);
</span><ins>+ return wrappedCallback;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static removeEventListener(eventType, listener, thisObject)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceControllersCSSStyleManagerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/CSSStyleManager.js (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Controllers/CSSStyleManager.js        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/CSSStyleManager.js        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -167,6 +167,92 @@
</span><span class="cx"> return styles;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ preferredInspectorStyleSheetForFrame(frame, callback)
+ {
+ var inspectorStyleSheets = this._inspectorStyleSheetsForFrame(frame);
+ for (let styleSheet of inspectorStyleSheets) {
+ if (styleSheet[WebInspector.CSSStyleManager.PreferredInspectorStyleSheetSymbol]) {
+ callback(styleSheet);
+ return;
+ }
+ }
+
+ if (CSSAgent.createStyleSheet) {
+ CSSAgent.createStyleSheet(frame.id, function(error, styleSheetId) {
+ let styleSheet = WebInspector.cssStyleManager.styleSheetForIdentifier(styleSheetId);
+ styleSheet[WebInspector.CSSStyleManager.PreferredInspectorStyleSheetSymbol] = true;
+ callback(styleSheet);
+ });
+ return;
+ }
+
+ // COMPATIBILITY (iOS 9): CSS.createStyleSheet did not exist.
+ // Legacy backends can only create the Inspector StyleSheet through CSS.addRule.
+ // Exploit that to create the Inspector StyleSheet for the document.body node in
+ // this frame, then get the StyleSheet for the new rule.
+
+ let expression = appendWebInspectorSourceURL("document");
+ let contextId = frame.pageExecutionContext.id;
+ RuntimeAgent.evaluate.invoke({expression, objectGroup: "", includeCommandLineAPI: false, doNotPauseOnExceptionsAndMuteConsole: true, contextId, returnByValue: false, generatePreview: false}, documentAvailable);
+
+ function documentAvailable(error, documentRemoteObjectPayload)
+ {
+ if (error) {
+ callback(null);
+ return;
+ }
+
+ let remoteObject = WebInspector.RemoteObject.fromPayload(documentRemoteObjectPayload);
+ remoteObject.pushNodeToFrontend(documentNodeAvailable.bind(null, remoteObject));
+ }
+
+ function documentNodeAvailable(remoteObject, documentNodeId)
+ {
+ remoteObject.release();
+
+ if (!documentNodeId) {
+ callback(null);
+ return;
+ }
+
+ DOMAgent.querySelector(documentNodeId, "body", bodyNodeAvailable);
+ }
+
+ function bodyNodeAvailable(error, bodyNodeId)
+ {
+ if (error) {
+ console.error(error);
+ callback(null);
+ return;
+ }
+
+ let selector = ""; // Intentionally empty.
+ CSSAgent.addRule(bodyNodeId, selector, cssRuleAvailable);
+ }
+
+ function cssRuleAvailable(error, payload)
+ {
+ if (error || !payload.ruleId) {
+ callback(null);
+ return;
+ }
+
+ let styleSheetId = payload.ruleId.styleSheetId;
+ let styleSheet = WebInspector.cssStyleManager.styleSheetForIdentifier(styleSheetId);
+ if (!styleSheet) {
+ callback(null);
+ return;
+ }
+
+ styleSheet[WebInspector.CSSStyleManager.PreferredInspectorStyleSheetSymbol] = true;
+
+ console.assert(styleSheet.isInspectorStyleSheet());
+ console.assert(styleSheet.parentFrame === frame);
+
+ callback(styleSheet);
+ }
+ }
+
</ins><span class="cx"> // Protected
</span><span class="cx">
</span><span class="cx"> mediaQueryResultChanged()
</span><span class="lines">@@ -216,6 +302,18 @@
</span><span class="cx">
</span><span class="cx"> // Private
</span><span class="cx">
</span><ins>+ _inspectorStyleSheetsForFrame(frame)
+ {
+ let styleSheets = [];
+
+ for (let styleSheet of this.styleSheets) {
+ if (styleSheet.isInspectorStyleSheet() && styleSheet.parentFrame === frame)
+ styleSheets.push(styleSheet);
+ }
+
+ return styleSheets;
+ }
+
</ins><span class="cx"> _nodePseudoClassesDidChange(event)
</span><span class="cx"> {
</span><span class="cx"> var node = event.target;
</span><span class="lines">@@ -443,3 +541,4 @@
</span><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> WebInspector.CSSStyleManager.ForceablePseudoClasses = ["active", "focus", "hover", "visited"];
</span><ins>+WebInspector.CSSStyleManager.PreferredInspectorStyleSheetSymbol = Symbol("css-style-manager-preferred-inspector-stylesheet");
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsCSSStyleSheetjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/CSSStyleSheet.js (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/CSSStyleSheet.js        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/CSSStyleSheet.js        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -112,6 +112,11 @@
</span><span class="cx"> return this._hasInfo;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ isInspectorStyleSheet()
+ {
+ return this._origin === WebInspector.CSSStyleSheet.Type.Inspector;
+ }
+
</ins><span class="cx"> isInlineStyleTag()
</span><span class="cx"> {
</span><span class="cx"> return this._inlineStyleTag;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsDOMNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -128,6 +128,18 @@
</span><span class="cx">
</span><span class="cx"> // Public
</span><span class="cx">
</span><ins>+ get frameIdentifier()
+ {
+ return this._frameIdentifier || this.ownerDocument.frameIdentifier;
+ }
+
+ get frame()
+ {
+ if (!this._frame)
+ this._frame = WebInspector.frameResourceManager.frameForIdentifier(this.frameIdentifier);
+ return this._frame;
+ }
+
</ins><span class="cx"> get children()
</span><span class="cx"> {
</span><span class="cx"> if (!this._children)
</span><span class="lines">@@ -643,11 +655,6 @@
</span><span class="cx"> callback.apply(null, arguments);
</span><span class="cx"> };
</span><span class="cx"> }
</span><del>-
- get frameIdentifier()
- {
- return this._frameIdentifier;
- }
</del><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> WebInspector.DOMNode.Event = {
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsDOMNodeStylesjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/DOMNodeStyles.js (189103 => 189104)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/DOMNodeStyles.js        2015-08-28 17:52:35 UTC (rev 189103)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/DOMNodeStyles.js        2015-08-28 17:59:27 UTC (rev 189104)
</span><span class="lines">@@ -235,9 +235,20 @@
</span><span class="cx"> this.refresh();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- var selector = this._node.appropriateSelectorFor(true);
</del><ins>+ let selector = this._node.appropriateSelectorFor(true);
</ins><span class="cx">
</span><del>- CSSAgent.addRule.invoke({contextNodeId: this._node.id, selector}, addedRule.bind(this));
</del><ins>+ // COMPATIBILITY (iOS 9): Before CSS.createStyleSheet, CSS.addRule could be called with a contextNode.
+ if (!CSSAgent.createStyleSheet) {
+ CSSAgent.addRule.invoke({contextNodeId: this._node.id , selector}, addedRule.bind(this));
+ return;
+ }
+
+ function inspectorStyleSheetAvailable(styleSheet)
+ {
+ CSSAgent.addRule(styleSheet.id, selector, addedRule.bind(this));
+ }
+
+ WebInspector.cssStyleManager.preferredInspectorStyleSheetForFrame(this._node.frame, inspectorStyleSheetAvailable.bind(this));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> addRuleWithSelector(selector)
</span></span></pre>
</div>
</div>
</body>
</html>