diff --git a/browser/base/content/content.js b/browser/base/content/content.js index 588be2f32ee7..d2f6c7800c47 100644 --- a/browser/base/content/content.js +++ b/browser/base/content/content.js @@ -1061,380 +1061,6 @@ var LightWeightThemeWebInstallListener = { LightWeightThemeWebInstallListener.init(); -var PageInfoListener = { - - init() { - addMessageListener("PageInfo:getData", this); - }, - - receiveMessage(message) { - let strings = message.data.strings; - let window; - let document; - - let frameOuterWindowID = message.data.frameOuterWindowID; - - // If inside frame then get the frame's window and document. - if (frameOuterWindowID != undefined) { - window = Services.wm.getOuterWindowWithId(frameOuterWindowID); - document = window.document; - } else { - window = content.window; - document = content.document; - } - - let pageInfoData = {metaViewRows: this.getMetaInfo(document), - docInfo: this.getDocumentInfo(document), - feeds: this.getFeedsInfo(document, strings), - windowInfo: this.getWindowInfo(window)}; - - sendAsyncMessage("PageInfo:data", pageInfoData); - - // Separate step so page info dialog isn't blank while waiting for this to finish. - this.getMediaInfo(document, window, strings); - }, - - getMetaInfo(document) { - let metaViewRows = []; - - // Get the meta tags from the page. - let metaNodes = document.getElementsByTagName("meta"); - - for (let metaNode of metaNodes) { - metaViewRows.push([metaNode.name || metaNode.httpEquiv || metaNode.getAttribute("property"), - metaNode.content]); - } - - return metaViewRows; - }, - - getWindowInfo(window) { - let windowInfo = {}; - windowInfo.isTopWindow = window == window.top; - - let hostName = null; - try { - hostName = Services.io.newURI(window.location.href).displayHost; - } catch (exception) { } - - windowInfo.hostName = hostName; - return windowInfo; - }, - - getDocumentInfo(document) { - let docInfo = {}; - docInfo.title = document.title; - docInfo.location = document.location.toString(); - try { - docInfo.location = Services.io.newURI(document.location.toString()).displaySpec; - } catch (exception) { } - docInfo.referrer = document.referrer; - try { - if (document.referrer) { - docInfo.referrer = Services.io.newURI(document.referrer).displaySpec; - } - } catch (exception) { } - docInfo.compatMode = document.compatMode; - docInfo.contentType = document.contentType; - docInfo.characterSet = document.characterSet; - docInfo.lastModified = document.lastModified; - docInfo.principal = document.nodePrincipal; - - let documentURIObject = {}; - documentURIObject.spec = document.documentURIObject.spec; - docInfo.documentURIObject = documentURIObject; - - docInfo.isContentWindowPrivate = PrivateBrowsingUtils.isContentWindowPrivate(content); - - return docInfo; - }, - - getFeedsInfo(document, strings) { - let feeds = []; - // Get the feeds from the page. - let linkNodes = document.getElementsByTagName("link"); - let length = linkNodes.length; - for (let i = 0; i < length; i++) { - let link = linkNodes[i]; - if (!link.href) { - continue; - } - let rel = link.rel && link.rel.toLowerCase(); - let rels = {}; - - if (rel) { - for (let relVal of rel.split(/\s+/)) { - rels[relVal] = true; - } - } - - if (rels.feed || (link.type && rels.alternate && !rels.stylesheet)) { - let type = Feeds.isValidFeed(link, document.nodePrincipal, "feed" in rels); - if (type) { - type = strings[type] || strings["application/rss+xml"]; - feeds.push([link.title, type, link.href]); - } - } - } - return feeds; - }, - - // Only called once to get the media tab's media elements from the content page. - getMediaInfo(document, window, strings) { - let frameList = this.goThroughFrames(document, window); - this.processFrames(document, frameList, strings); - }, - - goThroughFrames(document, window) { - let frameList = [document]; - if (window && window.frames.length > 0) { - let num = window.frames.length; - for (let i = 0; i < num; i++) { - // Recurse through the frames. - frameList.concat(this.goThroughFrames(window.frames[i].document, - window.frames[i])); - } - } - return frameList; - }, - - async processFrames(document, frameList, strings) { - let nodeCount = 0; - for (let doc of frameList) { - let iterator = doc.createTreeWalker(doc, content.NodeFilter.SHOW_ELEMENT); - - // Goes through all the elements on the doc. imageViewRows takes only the media elements. - while (iterator.nextNode()) { - let mediaItems = this.getMediaItems(document, strings, iterator.currentNode); - - if (mediaItems.length) { - sendAsyncMessage("PageInfo:mediaData", - {mediaItems, isComplete: false}); - } - - if (++nodeCount % 500 == 0) { - // setTimeout every 500 elements so we don't keep blocking the content process. - await new Promise(resolve => setTimeout(resolve, 10)); - } - } - } - // Send that page info media fetching has finished. - sendAsyncMessage("PageInfo:mediaData", {isComplete: true}); - }, - - getMediaItems(document, strings, elem) { - // Check for images defined in CSS (e.g. background, borders) - let computedStyle = elem.ownerGlobal.getComputedStyle(elem); - // A node can have multiple media items associated with it - for example, - // multiple background images. - let mediaItems = []; - - let addImage = (url, type, alt, el, isBg) => { - let element = this.serializeElementInfo(document, url, type, alt, el, isBg); - mediaItems.push([url, type, alt, element, isBg]); - }; - - if (computedStyle) { - let addImgFunc = (label, urls) => { - for (let url of urls) { - addImage(url, label, strings.notSet, elem, true); - } - }; - // FIXME: This is missing properties. See the implementation of - // getCSSImageURLs for a list of properties. - // - // If you don't care about the message you can also pass "all" here and - // get all the ones the browser knows about. - addImgFunc(strings.mediaBGImg, computedStyle.getCSSImageURLs("background-image")); - addImgFunc(strings.mediaBorderImg, computedStyle.getCSSImageURLs("border-image-source")); - addImgFunc(strings.mediaListImg, computedStyle.getCSSImageURLs("list-style-image")); - addImgFunc(strings.mediaCursor, computedStyle.getCSSImageURLs("cursor")); - } - - // One swi^H^H^Hif-else to rule them all. - if (elem instanceof content.HTMLImageElement) { - addImage(elem.src, strings.mediaImg, - (elem.hasAttribute("alt")) ? elem.alt : strings.notSet, elem, false); - } else if (elem instanceof content.SVGImageElement) { - try { - // Note: makeURLAbsolute will throw if either the baseURI is not a valid URI - // or the URI formed from the baseURI and the URL is not a valid URI. - if (elem.href.baseVal) { - let href = Services.io.newURI(elem.href.baseVal, null, Services.io.newURI(elem.baseURI)).spec; - addImage(href, strings.mediaImg, "", elem, false); - } - } catch (e) { } - } else if (elem instanceof content.HTMLVideoElement) { - addImage(elem.currentSrc, strings.mediaVideo, "", elem, false); - } else if (elem instanceof content.HTMLAudioElement) { - addImage(elem.currentSrc, strings.mediaAudio, "", elem, false); - } else if (elem instanceof content.HTMLLinkElement) { - if (elem.rel && /\bicon\b/i.test(elem.rel)) { - addImage(elem.href, strings.mediaLink, "", elem, false); - } - } else if (elem instanceof content.HTMLInputElement || elem instanceof content.HTMLButtonElement) { - if (elem.type.toLowerCase() == "image") { - addImage(elem.src, strings.mediaInput, - (elem.hasAttribute("alt")) ? elem.alt : strings.notSet, elem, false); - } - } else if (elem instanceof content.HTMLObjectElement) { - addImage(elem.data, strings.mediaObject, this.getValueText(elem), elem, false); - } else if (elem instanceof content.HTMLEmbedElement) { - addImage(elem.src, strings.mediaEmbed, "", elem, false); - } - - return mediaItems; - }, - - /** - * Set up a JSON element object with all the instanceOf and other infomation that - * makePreview in pageInfo.js uses to figure out how to display the preview. - */ - - serializeElementInfo(document, url, type, alt, item, isBG) { - let result = {}; - - let imageText; - if (!isBG && - !(item instanceof content.SVGImageElement) && - !(document instanceof content.ImageDocument)) { - imageText = item.title || item.alt; - - if (!imageText && !(item instanceof content.HTMLImageElement)) { - imageText = this.getValueText(item); - } - } - - result.imageText = imageText; - result.longDesc = item.longDesc; - result.numFrames = 1; - - if (item instanceof content.HTMLObjectElement || - item instanceof content.HTMLEmbedElement || - item instanceof content.HTMLLinkElement) { - result.mimeType = item.type; - } - - if (!result.mimeType && !isBG && item instanceof Ci.nsIImageLoadingContent) { - // Interface for image loading content. - let imageRequest = item.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST); - if (imageRequest) { - result.mimeType = imageRequest.mimeType; - let image = !(imageRequest.imageStatus & imageRequest.STATUS_ERROR) && imageRequest.image; - if (image) { - result.numFrames = image.numFrames; - } - } - } - - // If we have a data url, get the MIME type from the url. - if (!result.mimeType && url.startsWith("data:")) { - let dataMimeType = /^data:(image\/[^;,]+)/i.exec(url); - if (dataMimeType) - result.mimeType = dataMimeType[1].toLowerCase(); - } - - result.HTMLLinkElement = item instanceof content.HTMLLinkElement; - result.HTMLInputElement = item instanceof content.HTMLInputElement; - result.HTMLImageElement = item instanceof content.HTMLImageElement; - result.HTMLObjectElement = item instanceof content.HTMLObjectElement; - result.SVGImageElement = item instanceof content.SVGImageElement; - result.HTMLVideoElement = item instanceof content.HTMLVideoElement; - result.HTMLAudioElement = item instanceof content.HTMLAudioElement; - - if (isBG) { - // Items that are showing this image as a background - // image might not necessarily have a width or height, - // so we'll dynamically generate an image and send up the - // natural dimensions. - let img = content.document.createElement("img"); - img.src = url; - result.naturalWidth = img.naturalWidth; - result.naturalHeight = img.naturalHeight; - } else { - // Otherwise, we can use the current width and height - // of the image. - result.width = item.width; - result.height = item.height; - } - - if (item instanceof content.SVGImageElement) { - result.SVGImageElementWidth = item.width.baseVal.value; - result.SVGImageElementHeight = item.height.baseVal.value; - } - - result.baseURI = item.baseURI; - - return result; - }, - - // Other Misc Stuff - // Modified from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html - // parse a node to extract the contents of the node - getValueText(node) { - - let valueText = ""; - - // Form input elements don't generally contain information that is useful to our callers, so return nothing. - if (node instanceof content.HTMLInputElement || - node instanceof content.HTMLSelectElement || - node instanceof content.HTMLTextAreaElement) { - return valueText; - } - - // Otherwise recurse for each child. - let length = node.childNodes.length; - - for (let i = 0; i < length; i++) { - let childNode = node.childNodes[i]; - let nodeType = childNode.nodeType; - - // Text nodes are where the goods are. - if (nodeType == content.Node.TEXT_NODE) { - valueText += " " + childNode.nodeValue; - } else if (nodeType == content.Node.ELEMENT_NODE) { - // And elements can have more text inside them. - // Images are special, we want to capture the alt text as if the image weren't there. - if (childNode instanceof content.HTMLImageElement) { - valueText += " " + this.getAltText(childNode); - } else { - valueText += " " + this.getValueText(childNode); - } - } - } - - return this.stripWS(valueText); - }, - - // Copied from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html. - // Traverse the tree in search of an img or area element and grab its alt tag. - getAltText(node) { - let altText = ""; - - if (node.alt) { - return node.alt; - } - let length = node.childNodes.length; - for (let i = 0; i < length; i++) { - if ((altText = this.getAltText(node.childNodes[i]) != undefined)) { // stupid js warning... - return altText; - } - } - return ""; - }, - - // Copied from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html. - // Strip leading and trailing whitespace, and replace multiple consecutive whitespace characters with a single space. - stripWS(text) { - let middleRE = /\s+/g; - let endRE = /(^\s+)|(\s+$)/g; - - text = text.replace(middleRE, " "); - return text.replace(endRE, ""); - } -}; -PageInfoListener.init(); - let OfflineApps = { _docId: 0, _docIdMap: new Map(), diff --git a/browser/modules/PageInfoListener.jsm b/browser/modules/PageInfoListener.jsm new file mode 100644 index 000000000000..fab0816e8971 --- /dev/null +++ b/browser/modules/PageInfoListener.jsm @@ -0,0 +1,372 @@ +var PageInfoListener = { + init() { + addMessageListener("PageInfo:getData", this); + }, + + receiveMessage(message) { + let strings = message.data.strings; + let window; + let document; + + let frameOuterWindowID = message.data.frameOuterWindowID; + + // If inside frame then get the frame's window and document. + if (frameOuterWindowID != undefined) { + window = Services.wm.getOuterWindowWithId(frameOuterWindowID); + document = window.document; + } else { + window = content.window; + document = content.document; + } + + let pageInfoData = {metaViewRows: this.getMetaInfo(document), + docInfo: this.getDocumentInfo(document), + feeds: this.getFeedsInfo(document, strings), + windowInfo: this.getWindowInfo(window)}; + + sendAsyncMessage("PageInfo:data", pageInfoData); + + // Separate step so page info dialog isn't blank while waiting for this to finish. + this.getMediaInfo(document, window, strings); + }, + + getMetaInfo(document) { + let metaViewRows = []; + + // Get the meta tags from the page. + let metaNodes = document.getElementsByTagName("meta"); + + for (let metaNode of metaNodes) { + metaViewRows.push([metaNode.name || metaNode.httpEquiv || metaNode.getAttribute("property"), + metaNode.content]); + } + + return metaViewRows; + }, + + getWindowInfo(window) { + let windowInfo = {}; + windowInfo.isTopWindow = window == window.top; + + let hostName = null; + try { + hostName = Services.io.newURI(window.location.href).displayHost; + } catch (exception) { } + + windowInfo.hostName = hostName; + return windowInfo; + }, + + getDocumentInfo(document) { + let docInfo = {}; + docInfo.title = document.title; + docInfo.location = document.location.toString(); + try { + docInfo.location = Services.io.newURI(document.location.toString()).displaySpec; + } catch (exception) { } + docInfo.referrer = document.referrer; + try { + if (document.referrer) { + docInfo.referrer = Services.io.newURI(document.referrer).displaySpec; + } + } catch (exception) { } + docInfo.compatMode = document.compatMode; + docInfo.contentType = document.contentType; + docInfo.characterSet = document.characterSet; + docInfo.lastModified = document.lastModified; + docInfo.principal = document.nodePrincipal; + + let documentURIObject = {}; + documentURIObject.spec = document.documentURIObject.spec; + docInfo.documentURIObject = documentURIObject; + + docInfo.isContentWindowPrivate = PrivateBrowsingUtils.isContentWindowPrivate(content); + + return docInfo; + }, + + getFeedsInfo(document, strings) { + let feeds = []; + // Get the feeds from the page. + let linkNodes = document.getElementsByTagName("link"); + let length = linkNodes.length; + for (let i = 0; i < length; i++) { + let link = linkNodes[i]; + if (!link.href) { + continue; + } + let rel = link.rel && link.rel.toLowerCase(); + let rels = {}; + + if (rel) { + for (let relVal of rel.split(/\s+/)) { + rels[relVal] = true; + } + } + + if (rels.feed || (link.type && rels.alternate && !rels.stylesheet)) { + let type = Feeds.isValidFeed(link, document.nodePrincipal, "feed" in rels); + if (type) { + type = strings[type] || strings["application/rss+xml"]; + feeds.push([link.title, type, link.href]); + } + } + } + return feeds; + }, + + // Only called once to get the media tab's media elements from the content page. + getMediaInfo(document, window, strings) { + let frameList = this.goThroughFrames(document, window); + this.processFrames(document, frameList, strings); + }, + + goThroughFrames(document, window) { + let frameList = [document]; + if (window && window.frames.length > 0) { + let num = window.frames.length; + for (let i = 0; i < num; i++) { + // Recurse through the frames. + frameList.concat(this.goThroughFrames(window.frames[i].document, + window.frames[i])); + } + } + return frameList; + }, + + async processFrames(document, frameList, strings) { + let nodeCount = 0; + for (let doc of frameList) { + let iterator = doc.createTreeWalker(doc, content.NodeFilter.SHOW_ELEMENT); + + // Goes through all the elements on the doc. imageViewRows takes only the media elements. + while (iterator.nextNode()) { + let mediaItems = this.getMediaItems(document, strings, iterator.currentNode); + + if (mediaItems.length) { + sendAsyncMessage("PageInfo:mediaData", + {mediaItems, isComplete: false}); + } + + if (++nodeCount % 500 == 0) { + // setTimeout every 500 elements so we don't keep blocking the content process. + await new Promise(resolve => setTimeout(resolve, 10)); + } + } + } + // Send that page info media fetching has finished. + sendAsyncMessage("PageInfo:mediaData", {isComplete: true}); + }, + + getMediaItems(document, strings, elem) { + // Check for images defined in CSS (e.g. background, borders) + let computedStyle = elem.ownerGlobal.getComputedStyle(elem); + // A node can have multiple media items associated with it - for example, + // multiple background images. + let mediaItems = []; + + let addImage = (url, type, alt, el, isBg) => { + let element = this.serializeElementInfo(document, url, type, alt, el, isBg); + mediaItems.push([url, type, alt, element, isBg]); + }; + + if (computedStyle) { + let addImgFunc = (label, urls) => { + for (let url of urls) { + addImage(url, label, strings.notSet, elem, true); + } + }; + // FIXME: This is missing properties. See the implementation of + // getCSSImageURLs for a list of properties. + // + // If you don't care about the message you can also pass "all" here and + // get all the ones the browser knows about. + addImgFunc(strings.mediaBGImg, computedStyle.getCSSImageURLs("background-image")); + addImgFunc(strings.mediaBorderImg, computedStyle.getCSSImageURLs("border-image-source")); + addImgFunc(strings.mediaListImg, computedStyle.getCSSImageURLs("list-style-image")); + addImgFunc(strings.mediaCursor, computedStyle.getCSSImageURLs("cursor")); + } + + // One swi^H^H^Hif-else to rule them all. + if (elem instanceof content.HTMLImageElement) { + addImage(elem.src, strings.mediaImg, + (elem.hasAttribute("alt")) ? elem.alt : strings.notSet, elem, false); + } else if (elem instanceof content.SVGImageElement) { + try { + // Note: makeURLAbsolute will throw if either the baseURI is not a valid URI + // or the URI formed from the baseURI and the URL is not a valid URI. + if (elem.href.baseVal) { + let href = Services.io.newURI(elem.href.baseVal, null, Services.io.newURI(elem.baseURI)).spec; + addImage(href, strings.mediaImg, "", elem, false); + } + } catch (e) { } + } else if (elem instanceof content.HTMLVideoElement) { + addImage(elem.currentSrc, strings.mediaVideo, "", elem, false); + } else if (elem instanceof content.HTMLAudioElement) { + addImage(elem.currentSrc, strings.mediaAudio, "", elem, false); + } else if (elem instanceof content.HTMLLinkElement) { + if (elem.rel && /\bicon\b/i.test(elem.rel)) { + addImage(elem.href, strings.mediaLink, "", elem, false); + } + } else if (elem instanceof content.HTMLInputElement || elem instanceof content.HTMLButtonElement) { + if (elem.type.toLowerCase() == "image") { + addImage(elem.src, strings.mediaInput, + (elem.hasAttribute("alt")) ? elem.alt : strings.notSet, elem, false); + } + } else if (elem instanceof content.HTMLObjectElement) { + addImage(elem.data, strings.mediaObject, this.getValueText(elem), elem, false); + } else if (elem instanceof content.HTMLEmbedElement) { + addImage(elem.src, strings.mediaEmbed, "", elem, false); + } + + return mediaItems; + }, + + /** + * Set up a JSON element object with all the instanceOf and other infomation that + * makePreview in pageInfo.js uses to figure out how to display the preview. + */ + + serializeElementInfo(document, url, type, alt, item, isBG) { + let result = {}; + + let imageText; + if (!isBG && + !(item instanceof content.SVGImageElement) && + !(document instanceof content.ImageDocument)) { + imageText = item.title || item.alt; + + if (!imageText && !(item instanceof content.HTMLImageElement)) { + imageText = this.getValueText(item); + } + } + + result.imageText = imageText; + result.longDesc = item.longDesc; + result.numFrames = 1; + + if (item instanceof content.HTMLObjectElement || + item instanceof content.HTMLEmbedElement || + item instanceof content.HTMLLinkElement) { + result.mimeType = item.type; + } + + if (!result.mimeType && !isBG && item instanceof Ci.nsIImageLoadingContent) { + // Interface for image loading content. + let imageRequest = item.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST); + if (imageRequest) { + result.mimeType = imageRequest.mimeType; + let image = !(imageRequest.imageStatus & imageRequest.STATUS_ERROR) && imageRequest.image; + if (image) { + result.numFrames = image.numFrames; + } + } + } + + // If we have a data url, get the MIME type from the url. + if (!result.mimeType && url.startsWith("data:")) { + let dataMimeType = /^data:(image\/[^;,]+)/i.exec(url); + if (dataMimeType) + result.mimeType = dataMimeType[1].toLowerCase(); + } + + result.HTMLLinkElement = item instanceof content.HTMLLinkElement; + result.HTMLInputElement = item instanceof content.HTMLInputElement; + result.HTMLImageElement = item instanceof content.HTMLImageElement; + result.HTMLObjectElement = item instanceof content.HTMLObjectElement; + result.SVGImageElement = item instanceof content.SVGImageElement; + result.HTMLVideoElement = item instanceof content.HTMLVideoElement; + result.HTMLAudioElement = item instanceof content.HTMLAudioElement; + + if (isBG) { + // Items that are showing this image as a background + // image might not necessarily have a width or height, + // so we'll dynamically generate an image and send up the + // natural dimensions. + let img = content.document.createElement("img"); + img.src = url; + result.naturalWidth = img.naturalWidth; + result.naturalHeight = img.naturalHeight; + } else { + // Otherwise, we can use the current width and height + // of the image. + result.width = item.width; + result.height = item.height; + } + + if (item instanceof content.SVGImageElement) { + result.SVGImageElementWidth = item.width.baseVal.value; + result.SVGImageElementHeight = item.height.baseVal.value; + } + + result.baseURI = item.baseURI; + + return result; + }, + + // Other Misc Stuff + // Modified from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html + // parse a node to extract the contents of the node + getValueText(node) { + + let valueText = ""; + + // Form input elements don't generally contain information that is useful to our callers, so return nothing. + if (node instanceof content.HTMLInputElement || + node instanceof content.HTMLSelectElement || + node instanceof content.HTMLTextAreaElement) { + return valueText; + } + + // Otherwise recurse for each child. + let length = node.childNodes.length; + + for (let i = 0; i < length; i++) { + let childNode = node.childNodes[i]; + let nodeType = childNode.nodeType; + + // Text nodes are where the goods are. + if (nodeType == content.Node.TEXT_NODE) { + valueText += " " + childNode.nodeValue; + } else if (nodeType == content.Node.ELEMENT_NODE) { + // And elements can have more text inside them. + // Images are special, we want to capture the alt text as if the image weren't there. + if (childNode instanceof content.HTMLImageElement) { + valueText += " " + this.getAltText(childNode); + } else { + valueText += " " + this.getValueText(childNode); + } + } + } + + return this.stripWS(valueText); + }, + + // Copied from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html. + // Traverse the tree in search of an img or area element and grab its alt tag. + getAltText(node) { + let altText = ""; + + if (node.alt) { + return node.alt; + } + let length = node.childNodes.length; + for (let i = 0; i < length; i++) { + if ((altText = this.getAltText(node.childNodes[i]) != undefined)) { // stupid js warning... + return altText; + } + } + return ""; + }, + + // Copied from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html. + // Strip leading and trailing whitespace, and replace multiple consecutive whitespace characters with a single space. + stripWS(text) { + let middleRE = /\s+/g; + let endRE = /(^\s+)|(\s+$)/g; + + text = text.replace(middleRE, " "); + return text.replace(endRE, ""); + } +}; +PageInfoListener.init(); diff --git a/browser/modules/moz.build b/browser/modules/moz.build index a07360b2d452..5796d6ec5ac7 100644 --- a/browser/modules/moz.build +++ b/browser/modules/moz.build @@ -70,6 +70,9 @@ with Files("ExtensionsUI.jsm"): with Files("LaterRun.jsm"): BUG_COMPONENT = ("Firefox", "Tours") +with Files("PageInfoListener.jsm"): + BUG_COMPONENT = ("Firefox", "Page Info Window") + with Files("PermissionUI.jsm"): BUG_COMPONENT = ("Firefox", "Site Identity and Permission Panels") @@ -145,6 +148,7 @@ EXTRA_JS_MODULES += [ 'LaterRun.jsm', 'OpenInTabsUtils.jsm', 'PageActions.jsm', + 'PageInfoListener.jsm', 'PermissionUI.jsm', 'PingCentre.jsm', 'PluginContent.jsm',