diff options
Diffstat (limited to 'application/basilisk/base/content/pageinfo/pageInfo.js')
-rw-r--r-- | application/basilisk/base/content/pageinfo/pageInfo.js | 1140 |
1 files changed, 0 insertions, 1140 deletions
diff --git a/application/basilisk/base/content/pageinfo/pageInfo.js b/application/basilisk/base/content/pageinfo/pageInfo.js deleted file mode 100644 index 7a6d0a063..000000000 --- a/application/basilisk/base/content/pageinfo/pageInfo.js +++ /dev/null @@ -1,1140 +0,0 @@ -/* 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/. */ - -Components.utils.import("resource://gre/modules/LoadContextInfo.jsm"); -Components.utils.import("resource://gre/modules/Services.jsm"); - -// define a js object to implement nsITreeView -function pageInfoTreeView(treeid, copycol) -{ - // copycol is the index number for the column that we want to add to - // the copy-n-paste buffer when the user hits accel-c - this.treeid = treeid; - this.copycol = copycol; - this.rows = 0; - this.tree = null; - this.data = [ ]; - this.selection = null; - this.sortcol = -1; - this.sortdir = false; -} - -pageInfoTreeView.prototype = { - set rowCount(c) { throw "rowCount is a readonly property"; }, - get rowCount() { return this.rows; }, - - setTree: function(tree) - { - this.tree = tree; - }, - - getCellText: function(row, column) - { - // row can be null, but js arrays are 0-indexed. - // colidx cannot be null, but can be larger than the number - // of columns in the array. In this case it's the fault of - // whoever typoed while calling this function. - return this.data[row][column.index] || ""; - }, - - setCellValue: function(row, column, value) - { - }, - - setCellText: function(row, column, value) - { - this.data[row][column.index] = value; - }, - - addRow: function(row) - { - this.rows = this.data.push(row); - this.rowCountChanged(this.rows - 1, 1); - if (this.selection.count == 0 && this.rowCount && !gImageElement) { - this.selection.select(0); - } - }, - - addRows: function(rows) - { - for (let row of rows) { - this.addRow(row); - } - }, - - rowCountChanged: function(index, count) - { - this.tree.rowCountChanged(index, count); - }, - - invalidate: function() - { - this.tree.invalidate(); - }, - - clear: function() - { - if (this.tree) - this.tree.rowCountChanged(0, -this.rows); - this.rows = 0; - this.data = [ ]; - }, - - handleCopy: function(row) - { - return (row < 0 || this.copycol < 0) ? "" : (this.data[row][this.copycol] || ""); - }, - - performActionOnRow: function(action, row) - { - if (action == "copy") { - var data = this.handleCopy(row) - this.tree.treeBody.parentNode.setAttribute("copybuffer", data); - } - }, - - onPageMediaSort : function(columnname) - { - var tree = document.getElementById(this.treeid); - var treecol = tree.columns.getNamedColumn(columnname); - - this.sortdir = - gTreeUtils.sort( - tree, - this, - this.data, - treecol.index, - function textComparator(a, b) { return (a || "").toLowerCase().localeCompare((b || "").toLowerCase()); }, - this.sortcol, - this.sortdir - ); - - Array.forEach(tree.columns, function(col) { - col.element.removeAttribute("sortActive"); - col.element.removeAttribute("sortDirection"); - }); - treecol.element.setAttribute("sortActive", "true"); - treecol.element.setAttribute("sortDirection", this.sortdir ? - "ascending" : "descending"); - - this.sortcol = treecol.index; - }, - - getRowProperties: function(row) { return ""; }, - getCellProperties: function(row, column) { return ""; }, - getColumnProperties: function(column) { return ""; }, - isContainer: function(index) { return false; }, - isContainerOpen: function(index) { return false; }, - isSeparator: function(index) { return false; }, - isSorted: function() { return this.sortcol > -1 }, - canDrop: function(index, orientation) { return false; }, - drop: function(row, orientation) { return false; }, - getParentIndex: function(index) { return 0; }, - hasNextSibling: function(index, after) { return false; }, - getLevel: function(index) { return 0; }, - getImageSrc: function(row, column) { }, - getProgressMode: function(row, column) { }, - getCellValue: function(row, column) { }, - toggleOpenState: function(index) { }, - cycleHeader: function(col) { }, - selectionChanged: function() { }, - cycleCell: function(row, column) { }, - isEditable: function(row, column) { return false; }, - isSelectable: function(row, column) { return false; }, - performAction: function(action) { }, - performActionOnCell: function(action, row, column) { } -}; - -// mmm, yummy. global variables. -var gDocInfo = null; -var gImageElement = null; - -// column number to help using the data array -const COL_IMAGE_ADDRESS = 0; -const COL_IMAGE_TYPE = 1; -const COL_IMAGE_SIZE = 2; -const COL_IMAGE_ALT = 3; -const COL_IMAGE_COUNT = 4; -const COL_IMAGE_NODE = 5; -const COL_IMAGE_BG = 6; - -// column number to copy from, second argument to pageInfoTreeView's constructor -const COPYCOL_NONE = -1; -const COPYCOL_META_CONTENT = 1; -const COPYCOL_IMAGE = COL_IMAGE_ADDRESS; - -// one nsITreeView for each tree in the window -var gMetaView = new pageInfoTreeView('metatree', COPYCOL_META_CONTENT); -var gImageView = new pageInfoTreeView('imagetree', COPYCOL_IMAGE); - -gImageView.getCellProperties = function(row, col) { - var data = gImageView.data[row]; - var item = gImageView.data[row][COL_IMAGE_NODE]; - var props = ""; - if (!checkProtocol(data) || - item instanceof HTMLEmbedElement || - (item instanceof HTMLObjectElement && !item.type.startsWith("image/"))) - props += "broken"; - - if (col.element.id == "image-address") - props += " ltr"; - - return props; -}; - -gImageView.getCellText = function(row, column) { - var value = this.data[row][column.index]; - if (column.index == COL_IMAGE_SIZE) { - if (value == -1) { - return gStrings.unknown; - } - var kbSize = Number(Math.round(value / 1024 * 100) / 100); - return gBundle.getFormattedString("mediaFileSize", [kbSize]); - } - return value || ""; -}; - -gImageView.onPageMediaSort = function(columnname) { - var tree = document.getElementById(this.treeid); - var treecol = tree.columns.getNamedColumn(columnname); - - var comparator; - var index = treecol.index; - if (index == COL_IMAGE_SIZE || index == COL_IMAGE_COUNT) { - comparator = function numComparator(a, b) { return a - b; }; - } else { - comparator = function textComparator(a, b) { return (a || "").toLowerCase().localeCompare((b || "").toLowerCase()); }; - } - - this.sortdir = - gTreeUtils.sort( - tree, - this, - this.data, - index, - comparator, - this.sortcol, - this.sortdir - ); - - Array.forEach(tree.columns, function(col) { - col.element.removeAttribute("sortActive"); - col.element.removeAttribute("sortDirection"); - }); - treecol.element.setAttribute("sortActive", "true"); - treecol.element.setAttribute("sortDirection", this.sortdir ? - "ascending" : "descending"); - - this.sortcol = index; -}; - -var gImageHash = { }; - -// localized strings (will be filled in when the document is loaded) -// this isn't all of them, these are just the ones that would otherwise have been loaded inside a loop -var gStrings = { }; -var gBundle; - -const PERMISSION_CONTRACTID = "@mozilla.org/permissionmanager;1"; -const PREFERENCES_CONTRACTID = "@mozilla.org/preferences-service;1"; -const ATOM_CONTRACTID = "@mozilla.org/atom-service;1"; - -// a number of services I'll need later -// the cache services -const nsICacheStorageService = Components.interfaces.nsICacheStorageService; -const nsICacheStorage = Components.interfaces.nsICacheStorage; -const cacheService = Components.classes["@mozilla.org/netwerk/cache-storage-service;1"].getService(nsICacheStorageService); - -var loadContextInfo = LoadContextInfo.fromLoadContext( - window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) - .getInterface(Components.interfaces.nsIWebNavigation) - .QueryInterface(Components.interfaces.nsILoadContext), false); -var diskStorage = cacheService.diskCacheStorage(loadContextInfo, false); - -const nsICookiePermission = Components.interfaces.nsICookiePermission; -const nsIPermissionManager = Components.interfaces.nsIPermissionManager; - -const nsICertificateDialogs = Components.interfaces.nsICertificateDialogs; -const CERTIFICATEDIALOGS_CONTRACTID = "@mozilla.org/nsCertificateDialogs;1" - -// clipboard helper -function getClipboardHelper() { - try { - return Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper); - } catch (e) { - // do nothing, later code will handle the error - return null; - } -} -const gClipboardHelper = getClipboardHelper(); - -// Interface for image loading content -const nsIImageLoadingContent = Components.interfaces.nsIImageLoadingContent; - -// namespaces, don't need all of these yet... -const XLinkNS = "http://www.w3.org/1999/xlink"; -const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; -const XMLNS = "http://www.w3.org/XML/1998/namespace"; -const XHTMLNS = "http://www.w3.org/1999/xhtml"; -const XHTML2NS = "http://www.w3.org/2002/06/xhtml2" - -const XHTMLNSre = "^http\:\/\/www\.w3\.org\/1999\/xhtml$"; -const XHTML2NSre = "^http\:\/\/www\.w3\.org\/2002\/06\/xhtml2$"; -const XHTMLre = RegExp(XHTMLNSre + "|" + XHTML2NSre, ""); - -/* Overlays register functions here. - * These arrays are used to hold callbacks that Page Info will call at - * various stages. Use them by simply appending a function to them. - * For example, add a function to onLoadRegistry by invoking - * "onLoadRegistry.push(XXXLoadFunc);" - * The XXXLoadFunc should be unique to the overlay module, and will be - * invoked as "XXXLoadFunc();" - */ - -// These functions are called to build the data displayed in the Page Info window. -var onLoadRegistry = [ ]; - -// These functions are called to remove old data still displayed in -// the window when the document whose information is displayed -// changes. For example, at this time, the list of images of the Media -// tab is cleared. -var onResetRegistry = [ ]; - -// These functions are called once when all the elements in all of the target -// document (and all of its subframes, if any) have been processed -var onFinished = [ ]; - -// These functions are called once when the Page Info window is closed. -var onUnloadRegistry = [ ]; - -/* Called when PageInfo window is loaded. Arguments are: - * window.arguments[0] - (optional) an object consisting of - * - doc: (optional) document to use for source. if not provided, - * the calling window's document will be used - * - initialTab: (optional) id of the inital tab to display - */ -function onLoadPageInfo() -{ - gBundle = document.getElementById("pageinfobundle"); - gStrings.unknown = gBundle.getString("unknown"); - gStrings.notSet = gBundle.getString("notset"); - gStrings.mediaImg = gBundle.getString("mediaImg"); - gStrings.mediaBGImg = gBundle.getString("mediaBGImg"); - gStrings.mediaBorderImg = gBundle.getString("mediaBorderImg"); - gStrings.mediaListImg = gBundle.getString("mediaListImg"); - gStrings.mediaCursor = gBundle.getString("mediaCursor"); - gStrings.mediaObject = gBundle.getString("mediaObject"); - gStrings.mediaEmbed = gBundle.getString("mediaEmbed"); - gStrings.mediaLink = gBundle.getString("mediaLink"); - gStrings.mediaInput = gBundle.getString("mediaInput"); - gStrings.mediaVideo = gBundle.getString("mediaVideo"); - gStrings.mediaAudio = gBundle.getString("mediaAudio"); - - var args = "arguments" in window && - window.arguments.length >= 1 && - window.arguments[0]; - - // init media view - var imageTree = document.getElementById("imagetree"); - imageTree.view = gImageView; - - /* Select the requested tab, if the name is specified */ - loadTab(args); - Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService) - .notifyObservers(window, "page-info-dialog-loaded", null); -} - -function loadPageInfo(frameOuterWindowID, imageElement, browser) -{ - browser = browser || window.opener.gBrowser.selectedBrowser; - let mm = browser.messageManager; - - gStrings["application/rss+xml"] = gBundle.getString("feedRss"); - gStrings["application/atom+xml"] = gBundle.getString("feedAtom"); - gStrings["text/xml"] = gBundle.getString("feedXML"); - gStrings["application/xml"] = gBundle.getString("feedXML"); - gStrings["application/rdf+xml"] = gBundle.getString("feedXML"); - - // Look for pageInfoListener in content.js. Sends message to listener with arguments. - mm.sendAsyncMessage("PageInfo:getData", {strings: gStrings, - frameOuterWindowID: frameOuterWindowID}, - { imageElement }); - - let pageInfoData; - - // Get initial pageInfoData needed to display the general, feeds, permission and security tabs. - mm.addMessageListener("PageInfo:data", function onmessage(message) { - mm.removeMessageListener("PageInfo:data", onmessage); - pageInfoData = message.data; - let docInfo = pageInfoData.docInfo; - let windowInfo = pageInfoData.windowInfo; - let uri = makeURI(docInfo.documentURIObject.spec, - docInfo.documentURIObject.originCharset); - let principal = docInfo.principal; - gDocInfo = docInfo; - - gImageElement = pageInfoData.imageInfo; - - var titleFormat = windowInfo.isTopWindow ? "pageInfo.page.title" - : "pageInfo.frame.title"; - document.title = gBundle.getFormattedString(titleFormat, [docInfo.location]); - - document.getElementById("main-window").setAttribute("relatedUrl", docInfo.location); - - makeGeneralTab(pageInfoData.metaViewRows, docInfo); - initFeedTab(pageInfoData.feeds); - onLoadPermission(uri, principal); - securityOnLoad(uri, windowInfo); - }); - - // Get the media elements from content script to setup the media tab. - mm.addMessageListener("PageInfo:mediaData", function onmessage(message) { - // Page info window was closed. - if (window.closed) { - mm.removeMessageListener("PageInfo:mediaData", onmessage); - return; - } - - // The page info media fetching has been completed. - if (message.data.isComplete) { - mm.removeMessageListener("PageInfo:mediaData", onmessage); - onFinished.forEach(function(func) { func(pageInfoData); }); - return; - } - - for (let item of message.data.mediaItems) { - addImage(item); - } - - selectImage(); - }); - - /* Call registered overlay init functions */ - onLoadRegistry.forEach(function(func) { func(); }); -} - -function resetPageInfo(args) -{ - /* Reset Meta tags part */ - gMetaView.clear(); - - /* Reset Media tab */ - var mediaTab = document.getElementById("mediaTab"); - if (!mediaTab.hidden) { - Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService) - .removeObserver(imagePermissionObserver, "perm-changed"); - mediaTab.hidden = true; - } - gImageView.clear(); - gImageHash = {}; - - /* Reset Feeds Tab */ - var feedListbox = document.getElementById("feedListbox"); - while (feedListbox.firstChild) - feedListbox.removeChild(feedListbox.firstChild); - - /* Call registered overlay reset functions */ - onResetRegistry.forEach(function(func) { func(); }); - - /* Rebuild the data */ - loadTab(args); -} - -function onUnloadPageInfo() -{ - // Remove the observer, only if there is at least 1 image. - if (!document.getElementById("mediaTab").hidden) { - Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService) - .removeObserver(imagePermissionObserver, "perm-changed"); - } - - /* Call registered overlay unload functions */ - onUnloadRegistry.forEach(function(func) { func(); }); -} - -function doHelpButton() -{ - const helpTopics = { - "generalPanel": "pageinfo_general", - "mediaPanel": "pageinfo_media", - "feedPanel": "pageinfo_feed", - "permPanel": "pageinfo_permissions", - "securityPanel": "pageinfo_security" - }; - - var deck = document.getElementById("mainDeck"); - var helpdoc = helpTopics[deck.selectedPanel.id] || "pageinfo_general"; - openHelpLink(helpdoc); -} - -function showTab(id) -{ - var deck = document.getElementById("mainDeck"); - var pagel = document.getElementById(id + "Panel"); - deck.selectedPanel = pagel; -} - -function loadTab(args) -{ - // If the "View Image Info" context menu item was used, the related image - // element is provided as an argument. This can't be a background image. - let imageElement = args && args.imageElement; - let frameOuterWindowID = args && args.frameOuterWindowID; - let browser = args && args.browser; - - /* Load the page info */ - loadPageInfo(frameOuterWindowID, imageElement, browser); - - var initialTab = (args && args.initialTab) || "generalTab"; - var radioGroup = document.getElementById("viewGroup"); - initialTab = document.getElementById(initialTab) || document.getElementById("generalTab"); - radioGroup.selectedItem = initialTab; - radioGroup.selectedItem.doCommand(); - radioGroup.focus(); -} - -function toggleGroupbox(id) -{ - var elt = document.getElementById(id); - if (elt.hasAttribute("closed")) { - elt.removeAttribute("closed"); - if (elt.flexWhenOpened) - elt.flex = elt.flexWhenOpened; - } - else { - elt.setAttribute("closed", "true"); - if (elt.flex) { - elt.flexWhenOpened = elt.flex; - elt.flex = 0; - } - } -} - -function openCacheEntry(key, cb) -{ - var checkCacheListener = { - onCacheEntryCheck: function(entry, appCache) { - return Components.interfaces.nsICacheEntryOpenCallback.ENTRY_WANTED; - }, - onCacheEntryAvailable: function(entry, isNew, appCache, status) { - cb(entry); - } - }; - diskStorage.asyncOpenURI(Services.io.newURI(key, null, null), "", nsICacheStorage.OPEN_READONLY, checkCacheListener); -} - -function makeGeneralTab(metaViewRows, docInfo) -{ - var title = (docInfo.title) ? docInfo.title : gBundle.getString("noPageTitle"); - document.getElementById("titletext").value = title; - - var url = docInfo.location; - setItemValue("urltext", url); - - var referrer = ("referrer" in docInfo && docInfo.referrer); - setItemValue("refertext", referrer); - - var mode = ("compatMode" in docInfo && docInfo.compatMode == "BackCompat") ? "generalQuirksMode" : "generalStrictMode"; - document.getElementById("modetext").value = gBundle.getString(mode); - - // find out the mime type - var mimeType = docInfo.contentType; - setItemValue("typetext", mimeType); - - // get the document characterset - var encoding = docInfo.characterSet; - document.getElementById("encodingtext").value = encoding; - - let length = metaViewRows.length; - - var metaGroup = document.getElementById("metaTags"); - if (!length) - metaGroup.collapsed = true; - else { - var metaTagsCaption = document.getElementById("metaTagsCaption"); - if (length == 1) - metaTagsCaption.label = gBundle.getString("generalMetaTag"); - else - metaTagsCaption.label = gBundle.getFormattedString("generalMetaTags", [length]); - var metaTree = document.getElementById("metatree"); - metaTree.view = gMetaView; - - // Add the metaViewRows onto the general tab's meta info tree. - gMetaView.addRows(metaViewRows); - - metaGroup.collapsed = false; - } - - // get the date of last modification - var modifiedText = formatDate(docInfo.lastModified, gStrings.notSet); - document.getElementById("modifiedtext").value = modifiedText; - - // get cache info - var cacheKey = url.replace(/#.*$/, ""); - openCacheEntry(cacheKey, function(cacheEntry) { - var sizeText; - if (cacheEntry) { - var pageSize = cacheEntry.dataSize; - var kbSize = formatNumber(Math.round(pageSize / 1024 * 100) / 100); - sizeText = gBundle.getFormattedString("generalSize", [kbSize, formatNumber(pageSize)]); - } - setItemValue("sizetext", sizeText); - }); -} - -function addImage(imageViewRow) -{ - let [url, type, alt, elem, isBg] = imageViewRow; - - if (!url) - return; - - if (!gImageHash.hasOwnProperty(url)) - gImageHash[url] = { }; - if (!gImageHash[url].hasOwnProperty(type)) - gImageHash[url][type] = { }; - if (!gImageHash[url][type].hasOwnProperty(alt)) { - gImageHash[url][type][alt] = gImageView.data.length; - var row = [url, type, -1, alt, 1, elem, isBg]; - gImageView.addRow(row); - - // Fill in cache data asynchronously - openCacheEntry(url, function(cacheEntry) { - // The data at row[2] corresponds to the data size. - if (cacheEntry) { - row[2] = cacheEntry.dataSize; - // Invalidate the row to trigger a repaint. - gImageView.tree.invalidateRow(gImageView.data.indexOf(row)); - } - }); - - // Add the observer, only once. - if (gImageView.data.length == 1) { - document.getElementById("mediaTab").hidden = false; - Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService) - .addObserver(imagePermissionObserver, "perm-changed", false); - } - } - else { - var i = gImageHash[url][type][alt]; - gImageView.data[i][COL_IMAGE_COUNT]++; - // The same image can occur several times on the page at different sizes. - // If the "View Image Info" context menu item was used, ensure we select - // the correct element. - if (!gImageView.data[i][COL_IMAGE_BG] && - gImageElement && url == gImageElement.currentSrc && - gImageElement.width == elem.width && - gImageElement.height == elem.height && - gImageElement.imageText == elem.imageText) { - gImageView.data[i][COL_IMAGE_NODE] = elem; - } - } -} - -// Link Stuff -function openURL(target) -{ - var url = target.parentNode.childNodes[2].value; - window.open(url, "_blank", "chrome"); -} - -function onBeginLinkDrag(event, urlField, descField) -{ - if (event.originalTarget.localName != "treechildren") - return; - - var tree = event.target; - if (!("treeBoxObject" in tree)) - tree = tree.parentNode; - - var row = tree.treeBoxObject.getRowAt(event.clientX, event.clientY); - if (row == -1) - return; - - // Adding URL flavor - var col = tree.columns[urlField]; - var url = tree.view.getCellText(row, col); - col = tree.columns[descField]; - var desc = tree.view.getCellText(row, col); - - var dt = event.dataTransfer; - dt.setData("text/x-moz-url", url + "\n" + desc); - dt.setData("text/url-list", url); - dt.setData("text/plain", url); -} - -// Image Stuff -function getSelectedRows(tree) -{ - var start = { }; - var end = { }; - var numRanges = tree.view.selection.getRangeCount(); - - var rowArray = [ ]; - for (var t = 0; t < numRanges; t++) { - tree.view.selection.getRangeAt(t, start, end); - for (var v = start.value; v <= end.value; v++) - rowArray.push(v); - } - - return rowArray; -} - -function getSelectedRow(tree) -{ - var rows = getSelectedRows(tree); - return (rows.length == 1) ? rows[0] : -1; -} - -function selectSaveFolder(aCallback) -{ - const nsILocalFile = Components.interfaces.nsILocalFile; - const nsIFilePicker = Components.interfaces.nsIFilePicker; - let titleText = gBundle.getString("mediaSelectFolder"); - let fp = Components.classes["@mozilla.org/filepicker;1"]. - createInstance(nsIFilePicker); - let fpCallback = function fpCallback_done(aResult) { - if (aResult == nsIFilePicker.returnOK) { - aCallback(fp.file.QueryInterface(nsILocalFile)); - } else { - aCallback(null); - } - }; - - fp.init(window, titleText, nsIFilePicker.modeGetFolder); - fp.appendFilters(nsIFilePicker.filterAll); - try { - let prefs = Components.classes[PREFERENCES_CONTRACTID]. - getService(Components.interfaces.nsIPrefBranch); - let initialDir = prefs.getComplexValue("browser.download.dir", nsILocalFile); - if (initialDir) { - fp.displayDirectory = initialDir; - } - } catch (ex) { - } - fp.open(fpCallback); -} - -function saveMedia() -{ - var tree = document.getElementById("imagetree"); - var rowArray = getSelectedRows(tree); - if (rowArray.length == 1) { - var row = rowArray[0]; - var item = gImageView.data[row][COL_IMAGE_NODE]; - var url = gImageView.data[row][COL_IMAGE_ADDRESS]; - - if (url) { - var titleKey = "SaveImageTitle"; - - if (item instanceof HTMLVideoElement) - titleKey = "SaveVideoTitle"; - else if (item instanceof HTMLAudioElement) - titleKey = "SaveAudioTitle"; - - saveURL(url, null, titleKey, false, false, makeURI(item.baseURI), - null, gDocInfo.isContentWindowPrivate); - } - } else { - selectSaveFolder(function(aDirectory) { - if (aDirectory) { - var saveAnImage = function(aURIString, aChosenData, aBaseURI) { - uniqueFile(aChosenData.file); - internalSave(aURIString, null, null, null, null, false, "SaveImageTitle", - aChosenData, aBaseURI, null, false, null, gDocInfo.isContentWindowPrivate); - }; - - for (var i = 0; i < rowArray.length; i++) { - var v = rowArray[i]; - var dir = aDirectory.clone(); - var item = gImageView.data[v][COL_IMAGE_NODE]; - var uriString = gImageView.data[v][COL_IMAGE_ADDRESS]; - var uri = makeURI(uriString); - - try { - uri.QueryInterface(Components.interfaces.nsIURL); - dir.append(decodeURIComponent(uri.fileName)); - } catch (ex) { - // data:/blob: uris - // Supply a dummy filename, otherwise Download Manager - // will try to delete the base directory on failure. - dir.append(gImageView.data[v][COL_IMAGE_TYPE]); - } - - if (i == 0) { - saveAnImage(uriString, new AutoChosen(dir, uri), makeURI(item.baseURI)); - } else { - // This delay is a hack which prevents the download manager - // from opening many times. See bug 377339. - setTimeout(saveAnImage, 200, uriString, new AutoChosen(dir, uri), - makeURI(item.baseURI)); - } - } - } - }); - } -} - -function onBlockImage() -{ - var permissionManager = Components.classes[PERMISSION_CONTRACTID] - .getService(nsIPermissionManager); - - var checkbox = document.getElementById("blockImage"); - var uri = makeURI(document.getElementById("imageurltext").value); - if (checkbox.checked) - permissionManager.add(uri, "image", nsIPermissionManager.DENY_ACTION); - else - permissionManager.remove(uri, "image"); -} - -function onImageSelect() -{ - var previewBox = document.getElementById("mediaPreviewBox"); - var mediaSaveBox = document.getElementById("mediaSaveBox"); - var splitter = document.getElementById("mediaSplitter"); - var tree = document.getElementById("imagetree"); - var count = tree.view.selection.count; - if (count == 0) { - previewBox.collapsed = true; - mediaSaveBox.collapsed = true; - splitter.collapsed = true; - tree.flex = 1; - } - else if (count > 1) { - splitter.collapsed = true; - previewBox.collapsed = true; - mediaSaveBox.collapsed = false; - tree.flex = 1; - } - else { - mediaSaveBox.collapsed = true; - splitter.collapsed = false; - previewBox.collapsed = false; - tree.flex = 0; - makePreview(getSelectedRows(tree)[0]); - } -} - -// Makes the media preview (image, video, etc) for the selected row on the media tab. -function makePreview(row) -{ - var item = gImageView.data[row][COL_IMAGE_NODE]; - var url = gImageView.data[row][COL_IMAGE_ADDRESS]; - var isBG = gImageView.data[row][COL_IMAGE_BG]; - var isAudio = false; - - setItemValue("imageurltext", url); - setItemValue("imagetext", item.imageText); - setItemValue("imagelongdesctext", item.longDesc); - - // get cache info - var cacheKey = url.replace(/#.*$/, ""); - openCacheEntry(cacheKey, function(cacheEntry) { - // find out the file size - var sizeText; - if (cacheEntry) { - let imageSize = cacheEntry.dataSize; - var kbSize = Math.round(imageSize / 1024 * 100) / 100; - sizeText = gBundle.getFormattedString("generalSize", - [formatNumber(kbSize), formatNumber(imageSize)]); - } - else - sizeText = gBundle.getString("mediaUnknownNotCached"); - setItemValue("imagesizetext", sizeText); - - var mimeType = item.mimeType || this.getContentTypeFromHeaders(cacheEntry); - var numFrames = item.numFrames; - - var imageType; - if (mimeType) { - // We found the type, try to display it nicely - let imageMimeType = /^image\/(.*)/i.exec(mimeType); - if (imageMimeType) { - imageType = imageMimeType[1].toUpperCase(); - if (numFrames > 1) - imageType = gBundle.getFormattedString("mediaAnimatedImageType", - [imageType, numFrames]); - else - imageType = gBundle.getFormattedString("mediaImageType", [imageType]); - } - else { - // the MIME type doesn't begin with image/, display the raw type - imageType = mimeType; - } - } - else { - // We couldn't find the type, fall back to the value in the treeview - imageType = gImageView.data[row][COL_IMAGE_TYPE]; - } - setItemValue("imagetypetext", imageType); - - var imageContainer = document.getElementById("theimagecontainer"); - var oldImage = document.getElementById("thepreviewimage"); - - var isProtocolAllowed = checkProtocol(gImageView.data[row]); - - var newImage = new Image; - newImage.id = "thepreviewimage"; - var physWidth = 0, physHeight = 0; - var width = 0, height = 0; - - if ((item.HTMLLinkElement || item.HTMLInputElement || - item.HTMLImageElement || item.SVGImageElement || - (item.HTMLObjectElement && mimeType && mimeType.startsWith("image/")) || - isBG) && isProtocolAllowed) { - newImage.setAttribute("src", url); - physWidth = newImage.width || 0; - physHeight = newImage.height || 0; - - // "width" and "height" attributes must be set to newImage, - // even if there is no "width" or "height attribute in item; - // otherwise, the preview image cannot be displayed correctly. - // Since the image might have been loaded out-of-process, we expect - // the item to tell us its width / height dimensions. Failing that - // the item should tell us the natural dimensions of the image. Finally - // failing that, we'll assume that the image was never loaded in the - // other process (this can be true for favicons, for example), and so - // we'll assume that we can use the natural dimensions of the newImage - // we just created. If the natural dimensions of newImage are not known - // then the image is probably broken. - if (!isBG) { - newImage.width = ("width" in item && item.width) || newImage.naturalWidth; - newImage.height = ("height" in item && item.height) || newImage.naturalHeight; - } - else { - // the Width and Height of an HTML tag should not be used for its background image - // (for example, "table" can have "width" or "height" attributes) - newImage.width = item.naturalWidth || newImage.naturalWidth; - newImage.height = item.naturalHeight || newImage.naturalHeight; - } - - if (item.SVGImageElement) { - newImage.width = item.SVGImageElementWidth; - newImage.height = item.SVGImageElementHeight; - } - - width = newImage.width; - height = newImage.height; - - document.getElementById("theimagecontainer").collapsed = false - document.getElementById("brokenimagecontainer").collapsed = true; - } - else if (item.HTMLVideoElement && isProtocolAllowed) { - newImage = document.createElementNS("http://www.w3.org/1999/xhtml", "video"); - newImage.id = "thepreviewimage"; - newImage.src = url; - newImage.controls = true; - width = physWidth = item.videoWidth; - height = physHeight = item.videoHeight; - - document.getElementById("theimagecontainer").collapsed = false; - document.getElementById("brokenimagecontainer").collapsed = true; - } - else if (item.HTMLAudioElement && isProtocolAllowed) { - newImage = new Audio; - newImage.id = "thepreviewimage"; - newImage.src = url; - newImage.controls = true; - isAudio = true; - - document.getElementById("theimagecontainer").collapsed = false; - document.getElementById("brokenimagecontainer").collapsed = true; - } - else { - // fallback image for protocols not allowed (e.g., javascript:) - // or elements not [yet] handled (e.g., object, embed). - document.getElementById("brokenimagecontainer").collapsed = false; - document.getElementById("theimagecontainer").collapsed = true; - } - - let imageSize = ""; - if (url && !isAudio) { - if (width != physWidth || height != physHeight) { - imageSize = gBundle.getFormattedString("mediaDimensionsScaled", - [formatNumber(physWidth), - formatNumber(physHeight), - formatNumber(width), - formatNumber(height)]); - } - else { - imageSize = gBundle.getFormattedString("mediaDimensions", - [formatNumber(width), - formatNumber(height)]); - } - } - setItemValue("imagedimensiontext", imageSize); - - makeBlockImage(url); - - imageContainer.removeChild(oldImage); - imageContainer.appendChild(newImage); - }); -} - -function makeBlockImage(url) -{ - var permissionManager = Components.classes[PERMISSION_CONTRACTID] - .getService(nsIPermissionManager); - var prefs = Components.classes[PREFERENCES_CONTRACTID] - .getService(Components.interfaces.nsIPrefBranch); - - var checkbox = document.getElementById("blockImage"); - var imagePref = prefs.getIntPref("permissions.default.image"); - if (!(/^https?:/.test(url)) || imagePref == 2) - // We can't block the images from this host because either is is not - // for http(s) or we don't load images at all - checkbox.hidden = true; - else { - var uri = makeURI(url); - if (uri.host) { - checkbox.hidden = false; - checkbox.label = gBundle.getFormattedString("mediaBlockImage", [uri.host]); - var perm = permissionManager.testPermission(uri, "image"); - checkbox.checked = perm == nsIPermissionManager.DENY_ACTION; - } - else - checkbox.hidden = true; - } -} - -var imagePermissionObserver = { - observe: function (aSubject, aTopic, aData) - { - if (document.getElementById("mediaPreviewBox").collapsed) - return; - - if (aTopic == "perm-changed") { - var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission); - if (permission.type == "image") { - var imageTree = document.getElementById("imagetree"); - var row = getSelectedRow(imageTree); - var url = gImageView.data[row][COL_IMAGE_ADDRESS]; - if (permission.matchesURI(makeURI(url), true)) { - makeBlockImage(url); - } - } - } - } -} - -function getContentTypeFromHeaders(cacheEntryDescriptor) -{ - if (!cacheEntryDescriptor) - return null; - - let headers = cacheEntryDescriptor.getMetaDataElement("response-head"); - let type = /^Content-Type:\s*(.*?)\s*(?:\;|$)/mi.exec(headers); - return type && type[1]; -} - -function setItemValue(id, value) -{ - var item = document.getElementById(id); - if (value) { - item.parentNode.collapsed = false; - item.value = value; - } - else - item.parentNode.collapsed = true; -} - -function formatNumber(number) -{ - return (+number).toLocaleString(); // coerce number to a numeric value before calling toLocaleString() -} - -function formatDate(datestr, unknown) -{ - var date = new Date(datestr); - if (!date.valueOf()) - return unknown; - - const locale = Components.classes["@mozilla.org/chrome/chrome-registry;1"] - .getService(Components.interfaces.nsIXULChromeRegistry) - .getSelectedLocale("global", true); - const dtOptions = { year: 'numeric', month: 'long', day: 'numeric', - hour: 'numeric', minute: 'numeric', second: 'numeric' }; - return date.toLocaleString(locale, dtOptions); -} - -function doCopy() -{ - if (!gClipboardHelper) - return; - - var elem = document.commandDispatcher.focusedElement; - - if (elem && "treeBoxObject" in elem) { - var view = elem.view; - var selection = view.selection; - var text = [], tmp = ''; - var min = {}, max = {}; - - var count = selection.getRangeCount(); - - for (var i = 0; i < count; i++) { - selection.getRangeAt(i, min, max); - - for (var row = min.value; row <= max.value; row++) { - view.performActionOnRow("copy", row); - - tmp = elem.getAttribute("copybuffer"); - if (tmp) - text.push(tmp); - elem.removeAttribute("copybuffer"); - } - } - gClipboardHelper.copyString(text.join("\n")); - } -} - -function doSelectAllMedia() -{ - var tree = document.getElementById("imagetree"); - - if (tree) - tree.view.selection.selectAll(); -} - -function doSelectAll() -{ - var elem = document.commandDispatcher.focusedElement; - - if (elem && "treeBoxObject" in elem) - elem.view.selection.selectAll(); -} - -function selectImage() -{ - if (!gImageElement) - return; - - var tree = document.getElementById("imagetree"); - for (var i = 0; i < tree.view.rowCount; i++) { - // If the image row element is the image selected from the "View Image Info" context menu item. - let image = gImageView.data[i][COL_IMAGE_NODE]; - if (!gImageView.data[i][COL_IMAGE_BG] && - gImageElement.currentSrc == gImageView.data[i][COL_IMAGE_ADDRESS] && - gImageElement.width == image.width && - gImageElement.height == image.height && - gImageElement.imageText == image.imageText) { - tree.view.selection.select(i); - tree.treeBoxObject.ensureRowIsVisible(i); - tree.focus(); - return; - } - } -} - -function checkProtocol(img) -{ - var url = img[COL_IMAGE_ADDRESS]; - return /^data:image\//i.test(url) || - /^(https?|ftp|file|about|chrome|resource):/.test(url); -} |