PageRenderTime 60ms CodeModel.GetById 17ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 42#include "nsContextMenuInfo.h"
 43
 44#include "nsIImageLoadingContent.h"
 45#include "imgILoader.h"
 46#include "nsIDOMDocument.h"
 47#include "nsIDOMHTMLDocument.h"
 48#include "nsIDOMHTMLElement.h"
 49#include "nsIDOMHTMLHtmlElement.h"
 50#include "nsIDOMHTMLAnchorElement.h"
 51#include "nsIDOMHTMLImageElement.h"
 52#include "nsIDOMHTMLAreaElement.h"
 53#include "nsIDOMHTMLLinkElement.h"
 54#include "nsIDOMWindow.h"
 55#include "nsIDOMCSSStyleDeclaration.h"
 56#include "nsIDOMCSSValue.h"
 57#include "nsIDOMCSSPrimitiveValue.h"
 58#include "nsNetUtil.h"
 59#include "nsUnicharUtils.h"
 60#include "nsIDocument.h"
 61#include "nsIPrincipal.h"
 62#include "nsIChannelPolicy.h"
 63#include "nsIContentSecurityPolicy.h"
 64#include "nsIContentPolicy.h"
 65
 66//*****************************************************************************
 67// class nsContextMenuInfo
 68//*****************************************************************************
 69
 70NS_IMPL_ISUPPORTS1(nsContextMenuInfo, nsIContextMenuInfo)
 71
 72nsContextMenuInfo::nsContextMenuInfo()
 73{
 74}
 75
 76nsContextMenuInfo::~nsContextMenuInfo()
 77{
 78}
 79
 80/* readonly attribute nsIDOMEvent mouseEvent; */
 81NS_IMETHODIMP
 82nsContextMenuInfo::GetMouseEvent(nsIDOMEvent **aEvent)
 83{
 84  NS_ENSURE_ARG_POINTER(aEvent);
 85  NS_IF_ADDREF(*aEvent = mMouseEvent);
 86  return NS_OK;
 87}
 88
 89/* readonly attribute nsIDOMNode targetNode; */
 90NS_IMETHODIMP
 91nsContextMenuInfo::GetTargetNode(nsIDOMNode **aNode)
 92{
 93  NS_ENSURE_ARG_POINTER(aNode);
 94  NS_IF_ADDREF(*aNode = mDOMNode);
 95  return NS_OK;
 96}
 97
 98/* readonly attribute AString associatedLink; */
 99NS_IMETHODIMP
100nsContextMenuInfo::GetAssociatedLink(nsAString& aHRef)
101{
102  NS_ENSURE_STATE(mAssociatedLink);
103  aHRef.Truncate(0);
104    
105  nsCOMPtr<nsIDOMElement> content(do_QueryInterface(mAssociatedLink));
106  nsAutoString localName;
107  if (content)
108    content->GetLocalName(localName);
109
110  nsCOMPtr<nsIDOMElement> linkContent;
111  ToLowerCase(localName);
112  if (localName.EqualsLiteral("a") ||
113      localName.EqualsLiteral("area") ||
114      localName.EqualsLiteral("link")) {
115    bool hasAttr;
116    content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
117    if (hasAttr) {
118      linkContent = content;
119      nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(linkContent));
120      if (anchor)
121        anchor->GetHref(aHRef);
122      else {
123        nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(linkContent));
124        if (area)
125          area->GetHref(aHRef);
126        else {
127          nsCOMPtr<nsIDOMHTMLLinkElement> link(do_QueryInterface(linkContent));
128          if (link)
129            link->GetHref(aHRef);
130        }
131      }
132    }
133  }
134  else {
135    nsCOMPtr<nsIDOMNode> curr;
136    mAssociatedLink->GetParentNode(getter_AddRefs(curr));
137    while (curr) {
138      content = do_QueryInterface(curr);
139      if (!content)
140        break;
141      content->GetLocalName(localName);
142      ToLowerCase(localName);
143      if (localName.EqualsLiteral("a")) {
144        bool hasAttr;
145        content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
146        if (hasAttr) {
147          linkContent = content;
148          nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(linkContent));
149          if (anchor)
150            anchor->GetHref(aHRef);
151        }
152        else
153          linkContent = nsnull; // Links can't be nested.
154        break;
155      }
156
157      nsCOMPtr<nsIDOMNode> temp = curr;
158      temp->GetParentNode(getter_AddRefs(curr));
159    }
160  }
161
162  return NS_OK;
163}
164
165/* readonly attribute imgIContainer imageContainer; */
166NS_IMETHODIMP
167nsContextMenuInfo::GetImageContainer(imgIContainer **aImageContainer)
168{
169  NS_ENSURE_ARG_POINTER(aImageContainer);
170  NS_ENSURE_STATE(mDOMNode);
171  
172  nsCOMPtr<imgIRequest> request;
173  GetImageRequest(mDOMNode, getter_AddRefs(request));
174  if (request)
175    return request->GetImage(aImageContainer);
176
177  return NS_ERROR_FAILURE;
178}
179
180/* readonly attribute nsIURI imageSrc; */
181NS_IMETHODIMP
182nsContextMenuInfo::GetImageSrc(nsIURI **aURI)
183{
184  NS_ENSURE_ARG_POINTER(aURI);
185  NS_ENSURE_STATE(mDOMNode);
186  
187  nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(mDOMNode));
188  NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
189  return content->GetCurrentURI(aURI);
190}
191
192/* readonly attribute imgIContainer backgroundImageContainer; */
193NS_IMETHODIMP
194nsContextMenuInfo::GetBackgroundImageContainer(imgIContainer **aImageContainer)
195{
196  NS_ENSURE_ARG_POINTER(aImageContainer);
197  NS_ENSURE_STATE(mDOMNode);
198  
199  nsCOMPtr<imgIRequest> request;
200  GetBackgroundImageRequest(mDOMNode, getter_AddRefs(request));
201  if (request)
202    return request->GetImage(aImageContainer);
203
204  return NS_ERROR_FAILURE;
205}
206
207/* readonly attribute nsIURI backgroundImageSrc; */
208NS_IMETHODIMP
209nsContextMenuInfo::GetBackgroundImageSrc(nsIURI **aURI)
210{
211  NS_ENSURE_ARG_POINTER(aURI);
212  NS_ENSURE_STATE(mDOMNode);
213  
214  nsCOMPtr<imgIRequest> request;
215  GetBackgroundImageRequest(mDOMNode, getter_AddRefs(request));
216  if (request)
217    return request->GetURI(aURI);
218
219  return NS_ERROR_FAILURE;
220}
221
222//*****************************************************************************
223
224nsresult
225nsContextMenuInfo::GetImageRequest(nsIDOMNode *aDOMNode, imgIRequest **aRequest)
226{
227  NS_ENSURE_ARG(aDOMNode);
228  NS_ENSURE_ARG_POINTER(aRequest);
229
230  // Get content
231  nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(aDOMNode));
232  NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
233
234  return content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
235                             aRequest);
236}
237
238bool
239nsContextMenuInfo::HasBackgroundImage(nsIDOMNode * aDOMNode)
240{
241  NS_ENSURE_TRUE(aDOMNode, false);
242
243  nsCOMPtr<imgIRequest> request;
244  GetBackgroundImageRequest(aDOMNode, getter_AddRefs(request));
245  
246  return (request != nsnull);
247}
248
249nsresult
250nsContextMenuInfo::GetBackgroundImageRequest(nsIDOMNode *aDOMNode, imgIRequest **aRequest)
251{
252
253  NS_ENSURE_ARG(aDOMNode);
254  NS_ENSURE_ARG_POINTER(aRequest);
255
256  nsCOMPtr<nsIDOMNode> domNode = aDOMNode;
257
258  // special case for the <html> element: if it has no background-image
259  // we'll defer to <body>
260  nsCOMPtr<nsIDOMHTMLHtmlElement> htmlElement = do_QueryInterface(domNode);
261  if (htmlElement) {
262    nsAutoString nameSpace;
263    htmlElement->GetNamespaceURI(nameSpace);
264    if (nameSpace.IsEmpty()) {
265      nsresult rv = GetBackgroundImageRequestInternal(domNode, aRequest);
266      if (NS_SUCCEEDED(rv) && *aRequest)
267        return NS_OK;
268
269      // no background-image found
270      nsCOMPtr<nsIDOMDocument> document;
271      domNode->GetOwnerDocument(getter_AddRefs(document));
272      nsCOMPtr<nsIDOMHTMLDocument> htmlDocument(do_QueryInterface(document));
273      NS_ENSURE_TRUE(htmlDocument, NS_ERROR_FAILURE);
274
275      nsCOMPtr<nsIDOMHTMLElement> body;
276      htmlDocument->GetBody(getter_AddRefs(body));
277      domNode = do_QueryInterface(body);
278      NS_ENSURE_TRUE(domNode, NS_ERROR_FAILURE);
279    }
280  }
281  return GetBackgroundImageRequestInternal(domNode, aRequest);
282}
283
284nsresult
285nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgIRequest **aRequest)
286{
287  NS_ENSURE_ARG_POINTER(aDOMNode);
288
289  nsCOMPtr<nsIDOMNode> domNode = aDOMNode;
290  nsCOMPtr<nsIDOMNode> parentNode;
291
292  nsCOMPtr<nsIDOMDocument> document;
293  domNode->GetOwnerDocument(getter_AddRefs(document));
294  NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
295
296  nsCOMPtr<nsIDOMWindow> window;
297  document->GetDefaultView(getter_AddRefs(window));
298  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
299
300  nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue;
301  nsAutoString bgStringValue;
302
303  // get Content Security Policy to pass to LoadImage
304  nsCOMPtr<nsIDocument> doc(do_QueryInterface(document));
305  nsCOMPtr<nsIPrincipal> principal;
306  nsCOMPtr<nsIChannelPolicy> channelPolicy;
307  nsCOMPtr<nsIContentSecurityPolicy> csp;
308  if (doc) {
309    principal = doc->NodePrincipal();
310    nsresult rv = principal->GetCsp(getter_AddRefs(csp));
311    NS_ENSURE_SUCCESS(rv, rv);
312    if (csp) {
313      channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
314      channelPolicy->SetContentSecurityPolicy(csp);
315      channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE);
316    }
317  }
318  
319  while (true) {
320    nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(domNode));
321    // bail for the parent node of the root element or null argument
322    if (!domElement)
323      break;
324    
325    nsCOMPtr<nsIDOMCSSStyleDeclaration> computedStyle;
326    window->GetComputedStyle(domElement, EmptyString(),
327                             getter_AddRefs(computedStyle));
328    if (computedStyle) {
329      nsCOMPtr<nsIDOMCSSValue> cssValue;
330      computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-image"),
331                                         getter_AddRefs(cssValue));
332      primitiveValue = do_QueryInterface(cssValue);
333      if (primitiveValue) {
334        primitiveValue->GetStringValue(bgStringValue);
335        if (!bgStringValue.EqualsLiteral("none")) {
336          nsCOMPtr<nsIURI> bgUri;
337          NS_NewURI(getter_AddRefs(bgUri), bgStringValue);
338          NS_ENSURE_TRUE(bgUri, NS_ERROR_FAILURE);
339
340          nsCOMPtr<imgILoader> il(do_GetService(
341                                    "@mozilla.org/image/loader;1"));
342          NS_ENSURE_TRUE(il, NS_ERROR_FAILURE);
343
344          return il->LoadImage(bgUri, nsnull, nsnull, principal, nsnull,
345                               nsnull, nsnull, nsIRequest::LOAD_NORMAL, nsnull,
346                               nsnull, channelPolicy, aRequest);
347        }
348      }
349
350      // bail if we encounter non-transparent background-color
351      computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-color"),
352                                         getter_AddRefs(cssValue));
353      primitiveValue = do_QueryInterface(cssValue);
354      if (primitiveValue) {
355        primitiveValue->GetStringValue(bgStringValue);
356        if (!bgStringValue.EqualsLiteral("transparent"))
357          return NS_ERROR_FAILURE;
358      }
359    }
360
361    domNode->GetParentNode(getter_AddRefs(parentNode));
362    domNode = parentNode;
363  }
364
365  return NS_ERROR_FAILURE;
366}