/embedding/browser/webBrowser/nsContextMenuInfo.cpp

http://github.com/zpao/v8monkey · C++ · 366 lines · 258 code · 50 blank · 58 comment · 31 complexity · a6e45c03d448bd1aca6e3e7d169250d3 MD5 · raw file

  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * The Original Code is the Mozilla browser.
  16. *
  17. * The Initial Developer of the Original Code is
  18. * Netscape Communications, Inc.
  19. * Portions created by the Initial Developer are Copyright (C) 1999
  20. * the Initial Developer. All Rights Reserved.
  21. *
  22. * Contributor(s):
  23. * Chris Saari <saari@netscape.com>
  24. * Conrad Carlen <ccarlen@netscape.com>
  25. * Pierre Chanial <p_ch@verizon.net>
  26. * Ms2ger <ms2ger@gmail.com>
  27. *
  28. * Alternatively, the contents of this file may be used under the terms of
  29. * either the GNU General Public License Version 2 or later (the "GPL"), or
  30. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  31. * in which case the provisions of the GPL or the LGPL are applicable instead
  32. * of those above. If you wish to allow use of your version of this file only
  33. * under the terms of either the GPL or the LGPL, and not to allow others to
  34. * use your version of this file under the terms of the MPL, indicate your
  35. * decision by deleting the provisions above and replace them with the notice
  36. * and other provisions required by the GPL or the LGPL. If you do not delete
  37. * the provisions above, a recipient may use your version of this file under
  38. * the terms of any one of the MPL, the GPL or the LGPL.
  39. *
  40. * ***** END LICENSE BLOCK ***** */
  41. #include "nsContextMenuInfo.h"
  42. #include "nsIImageLoadingContent.h"
  43. #include "imgILoader.h"
  44. #include "nsIDOMDocument.h"
  45. #include "nsIDOMHTMLDocument.h"
  46. #include "nsIDOMHTMLElement.h"
  47. #include "nsIDOMHTMLHtmlElement.h"
  48. #include "nsIDOMHTMLAnchorElement.h"
  49. #include "nsIDOMHTMLImageElement.h"
  50. #include "nsIDOMHTMLAreaElement.h"
  51. #include "nsIDOMHTMLLinkElement.h"
  52. #include "nsIDOMWindow.h"
  53. #include "nsIDOMCSSStyleDeclaration.h"
  54. #include "nsIDOMCSSValue.h"
  55. #include "nsIDOMCSSPrimitiveValue.h"
  56. #include "nsNetUtil.h"
  57. #include "nsUnicharUtils.h"
  58. #include "nsIDocument.h"
  59. #include "nsIPrincipal.h"
  60. #include "nsIChannelPolicy.h"
  61. #include "nsIContentSecurityPolicy.h"
  62. #include "nsIContentPolicy.h"
  63. //*****************************************************************************
  64. // class nsContextMenuInfo
  65. //*****************************************************************************
  66. NS_IMPL_ISUPPORTS1(nsContextMenuInfo, nsIContextMenuInfo)
  67. nsContextMenuInfo::nsContextMenuInfo()
  68. {
  69. }
  70. nsContextMenuInfo::~nsContextMenuInfo()
  71. {
  72. }
  73. /* readonly attribute nsIDOMEvent mouseEvent; */
  74. NS_IMETHODIMP
  75. nsContextMenuInfo::GetMouseEvent(nsIDOMEvent **aEvent)
  76. {
  77. NS_ENSURE_ARG_POINTER(aEvent);
  78. NS_IF_ADDREF(*aEvent = mMouseEvent);
  79. return NS_OK;
  80. }
  81. /* readonly attribute nsIDOMNode targetNode; */
  82. NS_IMETHODIMP
  83. nsContextMenuInfo::GetTargetNode(nsIDOMNode **aNode)
  84. {
  85. NS_ENSURE_ARG_POINTER(aNode);
  86. NS_IF_ADDREF(*aNode = mDOMNode);
  87. return NS_OK;
  88. }
  89. /* readonly attribute AString associatedLink; */
  90. NS_IMETHODIMP
  91. nsContextMenuInfo::GetAssociatedLink(nsAString& aHRef)
  92. {
  93. NS_ENSURE_STATE(mAssociatedLink);
  94. aHRef.Truncate(0);
  95. nsCOMPtr<nsIDOMElement> content(do_QueryInterface(mAssociatedLink));
  96. nsAutoString localName;
  97. if (content)
  98. content->GetLocalName(localName);
  99. nsCOMPtr<nsIDOMElement> linkContent;
  100. ToLowerCase(localName);
  101. if (localName.EqualsLiteral("a") ||
  102. localName.EqualsLiteral("area") ||
  103. localName.EqualsLiteral("link")) {
  104. bool hasAttr;
  105. content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
  106. if (hasAttr) {
  107. linkContent = content;
  108. nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(linkContent));
  109. if (anchor)
  110. anchor->GetHref(aHRef);
  111. else {
  112. nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(linkContent));
  113. if (area)
  114. area->GetHref(aHRef);
  115. else {
  116. nsCOMPtr<nsIDOMHTMLLinkElement> link(do_QueryInterface(linkContent));
  117. if (link)
  118. link->GetHref(aHRef);
  119. }
  120. }
  121. }
  122. }
  123. else {
  124. nsCOMPtr<nsIDOMNode> curr;
  125. mAssociatedLink->GetParentNode(getter_AddRefs(curr));
  126. while (curr) {
  127. content = do_QueryInterface(curr);
  128. if (!content)
  129. break;
  130. content->GetLocalName(localName);
  131. ToLowerCase(localName);
  132. if (localName.EqualsLiteral("a")) {
  133. bool hasAttr;
  134. content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
  135. if (hasAttr) {
  136. linkContent = content;
  137. nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(linkContent));
  138. if (anchor)
  139. anchor->GetHref(aHRef);
  140. }
  141. else
  142. linkContent = nsnull; // Links can't be nested.
  143. break;
  144. }
  145. nsCOMPtr<nsIDOMNode> temp = curr;
  146. temp->GetParentNode(getter_AddRefs(curr));
  147. }
  148. }
  149. return NS_OK;
  150. }
  151. /* readonly attribute imgIContainer imageContainer; */
  152. NS_IMETHODIMP
  153. nsContextMenuInfo::GetImageContainer(imgIContainer **aImageContainer)
  154. {
  155. NS_ENSURE_ARG_POINTER(aImageContainer);
  156. NS_ENSURE_STATE(mDOMNode);
  157. nsCOMPtr<imgIRequest> request;
  158. GetImageRequest(mDOMNode, getter_AddRefs(request));
  159. if (request)
  160. return request->GetImage(aImageContainer);
  161. return NS_ERROR_FAILURE;
  162. }
  163. /* readonly attribute nsIURI imageSrc; */
  164. NS_IMETHODIMP
  165. nsContextMenuInfo::GetImageSrc(nsIURI **aURI)
  166. {
  167. NS_ENSURE_ARG_POINTER(aURI);
  168. NS_ENSURE_STATE(mDOMNode);
  169. nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(mDOMNode));
  170. NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
  171. return content->GetCurrentURI(aURI);
  172. }
  173. /* readonly attribute imgIContainer backgroundImageContainer; */
  174. NS_IMETHODIMP
  175. nsContextMenuInfo::GetBackgroundImageContainer(imgIContainer **aImageContainer)
  176. {
  177. NS_ENSURE_ARG_POINTER(aImageContainer);
  178. NS_ENSURE_STATE(mDOMNode);
  179. nsCOMPtr<imgIRequest> request;
  180. GetBackgroundImageRequest(mDOMNode, getter_AddRefs(request));
  181. if (request)
  182. return request->GetImage(aImageContainer);
  183. return NS_ERROR_FAILURE;
  184. }
  185. /* readonly attribute nsIURI backgroundImageSrc; */
  186. NS_IMETHODIMP
  187. nsContextMenuInfo::GetBackgroundImageSrc(nsIURI **aURI)
  188. {
  189. NS_ENSURE_ARG_POINTER(aURI);
  190. NS_ENSURE_STATE(mDOMNode);
  191. nsCOMPtr<imgIRequest> request;
  192. GetBackgroundImageRequest(mDOMNode, getter_AddRefs(request));
  193. if (request)
  194. return request->GetURI(aURI);
  195. return NS_ERROR_FAILURE;
  196. }
  197. //*****************************************************************************
  198. nsresult
  199. nsContextMenuInfo::GetImageRequest(nsIDOMNode *aDOMNode, imgIRequest **aRequest)
  200. {
  201. NS_ENSURE_ARG(aDOMNode);
  202. NS_ENSURE_ARG_POINTER(aRequest);
  203. // Get content
  204. nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(aDOMNode));
  205. NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
  206. return content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
  207. aRequest);
  208. }
  209. bool
  210. nsContextMenuInfo::HasBackgroundImage(nsIDOMNode * aDOMNode)
  211. {
  212. NS_ENSURE_TRUE(aDOMNode, false);
  213. nsCOMPtr<imgIRequest> request;
  214. GetBackgroundImageRequest(aDOMNode, getter_AddRefs(request));
  215. return (request != nsnull);
  216. }
  217. nsresult
  218. nsContextMenuInfo::GetBackgroundImageRequest(nsIDOMNode *aDOMNode, imgIRequest **aRequest)
  219. {
  220. NS_ENSURE_ARG(aDOMNode);
  221. NS_ENSURE_ARG_POINTER(aRequest);
  222. nsCOMPtr<nsIDOMNode> domNode = aDOMNode;
  223. // special case for the <html> element: if it has no background-image
  224. // we'll defer to <body>
  225. nsCOMPtr<nsIDOMHTMLHtmlElement> htmlElement = do_QueryInterface(domNode);
  226. if (htmlElement) {
  227. nsAutoString nameSpace;
  228. htmlElement->GetNamespaceURI(nameSpace);
  229. if (nameSpace.IsEmpty()) {
  230. nsresult rv = GetBackgroundImageRequestInternal(domNode, aRequest);
  231. if (NS_SUCCEEDED(rv) && *aRequest)
  232. return NS_OK;
  233. // no background-image found
  234. nsCOMPtr<nsIDOMDocument> document;
  235. domNode->GetOwnerDocument(getter_AddRefs(document));
  236. nsCOMPtr<nsIDOMHTMLDocument> htmlDocument(do_QueryInterface(document));
  237. NS_ENSURE_TRUE(htmlDocument, NS_ERROR_FAILURE);
  238. nsCOMPtr<nsIDOMHTMLElement> body;
  239. htmlDocument->GetBody(getter_AddRefs(body));
  240. domNode = do_QueryInterface(body);
  241. NS_ENSURE_TRUE(domNode, NS_ERROR_FAILURE);
  242. }
  243. }
  244. return GetBackgroundImageRequestInternal(domNode, aRequest);
  245. }
  246. nsresult
  247. nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgIRequest **aRequest)
  248. {
  249. NS_ENSURE_ARG_POINTER(aDOMNode);
  250. nsCOMPtr<nsIDOMNode> domNode = aDOMNode;
  251. nsCOMPtr<nsIDOMNode> parentNode;
  252. nsCOMPtr<nsIDOMDocument> document;
  253. domNode->GetOwnerDocument(getter_AddRefs(document));
  254. NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
  255. nsCOMPtr<nsIDOMWindow> window;
  256. document->GetDefaultView(getter_AddRefs(window));
  257. NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
  258. nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue;
  259. nsAutoString bgStringValue;
  260. // get Content Security Policy to pass to LoadImage
  261. nsCOMPtr<nsIDocument> doc(do_QueryInterface(document));
  262. nsCOMPtr<nsIPrincipal> principal;
  263. nsCOMPtr<nsIChannelPolicy> channelPolicy;
  264. nsCOMPtr<nsIContentSecurityPolicy> csp;
  265. if (doc) {
  266. principal = doc->NodePrincipal();
  267. nsresult rv = principal->GetCsp(getter_AddRefs(csp));
  268. NS_ENSURE_SUCCESS(rv, rv);
  269. if (csp) {
  270. channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
  271. channelPolicy->SetContentSecurityPolicy(csp);
  272. channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE);
  273. }
  274. }
  275. while (true) {
  276. nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(domNode));
  277. // bail for the parent node of the root element or null argument
  278. if (!domElement)
  279. break;
  280. nsCOMPtr<nsIDOMCSSStyleDeclaration> computedStyle;
  281. window->GetComputedStyle(domElement, EmptyString(),
  282. getter_AddRefs(computedStyle));
  283. if (computedStyle) {
  284. nsCOMPtr<nsIDOMCSSValue> cssValue;
  285. computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-image"),
  286. getter_AddRefs(cssValue));
  287. primitiveValue = do_QueryInterface(cssValue);
  288. if (primitiveValue) {
  289. primitiveValue->GetStringValue(bgStringValue);
  290. if (!bgStringValue.EqualsLiteral("none")) {
  291. nsCOMPtr<nsIURI> bgUri;
  292. NS_NewURI(getter_AddRefs(bgUri), bgStringValue);
  293. NS_ENSURE_TRUE(bgUri, NS_ERROR_FAILURE);
  294. nsCOMPtr<imgILoader> il(do_GetService(
  295. "@mozilla.org/image/loader;1"));
  296. NS_ENSURE_TRUE(il, NS_ERROR_FAILURE);
  297. return il->LoadImage(bgUri, nsnull, nsnull, principal, nsnull,
  298. nsnull, nsnull, nsIRequest::LOAD_NORMAL, nsnull,
  299. nsnull, channelPolicy, aRequest);
  300. }
  301. }
  302. // bail if we encounter non-transparent background-color
  303. computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-color"),
  304. getter_AddRefs(cssValue));
  305. primitiveValue = do_QueryInterface(cssValue);
  306. if (primitiveValue) {
  307. primitiveValue->GetStringValue(bgStringValue);
  308. if (!bgStringValue.EqualsLiteral("transparent"))
  309. return NS_ERROR_FAILURE;
  310. }
  311. }
  312. domNode->GetParentNode(getter_AddRefs(parentNode));
  313. domNode = parentNode;
  314. }
  315. return NS_ERROR_FAILURE;
  316. }