diff options
Diffstat (limited to 'mobile/android/components/HelperAppDialog.js')
-rw-r--r-- | mobile/android/components/HelperAppDialog.js | 373 |
1 files changed, 0 insertions, 373 deletions
diff --git a/mobile/android/components/HelperAppDialog.js b/mobile/android/components/HelperAppDialog.js deleted file mode 100644 index f127fb0b3..000000000 --- a/mobile/android/components/HelperAppDialog.js +++ /dev/null @@ -1,373 +0,0 @@ -// -*- indent-tabs-mode: nil; js-indent-level: 2 -*- -/* 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 ContentAreaUtils */ - -const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - -const APK_MIME_TYPE = "application/vnd.android.package-archive"; - -const OMA_DOWNLOAD_DESCRIPTOR_MIME_TYPE = "application/vnd.oma.dd+xml"; -const OMA_DRM_MESSAGE_MIME = "application/vnd.oma.drm.message"; -const OMA_DRM_CONTENT_MIME = "application/vnd.oma.drm.content"; -const OMA_DRM_RIGHTS_MIME = "application/vnd.oma.drm.rights+wbxml"; - -const PREF_BD_USEDOWNLOADDIR = "browser.download.useDownloadDir"; -const URI_GENERIC_ICON_DOWNLOAD = "drawable://alert_download"; - -Cu.import("resource://gre/modules/Downloads.jsm"); -Cu.import("resource://gre/modules/FileUtils.jsm"); -Cu.import("resource://gre/modules/HelperApps.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/NetUtil.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "RuntimePermissions", "resource://gre/modules/RuntimePermissions.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Snackbars", "resource://gre/modules/Snackbars.jsm"); - -// ----------------------------------------------------------------------- -// HelperApp Launcher Dialog -// ----------------------------------------------------------------------- - -XPCOMUtils.defineLazyGetter(this, "ContentAreaUtils", function() { - let ContentAreaUtils = {}; - Services.scriptloader.loadSubScript("chrome://global/content/contentAreaUtils.js", ContentAreaUtils); - return ContentAreaUtils; -}); - -function HelperAppLauncherDialog() { } - -HelperAppLauncherDialog.prototype = { - classID: Components.ID("{e9d277a0-268a-4ec2-bb8c-10fdf3e44611}"), - QueryInterface: XPCOMUtils.generateQI([Ci.nsIHelperAppLauncherDialog]), - - /** - * Returns false if `url` represents a local or special URL that we don't - * wish to ever download. - * - * Returns true otherwise. - */ - _canDownload: function (url, alreadyResolved=false) { - // The common case. - if (url.schemeIs("http") || - url.schemeIs("https") || - url.schemeIs("ftp")) { - return true; - } - - // The less-common opposite case. - if (url.schemeIs("chrome") || - url.schemeIs("jar") || - url.schemeIs("resource") || - url.schemeIs("wyciwyg") || - url.schemeIs("file")) { - return false; - } - - // For all other URIs, try to resolve them to an inner URI, and check that. - if (!alreadyResolved) { - let innerURI = NetUtil.newChannel({ - uri: url, - loadUsingSystemPrincipal: true - }).URI; - - if (!url.equals(innerURI)) { - return this._canDownload(innerURI, true); - } - } - - // Anything else is fine to download. - return true; - }, - - /** - * Returns true if `launcher` represents a download for which we wish - * to prompt. - */ - _shouldPrompt: function (launcher) { - let mimeType = this._getMimeTypeFromLauncher(launcher); - - // Straight equality: nsIMIMEInfo normalizes. - return APK_MIME_TYPE == mimeType || OMA_DOWNLOAD_DESCRIPTOR_MIME_TYPE == mimeType; - }, - - /** - * Returns true if `launcher` represents a download for which we wish to - * offer a "Save to disk" option. - */ - _shouldAddSaveToDiskIntent: function(launcher) { - let mimeType = this._getMimeTypeFromLauncher(launcher); - - // We can't handle OMA downloads. So don't even try. (Bug 1219078) - return mimeType != OMA_DOWNLOAD_DESCRIPTOR_MIME_TYPE; - }, - - /** - * Returns true if `launcher`represents a download that should not be handled by Firefox - * or a third-party app and instead be forwarded to Android's download manager. - */ - _shouldForwardToAndroidDownloadManager: function(aLauncher) { - let forwardDownload = Services.prefs.getBoolPref('browser.download.forward_oma_android_download_manager'); - if (!forwardDownload) { - return false; - } - - let mimeType = aLauncher.MIMEInfo.MIMEType; - if (!mimeType) { - mimeType = ContentAreaUtils.getMIMETypeForURI(aLauncher.source) || ""; - } - - return [ - OMA_DOWNLOAD_DESCRIPTOR_MIME_TYPE, - OMA_DRM_MESSAGE_MIME, - OMA_DRM_CONTENT_MIME, - OMA_DRM_RIGHTS_MIME - ].indexOf(mimeType) != -1; - }, - - show: function hald_show(aLauncher, aContext, aReason) { - if (!this._canDownload(aLauncher.source)) { - this._refuseDownload(aLauncher); - return; - } - - if (this._shouldForwardToAndroidDownloadManager(aLauncher)) { - Task.spawn(function* () { - try { - let hasPermission = yield RuntimePermissions.waitForPermissions(RuntimePermissions.WRITE_EXTERNAL_STORAGE); - if (hasPermission) { - this._downloadWithAndroidDownloadManager(aLauncher); - aLauncher.cancel(Cr.NS_BINDING_ABORTED); - } - } finally { - } - }.bind(this)).catch(Cu.reportError); - return; - } - - let bundle = Services.strings.createBundle("chrome://browser/locale/browser.properties"); - - let defaultHandler = new Object(); - let apps = HelperApps.getAppsForUri(aLauncher.source, { - mimeType: aLauncher.MIMEInfo.MIMEType, - }); - - if (this._shouldAddSaveToDiskIntent(aLauncher)) { - // Add a fake intent for save to disk at the top of the list. - apps.unshift({ - name: bundle.GetStringFromName("helperapps.saveToDisk"), - packageName: "org.mozilla.gecko.Download", - iconUri: "drawable://icon", - selected: true, // Default to download for files - launch: function() { - // Reset the preferredAction here. - aLauncher.MIMEInfo.preferredAction = Ci.nsIMIMEInfo.saveToDisk; - aLauncher.saveToDisk(null, false); - return true; - } - }); - } - - // We do not handle this download and there are no apps that want to do it - if (apps.length === 0) { - this._refuseDownload(aLauncher); - return; - } - - let callback = function(app) { - aLauncher.MIMEInfo.preferredAction = Ci.nsIMIMEInfo.useHelperApp; - if (!app.launch(aLauncher.source)) { - // Once the app is done we need to get rid of the temp file. This shouldn't - // get run in the saveToDisk case. - aLauncher.cancel(Cr.NS_BINDING_ABORTED); - } - } - - // See if the user already marked something as the default for this mimetype, - // and if that app is still installed. - let preferredApp = this._getPreferredApp(aLauncher); - if (preferredApp) { - let pref = apps.filter(function(app) { - return app.packageName === preferredApp; - }); - - if (pref.length > 0) { - callback(pref[0]); - return; - } - } - - // If there's only one choice, and we don't want to prompt, go right ahead - // and choose that app automatically. - if (!this._shouldPrompt(aLauncher) && (apps.length === 1)) { - callback(apps[0]); - return; - } - - // Otherwise, let's go through the prompt. - HelperApps.prompt(apps, { - title: bundle.GetStringFromName("helperapps.pick"), - buttons: [ - bundle.GetStringFromName("helperapps.alwaysUse"), - bundle.GetStringFromName("helperapps.useJustOnce") - ], - // Tapping an app twice should choose "Just once". - doubleTapButton: 1 - }, (data) => { - if (data.button < 0) { - return; - } - - callback(apps[data.icongrid0]); - - if (data.button === 0) { - this._setPreferredApp(aLauncher, apps[data.icongrid0]); - } - }); - }, - - _refuseDownload: function(aLauncher) { - aLauncher.cancel(Cr.NS_BINDING_ABORTED); - - Services.console.logStringMessage("Refusing download of non-downloadable file."); - - let bundle = Services.strings.createBundle("chrome://browser/locale/handling.properties"); - let failedText = bundle.GetStringFromName("download.blocked"); - - Snackbars.show(failedText, Snackbars.LENGTH_LONG); - }, - - _downloadWithAndroidDownloadManager(aLauncher) { - let mimeType = aLauncher.MIMEInfo.MIMEType; - if (!mimeType) { - mimeType = ContentAreaUtils.getMIMETypeForURI(aLauncher.source) || ""; - } - - Messaging.sendRequest({ - 'type': 'Download:AndroidDownloadManager', - 'uri': aLauncher.source.spec, - 'mimeType': mimeType, - 'filename': aLauncher.suggestedFileName - }); - }, - - _getPrefName: function getPrefName(mimetype) { - return "browser.download.preferred." + mimetype.replace("\\", "."); - }, - - _getMimeTypeFromLauncher: function (launcher) { - let mime = launcher.MIMEInfo.MIMEType; - if (!mime) - mime = ContentAreaUtils.getMIMETypeForURI(launcher.source) || ""; - return mime; - }, - - _getPreferredApp: function getPreferredApp(launcher) { - let mime = this._getMimeTypeFromLauncher(launcher); - if (!mime) - return; - - try { - return Services.prefs.getCharPref(this._getPrefName(mime)); - } catch(ex) { - Services.console.logStringMessage("Error getting pref for " + mime + "."); - } - return null; - }, - - _setPreferredApp: function setPreferredApp(launcher, app) { - let mime = this._getMimeTypeFromLauncher(launcher); - if (!mime) - return; - - if (app) - Services.prefs.setCharPref(this._getPrefName(mime), app.packageName); - else - Services.prefs.clearUserPref(this._getPrefName(mime)); - }, - - promptForSaveToFileAsync: function (aLauncher, aContext, aDefaultFile, - aSuggestedFileExt, aForcePrompt) { - Task.spawn(function* () { - let file = null; - try { - let hasPermission = yield RuntimePermissions.waitForPermissions(RuntimePermissions.WRITE_EXTERNAL_STORAGE); - if (hasPermission) { - // If we do have the STORAGE permission then pick the public downloads directory as destination - // for this file. Without the permission saveDestinationAvailable(null) will be called which - // will effectively cancel the download. - let preferredDir = yield Downloads.getPreferredDownloadsDirectory(); - file = this.validateLeafName(new FileUtils.File(preferredDir), - aDefaultFile, aSuggestedFileExt); - } - } finally { - // The file argument will be null in case any exception occurred. - aLauncher.saveDestinationAvailable(file); - } - }.bind(this)).catch(Cu.reportError); - }, - - validateLeafName: function hald_validateLeafName(aLocalFile, aLeafName, aFileExt) { - if (!(aLocalFile && this.isUsableDirectory(aLocalFile))) - return null; - - // Remove any leading periods, since we don't want to save hidden files - // automatically. - aLeafName = aLeafName.replace(/^\.+/, ""); - - if (aLeafName == "") - aLeafName = "unnamed" + (aFileExt ? "." + aFileExt : ""); - aLocalFile.append(aLeafName); - - this.makeFileUnique(aLocalFile); - return aLocalFile; - }, - - makeFileUnique: function hald_makeFileUnique(aLocalFile) { - try { - // Note - this code is identical to that in - // toolkit/content/contentAreaUtils.js. - // If you are updating this code, update that code too! We can't share code - // here since this is called in a js component. - let collisionCount = 0; - while (aLocalFile.exists()) { - collisionCount++; - if (collisionCount == 1) { - // Append "(2)" before the last dot in (or at the end of) the filename - // special case .ext.gz etc files so we don't wind up with .tar(2).gz - if (aLocalFile.leafName.match(/\.[^\.]{1,3}\.(gz|bz2|Z)$/i)) - aLocalFile.leafName = aLocalFile.leafName.replace(/\.[^\.]{1,3}\.(gz|bz2|Z)$/i, "(2)$&"); - else - aLocalFile.leafName = aLocalFile.leafName.replace(/(\.[^\.]*)?$/, "(2)$&"); - } - else { - // replace the last (n) in the filename with (n+1) - aLocalFile.leafName = aLocalFile.leafName.replace(/^(.*\()\d+\)/, "$1" + (collisionCount+1) + ")"); - } - } - aLocalFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600); - } - catch (e) { - dump("*** exception in validateLeafName: " + e + "\n"); - - if (e.result == Cr.NS_ERROR_FILE_ACCESS_DENIED) - throw e; - - if (aLocalFile.leafName == "" || aLocalFile.isDirectory()) { - aLocalFile.append("unnamed"); - if (aLocalFile.exists()) - aLocalFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600); - } - } - }, - - isUsableDirectory: function hald_isUsableDirectory(aDirectory) { - return aDirectory.exists() && aDirectory.isDirectory() && aDirectory.isWritable(); - }, -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([HelperAppLauncherDialog]); |