forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			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;
 | 
