1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/embedding/browser/webBrowser/nsContextMenuInfo.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,337 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsContextMenuInfo.h" 1.10 + 1.11 +#include "nsIImageLoadingContent.h" 1.12 +#include "imgLoader.h" 1.13 +#include "nsIDOMDocument.h" 1.14 +#include "nsIDOMHTMLDocument.h" 1.15 +#include "nsIDOMHTMLElement.h" 1.16 +#include "nsIDOMHTMLHtmlElement.h" 1.17 +#include "nsIDOMHTMLAnchorElement.h" 1.18 +#include "nsIDOMHTMLImageElement.h" 1.19 +#include "nsIDOMHTMLAreaElement.h" 1.20 +#include "nsIDOMHTMLLinkElement.h" 1.21 +#include "nsIDOMWindow.h" 1.22 +#include "nsIDOMCSSStyleDeclaration.h" 1.23 +#include "nsIDOMCSSValue.h" 1.24 +#include "nsIDOMCSSPrimitiveValue.h" 1.25 +#include "nsNetUtil.h" 1.26 +#include "nsUnicharUtils.h" 1.27 +#include "nsIDocument.h" 1.28 +#include "nsIPrincipal.h" 1.29 +#include "nsIChannelPolicy.h" 1.30 +#include "nsIContentSecurityPolicy.h" 1.31 +#include "nsIContentPolicy.h" 1.32 +#include "nsAutoPtr.h" 1.33 +#include "imgRequestProxy.h" 1.34 +#include "mozIThirdPartyUtil.h" 1.35 + 1.36 +//***************************************************************************** 1.37 +// class nsContextMenuInfo 1.38 +//***************************************************************************** 1.39 + 1.40 +NS_IMPL_ISUPPORTS(nsContextMenuInfo, nsIContextMenuInfo) 1.41 + 1.42 +nsContextMenuInfo::nsContextMenuInfo() 1.43 +{ 1.44 +} 1.45 + 1.46 +nsContextMenuInfo::~nsContextMenuInfo() 1.47 +{ 1.48 +} 1.49 + 1.50 +/* readonly attribute nsIDOMEvent mouseEvent; */ 1.51 +NS_IMETHODIMP 1.52 +nsContextMenuInfo::GetMouseEvent(nsIDOMEvent **aEvent) 1.53 +{ 1.54 + NS_ENSURE_ARG_POINTER(aEvent); 1.55 + NS_IF_ADDREF(*aEvent = mMouseEvent); 1.56 + return NS_OK; 1.57 +} 1.58 + 1.59 +/* readonly attribute nsIDOMNode targetNode; */ 1.60 +NS_IMETHODIMP 1.61 +nsContextMenuInfo::GetTargetNode(nsIDOMNode **aNode) 1.62 +{ 1.63 + NS_ENSURE_ARG_POINTER(aNode); 1.64 + NS_IF_ADDREF(*aNode = mDOMNode); 1.65 + return NS_OK; 1.66 +} 1.67 + 1.68 +/* readonly attribute AString associatedLink; */ 1.69 +NS_IMETHODIMP 1.70 +nsContextMenuInfo::GetAssociatedLink(nsAString& aHRef) 1.71 +{ 1.72 + NS_ENSURE_STATE(mAssociatedLink); 1.73 + aHRef.Truncate(0); 1.74 + 1.75 + nsCOMPtr<nsIDOMElement> content(do_QueryInterface(mAssociatedLink)); 1.76 + nsAutoString localName; 1.77 + if (content) 1.78 + content->GetLocalName(localName); 1.79 + 1.80 + nsCOMPtr<nsIDOMElement> linkContent; 1.81 + ToLowerCase(localName); 1.82 + if (localName.EqualsLiteral("a") || 1.83 + localName.EqualsLiteral("area") || 1.84 + localName.EqualsLiteral("link")) { 1.85 + bool hasAttr; 1.86 + content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr); 1.87 + if (hasAttr) { 1.88 + linkContent = content; 1.89 + nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(linkContent)); 1.90 + if (anchor) 1.91 + anchor->GetHref(aHRef); 1.92 + else { 1.93 + nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(linkContent)); 1.94 + if (area) 1.95 + area->GetHref(aHRef); 1.96 + else { 1.97 + nsCOMPtr<nsIDOMHTMLLinkElement> link(do_QueryInterface(linkContent)); 1.98 + if (link) 1.99 + link->GetHref(aHRef); 1.100 + } 1.101 + } 1.102 + } 1.103 + } 1.104 + else { 1.105 + nsCOMPtr<nsIDOMNode> curr; 1.106 + mAssociatedLink->GetParentNode(getter_AddRefs(curr)); 1.107 + while (curr) { 1.108 + content = do_QueryInterface(curr); 1.109 + if (!content) 1.110 + break; 1.111 + content->GetLocalName(localName); 1.112 + ToLowerCase(localName); 1.113 + if (localName.EqualsLiteral("a")) { 1.114 + bool hasAttr; 1.115 + content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr); 1.116 + if (hasAttr) { 1.117 + linkContent = content; 1.118 + nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(linkContent)); 1.119 + if (anchor) 1.120 + anchor->GetHref(aHRef); 1.121 + } 1.122 + else 1.123 + linkContent = nullptr; // Links can't be nested. 1.124 + break; 1.125 + } 1.126 + 1.127 + nsCOMPtr<nsIDOMNode> temp = curr; 1.128 + temp->GetParentNode(getter_AddRefs(curr)); 1.129 + } 1.130 + } 1.131 + 1.132 + return NS_OK; 1.133 +} 1.134 + 1.135 +/* readonly attribute imgIContainer imageContainer; */ 1.136 +NS_IMETHODIMP 1.137 +nsContextMenuInfo::GetImageContainer(imgIContainer **aImageContainer) 1.138 +{ 1.139 + NS_ENSURE_ARG_POINTER(aImageContainer); 1.140 + NS_ENSURE_STATE(mDOMNode); 1.141 + 1.142 + nsCOMPtr<imgIRequest> request; 1.143 + GetImageRequest(mDOMNode, getter_AddRefs(request)); 1.144 + if (request) 1.145 + return request->GetImage(aImageContainer); 1.146 + 1.147 + return NS_ERROR_FAILURE; 1.148 +} 1.149 + 1.150 +/* readonly attribute nsIURI imageSrc; */ 1.151 +NS_IMETHODIMP 1.152 +nsContextMenuInfo::GetImageSrc(nsIURI **aURI) 1.153 +{ 1.154 + NS_ENSURE_ARG_POINTER(aURI); 1.155 + NS_ENSURE_STATE(mDOMNode); 1.156 + 1.157 + nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(mDOMNode)); 1.158 + NS_ENSURE_TRUE(content, NS_ERROR_FAILURE); 1.159 + return content->GetCurrentURI(aURI); 1.160 +} 1.161 + 1.162 +/* readonly attribute imgIContainer backgroundImageContainer; */ 1.163 +NS_IMETHODIMP 1.164 +nsContextMenuInfo::GetBackgroundImageContainer(imgIContainer **aImageContainer) 1.165 +{ 1.166 + NS_ENSURE_ARG_POINTER(aImageContainer); 1.167 + NS_ENSURE_STATE(mDOMNode); 1.168 + 1.169 + nsRefPtr<imgRequestProxy> request; 1.170 + GetBackgroundImageRequest(mDOMNode, getter_AddRefs(request)); 1.171 + if (request) 1.172 + return request->GetImage(aImageContainer); 1.173 + 1.174 + return NS_ERROR_FAILURE; 1.175 +} 1.176 + 1.177 +/* readonly attribute nsIURI backgroundImageSrc; */ 1.178 +NS_IMETHODIMP 1.179 +nsContextMenuInfo::GetBackgroundImageSrc(nsIURI **aURI) 1.180 +{ 1.181 + NS_ENSURE_ARG_POINTER(aURI); 1.182 + NS_ENSURE_STATE(mDOMNode); 1.183 + 1.184 + nsRefPtr<imgRequestProxy> request; 1.185 + GetBackgroundImageRequest(mDOMNode, getter_AddRefs(request)); 1.186 + if (request) 1.187 + return request->GetURI(aURI); 1.188 + 1.189 + return NS_ERROR_FAILURE; 1.190 +} 1.191 + 1.192 +//***************************************************************************** 1.193 + 1.194 +nsresult 1.195 +nsContextMenuInfo::GetImageRequest(nsIDOMNode *aDOMNode, imgIRequest **aRequest) 1.196 +{ 1.197 + NS_ENSURE_ARG(aDOMNode); 1.198 + NS_ENSURE_ARG_POINTER(aRequest); 1.199 + 1.200 + // Get content 1.201 + nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(aDOMNode)); 1.202 + NS_ENSURE_TRUE(content, NS_ERROR_FAILURE); 1.203 + 1.204 + return content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, 1.205 + aRequest); 1.206 +} 1.207 + 1.208 +bool 1.209 +nsContextMenuInfo::HasBackgroundImage(nsIDOMNode * aDOMNode) 1.210 +{ 1.211 + NS_ENSURE_TRUE(aDOMNode, false); 1.212 + 1.213 + nsRefPtr<imgRequestProxy> request; 1.214 + GetBackgroundImageRequest(aDOMNode, getter_AddRefs(request)); 1.215 + 1.216 + return (request != nullptr); 1.217 +} 1.218 + 1.219 +nsresult 1.220 +nsContextMenuInfo::GetBackgroundImageRequest(nsIDOMNode *aDOMNode, imgRequestProxy **aRequest) 1.221 +{ 1.222 + 1.223 + NS_ENSURE_ARG(aDOMNode); 1.224 + NS_ENSURE_ARG_POINTER(aRequest); 1.225 + 1.226 + nsCOMPtr<nsIDOMNode> domNode = aDOMNode; 1.227 + 1.228 + // special case for the <html> element: if it has no background-image 1.229 + // we'll defer to <body> 1.230 + nsCOMPtr<nsIDOMHTMLHtmlElement> htmlElement = do_QueryInterface(domNode); 1.231 + if (htmlElement) { 1.232 + nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(domNode); 1.233 + nsAutoString nameSpace; 1.234 + element->GetNamespaceURI(nameSpace); 1.235 + if (nameSpace.IsEmpty()) { 1.236 + nsresult rv = GetBackgroundImageRequestInternal(domNode, aRequest); 1.237 + if (NS_SUCCEEDED(rv) && *aRequest) 1.238 + return NS_OK; 1.239 + 1.240 + // no background-image found 1.241 + nsCOMPtr<nsIDOMDocument> document; 1.242 + domNode->GetOwnerDocument(getter_AddRefs(document)); 1.243 + nsCOMPtr<nsIDOMHTMLDocument> htmlDocument(do_QueryInterface(document)); 1.244 + NS_ENSURE_TRUE(htmlDocument, NS_ERROR_FAILURE); 1.245 + 1.246 + nsCOMPtr<nsIDOMHTMLElement> body; 1.247 + htmlDocument->GetBody(getter_AddRefs(body)); 1.248 + domNode = do_QueryInterface(body); 1.249 + NS_ENSURE_TRUE(domNode, NS_ERROR_FAILURE); 1.250 + } 1.251 + } 1.252 + return GetBackgroundImageRequestInternal(domNode, aRequest); 1.253 +} 1.254 + 1.255 +nsresult 1.256 +nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgRequestProxy **aRequest) 1.257 +{ 1.258 + NS_ENSURE_ARG_POINTER(aDOMNode); 1.259 + 1.260 + nsCOMPtr<nsIDOMNode> domNode = aDOMNode; 1.261 + nsCOMPtr<nsIDOMNode> parentNode; 1.262 + 1.263 + nsCOMPtr<nsIDOMDocument> document; 1.264 + domNode->GetOwnerDocument(getter_AddRefs(document)); 1.265 + NS_ENSURE_TRUE(document, NS_ERROR_FAILURE); 1.266 + 1.267 + nsCOMPtr<nsIDOMWindow> window; 1.268 + document->GetDefaultView(getter_AddRefs(window)); 1.269 + NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); 1.270 + 1.271 + nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue; 1.272 + nsAutoString bgStringValue; 1.273 + 1.274 + // get Content Security Policy to pass to LoadImage 1.275 + nsCOMPtr<nsIDocument> doc(do_QueryInterface(document)); 1.276 + nsCOMPtr<nsIPrincipal> principal; 1.277 + nsCOMPtr<nsIChannelPolicy> channelPolicy; 1.278 + nsCOMPtr<nsIContentSecurityPolicy> csp; 1.279 + NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); 1.280 + 1.281 + principal = doc->NodePrincipal(); 1.282 + nsresult rv = principal->GetCsp(getter_AddRefs(csp)); 1.283 + NS_ENSURE_SUCCESS(rv, rv); 1.284 + if (csp) { 1.285 + channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1"); 1.286 + channelPolicy->SetContentSecurityPolicy(csp); 1.287 + channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE); 1.288 + } 1.289 + 1.290 + while (true) { 1.291 + nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(domNode)); 1.292 + // bail for the parent node of the root element or null argument 1.293 + if (!domElement) 1.294 + break; 1.295 + 1.296 + nsCOMPtr<nsIDOMCSSStyleDeclaration> computedStyle; 1.297 + window->GetComputedStyle(domElement, EmptyString(), 1.298 + getter_AddRefs(computedStyle)); 1.299 + if (computedStyle) { 1.300 + nsCOMPtr<nsIDOMCSSValue> cssValue; 1.301 + computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-image"), 1.302 + getter_AddRefs(cssValue)); 1.303 + primitiveValue = do_QueryInterface(cssValue); 1.304 + if (primitiveValue) { 1.305 + primitiveValue->GetStringValue(bgStringValue); 1.306 + if (!bgStringValue.EqualsLiteral("none")) { 1.307 + nsCOMPtr<nsIURI> bgUri; 1.308 + NS_NewURI(getter_AddRefs(bgUri), bgStringValue); 1.309 + NS_ENSURE_TRUE(bgUri, NS_ERROR_FAILURE); 1.310 + 1.311 + nsRefPtr<imgLoader> il = imgLoader::GetInstance(); 1.312 + NS_ENSURE_TRUE(il, NS_ERROR_FAILURE); 1.313 + nsCOMPtr<nsIURI> firstPartyIsolationURI; 1.314 + nsCOMPtr<mozIThirdPartyUtil> thirdPartySvc 1.315 + = do_GetService(THIRDPARTYUTIL_CONTRACTID); 1.316 + thirdPartySvc->GetFirstPartyIsolationURI(nullptr, doc, 1.317 + getter_AddRefs(firstPartyIsolationURI)); 1.318 + return il->LoadImage(bgUri, firstPartyIsolationURI, nullptr, principal, nullptr, 1.319 + nullptr, nullptr, nsIRequest::LOAD_NORMAL, 1.320 + nullptr, channelPolicy, EmptyString(), aRequest); 1.321 + } 1.322 + } 1.323 + 1.324 + // bail if we encounter non-transparent background-color 1.325 + computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-color"), 1.326 + getter_AddRefs(cssValue)); 1.327 + primitiveValue = do_QueryInterface(cssValue); 1.328 + if (primitiveValue) { 1.329 + primitiveValue->GetStringValue(bgStringValue); 1.330 + if (!bgStringValue.EqualsLiteral("transparent")) 1.331 + return NS_ERROR_FAILURE; 1.332 + } 1.333 + } 1.334 + 1.335 + domNode->GetParentNode(getter_AddRefs(parentNode)); 1.336 + domNode = parentNode; 1.337 + } 1.338 + 1.339 + return NS_ERROR_FAILURE; 1.340 +}