<commit_before>"use strict";

const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/NetUtil.jsm");

function dumpln(s) { dump(s + "\n"); }


/*****************
 * API INJECTION *
 *****************/

// Based on:
// https://bug549539.bugzilla.mozilla.org/attachment.cgi?id=429661
// https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_1.9.3
// http://mxr.mozilla.org/mozilla-central/source/toolkit/components/console/hudservice/HUDService.jsm#3240
// https://developer.mozilla.org/en/how_to_build_an_xpcom_component_in_javascript

function DOMFuzzHelper() {}

// Use runSoon to avoid false-positive leaks due to content JS on the stack (?)
function quitFromContent() { dumpln("Page called quitApplication."); runSoon(goQuitApplication); }
function quitApplicationSoon() { dumpln("Page called quitApplicationSoon."); runOnTimer(goQuitApplication); }

DOMFuzzHelper.prototype = {
  classDescription: "DOM fuzz helper",
  classID:          Components.ID("{59a52458-13e0-4d90-9d85-a637344f29a1}"),
  contractID:       "@squarefree.com/dom-fuzz-helper;1",

  QueryInterface:   XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer]),

  init: function(aWindow)
  {
    // Using bind(this) to ensure web page gets a *copy* of the function (is this necessary?)

    var api = {
      quitApplication:     quitFromContent.bind(this),
      quitApplicationSoon: quitApplicationSoon.bind(this),
      closeTabThenQuit:    closeTabThenQuit(aWindow),
      quitWithLeakCheck:   quitWithLeakCheck.bind(this),
      setGCZeal:           setGCZeal.bind(this),
      runSoon:             runSoon.bind(this),
      enableAccessibility: enableAccessibility.bind(this),
      GC:                  function() { Components.utils.forceGC(); },
      MP:                  sendMemoryPressureNotification.bind(this),
      CC:                  cycleCollect(aWindow),
      fontList:            fontList.bind(this),
      // zoom:             setZoomLevel(aWindow), // bug 576927
      printToFile:         printToFile(aWindow),
      openAboutMemory:     openNewTab.bind(this, aWindow, "about:memory"),

      __exposedProps__: {
        quitApplication: "r",
        quitApplicationSoon: "r",
        closeTabThenQuit: "r",
        quitWithLeakCheck: "r",
        setGCZeal: "r",
        runSoon: "r",
        enableAccessibility: "r",
        GC: "r",
        MP: "r",
        CC: "r",
        fontList: "r",
        // zoom: "r",
        printToFile: "r",
        openAboutMemory: "r",
      }
    };

    return api;
  }
};

const NSGetFactory = XPCOMUtils.generateNSGetFactory([DOMFuzzHelper]);



/*****************************
 * MISC PRIVILEGED FUNCTIONS *
 *****************************/

function openNewTab(w, url)
{
  w.open(url);
}

function closeTabThenQuit(w)
{
  return function() {
    runOnTimer(goQuitApplication);
    w.close();
  }
}

function fontList()
{
  return Components.classes["@mozilla.org/gfx/fontenumerator;1"]
          .createInstance(Components.interfaces.nsIFontEnumerator)
          .EnumerateAllFonts({})
          .join("\n");
}

function runSoon(f)
{
  var tm = Components.classes["@mozilla.org/thread-manager;1"]
             .getService(Components.interfaces.nsIThreadManager);

  tm.mainThread.dispatch({
    run: function() {
      f();
    }
  }, Components.interfaces.nsIThread.DISPATCH_NORMAL);
}


function enableAccessibility()
{
  try {
    Components.classes["@mozilla.org/accessibilityService;1"]
      .getService(Components.interfaces.nsIAccessibleRetrieval);
    dump("Enabled accessibility!\n");
  } catch(e) {
    dump("Couldn't enable accessibility: " + e + "\n");
  }
}

function sendMemoryPressureNotification()
{
  var os = Components.classes["@mozilla.org/observer-service;1"]
           .getService(Components.interfaces.nsIObserverService);
  os.notifyObservers(null, "memory-pressure", "heap-minimize");
}

function cycleCollect(window)
{
  return function cycleCollectInner() {
    window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
          .getInterface(Components.interfaces.nsIDOMWindowUtils)
          .cycleCollect();
  }
}

function setZoomLevel(window)
{
  return function setZoomLevelInner(textOrFull, factor) {
    var viewer = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                       .getInterface(Components.interfaces.nsIWebNavigation)
                       .QueryInterface(Components.interfaces.nsIDocShell)
                       .contentViewer
                       .QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);

    if (textOrFull == "text")
      viewer.textZoom = +factor;
    else if (textOrFull == "full")
      viewer.fullZoom = +factor;
  }
}

function printToFile(window)
{
  // Oddly asynchronous, at least on Linux.

  // Linux: works for PDF and PS.
  // Windows: works for PDF at least. Text may be invisible (bug 653336).
  // Mac: tested, printToFile is ignored and it goes to a printer!
  var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"]
                             .getService(Components.interfaces.nsIXULRuntime);
  dumpln("xulRuntime.OS: " + xulRuntime.OS);
  if (xulRuntime.OS != "Linux" && xulRuntime.OS != "WINNT") return function() { };

  var fired = false;

  return function printToFileInner(showHeaders, showBGColor, showBGImages, ps) {
    runSoon(function() {
        // Don't print more than once, it gets messy fast.
        if (fired) { return false; }
        fired = true;

        // Based on https://addons.mozilla.org/en-US/firefox/addon/5971/ by pavlov (<NAME>) and bho

        var webBrowserPrint = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
        .getInterface(Components.interfaces.nsIWebBrowserPrint);

        var nsIPrintSettings = Components.interfaces.nsIPrintSettings;
<commit_msg>Add bug number to comment<commit_after>"use strict";

const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/NetUtil.jsm");

function dumpln(s) { dump(s + "\n"); }


/*****************
 * API INJECTION *
 *****************/

// Based on:
// https://bug549539.bugzilla.mozilla.org/attachment.cgi?id=429661
// https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_1.9.3
// http://mxr.mozilla.org/mozilla-central/source/toolkit/components/console/hudservice/HUDService.jsm#3240
// https://developer.mozilla.org/en/how_to_build_an_xpcom_component_in_javascript

function DOMFuzzHelper() {}

// Use runSoon to avoid false-positive leaks due to content JS on the stack (?)
function quitFromContent() { dumpln("Page called quitApplication."); runSoon(goQuitApplication); }
function quitApplicationSoon() { dumpln("Page called quitApplicationSoon."); runOnTimer(goQuitApplication); }

DOMFuzzHelper.prototype = {
  classDescription: "DOM fuzz helper",
  classID:          Components.ID("{59a52458-13e0-4d90-9d85-a637344f29a1}"),
  contractID:       "@squarefree.com/dom-fuzz-helper;1",

  QueryInterface:   XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer]),

  init: function(aWindow)
  {
    // Using bind(this) to ensure web page gets a *copy* of the function (is this necessary?)

    var api = {
      quitApplication:     quitFromContent.bind(this),
      quitApplicationSoon: quitApplicationSoon.bind(this),
      closeTabThenQuit:    closeTabThenQuit(aWindow),
      quitWithLeakCheck:   quitWithLeakCheck.bind(this),
      setGCZeal:           setGCZeal.bind(this),
      runSoon:             runSoon.bind(this),
      enableAccessibility: enableAccessibility.bind(this),
      GC:                  function() { Components.utils.forceGC(); },
      MP:                  sendMemoryPressureNotification.bind(this),
      CC:                  cycleCollect(aWindow),
      fontList:            fontList.bind(this),
      // zoom:             setZoomLevel(aWindow), // bug 576927
      printToFile:         printToFile(aWindow),
      openAboutMemory:     openNewTab.bind(this, aWindow, "about:memory"),

      __exposedProps__: {
        quitApplication: "r",
        quitApplicationSoon: "r",
        closeTabThenQuit: "r",
        quitWithLeakCheck: "r",
        setGCZeal: "r",
        runSoon: "r",
        enableAccessibility: "r",
        GC: "r",
        MP: "r",
        CC: "r",
        fontList: "r",
        // zoom: "r",
        printToFile: "r",
        openAboutMemory: "r",
      }
    };

    return api;
  }
};

const NSGetFactory = XPCOMUtils.generateNSGetFactory([DOMFuzzHelper]);



/*****************************
 * MISC PRIVILEGED FUNCTIONS *
 *****************************/

function openNewTab(w, url)
{
  w.open(url);
}

function closeTabThenQuit(w)
{
  return function() {
    runOnTimer(goQuitApplication);
    w.close();
  }
}

function fontList()
{
  return Components.classes["@mozilla.org/gfx/fontenumerator;1"]
          .createInstance(Components.interfaces.nsIFontEnumerator)
          .EnumerateAllFonts({})
          .join("\n");
}

function runSoon(f)
{
  var tm = Components.classes["@mozilla.org/thread-manager;1"]
             .getService(Components.interfaces.nsIThreadManager);

  tm.mainThread.dispatch({
    run: function() {
      f();
    }
  }, Components.interfaces.nsIThread.DISPATCH_NORMAL);
}


function enableAccessibility()
{
  try {
    Components.classes["@mozilla.org/accessibilityService;1"]
      .getService(Components.interfaces.nsIAccessibleRetrieval);
    dump("Enabled accessibility!\n");
  } catch(e) {
    dump("Couldn't enable accessibility: " + e + "\n");
  }
}

function sendMemoryPressureNotification()
{
  var os = Components.classes["@mozilla.org/observer-service;1"]
           .getService(Components.interfaces.nsIObserverService);
  os.notifyObservers(null, "memory-pressure", "heap-minimize");
}

function cycleCollect(window)
{
  return function cycleCollectInner() {
    window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
          .getInterface(Components.interfaces.nsIDOMWindowUtils)
          .cycleCollect();
  }
}

function setZoomLevel(window)
{
  return function setZoomLevelInner(textOrFull, factor) {
    var viewer = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                       .getInterface(Components.interfaces.nsIWebNavigation)
                       .QueryInterface(Components.interfaces.nsIDocShell)
                       .contentViewer
                       .QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);

    if (textOrFull == "text")
      viewer.textZoom = +factor;
    else if (textOrFull == "full")
      viewer.fullZoom = +factor;
  }
}

function printToFile(window)
{
  // Oddly asynchronous, at least on Linux.

  // Linux: works for PDF and PS.
  // Windows: works for PDF at least. Text may be invisible (bug 653336).
  // Mac: tested, printToFile is ignored and it goes to a printer! (bug 675709)
  var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"]
                             .getService(Components.interfaces.nsIXULRuntime);
  dumpln("xulRuntime.OS: " + xulRuntime.OS);
  if (xulRuntime.OS != "Linux" && xulRuntime.OS != "WINNT") return function() { };

  var fired = false;

  return function printToFileInner(showHeaders, showBGColor, showBGImages, ps) {
    runSoon(function() {
        // Don't print more than once, it gets messy fast.
        if (fired) { return false; }
        fired = true;

        // Based on https://addons.mozilla.org/en-US/firefox/addon/5971/ by pavlov (<NAME>) and bho

        var webBrowserPrint = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
        .getInterface(Components.interfaces.nsIWebBrowserPrint);

        var nsIPrintSettings = Components.interfaces.nsIPrintSettings;

{'fraction_non_alphanumeric': 0.138119262261186, 'fraction_numerical': 0.011413448019187826, 'mean_word_length': 3.1971537660534537, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 8, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '356578', 'n_tokens_mistral': 3919, 'n_tokens_neox': 3687, 'n_words': 656}