home *** CD-ROM | disk | FTP | other *** search
- //@line 59 "/build/buildd/firefox-3.0-3.0.14+build2+nobinonly/build-tree/mozilla/browser/base/content/nsContextMenu.js"
-
- function nsContextMenu(aXulMenu, aBrowser) {
- this.target = null;
- this.browser = null;
- this.menu = null;
- this.isFrameImage = false;
- this.onTextInput = false;
- this.onKeywordField = false;
- this.onImage = false;
- this.onLoadedImage = false;
- this.onCompletedImage = false;
- this.onCanvas = false;
- this.onLink = false;
- this.onMailtoLink = false;
- this.onSaveableLink = false;
- this.onMetaDataItem = false;
- this.onMathML = false;
- this.link = false;
- this.linkURL = "";
- this.linkURI = null;
- this.linkProtocol = null;
- this.inFrame = false;
- this.hasBGImage = false;
- this.isTextSelected = false;
- this.isContentSelected = false;
- this.inDirList = false;
- this.shouldDisplay = true;
- this.isDesignMode = false;
- this.possibleSpellChecking = false;
- this.ellipsis = "\u2026";
- try {
- this.ellipsis = gPrefService.getComplexValue("intl.ellipsis",
- Ci.nsIPrefLocalizedString).data;
- } catch (e) { }
-
- // Initialize new menu.
- this.initMenu(aXulMenu, aBrowser);
- }
-
- // Prototype for nsContextMenu "class."
- nsContextMenu.prototype = {
- // onDestroy is a no-op at this point.
- onDestroy: function () {
- },
-
- // Initialize context menu.
- initMenu: function CM_initMenu(aPopup, aBrowser) {
- this.menu = aPopup;
- this.browser = aBrowser;
-
- this.isFrameImage = document.getElementById("isFrameImage");
-
- // Get contextual info.
- this.setTarget(document.popupNode, document.popupRangeParent,
- document.popupRangeOffset);
-
- this.isTextSelected = this.isTextSelection();
- this.isContentSelected = this.isContentSelection();
-
- // Initialize (disable/remove) menu items.
- this.initItems();
- },
-
- initItems: function CM_initItems() {
- this.initOpenItems();
- this.initNavigationItems();
- this.initViewItems();
- this.initMiscItems();
- this.initSpellingItems();
- this.initSaveItems();
- this.initClipboardItems();
- this.initMetadataItems();
- },
-
- initOpenItems: function CM_initOpenItems() {
- var shouldShow = this.onSaveableLink ||
- (this.inDirList && this.onLink);
- this.showItem("context-openlink", shouldShow);
- this.showItem("context-openlinkintab", shouldShow);
- this.showItem("context-sep-open", shouldShow);
- },
-
- initNavigationItems: function CM_initNavigationItems() {
- var shouldShow = !(this.isContentSelected || this.onLink || this.onImage ||
- this.onCanvas || this.onTextInput);
- this.showItem("context-back", shouldShow);
- this.showItem("context-forward", shouldShow);
- this.showItem("context-reload", shouldShow);
- this.showItem("context-stop", shouldShow);
- this.showItem("context-sep-stop", shouldShow);
-
- // XXX: Stop is determined in browser.js; the canStop broadcaster is broken
- //this.setItemAttrFromNode( "context-stop", "disabled", "canStop" );
- },
-
- initSaveItems: function CM_initSaveItems() {
- var shouldShow = !(this.inDirList || this.onTextInput || this.onLink ||
- this.isContentSelected || this.onImage || this.onCanvas);
- this.showItem("context-savepage", shouldShow);
- this.showItem("context-sendpage", shouldShow);
-
- // Save+Send link depends on whether we're in a link.
- this.showItem("context-savelink", this.onSaveableLink);
- this.showItem("context-sendlink", this.onSaveableLink);
-
- // Save image depends on whether we're on a loaded image, or a canvas.
- this.showItem("context-saveimage", this.onLoadedImage || this.onCanvas);
- // We can send an image (even unloaded), but not a canvas:
- this.showItem("context-sendimage", this.onImage);
- },
-
- initViewItems: function CM_initViewItems() {
- // View source is always OK, unless in directory listing.
- this.showItem("context-viewpartialsource-selection",
- this.isContentSelected);
- this.showItem("context-viewpartialsource-mathml",
- this.onMathML && !this.isContentSelected);
-
- var shouldShow = !(this.inDirList || this.isContentSelected ||
- this.onImage || this.onLink || this.onTextInput);
- this.showItem("context-viewsource", shouldShow);
- this.showItem("context-viewinfo", shouldShow);
-
- this.showItem("context-sep-properties",
- !(this.inDirList || this.isContentSelected ||
- this.onTextInput));
-
- // Set as Desktop background depends on whether an image was clicked on,
- // and only works if we have a shell service.
- var haveSetDesktopBackground = false;
- //@line 190 "/build/buildd/firefox-3.0-3.0.14+build2+nobinonly/build-tree/mozilla/browser/base/content/nsContextMenu.js"
- // Only enable Set as Desktop Background if we can get the shell service.
- var shell = getShellService();
- if (shell)
- haveSetDesktopBackground = true;
- //@line 195 "/build/buildd/firefox-3.0-3.0.14+build2+nobinonly/build-tree/mozilla/browser/base/content/nsContextMenu.js"
- this.showItem("context-setDesktopBackground",
- haveSetDesktopBackground && this.onLoadedImage);
-
- if (haveSetDesktopBackground && this.onLoadedImage) {
- document.getElementById("context-setDesktopBackground")
- .disabled = this.disableSetDesktopBackground();
- }
-
- // Show image depends on an image that's not fully loaded
- this.showItem("context-showimage", (this.onImage && !this.onCompletedImage));
-
- // View image depends on having an image that's not standalone
- // (or is in a frame), or a canvas.
- this.showItem("context-viewimage", (this.onImage &&
- (!this.onStandaloneImage || this.inFrame)) || this.onCanvas);
-
- // View background image depends on whether there is one.
- this.showItem("context-viewbgimage", shouldShow);
- this.showItem("context-sep-viewbgimage", shouldShow);
- document.getElementById("context-viewbgimage")
- .disabled = !this.hasBGImage;
- },
-
- initMiscItems: function CM_initMiscItems() {
- // Use "Bookmark This Link" if on a link.
- this.showItem("context-bookmarkpage",
- !(this.isContentSelected || this.onTextInput ||
- this.onLink || this.onImage));
- this.showItem("context-bookmarklink", this.onLink && !this.onMailtoLink);
- this.showItem("context-searchselect", this.isTextSelected);
- this.showItem("context-keywordfield",
- this.onTextInput && this.onKeywordField);
- this.showItem("frame", this.inFrame);
- this.showItem("frame-sep", this.inFrame);
-
- // Hide menu entries for images, show otherwise
- if (this.inFrame) {
- if (mimeTypeIsTextBased(this.target.ownerDocument.contentType))
- this.isFrameImage.removeAttribute('hidden');
- else
- this.isFrameImage.setAttribute('hidden', 'true');
- }
-
- // BiDi UI
- this.showItem("context-sep-bidi", top.gBidiUI);
- this.showItem("context-bidi-text-direction-toggle",
- this.onTextInput && top.gBidiUI);
- this.showItem("context-bidi-page-direction-toggle",
- !this.onTextInput && top.gBidiUI);
-
- if (this.onImage) {
- var blockImage = document.getElementById("context-blockimage");
-
- var uri = this.target
- .QueryInterface(Ci.nsIImageLoadingContent)
- .currentURI;
-
- // this throws if the image URI doesn't have a host (eg, data: image URIs)
- // see bug 293758 for details
- var hostLabel = "";
- try {
- hostLabel = uri.host;
- } catch (ex) { }
-
- if (hostLabel) {
- var shortenedUriHost = hostLabel.replace(/^www\./i,"");
- if (shortenedUriHost.length > 15)
- shortenedUriHost = shortenedUriHost.substr(0,15) + this.ellipsis;
- blockImage.label = gNavigatorBundle.getFormattedString("blockImages", [shortenedUriHost]);
-
- if (this.isImageBlocked())
- blockImage.setAttribute("checked", "true");
- else
- blockImage.removeAttribute("checked");
- }
- }
-
- // Only show the block image item if the image can be blocked
- this.showItem("context-blockimage", this.onImage && hostLabel);
- },
-
- initSpellingItems: function() {
- var canSpell = InlineSpellCheckerUI.canSpellCheck;
- var onMisspelling = InlineSpellCheckerUI.overMisspelling;
- this.showItem("spell-check-enabled", canSpell);
- this.showItem("spell-separator", canSpell || this.possibleSpellChecking);
- if (canSpell) {
- document.getElementById("spell-check-enabled")
- .setAttribute("checked", InlineSpellCheckerUI.enabled);
- }
-
- this.showItem("spell-add-to-dictionary", onMisspelling);
-
- // suggestion list
- this.showItem("spell-suggestions-separator", onMisspelling);
- if (onMisspelling) {
- var menu = document.getElementById("contentAreaContextMenu");
- var suggestionsSeparator =
- document.getElementById("spell-add-to-dictionary");
- var numsug = InlineSpellCheckerUI.addSuggestionsToMenu(menu, suggestionsSeparator, 5);
- this.showItem("spell-no-suggestions", numsug == 0);
- }
- else
- this.showItem("spell-no-suggestions", false);
-
- // dictionary list
- this.showItem("spell-dictionaries", InlineSpellCheckerUI.enabled);
- if (canSpell) {
- var dictMenu = document.getElementById("spell-dictionaries-menu");
- var dictSep = document.getElementById("spell-language-separator");
- InlineSpellCheckerUI.addDictionaryListToMenu(dictMenu, dictSep);
- this.showItem("spell-add-dictionaries-main", false);
- }
- else if (this.possibleSpellChecking) {
- // when there is no spellchecker but we might be able to spellcheck
- // add the add to dictionaries item. This will ensure that people
- // with no dictionaries will be able to download them
- this.showItem("spell-add-dictionaries-main", true);
- }
- else
- this.showItem("spell-add-dictionaries-main", false);
- },
-
- initClipboardItems: function() {
- // Copy depends on whether there is selected text.
- // Enabling this context menu item is now done through the global
- // command updating system
- // this.setItemAttr( "context-copy", "disabled", !this.isTextSelected() );
- goUpdateGlobalEditMenuItems();
-
- this.showItem("context-undo", this.onTextInput);
- this.showItem("context-sep-undo", this.onTextInput);
- this.showItem("context-cut", this.onTextInput);
- this.showItem("context-copy",
- this.isContentSelected || this.onTextInput);
- this.showItem("context-paste", this.onTextInput);
- this.showItem("context-delete", this.onTextInput);
- this.showItem("context-sep-paste", this.onTextInput);
- this.showItem("context-selectall",
- !(this.onLink || this.onImage) || this.isDesignMode);
- this.showItem("context-sep-selectall", this.isContentSelected );
-
- // XXX dr
- // ------
- // nsDocumentViewer.cpp has code to determine whether we're
- // on a link or an image. we really ought to be using that...
-
- // Copy email link depends on whether we're on an email link.
- this.showItem("context-copyemail", this.onMailtoLink);
-
- // Copy link location depends on whether we're on a non-mailto link.
- this.showItem("context-copylink", this.onLink && !this.onMailtoLink);
- this.showItem("context-sep-copylink", this.onLink && this.onImage);
-
- //@line 350 "/build/buildd/firefox-3.0-3.0.14+build2+nobinonly/build-tree/mozilla/browser/base/content/nsContextMenu.js"
- // Copy image contents depends on whether we're on an image.
- this.showItem("context-copyimage-contents", this.onImage);
- //@line 353 "/build/buildd/firefox-3.0-3.0.14+build2+nobinonly/build-tree/mozilla/browser/base/content/nsContextMenu.js"
- // Copy image location depends on whether we're on an image.
- this.showItem("context-copyimage", this.onImage);
- this.showItem("context-sep-copyimage", this.onImage);
- },
-
- initMetadataItems: function() {
- // Show if user clicked on something which has metadata.
- this.showItem("context-metadata", this.onMetaDataItem);
- },
-
- // Set various context menu attributes based on the state of the world.
- setTarget: function (aNode, aRangeParent, aRangeOffset) {
- const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
- if (aNode.namespaceURI == xulNS ||
- this.isTargetAFormControl(aNode)) {
- this.shouldDisplay = false;
- }
-
- // Initialize contextual info.
- this.onImage = false;
- this.onLoadedImage = false;
- this.onCompletedImage = false;
- this.onStandaloneImage = false;
- this.onCanvas = false;
- this.onMetaDataItem = false;
- this.onTextInput = false;
- this.onKeywordField = false;
- this.imageURL = "";
- this.onLink = false;
- this.linkURL = "";
- this.linkURI = null;
- this.linkProtocol = "";
- this.onMathML = false;
- this.inFrame = false;
- this.hasBGImage = false;
- this.bgImageURL = "";
- this.possibleSpellChecking = false;
-
- // Clear any old spellchecking items from the menu, this used to
- // be in the menu hiding code but wasn't getting called in all
- // situations. Here, we can ensure it gets cleaned up any time the
- // menu is shown. Note: must be before uninit because that clears the
- // internal vars
- InlineSpellCheckerUI.clearSuggestionsFromMenu();
- InlineSpellCheckerUI.clearDictionaryListFromMenu();
-
- InlineSpellCheckerUI.uninit();
-
- // Remember the node that was clicked.
- this.target = aNode;
-
- // First, do checks for nodes that never have children.
- if (this.target.nodeType == Node.ELEMENT_NODE) {
- // See if the user clicked on an image.
- if (this.target instanceof Ci.nsIImageLoadingContent &&
- this.target.currentURI) {
- this.onImage = true;
- this.onMetaDataItem = true;
-
- var request =
- this.target.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
- if (request && (request.imageStatus & request.STATUS_SIZE_AVAILABLE))
- this.onLoadedImage = true;
- if (request && (request.imageStatus & request.STATUS_LOAD_COMPLETE))
- this.onCompletedImage = true;
-
- this.imageURL = this.target.currentURI.spec;
- if (this.target.ownerDocument instanceof ImageDocument)
- this.onStandaloneImage = true;
- }
- else if (this.target instanceof HTMLCanvasElement) {
- this.onCanvas = true;
- }
- else if (this.target instanceof HTMLInputElement ) {
- this.onTextInput = this.isTargetATextBox(this.target);
- // allow spellchecking UI on all writable text boxes except passwords
- if (this.onTextInput && ! this.target.readOnly &&
- this.target.type != "password") {
- this.possibleSpellChecking = true;
- InlineSpellCheckerUI.init(this.target.QueryInterface(Ci.nsIDOMNSEditableElement).editor);
- InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset);
- }
- this.onKeywordField = this.isTargetAKeywordField(this.target);
- }
- else if (this.target instanceof HTMLTextAreaElement) {
- this.onTextInput = true;
- if (!this.target.readOnly) {
- this.possibleSpellChecking = true;
- InlineSpellCheckerUI.init(this.target.QueryInterface(Ci.nsIDOMNSEditableElement).editor);
- InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset);
- }
- }
- else if (this.target instanceof HTMLHtmlElement) {
- var bodyElt = this.target.ownerDocument.body;
- if (bodyElt) {
- var computedURL = this.getComputedURL(bodyElt, "background-image");
- if (computedURL) {
- this.hasBGImage = true;
- this.bgImageURL = makeURLAbsolute(bodyElt.baseURI,
- computedURL);
- }
- }
- }
- else if ("HTTPIndex" in content &&
- content.HTTPIndex instanceof Ci.nsIHTTPIndex) {
- this.inDirList = true;
- // Bubble outward till we get to an element with URL attribute
- // (which should be the href).
- var root = this.target;
- while (root && !this.link) {
- if (root.tagName == "tree") {
- // Hit root of tree; must have clicked in empty space;
- // thus, no link.
- break;
- }
-
- if (root.getAttribute("URL")) {
- // Build pseudo link object so link-related functions work.
- this.onLink = true;
- this.link = { href : root.getAttribute("URL"),
- getAttribute: function (aAttr) {
- if (aAttr == "title") {
- return root.firstChild.firstChild
- .getAttribute("label");
- }
- else
- return "";
- }
- };
-
- // If element is a directory, then you can't save it.
- this.onSaveableLink = root.getAttribute("container") != "true";
- }
- else
- root = root.parentNode;
- }
- }
- }
-
- // Second, bubble out, looking for items of interest that can have childen.
- // Always pick the innermost link, background image, etc.
- const XMLNS = "http://www.w3.org/XML/1998/namespace";
- var elem = this.target;
- while (elem) {
- if (elem.nodeType == Node.ELEMENT_NODE) {
- // Link?
- if (!this.onLink &&
- ((elem instanceof HTMLAnchorElement && elem.href) ||
- (elem instanceof HTMLAreaElement && elem.href) ||
- elem instanceof HTMLLinkElement ||
- elem.getAttributeNS("http://www.w3.org/1999/xlink", "type") == "simple")) {
-
- // Target is a link or a descendant of a link.
- this.onLink = true;
- this.onMetaDataItem = true;
-
- // xxxmpc: this is kind of a hack to work around a Gecko bug (see bug 266932)
- // we're going to walk up the DOM looking for a parent link node,
- // this shouldn't be necessary, but we're matching the existing behaviour for left click
- var realLink = elem;
- var parent = elem;
- while ((parent = parent.parentNode) &&
- (parent.nodeType == Node.ELEMENT_NODE)) {
- try {
- if ((parent instanceof HTMLAnchorElement && parent.href) ||
- (parent instanceof HTMLAreaElement && parent.href) ||
- parent instanceof HTMLLinkElement ||
- parent.getAttributeNS("http://www.w3.org/1999/xlink", "type") == "simple")
- realLink = parent;
- } catch (e) { }
- }
-
- // Remember corresponding element.
- this.link = realLink;
- this.linkURL = this.getLinkURL();
- this.linkURI = this.getLinkURI();
- this.linkProtocol = this.getLinkProtocol();
- this.onMailtoLink = (this.linkProtocol == "mailto");
- this.onSaveableLink = this.isLinkSaveable( this.link );
- }
-
- // Metadata item?
- if (!this.onMetaDataItem) {
- // We display metadata on anything which fits
- // the below test, as well as for links and images
- // (which set this.onMetaDataItem to true elsewhere)
- if ((elem instanceof HTMLQuoteElement && elem.cite) ||
- (elem instanceof HTMLTableElement && elem.summary) ||
- (elem instanceof HTMLModElement &&
- (elem.cite || elem.dateTime)) ||
- (elem instanceof HTMLElement &&
- (elem.title || elem.lang)) ||
- elem.getAttributeNS(XMLNS, "lang")) {
- this.onMetaDataItem = true;
- }
- }
-
- // Background image? Don't bother if we've already found a
- // background image further down the hierarchy. Otherwise,
- // we look for the computed background-image style.
- if (!this.hasBGImage) {
- var bgImgUrl = this.getComputedURL( elem, "background-image" );
- if (bgImgUrl) {
- this.hasBGImage = true;
- this.bgImageURL = makeURLAbsolute(elem.baseURI,
- bgImgUrl);
- }
- }
- }
-
- elem = elem.parentNode;
- }
-
- // See if the user clicked on MathML
- const NS_MathML = "http://www.w3.org/1998/Math/MathML";
- if ((this.target.nodeType == Node.TEXT_NODE &&
- this.target.parentNode.namespaceURI == NS_MathML)
- || (this.target.namespaceURI == NS_MathML))
- this.onMathML = true;
-
- // See if the user clicked in a frame.
- var docDefaultView = this.target.ownerDocument.defaultView;
- if (docDefaultView != docDefaultView.top)
- this.inFrame = true;
-
- // if the document is editable, show context menu like in text inputs
- var win = this.target.ownerDocument.defaultView;
- if (win) {
- var isEditable = false;
- try {
- var editingSession = win.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession);
- if (editingSession.windowIsEditable(win) &&
- this.getComputedStyle(this.target, "-moz-user-modify") == "read-write") {
- isEditable = true;
- }
- }
- catch(ex) {
- // If someone built with composer disabled, we can't get an editing session.
- }
-
- if (isEditable) {
- this.onTextInput = true;
- this.onKeywordField = false;
- this.onImage = false;
- this.onLoadedImage = false;
- this.onCompletedImage = false;
- this.onMetaDataItem = false;
- this.onMathML = false;
- this.inFrame = false;
- this.hasBGImage = false;
- this.isDesignMode = true;
- this.possibleSpellChecking = true;
- InlineSpellCheckerUI.init(editingSession.getEditorForWindow(win));
- var canSpell = InlineSpellCheckerUI.canSpellCheck;
- InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset);
- this.showItem("spell-check-enabled", canSpell);
- this.showItem("spell-separator", canSpell);
- }
- }
- },
-
- // Returns the computed style attribute for the given element.
- getComputedStyle: function(aElem, aProp) {
- return aElem.ownerDocument
- .defaultView
- .getComputedStyle(aElem, "").getPropertyValue(aProp);
- },
-
- // Returns a "url"-type computed style attribute value, with the url() stripped.
- getComputedURL: function(aElem, aProp) {
- var url = aElem.ownerDocument
- .defaultView.getComputedStyle(aElem, "")
- .getPropertyCSSValue(aProp);
- return url.primitiveType == CSSPrimitiveValue.CSS_URI ?
- url.getStringValue() : null;
- },
-
- // Returns true if clicked-on link targets a resource that can be saved.
- isLinkSaveable: function(aLink) {
- // We don't do the Right Thing for news/snews yet, so turn them off
- // until we do.
- return this.linkProtocol && !(
- this.linkProtocol == "mailto" ||
- this.linkProtocol == "javascript" ||
- this.linkProtocol == "news" ||
- this.linkProtocol == "snews" );
- },
-
- // Open linked-to URL in a new window.
- openLink : function () {
- openNewWindowWith(this.linkURL, this.target.ownerDocument, null, false);
- },
-
- // Open linked-to URL in a new tab.
- openLinkInTab: function() {
- openNewTabWith(this.linkURL, this.target.ownerDocument, null, null, false);
- },
-
- // Open frame in a new tab.
- openFrameInTab: function() {
- var doc = this.target.ownerDocument;
- var frameURL = doc.location.href;
- var referrer = doc.referrer;
-
- return openNewTabWith(frameURL, null, null, null, false,
- referrer ? makeURI(referrer) : null);
- },
-
- // Reload clicked-in frame.
- reloadFrame: function() {
- this.target.ownerDocument.location.reload();
- },
-
- // Open clicked-in frame in its own window.
- openFrame: function() {
- var doc = this.target.ownerDocument;
- var frameURL = doc.location.href;
- var referrer = doc.referrer;
-
- return openNewWindowWith(frameURL, null, null, false,
- referrer ? makeURI(referrer) : null);
- },
-
- // Open clicked-in frame in the same window.
- showOnlyThisFrame: function() {
- var doc = this.target.ownerDocument;
- var frameURL = doc.location.href;
-
- urlSecurityCheck(frameURL, this.browser.contentPrincipal,
- Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
- var referrer = doc.referrer;
- this.browser.loadURI(frameURL, referrer ? makeURI(referrer) : null);
- },
-
- // View Partial Source
- viewPartialSource: function(aContext) {
- var focusedWindow = document.commandDispatcher.focusedWindow;
- if (focusedWindow == window)
- focusedWindow = content;
-
- var docCharset = null;
- if (focusedWindow)
- docCharset = "charset=" + focusedWindow.document.characterSet;
-
- // "View Selection Source" and others such as "View MathML Source"
- // are mutually exclusive, with the precedence given to the selection
- // when there is one
- var reference = null;
- if (aContext == "selection")
- reference = focusedWindow.getSelection();
- else if (aContext == "mathml")
- reference = this.target;
- else
- throw "not reached";
-
- // unused (and play nice for fragments generated via XSLT too)
- var docUrl = null;
- window.openDialog("chrome://global/content/viewPartialSource.xul",
- "_blank", "scrollbars,resizable,chrome,dialog=no",
- docUrl, docCharset, reference, aContext);
- },
-
- // Open new "view source" window with the frame's URL.
- viewFrameSource: function() {
- BrowserViewSourceOfDocument(this.target.ownerDocument);
- },
-
- viewInfo: function() {
- BrowserPageInfo(this.target.ownerDocument.defaultView.top.document);
- },
-
- viewFrameInfo: function() {
- BrowserPageInfo(this.target.ownerDocument);
- },
-
- showImage: function(e) {
- urlSecurityCheck(this.imageURL,
- this.browser.contentPrincipal,
- Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
-
- if (this.target instanceof Ci.nsIImageLoadingContent)
- this.target.forceReload();
- },
-
- // Change current window to the URL of the image.
- viewImage: function(e) {
- var viewURL;
-
- if (this.onCanvas)
- viewURL = this.target.toDataURL();
- else {
- viewURL = this.imageURL;
- urlSecurityCheck(viewURL,
- this.browser.contentPrincipal,
- Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
- }
-
- var doc = this.target.ownerDocument;
- openUILink(viewURL, e, null, null, null, null, doc.documentURIObject );
- },
-
- // Change current window to the URL of the background image.
- viewBGImage: function(e) {
- urlSecurityCheck(this.bgImageURL,
- this.browser.contentPrincipal,
- Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
- var doc = this.target.ownerDocument;
- openUILink(this.bgImageURL, e, null, null, null, null, doc.documentURIObject );
- },
-
- disableSetDesktopBackground: function() {
- // Disable the Set as Desktop Background menu item if we're still trying
- // to load the image or the load failed.
- if (!(this.target instanceof Ci.nsIImageLoadingContent))
- return true;
-
- if (("complete" in this.target) && !this.target.complete)
- return true;
-
- if (this.target.currentURI.schemeIs("javascript"))
- return true;
-
- var request = this.target
- .QueryInterface(Ci.nsIImageLoadingContent)
- .getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
- if (!request)
- return true;
-
- return false;
- },
-
- setDesktopBackground: function() {
- // Paranoia: check disableSetDesktopBackground again, in case the
- // image changed since the context menu was initiated.
- if (this.disableSetDesktopBackground())
- return;
-
- urlSecurityCheck(this.target.currentURI.spec,
- this.target.ownerDocument.nodePrincipal);
-
- // Confirm since it's annoying if you hit this accidentally.
- const kDesktopBackgroundURL =
- "chrome://browser/content/setDesktopBackground.xul";
- //@line 815 "/build/buildd/firefox-3.0-3.0.14+build2+nobinonly/build-tree/mozilla/browser/base/content/nsContextMenu.js"
- // On non-Mac platforms, the Set Wallpaper dialog is modal.
- openDialog(kDesktopBackgroundURL, "",
- "centerscreen,chrome,dialog,modal,dependent",
- this.target);
- //@line 820 "/build/buildd/firefox-3.0-3.0.14+build2+nobinonly/build-tree/mozilla/browser/base/content/nsContextMenu.js"
- },
-
- // Save URL of clicked-on frame.
- saveFrame: function () {
- saveDocument(this.target.ownerDocument);
- },
-
- // Save URL of clicked-on link.
- saveLink: function() {
- // canonical def in nsURILoader.h
- const NS_ERROR_SAVE_LINK_AS_TIMEOUT = 0x805d0020;
-
- var doc = this.target.ownerDocument;
- urlSecurityCheck(this.linkURL, doc.nodePrincipal);
- var linkText = this.linkText();
- var linkURL = this.linkURL;
-
-
- // an object to proxy the data through to
- // nsIExternalHelperAppService.doContent, which will wait for the
- // appropriate MIME-type headers and then prompt the user with a
- // file picker
- function saveAsListener() {}
- saveAsListener.prototype = {
- extListener: null,
-
- onStartRequest: function saveLinkAs_onStartRequest(aRequest, aContext) {
-
- // if the timer fired, the error status will have been caused by that,
- // and we'll be restarting in onStopRequest, so no reason to notify
- // the user
- if (aRequest.status == NS_ERROR_SAVE_LINK_AS_TIMEOUT)
- return;
-
- timer.cancel();
-
- // some other error occured; notify the user...
- if (!Components.isSuccessCode(aRequest.status)) {
- try {
- const sbs = Cc["@mozilla.org/intl/stringbundle;1"].
- getService(Ci.nsIStringBundleService);
- const bundle = sbs.createBundle(
- "chrome://mozapps/locale/downloads/downloads.properties");
-
- const title = bundle.GetStringFromName("downloadErrorAlertTitle");
- const msg = bundle.GetStringFromName("downloadErrorGeneric");
-
- const promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"].
- getService(Ci.nsIPromptService);
- promptSvc.alert(doc.defaultView, title, msg);
- } catch (ex) {}
- return;
- }
-
- var extHelperAppSvc =
- Cc["@mozilla.org/uriloader/external-helper-app-service;1"].
- getService(Ci.nsIExternalHelperAppService);
- var channel = aRequest.QueryInterface(Ci.nsIChannel);
- this.extListener =
- extHelperAppSvc.doContent(channel.contentType, aRequest,
- doc.defaultView, true);
- this.extListener.onStartRequest(aRequest, aContext);
- },
-
- onStopRequest: function saveLinkAs_onStopRequest(aRequest, aContext,
- aStatusCode) {
- if (aStatusCode == NS_ERROR_SAVE_LINK_AS_TIMEOUT) {
- // do it the old fashioned way, which will pick the best filename
- // it can without waiting.
- saveURL(linkURL, linkText, null, true, false, doc.documentURIObject);
- }
- if (this.extListener)
- this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
- },
-
- onDataAvailable: function saveLinkAs_onDataAvailable(aRequest, aContext,
- aInputStream,
- aOffset, aCount) {
- this.extListener.onDataAvailable(aRequest, aContext, aInputStream,
- aOffset, aCount);
- }
- }
-
- // in case we need to prompt the user for authentication
- function callbacks() {}
- callbacks.prototype = {
- getInterface: function sLA_callbacks_getInterface(aIID) {
- if (aIID.equals(Ci.nsIAuthPrompt) || aIID.equals(Ci.nsIAuthPrompt2)) {
- var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
- getService(Ci.nsIPromptFactory);
- return ww.getPrompt(doc.defaultView, aIID);
- }
- throw Cr.NS_ERROR_NO_INTERFACE;
- }
- }
-
- // if it we don't have the headers after a short time, the user
- // won't have received any feedback from their click. that's bad. so
- // we give up waiting for the filename.
- function timerCallback() {}
- timerCallback.prototype = {
- notify: function sLA_timer_notify(aTimer) {
- channel.cancel(NS_ERROR_SAVE_LINK_AS_TIMEOUT);
- return;
- }
- }
-
- // set up a channel to do the saving
- var ioService = Cc["@mozilla.org/network/io-service;1"].
- getService(Ci.nsIIOService);
- var channel = ioService.newChannelFromURI(this.getLinkURI());
- channel.notificationCallbacks = new callbacks();
- channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE |
- Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS;
- if (channel instanceof Ci.nsIHttpChannel)
- channel.referrer = doc.documentURIObject;
-
- // fallback to the old way if we don't see the headers quickly
- var timeToWait =
- gPrefService.getIntPref("browser.download.saveLinkAsFilenameTimeout");
- var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- timer.initWithCallback(new timerCallback(), timeToWait,
- timer.TYPE_ONE_SHOT);
-
- // kick off the channel with our proxy object as the listener
- channel.asyncOpen(new saveAsListener(), null);
- },
-
- sendLink: function() {
- // we don't know the title of the link so pass in an empty string
- MailIntegration.sendMessage( this.linkURL, "" );
- },
-
- // Save URL of clicked-on image.
- saveImage: function() {
- var doc = this.target.ownerDocument;
- if (this.onCanvas) {
- // Bypass cache, since it's a data: URL.
- saveImageURL(this.target.toDataURL(), "canvas.png", "SaveImageTitle",
- true, false, doc.documentURIObject);
- }
- else {
- urlSecurityCheck(this.imageURL, doc.nodePrincipal);
- saveImageURL(this.imageURL, null, "SaveImageTitle", false,
- false, doc.documentURIObject);
- }
- },
-
- sendImage: function() {
- MailIntegration.sendMessage(this.imageURL, "");
- },
-
- toggleImageBlocking: function(aBlock) {
- var permissionmanager = Cc["@mozilla.org/permissionmanager;1"].
- getService(Ci.nsIPermissionManager);
-
- var uri = this.target.QueryInterface(Ci.nsIImageLoadingContent).currentURI;
-
- if (aBlock)
- permissionmanager.add(uri, "image", Ci.nsIPermissionManager.DENY_ACTION);
- else
- permissionmanager.remove(uri.host, "image");
-
- var brandBundle = document.getElementById("bundle_brand");
- var app = brandBundle.getString("brandShortName");
- var bundle_browser = document.getElementById("bundle_browser");
- var message = bundle_browser.getFormattedString(aBlock ?
- "imageBlockedWarning" : "imageAllowedWarning", [app, uri.host]);
-
- var notificationBox = this.browser.getNotificationBox();
- var notification = notificationBox.getNotificationWithValue("images-blocked");
-
- if (notification)
- notification.label = message;
- else {
- var self = this;
- var buttons = [{
- label: bundle_browser.getString("undo"),
- accessKey: bundle_browser.getString("undo.accessKey"),
- callback: function() { self.toggleImageBlocking(!aBlock); }
- }];
- const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
- notificationBox.appendNotification(message, "images-blocked",
- "chrome://browser/skin/Info.png",
- priority, buttons);
- }
-
- // Reload the page to show the effect instantly
- BrowserReload();
- },
-
- isImageBlocked: function() {
- var permissionmanager = Cc["@mozilla.org/permissionmanager;1"].
- getService(Ci.nsIPermissionManager);
-
- var uri = this.target.QueryInterface(Ci.nsIImageLoadingContent).currentURI;
-
- return permissionmanager.testPermission(uri, "image") == Ci.nsIPermissionManager.DENY_ACTION;
- },
-
- // Generate email address and put it on clipboard.
- copyEmail: function() {
- // Copy the comma-separated list of email addresses only.
- // There are other ways of embedding email addresses in a mailto:
- // link, but such complex parsing is beyond us.
- var url = this.linkURL;
- var qmark = url.indexOf("?");
- var addresses;
-
- // 7 == length of "mailto:"
- addresses = qmark > 7 ? url.substring(7, qmark) : url.substr(7);
-
- // Let's try to unescape it using a character set
- // in case the address is not ASCII.
- try {
- var characterSet = this.target.ownerDocument.characterSet;
- const textToSubURI = Cc["@mozilla.org/intl/texttosuburi;1"].
- getService(Ci.nsITextToSubURI);
- addresses = textToSubURI.unEscapeURIForUI(characterSet, addresses);
- }
- catch(ex) {
- // Do nothing.
- }
-
- var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
- getService(Ci.nsIClipboardHelper);
- clipboard.copyString(addresses);
- },
-
- // Open Metadata window for node
- showMetadata: function () {
- window.openDialog("chrome://browser/content/metaData.xul",
- "_blank",
- "scrollbars,resizable,chrome,dialog=no",
- this.target);
- },
-
- ///////////////
- // Utilities //
- ///////////////
-
- // Show/hide one item (specified via name or the item element itself).
- showItem: function(aItemOrId, aShow) {
- var item = aItemOrId.constructor == String ?
- document.getElementById(aItemOrId) : aItemOrId;
- if (item)
- item.hidden = !aShow;
- },
-
- // Set given attribute of specified context-menu item. If the
- // value is null, then it removes the attribute (which works
- // nicely for the disabled attribute).
- setItemAttr: function(aID, aAttr, aVal ) {
- var elem = document.getElementById(aID);
- if (elem) {
- if (aVal == null) {
- // null indicates attr should be removed.
- elem.removeAttribute(aAttr);
- }
- else {
- // Set attr=val.
- elem.setAttribute(aAttr, aVal);
- }
- }
- },
-
- // Set context menu attribute according to like attribute of another node
- // (such as a broadcaster).
- setItemAttrFromNode: function(aItem_id, aAttr, aOther_id) {
- var elem = document.getElementById(aOther_id);
- if (elem && elem.getAttribute(aAttr) == "true")
- this.setItemAttr(aItem_id, aAttr, "true");
- else
- this.setItemAttr(aItem_id, aAttr, null);
- },
-
- // Temporary workaround for DOM api not yet implemented by XUL nodes.
- cloneNode: function(aItem) {
- // Create another element like the one we're cloning.
- var node = document.createElement(aItem.tagName);
-
- // Copy attributes from argument item to the new one.
- var attrs = aItem.attributes;
- for (var i = 0; i < attrs.length; i++) {
- var attr = attrs.item(i);
- node.setAttribute(attr.nodeName, attr.nodeValue);
- }
-
- // Voila!
- return node;
- },
-
- // Generate fully qualified URL for clicked-on link.
- getLinkURL: function() {
- var href = this.link.href;
- if (href)
- return href;
-
- href = this.link.getAttributeNS("http://www.w3.org/1999/xlink",
- "href");
-
- if (!href || !href.match(/\S/)) {
- // Without this we try to save as the current doc,
- // for example, HTML case also throws if empty
- throw "Empty href";
- }
-
- return makeURLAbsolute(this.link.baseURI, href);
- },
-
- getLinkURI: function() {
- var ioService = Cc["@mozilla.org/network/io-service;1"].
- getService(Ci.nsIIOService);
- try {
- return ioService.newURI(this.linkURL, null, null);
- }
- catch (ex) {
- // e.g. empty URL string
- }
-
- return null;
- },
-
- getLinkProtocol: function() {
- if (this.linkURI)
- return this.linkURI.scheme; // can be |undefined|
-
- return null;
- },
-
- // Get text of link.
- linkText: function() {
- var text = gatherTextUnder(this.link);
- if (!text || !text.match(/\S/)) {
- text = this.link.getAttribute("title");
- if (!text || !text.match(/\S/)) {
- text = this.link.getAttribute("alt");
- if (!text || !text.match(/\S/))
- text = this.linkURL;
- }
- }
-
- return text;
- },
-
- // Get selected text. Only display the first 15 chars.
- isTextSelection: function() {
- // Get 16 characters, so that we can trim the selection if it's greater
- // than 15 chars
- var selectedText = getBrowserSelection(16);
-
- if (!selectedText)
- return false;
-
- if (selectedText.length > 15)
- selectedText = selectedText.substr(0,15) + this.ellipsis;
-
- // Use the current engine if the search bar is visible, the default
- // engine otherwise.
- var engineName = "";
- var ss = Cc["@mozilla.org/browser/search-service;1"].
- getService(Ci.nsIBrowserSearchService);
- if (isElementVisible(BrowserSearch.searchBar))
- engineName = ss.currentEngine.name;
- else
- engineName = ss.defaultEngine.name;
-
- // format "Search <engine> for <selection>" string to show in menu
- var menuLabel = gNavigatorBundle.getFormattedString("contextMenuSearchText",
- [engineName,
- selectedText]);
- document.getElementById("context-searchselect").label = menuLabel;
-
- return true;
- },
-
- // Returns true if anything is selected.
- isContentSelection: function() {
- return !document.commandDispatcher.focusedWindow.getSelection().isCollapsed;
- },
-
- toString: function () {
- return "contextMenu.target = " + this.target + "\n" +
- "contextMenu.onImage = " + this.onImage + "\n" +
- "contextMenu.onLink = " + this.onLink + "\n" +
- "contextMenu.link = " + this.link + "\n" +
- "contextMenu.inFrame = " + this.inFrame + "\n" +
- "contextMenu.hasBGImage = " + this.hasBGImage + "\n";
- },
-
- // Returns true if aNode is a from control (except text boxes).
- // This is used to disable the context menu for form controls.
- isTargetAFormControl: function(aNode) {
- if (aNode instanceof HTMLInputElement)
- return (aNode.type != "text" && aNode.type != "password");
-
- return (aNode instanceof HTMLButtonElement) ||
- (aNode instanceof HTMLSelectElement) ||
- (aNode instanceof HTMLOptionElement) ||
- (aNode instanceof HTMLOptGroupElement);
- },
-
- isTargetATextBox: function(node) {
- if (node instanceof HTMLInputElement)
- return (node.type == "text" || node.type == "password")
-
- return (node instanceof HTMLTextAreaElement);
- },
-
- isTargetAKeywordField: function(aNode) {
- var form = aNode.form;
- if (!form)
- return false;
-
- var method = form.method.toUpperCase();
-
- // These are the following types of forms we can create keywords for:
- //
- // method encoding type can create keyword
- // GET * YES
- // * YES
- // POST YES
- // POST application/x-www-form-urlencoded YES
- // POST text/plain NO (a little tricky to do)
- // POST multipart/form-data NO
- // POST everything else YES
- return (method == "GET" || method == "") ||
- (form.enctype != "text/plain") && (form.enctype != "multipart/form-data");
- },
-
- // Determines whether or not the separator with the specified ID should be
- // shown or not by determining if there are any non-hidden items between it
- // and the previous separator.
- shouldShowSeparator: function (aSeparatorID) {
- var separator = document.getElementById(aSeparatorID);
- if (separator) {
- var sibling = separator.previousSibling;
- while (sibling && sibling.localName != "menuseparator") {
- if (!sibling.hidden)
- return true;
- sibling = sibling.previousSibling;
- }
- }
- return false;
- },
-
- addDictionaries: function() {
- var uri = formatURL("browser.dictionaries.download.url", true);
-
- var locale = "-";
- try {
- locale = gPrefService.getComplexValue("intl.accept_languages",
- Ci.nsIPrefLocalizedString).data;
- }
- catch (e) { }
-
- var version = "-";
- try {
- version = Cc["@mozilla.org/xre/app-info;1"].
- getService(Ci.nsIXULAppInfo).version;
- }
- catch (e) { }
-
- uri = uri.replace(/%LOCALE%/, escape(locale)).replace(/%VERSION%/, version);
-
- var newWindowPref = gPrefService.getIntPref("browser.link.open_newwindow");
- var where = newWindowPref == 3 ? "tab" : "window";
-
- openUILinkIn(uri, where);
- },
-
- bookmarkThisPage: function CM_bookmarkThisPage() {
- window.top.PlacesCommandHook.bookmarkPage(this.browser, PlacesUtils.bookmarksMenuFolderId, true);
- },
-
- bookmarkLink: function CM_bookmarkLink() {
- window.top.PlacesCommandHook.bookmarkLink(PlacesUtils.bookmarksMenuFolderId, this.linkURL,
- this.linkText());
- },
-
- addBookmarkForFrame: function CM_addBookmarkForFrame() {
- var doc = this.target.ownerDocument;
- var uri = doc.documentURIObject;
-
- var itemId = PlacesUtils.getMostRecentBookmarkForURI(uri);
- if (itemId == -1) {
- var title = doc.title;
- var description = PlacesUIUtils.getDescriptionFromDocument(doc);
-
- var descAnno = { name: DESCRIPTION_ANNO, value: description };
- var txn = PlacesUIUtils.ptm.createItem(uri,
- PlacesUtils.bookmarksMenuFolderId,
- -1, title, null, [descAnno]);
- PlacesUIUtils.ptm.doTransaction(txn);
- itemId = PlacesUtils.getMostRecentBookmarkForURI(uri);
- StarUI.beginBatch();
- }
-
- window.top.StarUI.showEditBookmarkPopup(itemId, this.browser, "overlap");
- },
-
- savePageAs: function CM_savePageAs() {
- saveDocument(this.browser.contentDocument);
- },
-
- sendPage: function CM_sendPage() {
- MailIntegration.sendLinkForWindow(this.browser.contentWindow);
- },
-
- printFrame: function CM_printFrame() {
- PrintUtils.print(this.target.ownerDocument.defaultView);
- },
-
- switchPageDirection: function CM_switchPageDirection() {
- SwitchDocumentDirection(this.browser.contentWindow);
- }
- };
-