extensions-helper.js (3025B)
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 5 "use strict"; 6 7 const lazy = {}; 8 9 ChromeUtils.defineESModuleGetters(lazy, { 10 FileUtils: "resource://gre/modules/FileUtils.sys.mjs", 11 }); 12 13 const { 14 PREFERENCES, 15 } = require("resource://devtools/client/aboutdebugging/src/constants.js"); 16 17 exports.parseFileUri = function (url) { 18 // Strip a leading slash from Windows drive letter URIs. 19 // file:///home/foo ~> /home/foo 20 // file:///C:/foo ~> C:/foo 21 const windowsRegex = /^file:\/\/\/([a-zA-Z]:\/.*)/; 22 if (windowsRegex.test(url)) { 23 return windowsRegex.exec(url)[1]; 24 } 25 return url.slice("file://".length); 26 }; 27 28 exports.getExtensionUuid = function (extension) { 29 const { manifestURL } = extension; 30 // Strip off the protocol and rest, leaving us with just the UUID. 31 return manifestURL ? /moz-extension:\/\/([^/]*)/.exec(manifestURL)[1] : null; 32 }; 33 34 /** 35 * Open a file picker to allow the user to locate a temporary extension. A temporary 36 * extension can either be: 37 * - a folder 38 * - a .xpi file 39 * - a .zip file 40 * 41 * @param {Window} win 42 * The window object where the filepicker should be opened. 43 * Note: We cannot use the global window object here because it is undefined if 44 * this module is loaded from a file outside of devtools/client/aboutdebugging/. 45 * See browser-loader.sys.mjs `uri.startsWith(baseURI)` for more details. 46 * @param {string} message 47 * The help message that should be displayed to the user in the filepicker. 48 * @return {Promise} returns a promise that resolves a File object corresponding to the 49 * file selected by the user. 50 */ 51 exports.openTemporaryExtension = function (win, message) { 52 return new Promise(resolve => { 53 const fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); 54 fp.init(win.browsingContext, message, Ci.nsIFilePicker.modeOpen); 55 56 // Try to set the last directory used as "displayDirectory". 57 try { 58 const lastDirPath = Services.prefs.getCharPref( 59 PREFERENCES.TEMPORARY_EXTENSION_PATH, 60 "" 61 ); 62 const lastDir = new lazy.FileUtils.File(lastDirPath); 63 fp.displayDirectory = lastDir; 64 } catch (e) { 65 // Empty or invalid value, nothing to handle. 66 } 67 68 fp.open(res => { 69 if (res == Ci.nsIFilePicker.returnCancel || !fp.file) { 70 return; 71 } 72 let file = fp.file; 73 // AddonManager.installTemporaryAddon accepts either 74 // addon directory or final xpi file. 75 if ( 76 !file.isDirectory() && 77 !file.leafName.endsWith(".xpi") && 78 !file.leafName.endsWith(".zip") 79 ) { 80 file = file.parent; 81 } 82 83 // We are about to resolve, store the path to the file for the next call. 84 Services.prefs.setCharPref( 85 PREFERENCES.TEMPORARY_EXTENSION_PATH, 86 file.path 87 ); 88 89 resolve(file); 90 }); 91 }); 92 };