зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1461444 - Part 0. Copy PageInfoListener code from content.js to a new file. r=johannh
--HG-- rename : browser/base/content/content.js => browser/modules/PageInfoListener.jsm
This commit is contained in:
Родитель
24fba1c383
Коммит
9c7cf9d19b
|
@ -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(),
|
||||
|
|
|
@ -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();
|
|
@ -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',
|
||||
|
|
Загрузка…
Ссылка в новой задаче