Bug 1265526 - Correctly categorize blob URLs and wasm frames as user content; r=julienw
authorGreg Tatum <tatum.creative@gmail.com>
Fri, 26 May 2017 18:07:56 -0500
changeset 410980 d218a8cbd8f7d2b8882b52e111a82646cbf999df
parent 410979 b9658a599512b6ab7ba24766bab946c4370f9979
child 410981 0529a8cb549c58cb886ee0725db3a36b2430ae40
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjulienw
bugs1265526
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1265526 - Correctly categorize blob URLs and wasm frames as user content; r=julienw asm.js and wasm frames were not being correctly identified as user content in the perf devtool. This patch correctly finds blob urls that were being mis-identified as platform content, and wasm frames, which do not have any identifying information other than their function name containing wasm-function. MozReview-Commit-ID: 4DjqATCKBK0
devtools/client/performance/modules/logic/frame-utils.js
devtools/client/shared/source-utils.js
devtools/client/shared/test/unit/test_source-utils.js
--- a/devtools/client/performance/modules/logic/frame-utils.js
+++ b/devtools/client/performance/modules/logic/frame-utils.js
@@ -1,17 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 const global = require("devtools/client/performance/modules/global");
 const demangle = require("devtools/client/shared/demangle");
 const { assert } = require("devtools/shared/DevToolsUtils");
-const { isChromeScheme, isContentScheme, parseURL } =
+const { isChromeScheme, isContentScheme, isWASM, parseURL } =
   require("devtools/client/shared/source-utils");
 
 const { CATEGORY_MASK, CATEGORY_MAPPINGS } = require("devtools/client/performance/modules/categories");
 
 // Character codes used in various parsing helper functions.
 const CHAR_CODE_R = "r".charCodeAt(0);
 const CHAR_CODE_0 = "0".charCodeAt(0);
 const CHAR_CODE_9 = "9".charCodeAt(0);
@@ -216,17 +216,19 @@ function computeIsContentAndCategory(fra
         break;
       }
     }
   } else {
     // Cases 2) and 3)
     schemeStartIndex = 0;
   }
 
-  if (isContentScheme(location, schemeStartIndex)) {
+  // We can't know if WASM frames are content or not at the time of this writing, so label
+  // them all as content.
+  if (isContentScheme(location, schemeStartIndex) || isWASM(location)) {
     frame.isContent = true;
     return;
   }
 
   if (schemeStartIndex !== 0) {
     for (let j = schemeStartIndex; j < location.length; j++) {
       if (location.charCodeAt(j) === CHAR_CODE_R &&
           isChromeScheme(location, j) &&
--- a/devtools/client/shared/source-utils.js
+++ b/devtools/client/shared/source-utils.js
@@ -5,32 +5,37 @@
 
 const { LocalizationHelper } = require("devtools/shared/l10n");
 
 const l10n = new LocalizationHelper("devtools/client/locales/components.properties");
 const UNKNOWN_SOURCE_STRING = l10n.getStr("frame.unknownSource");
 
 // Character codes used in various parsing helper functions.
 const CHAR_CODE_A = "a".charCodeAt(0);
+const CHAR_CODE_B = "b".charCodeAt(0);
 const CHAR_CODE_C = "c".charCodeAt(0);
 const CHAR_CODE_D = "d".charCodeAt(0);
 const CHAR_CODE_E = "e".charCodeAt(0);
 const CHAR_CODE_F = "f".charCodeAt(0);
 const CHAR_CODE_H = "h".charCodeAt(0);
 const CHAR_CODE_I = "i".charCodeAt(0);
 const CHAR_CODE_J = "j".charCodeAt(0);
 const CHAR_CODE_L = "l".charCodeAt(0);
 const CHAR_CODE_M = "m".charCodeAt(0);
+const CHAR_CODE_N = "n".charCodeAt(0);
 const CHAR_CODE_O = "o".charCodeAt(0);
 const CHAR_CODE_P = "p".charCodeAt(0);
 const CHAR_CODE_R = "r".charCodeAt(0);
 const CHAR_CODE_S = "s".charCodeAt(0);
 const CHAR_CODE_T = "t".charCodeAt(0);
 const CHAR_CODE_U = "u".charCodeAt(0);
+const CHAR_CODE_W = "w".charCodeAt(0);
 const CHAR_CODE_COLON = ":".charCodeAt(0);
+const CHAR_CODE_DASH = "-".charCodeAt(0);
+const CHAR_CODE_L_SQUARE_BRACKET = "[".charCodeAt(0);
 const CHAR_CODE_SLASH = "/".charCodeAt(0);
 const CHAR_CODE_CAP_S = "S".charCodeAt(0);
 
 // The cache used in the `parseURL` function.
 const gURLStore = new Map();
 // The cache used in the `getSourceNames` function.
 const gSourceNamesStore = new Map();
 
@@ -243,16 +248,28 @@ function isContentScheme(location, i = 0
     // "app://"
     case CHAR_CODE_A:
       if (location.charCodeAt(++i) == CHAR_CODE_P &&
           location.charCodeAt(++i) == CHAR_CODE_P) {
         return isColonSlashSlash(location, i);
       }
       return false;
 
+    // "blob:"
+    case CHAR_CODE_B:
+      if (
+        location.charCodeAt(++i) == CHAR_CODE_L &&
+        location.charCodeAt(++i) == CHAR_CODE_O &&
+        location.charCodeAt(++i) == CHAR_CODE_B &&
+        location.charCodeAt(++i) == CHAR_CODE_COLON
+      ) {
+        return isContentScheme(location, i + 1);
+      }
+      return false;
+
     default:
       return false;
   }
 }
 
 function isChromeScheme(location, i = 0) {
   let firstChar = location.charCodeAt(i);
 
@@ -294,16 +311,36 @@ function isChromeScheme(location, i = 0)
       }
       return false;
 
     default:
       return false;
   }
 }
 
+function isWASM(location, i = 0) {
+  return (
+    // "wasm-function["
+    location.charCodeAt(i) === CHAR_CODE_W &&
+    location.charCodeAt(++i) === CHAR_CODE_A &&
+    location.charCodeAt(++i) === CHAR_CODE_S &&
+    location.charCodeAt(++i) === CHAR_CODE_M &&
+    location.charCodeAt(++i) === CHAR_CODE_DASH &&
+    location.charCodeAt(++i) === CHAR_CODE_F &&
+    location.charCodeAt(++i) === CHAR_CODE_U &&
+    location.charCodeAt(++i) === CHAR_CODE_N &&
+    location.charCodeAt(++i) === CHAR_CODE_C &&
+    location.charCodeAt(++i) === CHAR_CODE_T &&
+    location.charCodeAt(++i) === CHAR_CODE_I &&
+    location.charCodeAt(++i) === CHAR_CODE_O &&
+    location.charCodeAt(++i) === CHAR_CODE_N &&
+    location.charCodeAt(++i) === CHAR_CODE_L_SQUARE_BRACKET
+  );
+}
+
 /**
  * A utility method to get the file name from a sourcemapped location
  * The sourcemap location can be in any form. This method returns a
  * formatted file name for different cases like Windows or OSX.
  * @param source
  * @returns String
  */
 function getSourceMappedFile(source) {
@@ -319,10 +356,11 @@ function getSourceMappedFile(source) {
   return source;
 }
 
 exports.parseURL = parseURL;
 exports.getSourceNames = getSourceNames;
 exports.isScratchpadScheme = isScratchpadScheme;
 exports.isChromeScheme = isChromeScheme;
 exports.isContentScheme = isContentScheme;
+exports.isWASM = isWASM;
 exports.isDataScheme = isDataScheme;
 exports.getSourceMappedFile = getSourceMappedFile;
--- a/devtools/client/shared/test/unit/test_source-utils.js
+++ b/devtools/client/shared/test/unit/test_source-utils.js
@@ -14,17 +14,18 @@ function run_test() {
   run_next_test();
 }
 
 const CHROME_URLS = [
   "chrome://foo", "resource://baz", "jar:file:///Users/root"
 ];
 
 const CONTENT_URLS = [
-  "http://mozilla.org", "https://mozilla.org", "file:///Users/root", "app://fxosapp"
+  "http://mozilla.org", "https://mozilla.org", "file:///Users/root", "app://fxosapp",
+  "blob:http://mozilla.org", "blob:https://mozilla.org"
 ];
 
 // Test `sourceUtils.parseURL`
 add_task(function* () {
   let parsed = sourceUtils.parseURL("https://foo.com:8888/boo/bar.js?q=query");
   equal(parsed.fileName, "bar.js", "parseURL parsed valid fileName");
   equal(parsed.host, "foo.com:8888", "parseURL parsed valid host");
   equal(parsed.hostname, "foo.com", "parseURL parsed valid hostname");
@@ -56,16 +57,23 @@ add_task(function* () {
     ok(sourceUtils.isChromeScheme(url), `${url} correctly identified as chrome scheme`);
   }
   for (let url of CONTENT_URLS) {
     ok(!sourceUtils.isChromeScheme(url),
        `${url} correctly identified as not chrome scheme`);
   }
 });
 
+// Test `sourceUtils.isWASM`.
+add_task(function* () {
+  ok(sourceUtils.isWASM("wasm-function[66240] (?:13870536)"),
+                        "wasm function correctly identified");
+  ok(!sourceUtils.isWASM(CHROME_URLS[0]), `A chrome url does not identify as wasm.`);
+});
+
 // Test `sourceUtils.isDataScheme`.
 add_task(function* () {
   let dataURI = "data:text/html;charset=utf-8,<!DOCTYPE html></html>";
   ok(sourceUtils.isDataScheme(dataURI), `${dataURI} correctly identified as data scheme`);
 
   for (let url of CHROME_URLS) {
     ok(!sourceUtils.isDataScheme(url), `${url} correctly identified as not data scheme`);
   }