Bug 1263439 - Fix empty rules panel when stylesheet href is created with 'URL.createObjectURL' and has a data-uri sourcemap. r=pbro draft
authorNicolas Chevobbe <chevobbe.nicolas@gmail.com>
Sun, 10 Apr 2016 15:02:48 +0200
changeset 349834 cc9fb4d96e4d71a967646f017bd8a3ff3d383f23
parent 347695 71d3427c683190cdb409063ad67e24d5926f4591
child 518198 81531e3a3cd7620afda25014d8fc4243b16ac5f2
push id15192
push userchevobbe.nicolas@gmail.com
push dateTue, 12 Apr 2016 11:41:49 +0000
reviewerspbro
bugs1263439
milestone48.0a1
Bug 1263439 - Fix empty rules panel when stylesheet href is created with 'URL.createObjectURL' and has a data-uri sourcemap. r=pbro An error was thrown : ` Full Message: Component returned failure code: 0x804b000a (NS_ERROR_MALFORMED_URI) [nsIIOService.newURI] Full Stack: JS frame :: resource://gre/modules/commonjs/toolkit/loader.js -> resource://devtools/server/actors/stylesheets.js :: dirname :: line 1202 JS frame :: resource://gre/modules/commonjs/toolkit/loader.js -> resource://devtools/server/actors/stylesheets.js :: StyleSheetActor<._setSourceMapRoot :: line 806 JS frame :: resource://gre/modules/commonjs/toolkit/loader.js -> resource://devtools/server/actors/stylesheets.js :: StyleSheetActor<._fetchSourceMap/</map< :: line 779 ` Stripping out the "blob:" part of the safeUrl before calling the `dirname` function resolves the bug. MozReview-Commit-ID: 9uth6vyAR2u
devtools/client/inspector/rules/test/browser.ini
devtools/client/inspector/rules/test/browser_rules_blob_stylesheet.js
devtools/client/inspector/rules/test/doc_blob_stylesheet.html
devtools/server/actors/stylesheets.js
--- a/devtools/client/inspector/rules/test/browser.ini
+++ b/devtools/client/inspector/rules/test/browser.ini
@@ -1,13 +1,14 @@
 [DEFAULT]
 tags = devtools
 subsuite = devtools
 support-files =
   doc_author-sheet.html
+  doc_blob_stylesheet.html
   doc_content_stylesheet.html
   doc_content_stylesheet_imported.css
   doc_content_stylesheet_imported2.css
   doc_content_stylesheet_linked.css
   doc_content_stylesheet_script.css
   doc_copystyles.css
   doc_copystyles.html
   doc_cssom.html
@@ -50,16 +51,17 @@ support-files =
 [browser_rules_add-rule_02.js]
 [browser_rules_add-rule_03.js]
 [browser_rules_add-rule_04.js]
 [browser_rules_add-rule_05.js]
 [browser_rules_add-rule_pseudo_class.js]
 [browser_rules_authored.js]
 [browser_rules_authored_color.js]
 [browser_rules_authored_override.js]
+[browser_rules_blob_stylesheet.js]
 [browser_rules_colorpicker-and-image-tooltip_01.js]
 [browser_rules_colorpicker-and-image-tooltip_02.js]
 [browser_rules_colorpicker-appears-on-swatch-click.js]
 [browser_rules_colorpicker-commit-on-ENTER.js]
 [browser_rules_colorpicker-edit-gradient.js]
 [browser_rules_colorpicker-hides-on-tooltip.js]
 [browser_rules_colorpicker-multiple-changes.js]
 [browser_rules_colorpicker-release-outside-frame.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/rules/test/browser_rules_blob_stylesheet.js
@@ -0,0 +1,21 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the rule-view content is correct for stylesheet generated from
+// URL.createObjectURL(cssBlob)
+const TEST_URL = URL_ROOT + "doc_blob_stylesheet.html";
+
+add_task(function*() {
+  yield addTab(TEST_URL);
+  let {inspector, view} = yield openRuleView();
+
+  yield selectNode("h1", inspector);
+  is(view.element.querySelectorAll("#noResults").length, 0,
+    "The no-results element is not displayed.");
+
+  is(view.element.querySelectorAll(".ruleview-rule").length, 2,
+    "There are 2 displayed rules");
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/rules/test/doc_blob_stylesheet.html
@@ -0,0 +1,24 @@
+<head>
+  <title>Blob stylesheet sourcemap</title>
+</head>
+<body>
+<h1>Test</h1>
+<script>
+var cssContent = `body {
+  background-color: black;
+}
+body > h1 {
+  color: white;
+}
+/*# sourceMappingURL=data:application/json;base64,ewoidmVyc2lvbiI6IDMsCiJtYXBwaW5ncyI6ICJBQUFBLElBQUs7RUFDSCxnQkFBZ0IsRUFBRSxLQUFLOztBQUN2QixTQUFPO0VBQ0wsS0FBSyxFQUFFLEtBQUsiLAoic291cmNlcyI6IFsidGVzdC5zY3NzIl0sCiJzb3VyY2VzQ29udGVudCI6IFsiYm9keSB7XG4gIGJhY2tncm91bmQtY29sb3I6IGJsYWNrO1xuICAmID4gaDEge1xuICAgIGNvbG9yOiB3aGl0ZTsgIFxuICB9XG59XG4iXSwKIm5hbWVzIjogW10sCiJmaWxlIjogInRlc3QuY3NzIgp9Cg== */`;
+var cssBlob = new Blob([cssContent], {type: 'text/css'});
+var url = URL.createObjectURL(cssBlob);
+
+var head  = document.querySelector('head');
+var link  = document.createElement('link');
+link.rel  = 'stylesheet';
+link.type = 'text/css';
+link.href = url;
+head.appendChild(link);
+</script>
+</body>
--- a/devtools/server/actors/stylesheets.js
+++ b/devtools/server/actors/stylesheets.js
@@ -798,16 +798,19 @@ var StyleSheetActor = protocol.ActorClas
     }
     this._originalSources = null;
   },
 
   /**
    * Sets the source map's sourceRoot to be relative to the source map url.
    */
   _setSourceMapRoot: function(aSourceMap, aAbsSourceMapURL, aScriptURL) {
+    if (aScriptURL.startsWith("blob:")) {
+      aScriptURL = aScriptURL.replace("blob:", "");
+    }
     const base = dirname(
       aAbsSourceMapURL.startsWith("data:")
         ? aScriptURL
         : aAbsSourceMapURL);
     aSourceMap.sourceRoot = aSourceMap.sourceRoot
       ? normalize(aSourceMap.sourceRoot, base)
       : base;
   },