Bumping manifests a=b2g-bump
[gecko.git] / embedding / browser / nsContextMenuInfo.cpp
blobbd2edfe018f02ba2c0691ecc98647e0fe59406fe
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsContextMenuInfo.h"
8 #include "nsIImageLoadingContent.h"
9 #include "imgLoader.h"
10 #include "nsIDOMDocument.h"
11 #include "nsIDOMHTMLDocument.h"
12 #include "nsIDOMHTMLElement.h"
13 #include "nsIDOMHTMLHtmlElement.h"
14 #include "nsIDOMHTMLAnchorElement.h"
15 #include "nsIDOMHTMLImageElement.h"
16 #include "nsIDOMHTMLAreaElement.h"
17 #include "nsIDOMHTMLLinkElement.h"
18 #include "nsIDOMWindow.h"
19 #include "nsIDOMCSSStyleDeclaration.h"
20 #include "nsIDOMCSSValue.h"
21 #include "nsIDOMCSSPrimitiveValue.h"
22 #include "nsNetUtil.h"
23 #include "nsUnicharUtils.h"
24 #include "nsIDocument.h"
25 #include "nsIPrincipal.h"
26 #include "nsIContentSecurityPolicy.h"
27 #include "nsIContentPolicy.h"
28 #include "nsAutoPtr.h"
29 #include "imgRequestProxy.h"
32 //*****************************************************************************
33 // class nsContextMenuInfo
34 //*****************************************************************************
36 NS_IMPL_ISUPPORTS(nsContextMenuInfo, nsIContextMenuInfo)
38 nsContextMenuInfo::nsContextMenuInfo()
42 nsContextMenuInfo::~nsContextMenuInfo()
46 /* readonly attribute nsIDOMEvent mouseEvent; */
47 NS_IMETHODIMP
48 nsContextMenuInfo::GetMouseEvent(nsIDOMEvent **aEvent)
50 NS_ENSURE_ARG_POINTER(aEvent);
51 NS_IF_ADDREF(*aEvent = mMouseEvent);
52 return NS_OK;
55 /* readonly attribute nsIDOMNode targetNode; */
56 NS_IMETHODIMP
57 nsContextMenuInfo::GetTargetNode(nsIDOMNode **aNode)
59 NS_ENSURE_ARG_POINTER(aNode);
60 NS_IF_ADDREF(*aNode = mDOMNode);
61 return NS_OK;
64 /* readonly attribute AString associatedLink; */
65 NS_IMETHODIMP
66 nsContextMenuInfo::GetAssociatedLink(nsAString& aHRef)
68 NS_ENSURE_STATE(mAssociatedLink);
69 aHRef.Truncate(0);
71 nsCOMPtr<nsIDOMElement> content(do_QueryInterface(mAssociatedLink));
72 nsAutoString localName;
73 if (content)
74 content->GetLocalName(localName);
76 nsCOMPtr<nsIDOMElement> linkContent;
77 ToLowerCase(localName);
78 if (localName.EqualsLiteral("a") ||
79 localName.EqualsLiteral("area") ||
80 localName.EqualsLiteral("link")) {
81 bool hasAttr;
82 content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
83 if (hasAttr) {
84 linkContent = content;
85 nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(linkContent));
86 if (anchor)
87 anchor->GetHref(aHRef);
88 else {
89 nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(linkContent));
90 if (area)
91 area->GetHref(aHRef);
92 else {
93 nsCOMPtr<nsIDOMHTMLLinkElement> link(do_QueryInterface(linkContent));
94 if (link)
95 link->GetHref(aHRef);
100 else {
101 nsCOMPtr<nsIDOMNode> curr;
102 mAssociatedLink->GetParentNode(getter_AddRefs(curr));
103 while (curr) {
104 content = do_QueryInterface(curr);
105 if (!content)
106 break;
107 content->GetLocalName(localName);
108 ToLowerCase(localName);
109 if (localName.EqualsLiteral("a")) {
110 bool hasAttr;
111 content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
112 if (hasAttr) {
113 linkContent = content;
114 nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(linkContent));
115 if (anchor)
116 anchor->GetHref(aHRef);
118 else
119 linkContent = nullptr; // Links can't be nested.
120 break;
123 nsCOMPtr<nsIDOMNode> temp = curr;
124 temp->GetParentNode(getter_AddRefs(curr));
128 return NS_OK;
131 /* readonly attribute imgIContainer imageContainer; */
132 NS_IMETHODIMP
133 nsContextMenuInfo::GetImageContainer(imgIContainer **aImageContainer)
135 NS_ENSURE_ARG_POINTER(aImageContainer);
136 NS_ENSURE_STATE(mDOMNode);
138 nsCOMPtr<imgIRequest> request;
139 GetImageRequest(mDOMNode, getter_AddRefs(request));
140 if (request)
141 return request->GetImage(aImageContainer);
143 return NS_ERROR_FAILURE;
146 /* readonly attribute nsIURI imageSrc; */
147 NS_IMETHODIMP
148 nsContextMenuInfo::GetImageSrc(nsIURI **aURI)
150 NS_ENSURE_ARG_POINTER(aURI);
151 NS_ENSURE_STATE(mDOMNode);
153 nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(mDOMNode));
154 NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
155 return content->GetCurrentURI(aURI);
158 /* readonly attribute imgIContainer backgroundImageContainer; */
159 NS_IMETHODIMP
160 nsContextMenuInfo::GetBackgroundImageContainer(imgIContainer **aImageContainer)
162 NS_ENSURE_ARG_POINTER(aImageContainer);
163 NS_ENSURE_STATE(mDOMNode);
165 nsRefPtr<imgRequestProxy> request;
166 GetBackgroundImageRequest(mDOMNode, getter_AddRefs(request));
167 if (request)
168 return request->GetImage(aImageContainer);
170 return NS_ERROR_FAILURE;
173 /* readonly attribute nsIURI backgroundImageSrc; */
174 NS_IMETHODIMP
175 nsContextMenuInfo::GetBackgroundImageSrc(nsIURI **aURI)
177 NS_ENSURE_ARG_POINTER(aURI);
178 NS_ENSURE_STATE(mDOMNode);
180 nsRefPtr<imgRequestProxy> request;
181 GetBackgroundImageRequest(mDOMNode, getter_AddRefs(request));
182 if (request)
183 return request->GetURI(aURI);
185 return NS_ERROR_FAILURE;
188 //*****************************************************************************
190 nsresult
191 nsContextMenuInfo::GetImageRequest(nsIDOMNode *aDOMNode, imgIRequest **aRequest)
193 NS_ENSURE_ARG(aDOMNode);
194 NS_ENSURE_ARG_POINTER(aRequest);
196 // Get content
197 nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(aDOMNode));
198 NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
200 return content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
201 aRequest);
204 bool
205 nsContextMenuInfo::HasBackgroundImage(nsIDOMNode * aDOMNode)
207 NS_ENSURE_TRUE(aDOMNode, false);
209 nsRefPtr<imgRequestProxy> request;
210 GetBackgroundImageRequest(aDOMNode, getter_AddRefs(request));
212 return (request != nullptr);
215 nsresult
216 nsContextMenuInfo::GetBackgroundImageRequest(nsIDOMNode *aDOMNode, imgRequestProxy **aRequest)
219 NS_ENSURE_ARG(aDOMNode);
220 NS_ENSURE_ARG_POINTER(aRequest);
222 nsCOMPtr<nsIDOMNode> domNode = aDOMNode;
224 // special case for the <html> element: if it has no background-image
225 // we'll defer to <body>
226 nsCOMPtr<nsIDOMHTMLHtmlElement> htmlElement = do_QueryInterface(domNode);
227 if (htmlElement) {
228 nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(domNode);
229 nsAutoString nameSpace;
230 element->GetNamespaceURI(nameSpace);
231 if (nameSpace.IsEmpty()) {
232 nsresult rv = GetBackgroundImageRequestInternal(domNode, aRequest);
233 if (NS_SUCCEEDED(rv) && *aRequest)
234 return NS_OK;
236 // no background-image found
237 nsCOMPtr<nsIDOMDocument> document;
238 domNode->GetOwnerDocument(getter_AddRefs(document));
239 nsCOMPtr<nsIDOMHTMLDocument> htmlDocument(do_QueryInterface(document));
240 NS_ENSURE_TRUE(htmlDocument, NS_ERROR_FAILURE);
242 nsCOMPtr<nsIDOMHTMLElement> body;
243 htmlDocument->GetBody(getter_AddRefs(body));
244 domNode = do_QueryInterface(body);
245 NS_ENSURE_TRUE(domNode, NS_ERROR_FAILURE);
248 return GetBackgroundImageRequestInternal(domNode, aRequest);
251 nsresult
252 nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgRequestProxy **aRequest)
254 NS_ENSURE_ARG_POINTER(aDOMNode);
256 nsCOMPtr<nsIDOMNode> domNode = aDOMNode;
257 nsCOMPtr<nsIDOMNode> parentNode;
259 nsCOMPtr<nsIDOMDocument> document;
260 domNode->GetOwnerDocument(getter_AddRefs(document));
261 NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
263 nsCOMPtr<nsIDOMWindow> window;
264 document->GetDefaultView(getter_AddRefs(window));
265 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
267 nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue;
268 nsAutoString bgStringValue;
270 nsCOMPtr<nsIDocument> doc(do_QueryInterface(document));
271 nsCOMPtr<nsIPrincipal> principal = doc ? doc->NodePrincipal() : nullptr;
273 while (true) {
274 nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(domNode));
275 // bail for the parent node of the root element or null argument
276 if (!domElement)
277 break;
279 nsCOMPtr<nsIDOMCSSStyleDeclaration> computedStyle;
280 window->GetComputedStyle(domElement, EmptyString(),
281 getter_AddRefs(computedStyle));
282 if (computedStyle) {
283 nsCOMPtr<nsIDOMCSSValue> cssValue;
284 computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-image"),
285 getter_AddRefs(cssValue));
286 primitiveValue = do_QueryInterface(cssValue);
287 if (primitiveValue) {
288 primitiveValue->GetStringValue(bgStringValue);
289 if (!bgStringValue.EqualsLiteral("none")) {
290 nsCOMPtr<nsIURI> bgUri;
291 NS_NewURI(getter_AddRefs(bgUri), bgStringValue);
292 NS_ENSURE_TRUE(bgUri, NS_ERROR_FAILURE);
294 nsRefPtr<imgLoader> il = imgLoader::GetInstance();
295 NS_ENSURE_TRUE(il, NS_ERROR_FAILURE);
297 return il->LoadImage(bgUri, nullptr, nullptr,
298 doc->GetReferrerPolicy(), principal, nullptr,
299 nullptr, nullptr, nsIRequest::LOAD_NORMAL,
300 nullptr, nsIContentPolicy::TYPE_IMAGE,
301 EmptyString(), aRequest);
305 // bail if we encounter non-transparent background-color
306 computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-color"),
307 getter_AddRefs(cssValue));
308 primitiveValue = do_QueryInterface(cssValue);
309 if (primitiveValue) {
310 primitiveValue->GetStringValue(bgStringValue);
311 if (!bgStringValue.EqualsLiteral("transparent"))
312 return NS_ERROR_FAILURE;
316 domNode->GetParentNode(getter_AddRefs(parentNode));
317 domNode = parentNode;
320 return NS_ERROR_FAILURE;