Bug 1544359 - Fixed report site issue extension: added marfeel and mobify support, fixed labels being passed to the server. r=twisniewski,Gijs, a=jcristau
authorksenia <kberezina@mozilla.com>
Sat, 01 Jun 2019 19:13:26 +0000
changeset 537030 87f1246a1c3dbac25673d8b84ca55ec70932b5b8
parent 537029 ac99437a9c7a2b334e8201098170b7766c10bd13
child 537031 01f0e8d1402c59cd01a65ae644f380081d8a0b36
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstwisniewski, Gijs, jcristau
bugs1544359
milestone68.0
Bug 1544359 - Fixed report site issue extension: added marfeel and mobify support, fixed labels being passed to the server. r=twisniewski,Gijs, a=jcristau Fixed report site issue: added marfeel and mobify support, fixed labels being passed to the server Differential Revision: https://phabricator.services.mozilla.com/D33018
browser/extensions/report-site-issue/background.js
browser/extensions/report-site-issue/test/browser/browser.ini
browser/extensions/report-site-issue/test/browser/browser_report_site_issue.js
browser/extensions/report-site-issue/test/browser/fastclick.html
browser/extensions/report-site-issue/test/browser/fastclick1.html
browser/extensions/report-site-issue/test/browser/fastclick2.html
browser/extensions/report-site-issue/test/browser/frameworks.html
browser/extensions/report-site-issue/test/browser/head.js
browser/extensions/report-site-issue/test/browser/webcompat.html
mobile/android/extensions/report-site-issue/background.js
--- a/browser/extensions/report-site-issue/background.js
+++ b/browser/extensions/report-site-issue/background.js
@@ -10,16 +10,18 @@ const Config = {
   newIssueEndpoint: "https://webcompat.com/issues/new",
   newIssueEndpointPref: "newIssueEndpoint",
   screenshotFormat: {
     format: "jpeg",
     quality: 75,
   },
 };
 
+const FRAMEWORK_KEYS = ["hasFastClick", "hasMobify", "hasMarfeel"];
+
 browser.pageActionExtras.setLabelForHistogram("webcompat");
 
 browser.pageAction.onClicked.addListener(tab => {
   return getWebCompatInfoForTab(tab).then(
     info => {
       return openWebCompatTab(info);
     },
     err => {
@@ -56,53 +58,77 @@ function hasFastClickPageScript() {
       }
     } catch (_) {
     }
   }
 
   return false;
 }
 
-function checkForFastClick(tabId) {
+function hasMobifyPageScript() {
+  const win = window.wrappedJSObject;
+  return !!(win.Mobify && win.Mobify.Tag);
+}
+
+function hasMarfeelPageScript() {
+  const win = window.wrappedJSObject;
+  return !!win.marfeel;
+}
+
+function checkForFrameworks(tabId) {
   return browser.tabs.executeScript(tabId, {
-    code: `${hasFastClickPageScript};hasFastClickPageScript()`,
-  }).then(([hasFastClick]) => hasFastClick).catch(() => false);
+    code: `
+      (function() {
+        ${hasFastClickPageScript};
+        ${hasMobifyPageScript};
+        ${hasMarfeelPageScript};
+        
+        const result = {
+          hasFastClick: hasFastClickPageScript(),
+          hasMobify: hasMobifyPageScript(),
+          hasMarfeel: hasMarfeelPageScript(),
+        }
+
+        return result;
+      })();
+    `,
+  }).then(([results]) => results).catch(() => false);
 }
 
 function getWebCompatInfoForTab(tab) {
   const {id, url} = tab;
   return Promise.all([
     browser.browserInfo.getBlockList(),
     browser.browserInfo.getBuildID(),
     browser.browserInfo.getGraphicsPrefs(),
     browser.browserInfo.getUpdateChannel(),
     browser.browserInfo.hasTouchScreen(),
     browser.tabExtras.getWebcompatInfo(id),
-    checkForFastClick(id),
+    checkForFrameworks(id),
     browser.tabs.captureTab(id, Config.screenshotFormat).catch(e => {
       console.error("WebCompat Reporter: getting a screenshot failed", e);
       return Promise.resolve(undefined);
     }),
   ]).then(([blockList, buildID, graphicsPrefs, channel, hasTouchScreen,
-            frameInfo, hasFastClick, screenshot]) => {
+            frameInfo, frameworks, screenshot]) => {
     if (channel !== "linux") {
       delete graphicsPrefs["layers.acceleration.force-enabled"];
     }
 
     const consoleLog = frameInfo.log;
     delete frameInfo.log;
 
     return Object.assign(frameInfo, {
       tabId: id,
       blockList,
       details: Object.assign(graphicsPrefs, {
         buildID,
         channel,
         consoleLog,
-        hasFastClick,
+        frameworks,
         hasTouchScreen,
         "mixed active content blocked": frameInfo.hasMixedActiveContentBlocked,
         "mixed passive content blocked": frameInfo.hasMixedDisplayContentBlocked,
         "tracking content blocked": frameInfo.hasTrackingContentBlocked ?
                                     `true (${blockList})` : "false",
       }),
       screenshot,
       url,
@@ -125,28 +151,32 @@ async function openWebCompatTab(compatIn
   const url = new URL(Config.newIssueEndpoint);
   const {details} = compatInfo;
   const params = {
     url: `${compatInfo.url}`,
     utm_source: "desktop-reporter",
     utm_campaign: "report-site-issue-button",
     src: "desktop-reporter",
     details,
-    label: [],
+    extra_labels: [],
   };
-  if (details.hasFastClick) {
-    params.label.push("type-fastclick");
-  } else {
-    delete details.hasFastClick;
+
+  for (let framework of FRAMEWORK_KEYS) {
+    if (details.frameworks[framework]) {
+      params.details[framework] = true;
+      params.extra_labels.push(framework.replace(/^has/, "type-").toLowerCase());
+    }
   }
+  delete details.frameworks;
+
   if (details["gfx.webrender.all"] || details["gfx.webrender.enabled"]) {
-    params.label.push("type-webrender-enabled");
+    params.extra_labels.push("type-webrender-enabled");
   }
   if (compatInfo.hasTrackingContentBlocked) {
-    params.label.push(`type-tracking-protection-${compatInfo.blockList}`);
+    params.extra_labels.push(`type-tracking-protection-${compatInfo.blockList}`);
   }
 
   const tab = await browser.tabs.create({url: "about:blank"});
   const json = stripNonASCIIChars(JSON.stringify(params));
   await browser.tabExtras.loadURIWithPostData(tab.id, url.href, json,
                                               "application/json");
   await browser.tabs.executeScript(tab.id, {
     runAt: "document_end",
--- a/browser/extensions/report-site-issue/test/browser/browser.ini
+++ b/browser/extensions/report-site-issue/test/browser/browser.ini
@@ -1,11 +1,11 @@
 [DEFAULT]
 support-files =
-  fastclick1.html
-  fastclick2.html
+  frameworks.html
+  fastclick.html
   head.js
   test.html
   webcompat.html
 
 [browser_disabled_cleanup.js]
 [browser_button_state.js]
 [browser_report_site_issue.js]
--- a/browser/extensions/report-site-issue/test/browser/browser_report_site_issue.js
+++ b/browser/extensions/report-site-issue/test/browser/browser_report_site_issue.js
@@ -74,16 +74,18 @@ add_task(async function test_opened_page
     ok(Array.isArray(details.consoleLog), "Details has a consoleLog array.");
     ok(details.consoleLog[0].match(/console\.log\(null\)[\s\S]*test.html:\d+:\d+/m), "Can handle degenerate console logs");
     ok(details.consoleLog[1].match(/console\.error\(colored message\)[\s\S]*test.html:\d+:\d+/m), "Can handle fancy console logs");
     ok(details.consoleLog[2].match(/document\.access is undefined[\s\S]*test.html:\d+:\d+/m), "Script errors are logged");
     ok(typeof details.buildID == "string", "Details has a buildID string.");
     ok(typeof details.channel == "string", "Details has a channel string.");
     ok(typeof details.hasTouchScreen == "boolean", "Details has a hasTouchScreen flag.");
     ok(typeof details.hasFastClick == "undefined", "Details does not have FastClick if not found.");
+    ok(typeof details.hasMobify == "undefined", "Details does not have Mobify if not found.");
+    ok(typeof details.hasMarfeel == "undefined", "Details does not have Marfeel if not found.");
     ok(typeof details["mixed active content blocked"] == "boolean", "Details has a mixed active content blocked flag.");
     ok(typeof details["mixed passive content blocked"] == "boolean", "Details has a mixed passive content blocked flag.");
     ok(typeof details["tracking content blocked"] == "string", "Details has a tracking content blocked string.");
     ok(typeof details["gfx.webrender.all"] == "boolean", "Details has gfx.webrender.all.");
     ok(typeof details["gfx.webrender.blob-images"] == "boolean", "Details has gfx.webrender.blob-images.");
     ok(typeof details["gfx.webrender.enabled"] == "boolean", "Details has gfx.webrender.enabled.");
     ok(typeof details["image.mem.shared"] == "boolean", "Details has image.mem.shared.");
 
@@ -93,39 +95,59 @@ add_task(async function test_opened_page
     ok(bgUrl.startsWith("data:image/jpeg;base64,"), "A jpeg screenshot was successfully postMessaged");
     await isGreen(bgUrl);
   });
 
   BrowserTestUtils.removeTab(tab2);
   BrowserTestUtils.removeTab(tab1);
 });
 
-add_task(async function test_fastclick_detection1() {
-  let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, FASTCLICK_TEST_PAGE1);
+add_task(async function test_framework_detection() {
+  let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, FRAMEWORKS_TEST_PAGE);
+  let tab2 = await clickToReportAndAwaitReportTabLoad();
+
+  await ContentTask.spawn(tab2.linkedBrowser, {}, async function(args) {
+    let doc = content.document;
+    let detailsParam = doc.getElementById("details").innerText;
+    const details = JSON.parse(detailsParam);
+    ok(typeof details == "object", "Details param is a stringified JSON object.");
+    is(details.hasFastClick, true, "FastClick was found.");
+    is(details.hasMobify, true, "Mobify was found.");
+    is(details.hasMarfeel, true, "Marfeel was found.");
+  });
+
+  BrowserTestUtils.removeTab(tab2);
+  BrowserTestUtils.removeTab(tab1);
+});
+
+add_task(async function test_fastclick_detection() {
+  let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, FASTCLICK_TEST_PAGE);
   let tab2 = await clickToReportAndAwaitReportTabLoad();
 
   await ContentTask.spawn(tab2.linkedBrowser, {}, async function(args) {
     let doc = content.document;
     let detailsParam = doc.getElementById("details").innerText;
     const details = JSON.parse(detailsParam);
     ok(typeof details == "object", "Details param is a stringified JSON object.");
     is(details.hasFastClick, true, "FastClick was found.");
   });
 
   BrowserTestUtils.removeTab(tab2);
   BrowserTestUtils.removeTab(tab1);
 });
 
-add_task(async function test_fastclick_detection2() {
-  let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, FASTCLICK_TEST_PAGE2);
+add_task(async function test_framework_label() {
+  let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, FRAMEWORKS_TEST_PAGE);
   let tab2 = await clickToReportAndAwaitReportTabLoad();
 
   await ContentTask.spawn(tab2.linkedBrowser, {}, async function(args) {
     let doc = content.document;
-    let detailsParam = doc.getElementById("details").innerText;
-    const details = JSON.parse(detailsParam);
-    ok(typeof details == "object", "Details param is a stringified JSON object.");
-    is(details.hasFastClick, true, "FastClick was found.");
+    let labelParam = doc.getElementById("label").innerText;
+    const label = JSON.parse(labelParam);
+    ok(typeof label == "object", "Label param is a stringified JSON object.");
+    is(label.includes("type-fastclick"), true, "FastClick was found.");
+    is(label.includes("type-mobify"), true, "Mobify was found.");
+    is(label.includes("type-marfeel"), true, "Marfeel was found.");
   });
 
   BrowserTestUtils.removeTab(tab2);
   BrowserTestUtils.removeTab(tab1);
 });
rename from browser/extensions/report-site-issue/test/browser/fastclick2.html
rename to browser/extensions/report-site-issue/test/browser/fastclick.html
rename from browser/extensions/report-site-issue/test/browser/fastclick1.html
rename to browser/extensions/report-site-issue/test/browser/frameworks.html
--- a/browser/extensions/report-site-issue/test/browser/fastclick1.html
+++ b/browser/extensions/report-site-issue/test/browser/frameworks.html
@@ -1,6 +1,8 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <script>
   "use strict";
   function FastClick() {}
+  function marfeel() {}
+  var Mobify = {Tag: "something"};
 </script>
--- a/browser/extensions/report-site-issue/test/browser/head.js
+++ b/browser/extensions/report-site-issue/test/browser/head.js
@@ -5,18 +5,18 @@ ChromeUtils.defineModuleGetter(this, "Ad
 
 const {Management} = ChromeUtils.import("resource://gre/modules/Extension.jsm", null);
 
 const PREF_WC_REPORTER_ENABLED = "extensions.webcompat-reporter.enabled";
 const PREF_WC_REPORTER_ENDPOINT = "extensions.webcompat-reporter.newIssueEndpoint";
 
 const TEST_ROOT = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
 const TEST_PAGE = TEST_ROOT + "test.html";
-const FASTCLICK_TEST_PAGE1 = TEST_ROOT + "fastclick1.html";
-const FASTCLICK_TEST_PAGE2 = TEST_ROOT + "fastclick2.html";
+const FRAMEWORKS_TEST_PAGE = TEST_ROOT + "frameworks.html";
+const FASTCLICK_TEST_PAGE = TEST_ROOT + "fastclick.html";
 const NEW_ISSUE_PAGE = TEST_ROOT + "webcompat.html";
 
 const WC_ADDON_ID = "webcompat-reporter@mozilla.org";
 
 const WC_PAGE_ACTION_ID = "webcompat-reporter_mozilla_org";
 const WC_PAGE_ACTION_PANEL_ID = "pageAction-panel-webcompat-reporter_mozilla_org";
 const WC_PAGE_ACTION_URLBAR_ID = "pageAction-urlbar-webcompat-reporter_mozilla_org";
 
@@ -181,16 +181,18 @@ async function startIssueServer() {
   });
 
   server.registerPathHandler("/new", function(request, response) {
     response.setHeader("Content-Type", "text/html", false);
     response.setStatusLine(request.httpVersion, 200, "OK");
     const postData = JSON.parse(getRequestData(request));
     const url = postData.url;
     const details = JSON.stringify(postData.details);
+    const label = JSON.stringify(postData.extra_labels);
     const output = landingTemplate.replace("$$URL$$", url)
-                                  .replace("$$DETAILS$$", details);
+                                  .replace("$$DETAILS$$", details)
+                                  .replace("$$LABEL$$", label);
     response.write(output);
   });
 
   server.start(-1);
   return `http://localhost:${server.identity.primaryPort}/new`;
 }
--- a/browser/extensions/report-site-issue/test/browser/webcompat.html
+++ b/browser/extensions/report-site-issue/test/browser/webcompat.html
@@ -1,15 +1,16 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <style>
  #screenshot-preview {width: 200px; height: 200px;}
 </style>
 <div id="url">$$URL$$</div>
 <div id="details">$$DETAILS$$</div>
+<div id="label">$$LABEL$$</div>
 <div id="screenshot-preview">Fail</div>
 <script>
 "use strict";
 let preview = document.getElementById("screenshot-preview");
 
 function getBlobAsDataURL(blob) {
   return new Promise((resolve, reject) => {
     let reader = new FileReader();
--- a/mobile/android/extensions/report-site-issue/background.js
+++ b/mobile/android/extensions/report-site-issue/background.js
@@ -10,16 +10,18 @@ const Config = {
   newIssueEndpoint: "https://webcompat.com/issues/new",
   newIssueEndpointPref: "newIssueEndpoint",
   screenshotFormat: {
     format: "jpeg",
     quality: 75,
   },
 };
 
+const FRAMEWORK_KEYS = ["hasFastClick", "hasMobify", "hasMarfeel"];
+
 // If parental controls are on, we don't activate (that is, we don't show our
 // menu item or prompt the user when they use "request desktop site".
 browser.browserInfo.getParentalControlsEnabled().then(enabled => {
   if (enabled) {
     return;
   }
 
   browser.aboutConfigPrefs.onEndpointPrefChange.addListener(checkEndpointPref);
@@ -124,53 +126,77 @@ function hasFastClickPageScript() {
       }
     } catch (_) {
     }
   }
 
   return false;
 }
 
-function checkForFastClick(tabId) {
+function hasMobifyPageScript() {
+  const win = window.wrappedJSObject;
+  return !!(win.Mobify && win.Mobify.Tag);
+}
+
+function hasMarfeelPageScript() {
+  const win = window.wrappedJSObject;
+  return !!win.marfeel;
+}
+
+function checkForFrameworks(tabId) {
   return browser.tabs.executeScript(tabId, {
-    code: `${hasFastClickPageScript};hasFastClickPageScript()`,
-  }).then(([hasFastClick]) => hasFastClick).catch(() => false);
+    code: `
+      (function() {
+        ${hasFastClickPageScript};
+        ${hasMobifyPageScript};
+        ${hasMarfeelPageScript};
+        
+        const result = {
+          hasFastClick: hasFastClickPageScript(),
+          hasMobify: hasMobifyPageScript(),
+          hasMarfeel: hasMarfeelPageScript(),
+        }
+
+        return result;
+      })();
+    `,
+  }).then(([results]) => results).catch(() => false);
 }
 
 function getWebCompatInfoForTab(tab) {
   const {id, windiwId, url} = tab;
   return Promise.all([
     browser.browserInfo.getBlockList(),
     browser.browserInfo.getBuildID(),
     browser.browserInfo.getGraphicsPrefs(),
     browser.browserInfo.getUpdateChannel(),
     browser.browserInfo.hasTouchScreen(),
     browser.tabExtras.getWebcompatInfo(id),
-    checkForFastClick(id),
+    checkForFrameworks(id),
     browser.tabs.captureVisibleTab(windiwId, Config.screenshotFormat).catch(e => {
       console.error("Report Site Issue: getting a screenshot failed", e);
       return Promise.resolve(undefined);
     }),
   ]).then(([blockList, buildID, graphicsPrefs, channel, hasTouchScreen,
-            frameInfo, hasFastClick, screenshot]) => {
+            frameInfo, frameworks, screenshot]) => {
     if (channel !== "linux") {
       delete graphicsPrefs["layers.acceleration.force-enabled"];
     }
 
     const consoleLog = frameInfo.log;
     delete frameInfo.log;
 
     return Object.assign(frameInfo, {
       tabId: id,
       blockList,
       details: Object.assign(graphicsPrefs, {
         buildID,
         channel,
         consoleLog,
-        hasFastClick,
+        frameworks,
         hasTouchScreen,
         "mixed active content blocked": frameInfo.hasMixedActiveContentBlocked,
         "mixed passive content blocked": frameInfo.hasMixedDisplayContentBlocked,
         "tracking content blocked": frameInfo.hasTrackingContentBlocked ?
                                     `true (${blockList})` : "false",
       }),
       screenshot,
       url,
@@ -187,28 +213,32 @@ async function openWebCompatTab(compatIn
   const url = new URL(Config.newIssueEndpoint);
   const {details} = compatInfo;
   const params = {
     url: `${compatInfo.url}`,
     utm_source: "mobile-reporter",
     utm_campaign: "report-site-issue-button",
     src: "mobile-reporter",
     details,
-    label: [],
+    extra_labels: [],
   };
-  if (details.hasFastClick) {
-    params.label.push("type-fastclick");
-  } else {
-    delete details.hasFastClick;
+
+  for (let framework of FRAMEWORK_KEYS) {
+    if (details.frameworks[framework]) {
+      params.details[framework] = true;
+      params.extra_labels.push(framework.replace(/^has/, "type-").toLowerCase());
+    }
   }
+  delete details.frameworks;
+
   if (details["gfx.webrender.all"] || details["gfx.webrender.enabled"]) {
-    params.label.push("type-webrender-enabled");
+    params.extra_labels.push("type-webrender-enabled");
   }
   if (compatInfo.hasTrackingContentBlocked) {
-    params.label.push(`type-tracking-protection-${compatInfo.blockList}`);
+    params.extra_labels.push(`type-tracking-protection-${compatInfo.blockList}`);
   }
 
   // Need custom API for private tabs until https://bugzil.la/1372178 is fixed
   const tab = usePrivateTab ? await browser.tabExtras.createPrivateTab() :
                               await browser.tabs.create({url: "about:blank"});
   const json = stripNonASCIIChars(JSON.stringify(params));
   await browser.tabExtras.loadURIWithPostData(tab.id, url.href, json,
                                               "application/json");