Back to index

lightning-sunbird  0.9+nobinonly
nsContextMenuInfo.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is the Mozilla browser.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications, Inc.
00020  * Portions created by the Initial Developer are Copyright (C) 1999
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Chris Saari <saari@netscape.com>
00025  *   Conrad Carlen <ccarlen@netscape.com>
00026  *   Pierre Chanial <p_ch@verizon.net>
00027  *
00028  * Alternatively, the contents of this file may be used under the terms of
00029  * either the GNU General Public License Version 2 or later (the "GPL"), or
00030  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00031  * in which case the provisions of the GPL or the LGPL are applicable instead
00032  * of those above. If you wish to allow use of your version of this file only
00033  * under the terms of either the GPL or the LGPL, and not to allow others to
00034  * use your version of this file under the terms of the MPL, indicate your
00035  * decision by deleting the provisions above and replace them with the notice
00036  * and other provisions required by the GPL or the LGPL. If you do not delete
00037  * the provisions above, a recipient may use your version of this file under
00038  * the terms of any one of the MPL, the GPL or the LGPL.
00039  *
00040  * ***** END LICENSE BLOCK ***** */
00041 
00042 #include "nsContextMenuInfo.h"
00043 
00044 #include "nsIImageLoadingContent.h"
00045 #include "imgILoader.h"
00046 #include "nsIDOMDocument.h"
00047 #include "nsIDOMHTMLDocument.h"
00048 #include "nsIDOMHTMLElement.h"
00049 #include "nsIDOMHTMLHtmlElement.h"
00050 #include "nsIDOMHTMLAnchorElement.h"
00051 #include "nsIDOMHTMLImageElement.h"
00052 #include "nsIDOMHTMLAreaElement.h"
00053 #include "nsIDOMHTMLLinkElement.h"
00054 #include "nsIDOMDocumentView.h"
00055 #include "nsIDOMAbstractView.h"
00056 #include "nsIDOMViewCSS.h"
00057 #include "nsIDOMCSSStyleDeclaration.h"
00058 #include "nsIDOMCSSValue.h"
00059 #include "nsIDOMCSSPrimitiveValue.h"
00060 #include "nsNetUtil.h"
00061 #include "nsUnicharUtils.h"
00062 
00063 //*****************************************************************************
00064 // class nsContextMenuInfo
00065 //*****************************************************************************
00066 
00067 NS_IMPL_ISUPPORTS1(nsContextMenuInfo, nsIContextMenuInfo)
00068 
00069 nsContextMenuInfo::nsContextMenuInfo()
00070 {
00071 }
00072 
00073 nsContextMenuInfo::~nsContextMenuInfo()
00074 {
00075 }
00076 
00077 /* readonly attribute nsIDOMEvent mouseEvent; */
00078 NS_IMETHODIMP
00079 nsContextMenuInfo::GetMouseEvent(nsIDOMEvent **aEvent)
00080 {
00081   NS_ENSURE_ARG_POINTER(aEvent);
00082   NS_IF_ADDREF(*aEvent = mMouseEvent);
00083   return NS_OK;
00084 }
00085 
00086 /* readonly attribute nsIDOMNode targetNode; */
00087 NS_IMETHODIMP
00088 nsContextMenuInfo::GetTargetNode(nsIDOMNode **aNode)
00089 {
00090   NS_ENSURE_ARG_POINTER(aNode);
00091   NS_IF_ADDREF(*aNode = mDOMNode);
00092   return NS_OK;
00093 }
00094 
00095 /* readonly attribute AString associatedLink; */
00096 NS_IMETHODIMP
00097 nsContextMenuInfo::GetAssociatedLink(nsAString& aHRef)
00098 {
00099   NS_ENSURE_STATE(mAssociatedLink);
00100   aHRef.Truncate(0);
00101     
00102   nsCOMPtr<nsIDOMElement> content(do_QueryInterface(mAssociatedLink));
00103   nsAutoString localName;
00104   if (content)
00105     content->GetLocalName(localName);
00106 
00107   nsCOMPtr<nsIDOMElement> linkContent;
00108   ToLowerCase(localName);
00109   if (localName.EqualsLiteral("a") ||
00110       localName.EqualsLiteral("area") ||
00111       localName.EqualsLiteral("link")) {
00112     PRBool hasAttr;
00113     content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
00114     if (hasAttr) {
00115       linkContent = content;
00116       nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(linkContent));
00117       if (anchor)
00118         anchor->GetHref(aHRef);
00119       else {
00120         nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(linkContent));
00121         if (area)
00122           area->GetHref(aHRef);
00123         else {
00124           nsCOMPtr<nsIDOMHTMLLinkElement> link(do_QueryInterface(linkContent));
00125           if (link)
00126             link->GetHref(aHRef);
00127         }
00128       }
00129     }
00130   }
00131   else {
00132     nsCOMPtr<nsIDOMNode> curr;
00133     mAssociatedLink->GetParentNode(getter_AddRefs(curr));
00134     while (curr) {
00135       content = do_QueryInterface(curr);
00136       if (!content)
00137         break;
00138       content->GetLocalName(localName);
00139       ToLowerCase(localName);
00140       if (localName.EqualsLiteral("a")) {
00141         PRBool hasAttr;
00142         content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
00143         if (hasAttr) {
00144           linkContent = content;
00145           nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(linkContent));
00146           if (anchor)
00147             anchor->GetHref(aHRef);
00148         }
00149         else
00150           linkContent = nsnull; // Links can't be nested.
00151         break;
00152       }
00153 
00154       nsCOMPtr<nsIDOMNode> temp = curr;
00155       temp->GetParentNode(getter_AddRefs(curr));
00156     }
00157   }
00158 
00159   return NS_OK;
00160 }
00161 
00162 /* readonly attribute imgIContainer imageContainer; */
00163 NS_IMETHODIMP
00164 nsContextMenuInfo::GetImageContainer(imgIContainer **aImageContainer)
00165 {
00166   NS_ENSURE_ARG_POINTER(aImageContainer);
00167   NS_ENSURE_STATE(mDOMNode);
00168   
00169   nsCOMPtr<imgIRequest> request;
00170   GetImageRequest(mDOMNode, getter_AddRefs(request));
00171   if (request)
00172     return request->GetImage(aImageContainer);
00173 
00174   return NS_ERROR_FAILURE;
00175 }
00176 
00177 /* readonly attribute nsIURI imageSrc; */
00178 NS_IMETHODIMP
00179 nsContextMenuInfo::GetImageSrc(nsIURI **aURI)
00180 {
00181   NS_ENSURE_ARG_POINTER(aURI);
00182   NS_ENSURE_STATE(mDOMNode);
00183   
00184   // First try the easy case of our node being a nsIDOMHTMLImageElement
00185   nsCOMPtr<nsIDOMHTMLImageElement> imgElement(do_QueryInterface(mDOMNode));
00186   if (imgElement) {
00187     nsAutoString imgSrcSpec;
00188     nsresult rv = imgElement->GetSrc(imgSrcSpec);
00189     if (NS_SUCCEEDED(rv))
00190       return NS_NewURI(aURI, NS_ConvertUCS2toUTF8(imgSrcSpec));
00191   }
00192   
00193   // If not, dig deeper.
00194   nsCOMPtr<imgIRequest> request;
00195   GetImageRequest(mDOMNode, getter_AddRefs(request));
00196   if (request)
00197     return request->GetURI(aURI);
00198 
00199   return NS_ERROR_FAILURE;
00200 }
00201 
00202 /* readonly attribute imgIContainer backgroundImageContainer; */
00203 NS_IMETHODIMP
00204 nsContextMenuInfo::GetBackgroundImageContainer(imgIContainer **aImageContainer)
00205 {
00206   NS_ENSURE_ARG_POINTER(aImageContainer);
00207   NS_ENSURE_STATE(mDOMNode);
00208   
00209   nsCOMPtr<imgIRequest> request;
00210   GetBackgroundImageRequest(mDOMNode, getter_AddRefs(request));
00211   if (request)
00212     return request->GetImage(aImageContainer);
00213 
00214   return NS_ERROR_FAILURE;
00215 }
00216 
00217 /* readonly attribute nsIURI backgroundImageSrc; */
00218 NS_IMETHODIMP
00219 nsContextMenuInfo::GetBackgroundImageSrc(nsIURI **aURI)
00220 {
00221   NS_ENSURE_ARG_POINTER(aURI);
00222   NS_ENSURE_STATE(mDOMNode);
00223   
00224   nsCOMPtr<imgIRequest> request;
00225   GetBackgroundImageRequest(mDOMNode, getter_AddRefs(request));
00226   if (request)
00227     return request->GetURI(aURI);
00228 
00229   return NS_ERROR_FAILURE;
00230 }
00231 
00232 //*****************************************************************************
00233 
00234 nsresult
00235 nsContextMenuInfo::GetImageRequest(nsIDOMNode *aDOMNode, imgIRequest **aRequest)
00236 {
00237   NS_ENSURE_ARG(aDOMNode);
00238   NS_ENSURE_ARG_POINTER(aRequest);
00239 
00240   // Get content
00241   nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(aDOMNode));
00242   NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
00243 
00244   return content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
00245                              aRequest);
00246 }
00247 
00248 PRBool
00249 nsContextMenuInfo::HasBackgroundImage(nsIDOMNode * aDOMNode)
00250 {
00251   NS_ENSURE_ARG(aDOMNode);
00252 
00253   nsCOMPtr<imgIRequest> request;
00254   GetBackgroundImageRequest(aDOMNode, getter_AddRefs(request));
00255   
00256   return (request != nsnull);
00257 }
00258 
00259 nsresult
00260 nsContextMenuInfo::GetBackgroundImageRequest(nsIDOMNode *aDOMNode, imgIRequest **aRequest)
00261 {
00262 
00263   NS_ENSURE_ARG(aDOMNode);
00264   NS_ENSURE_ARG_POINTER(aRequest);
00265 
00266   nsCOMPtr<nsIDOMNode> domNode = aDOMNode;
00267 
00268   // special case for the <html> element: if it has no background-image
00269   // we'll defer to <body>
00270   nsCOMPtr<nsIDOMHTMLHtmlElement> htmlElement = do_QueryInterface(domNode);
00271   if (htmlElement) {
00272     nsAutoString nameSpace;
00273     htmlElement->GetNamespaceURI(nameSpace);
00274     if (nameSpace.IsEmpty()) {
00275       nsresult rv = GetBackgroundImageRequestInternal(domNode, aRequest);
00276       if (NS_SUCCEEDED(rv) && *aRequest)
00277         return NS_OK;
00278 
00279       // no background-image found
00280       nsCOMPtr<nsIDOMDocument> document;
00281       domNode->GetOwnerDocument(getter_AddRefs(document));
00282       nsCOMPtr<nsIDOMHTMLDocument> htmlDocument(do_QueryInterface(document));
00283       NS_ENSURE_TRUE(htmlDocument, NS_ERROR_FAILURE);
00284 
00285       nsCOMPtr<nsIDOMHTMLElement> body;
00286       htmlDocument->GetBody(getter_AddRefs(body));
00287       domNode = do_QueryInterface(body);
00288     }
00289   }
00290   return GetBackgroundImageRequestInternal(domNode, aRequest);
00291 }
00292 
00293 nsresult
00294 nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgIRequest **aRequest)
00295 {
00296 
00297   nsCOMPtr<nsIDOMNode> domNode = aDOMNode;
00298   nsCOMPtr<nsIDOMNode> parentNode;
00299 
00300   nsCOMPtr<nsIDOMDocument> document;
00301   domNode->GetOwnerDocument(getter_AddRefs(document));
00302   nsCOMPtr<nsIDOMDocumentView> docView(do_QueryInterface(document));
00303   NS_ENSURE_TRUE(docView, NS_ERROR_FAILURE);
00304 
00305   nsCOMPtr<nsIDOMAbstractView> defaultView;
00306   docView->GetDefaultView(getter_AddRefs(defaultView));
00307   nsCOMPtr<nsIDOMViewCSS> defaultCSSView(do_QueryInterface(defaultView));
00308   NS_ENSURE_TRUE(defaultCSSView, NS_ERROR_FAILURE);
00309 
00310   nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue;
00311   nsAutoString bgStringValue;
00312 
00313   while (PR_TRUE) {
00314     nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(domNode));
00315     // bail for the parent node of the root element or null argument
00316     if (!domElement)
00317       break;
00318     
00319     nsCOMPtr<nsIDOMCSSStyleDeclaration> computedStyle;
00320     defaultCSSView->GetComputedStyle(domElement, EmptyString(),
00321                                      getter_AddRefs(computedStyle));
00322     if (computedStyle) {
00323       nsCOMPtr<nsIDOMCSSValue> cssValue;
00324       computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-image"),
00325                                          getter_AddRefs(cssValue));
00326       primitiveValue = do_QueryInterface(cssValue);
00327       if (primitiveValue) {
00328         primitiveValue->GetStringValue(bgStringValue);
00329         if (!bgStringValue.EqualsLiteral("none")) {
00330           nsCOMPtr<nsIURI> bgUri;
00331           NS_NewURI(getter_AddRefs(bgUri), bgStringValue);
00332           NS_ENSURE_TRUE(bgUri, NS_ERROR_FAILURE);
00333 
00334           nsCOMPtr<imgILoader> il(do_GetService(
00335                                     "@mozilla.org/image/loader;1"));
00336           NS_ENSURE_TRUE(il, NS_ERROR_FAILURE);
00337 
00338           return il->LoadImage(bgUri, nsnull, nsnull, nsnull, nsnull, nsnull,
00339                                nsIRequest::LOAD_NORMAL, nsnull, nsnull,
00340                                aRequest);
00341         }
00342       }
00343 
00344       // bail if we encounter non-transparent background-color
00345       computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-color"),
00346                                          getter_AddRefs(cssValue));
00347       primitiveValue = do_QueryInterface(cssValue);
00348       if (primitiveValue) {
00349         primitiveValue->GetStringValue(bgStringValue);
00350         if (!bgStringValue.EqualsLiteral("transparent"))
00351           return NS_ERROR_FAILURE;
00352       }
00353     }
00354 
00355     domNode->GetParentNode(getter_AddRefs(parentNode));
00356     domNode = parentNode;
00357   }
00358 
00359   return NS_ERROR_FAILURE;
00360 }