mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 02:09:05 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			163 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* 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/. */
 | 
						|
 | 
						|
/* globals global, browser, documentMetadata, util, uicontrol, ui, catcher */
 | 
						|
/* globals domainFromUrl, randomString, shot, blobConverters */
 | 
						|
 | 
						|
"use strict";
 | 
						|
 | 
						|
this.shooter = (function () {
 | 
						|
  // eslint-disable-line no-unused-vars
 | 
						|
  const exports = {};
 | 
						|
  const { AbstractShot } = shot;
 | 
						|
 | 
						|
  const RANDOM_STRING_LENGTH = 16;
 | 
						|
  let backend;
 | 
						|
  let shotObject;
 | 
						|
  const callBackground = global.callBackground;
 | 
						|
 | 
						|
  function regexpEscape(str) {
 | 
						|
    // http://stackoverflow.com/questions/3115150/how-to-escape-regular-expression-special-characters-using-javascript
 | 
						|
    return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
 | 
						|
  }
 | 
						|
 | 
						|
  function sanitizeError(data) {
 | 
						|
    const href = new RegExp(regexpEscape(window.location.href), "g");
 | 
						|
    const origin = new RegExp(
 | 
						|
      `${regexpEscape(window.location.origin)}[^ \t\n\r",>]*`,
 | 
						|
      "g"
 | 
						|
    );
 | 
						|
    const json = JSON.stringify(data)
 | 
						|
      .replace(href, "REDACTED_HREF")
 | 
						|
      .replace(origin, "REDACTED_URL");
 | 
						|
    const result = JSON.parse(json);
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  catcher.registerHandler(errorObj => {
 | 
						|
    callBackground("reportError", sanitizeError(errorObj));
 | 
						|
  });
 | 
						|
 | 
						|
  function hideUIFrame() {
 | 
						|
    ui.iframe.hide();
 | 
						|
    return Promise.resolve(null);
 | 
						|
  }
 | 
						|
 | 
						|
  function screenshotPage(dataUrl, selectedPos, type, screenshotTaskFn) {
 | 
						|
    let promise = Promise.resolve(dataUrl);
 | 
						|
 | 
						|
    if (!dataUrl) {
 | 
						|
      promise = callBackground(
 | 
						|
        "screenshotPage",
 | 
						|
        selectedPos.toJSON(),
 | 
						|
        type,
 | 
						|
        window.devicePixelRatio
 | 
						|
      );
 | 
						|
    }
 | 
						|
 | 
						|
    catcher.watchPromise(
 | 
						|
      promise.then(dataLoc => {
 | 
						|
        screenshotTaskFn(dataLoc);
 | 
						|
      })
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  exports.downloadShot = function (selectedPos, previewDataUrl, type) {
 | 
						|
    const shotPromise = previewDataUrl
 | 
						|
      ? Promise.resolve(previewDataUrl)
 | 
						|
      : hideUIFrame();
 | 
						|
    catcher.watchPromise(
 | 
						|
      shotPromise.then(dataUrl => {
 | 
						|
        screenshotPage(dataUrl, selectedPos, type, url => {
 | 
						|
          let typeFromDataUrl = blobConverters.getTypeFromDataUrl(url);
 | 
						|
          typeFromDataUrl = typeFromDataUrl
 | 
						|
            ? typeFromDataUrl.split("/", 2)[1]
 | 
						|
            : null;
 | 
						|
          shotObject.delAllClips();
 | 
						|
          shotObject.addClip({
 | 
						|
            createdDate: Date.now(),
 | 
						|
            image: {
 | 
						|
              url,
 | 
						|
              type: typeFromDataUrl,
 | 
						|
              location: selectedPos,
 | 
						|
            },
 | 
						|
          });
 | 
						|
          ui.triggerDownload(url, shotObject.filename);
 | 
						|
          uicontrol.deactivate();
 | 
						|
        });
 | 
						|
      })
 | 
						|
    );
 | 
						|
  };
 | 
						|
 | 
						|
  exports.preview = function (selectedPos, type) {
 | 
						|
    catcher.watchPromise(
 | 
						|
      hideUIFrame().then(dataUrl => {
 | 
						|
        screenshotPage(dataUrl, selectedPos, type, url => {
 | 
						|
          ui.iframe.usePreview();
 | 
						|
          ui.Preview.display(url);
 | 
						|
        });
 | 
						|
      })
 | 
						|
    );
 | 
						|
  };
 | 
						|
 | 
						|
  let copyInProgress = null;
 | 
						|
  exports.copyShot = function (selectedPos, previewDataUrl, type) {
 | 
						|
    // This is pretty slow. We'll ignore additional user triggered copy events
 | 
						|
    // while it is in progress.
 | 
						|
    if (copyInProgress) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    // A max of five seconds in case some error occurs.
 | 
						|
    copyInProgress = setTimeout(() => {
 | 
						|
      copyInProgress = null;
 | 
						|
    }, 5000);
 | 
						|
 | 
						|
    const unsetCopyInProgress = () => {
 | 
						|
      if (copyInProgress) {
 | 
						|
        clearTimeout(copyInProgress);
 | 
						|
        copyInProgress = null;
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const shotPromise = previewDataUrl
 | 
						|
      ? Promise.resolve(previewDataUrl)
 | 
						|
      : hideUIFrame();
 | 
						|
    catcher.watchPromise(
 | 
						|
      shotPromise.then(dataUrl => {
 | 
						|
        screenshotPage(dataUrl, selectedPos, type, url => {
 | 
						|
          const blob = blobConverters.dataUrlToBlob(url);
 | 
						|
          catcher.watchPromise(
 | 
						|
            callBackground("copyShotToClipboard", blob).then(() => {
 | 
						|
              uicontrol.deactivate();
 | 
						|
              unsetCopyInProgress();
 | 
						|
            }, unsetCopyInProgress)
 | 
						|
          );
 | 
						|
        });
 | 
						|
      })
 | 
						|
    );
 | 
						|
  };
 | 
						|
 | 
						|
  exports.sendEvent = function (...args) {
 | 
						|
    const maybeOptions = args[args.length - 1];
 | 
						|
 | 
						|
    if (typeof maybeOptions === "object") {
 | 
						|
      maybeOptions.incognito = browser.extension.inIncognitoContext;
 | 
						|
    } else {
 | 
						|
      args.push({ incognito: browser.extension.inIncognitoContext });
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  catcher.watchFunction(() => {
 | 
						|
    shotObject = new AbstractShot(
 | 
						|
      backend,
 | 
						|
      randomString(RANDOM_STRING_LENGTH) + "/" + domainFromUrl(location),
 | 
						|
      {
 | 
						|
        origin: shot.originFromUrl(location.href),
 | 
						|
      }
 | 
						|
    );
 | 
						|
    shotObject.update(documentMetadata());
 | 
						|
  })();
 | 
						|
 | 
						|
  return exports;
 | 
						|
})();
 | 
						|
null;
 |