csscoverage.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. "use strict";
  5. const { Cc, Ci } = require("chrome");
  6. const domtemplate = require("gcli/util/domtemplate");
  7. const csscoverage = require("devtools/shared/fronts/csscoverage");
  8. const l10n = csscoverage.l10n;
  9. loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
  10. loader.lazyImporter(this, "Chart", "resource://devtools/client/shared/widgets/Chart.jsm");
  11. /**
  12. * The commands/converters for GCLI
  13. */
  14. exports.items = [
  15. {
  16. name: "csscoverage",
  17. hidden: true,
  18. description: l10n.lookup("csscoverageDesc"),
  19. },
  20. {
  21. item: "command",
  22. runAt: "client",
  23. name: "csscoverage start",
  24. hidden: true,
  25. description: l10n.lookup("csscoverageStartDesc2"),
  26. params: [
  27. {
  28. name: "noreload",
  29. type: "boolean",
  30. description: l10n.lookup("csscoverageStartNoReloadDesc"),
  31. manual: l10n.lookup("csscoverageStartNoReloadManual")
  32. }
  33. ],
  34. exec: function*(args, context) {
  35. let usage = yield csscoverage.getUsage(context.environment.target);
  36. if (usage == null) {
  37. throw new Error(l10n.lookup("csscoverageNoRemoteError"));
  38. }
  39. yield usage.start(context.environment.chromeWindow,
  40. context.environment.target, args.noreload);
  41. }
  42. },
  43. {
  44. item: "command",
  45. runAt: "client",
  46. name: "csscoverage stop",
  47. hidden: true,
  48. description: l10n.lookup("csscoverageStopDesc2"),
  49. exec: function*(args, context) {
  50. let target = context.environment.target;
  51. let usage = yield csscoverage.getUsage(target);
  52. if (usage == null) {
  53. throw new Error(l10n.lookup("csscoverageNoRemoteError"));
  54. }
  55. yield usage.stop();
  56. yield gDevTools.showToolbox(target, "styleeditor");
  57. }
  58. },
  59. {
  60. item: "command",
  61. runAt: "client",
  62. name: "csscoverage oneshot",
  63. hidden: true,
  64. description: l10n.lookup("csscoverageOneShotDesc2"),
  65. exec: function*(args, context) {
  66. let target = context.environment.target;
  67. let usage = yield csscoverage.getUsage(target);
  68. if (usage == null) {
  69. throw new Error(l10n.lookup("csscoverageNoRemoteError"));
  70. }
  71. yield usage.oneshot();
  72. yield gDevTools.showToolbox(target, "styleeditor");
  73. }
  74. },
  75. {
  76. item: "command",
  77. runAt: "client",
  78. name: "csscoverage toggle",
  79. hidden: true,
  80. description: l10n.lookup("csscoverageToggleDesc2"),
  81. state: {
  82. isChecked: function(target) {
  83. return csscoverage.getUsage(target).then(usage => {
  84. return usage.isRunning();
  85. });
  86. },
  87. onChange: function(target, handler) {
  88. csscoverage.getUsage(target).then(usage => {
  89. this.handler = ev => { handler("state-change", ev); };
  90. usage.on("state-change", this.handler);
  91. });
  92. },
  93. offChange: function(target, handler) {
  94. csscoverage.getUsage(target).then(usage => {
  95. usage.off("state-change", this.handler);
  96. this.handler = undefined;
  97. });
  98. },
  99. },
  100. exec: function*(args, context) {
  101. let target = context.environment.target;
  102. let usage = yield csscoverage.getUsage(target);
  103. if (usage == null) {
  104. throw new Error(l10n.lookup("csscoverageNoRemoteError"));
  105. }
  106. yield usage.toggle(context.environment.chromeWindow,
  107. context.environment.target);
  108. }
  109. },
  110. {
  111. item: "command",
  112. runAt: "client",
  113. name: "csscoverage report",
  114. hidden: true,
  115. description: l10n.lookup("csscoverageReportDesc2"),
  116. exec: function*(args, context) {
  117. let usage = yield csscoverage.getUsage(context.environment.target);
  118. if (usage == null) {
  119. throw new Error(l10n.lookup("csscoverageNoRemoteError"));
  120. }
  121. return {
  122. isTypedData: true,
  123. type: "csscoveragePageReport",
  124. data: yield usage.createPageReport()
  125. };
  126. }
  127. },
  128. {
  129. item: "converter",
  130. from: "csscoveragePageReport",
  131. to: "dom",
  132. exec: function*(csscoveragePageReport, context) {
  133. let target = context.environment.target;
  134. let toolbox = yield gDevTools.showToolbox(target, "styleeditor");
  135. let panel = toolbox.getCurrentPanel();
  136. let host = panel._panelDoc.querySelector(".csscoverage-report");
  137. let templ = panel._panelDoc.querySelector(".csscoverage-template");
  138. templ = templ.cloneNode(true);
  139. templ.hidden = false;
  140. let data = {
  141. preload: csscoveragePageReport.preload,
  142. unused: csscoveragePageReport.unused,
  143. summary: csscoveragePageReport.summary,
  144. onback: () => {
  145. // The back button clears and hides .csscoverage-report
  146. while (host.hasChildNodes()) {
  147. host.removeChild(host.firstChild);
  148. }
  149. host.hidden = true;
  150. }
  151. };
  152. let addOnClick = rule => {
  153. rule.onclick = () => {
  154. panel.selectStyleSheet(rule.url, rule.start.line);
  155. };
  156. };
  157. data.preload.forEach(page => {
  158. page.rules.forEach(addOnClick);
  159. });
  160. data.unused.forEach(page => {
  161. page.rules.forEach(addOnClick);
  162. });
  163. let options = { allowEval: true, stack: "styleeditor.xul" };
  164. domtemplate.template(templ, data, options);
  165. while (templ.hasChildNodes()) {
  166. host.appendChild(templ.firstChild);
  167. }
  168. // Create a new chart.
  169. let container = host.querySelector(".csscoverage-report-chart");
  170. let chart = Chart.PieTable(panel._panelDoc, {
  171. diameter: 200, // px
  172. title: "CSS Usage",
  173. data: [
  174. { size: data.summary.preload, label: "Used Preload" },
  175. { size: data.summary.used, label: "Used" },
  176. { size: data.summary.unused, label: "Unused" }
  177. ]
  178. });
  179. container.appendChild(chart.node);
  180. host.hidden = false;
  181. }
  182. }
  183. ];