PageRenderTime 58ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp

http://github.com/zpao/v8monkey
C++ | 1862 lines | 1314 code | 275 blank | 273 comment | 217 complexity | 4f39f29c5eef5b8bb178367f40028b2f MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-3.0, AGPL-1.0, LGPL-2.1, BSD-3-Clause, GPL-2.0, JSON, Apache-2.0, 0BSD
  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. * Travis Bogard <travis@netscape.com>
  24. * Adam Lock <adamlock@netscape.com>
  25. * Mike Pinkerton <pinkerton@netscape.com>
  26. * Dan Rosen <dr@netscape.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. // Local Includes
  42. #include "nsDocShellTreeOwner.h"
  43. #include "nsWebBrowser.h"
  44. // Helper Classes
  45. #include "nsStyleCoord.h"
  46. #include "nsSize.h"
  47. #include "nsHTMLReflowState.h"
  48. #include "nsIServiceManager.h"
  49. #include "nsComponentManagerUtils.h"
  50. #include "nsXPIDLString.h"
  51. #include "nsIAtom.h"
  52. #include "nsReadableUtils.h"
  53. #include "nsUnicharUtils.h"
  54. #include "nsISimpleEnumerator.h"
  55. #include "nsGUIEvent.h"
  56. #include "mozilla/LookAndFeel.h"
  57. // Interfaces needed to be included
  58. #include "nsPresContext.h"
  59. #include "nsIContextMenuListener.h"
  60. #include "nsIContextMenuListener2.h"
  61. #include "nsITooltipListener.h"
  62. #include "nsIPrivateDOMEvent.h"
  63. #include "nsIDOMNode.h"
  64. #include "nsIDOMNodeList.h"
  65. #include "nsIDOMDocument.h"
  66. #include "nsIDOMDocumentType.h"
  67. #include "nsIDOMElement.h"
  68. #include "Link.h"
  69. #include "nsIDOMSVGElement.h"
  70. #include "nsIDOMSVGTitleElement.h"
  71. #include "nsIDOMEvent.h"
  72. #include "nsIDOMMouseEvent.h"
  73. #include "nsIDOMNSEvent.h"
  74. #include "nsIDOMNamedNodeMap.h"
  75. #include "nsIFormControl.h"
  76. #include "nsIDOMHTMLInputElement.h"
  77. #include "nsIDOMHTMLTextAreaElement.h"
  78. #include "nsIDOMHTMLHtmlElement.h"
  79. #include "nsIDOMHTMLAppletElement.h"
  80. #include "nsIDOMHTMLObjectElement.h"
  81. #include "nsIDOMHTMLEmbedElement.h"
  82. #include "nsIDOMHTMLDocument.h"
  83. #include "nsIImageLoadingContent.h"
  84. #include "nsIWebNavigation.h"
  85. #include "nsIDOMHTMLElement.h"
  86. #include "nsIPresShell.h"
  87. #include "nsPIDOMWindow.h"
  88. #include "nsPIWindowRoot.h"
  89. #include "nsIDOMWindowCollection.h"
  90. #include "nsIWindowWatcher.h"
  91. #include "nsPIWindowWatcher.h"
  92. #include "nsIPrompt.h"
  93. #include "nsRect.h"
  94. #include "nsIWebBrowserChromeFocus.h"
  95. #include "nsIContent.h"
  96. #include "imgIContainer.h"
  97. #include "nsContextMenuInfo.h"
  98. #include "nsPresContext.h"
  99. #include "nsIViewManager.h"
  100. #include "nsIView.h"
  101. #include "nsEventListenerManager.h"
  102. #include "nsIDOMDragEvent.h"
  103. #include "nsIConstraintValidation.h"
  104. using namespace mozilla;
  105. //
  106. // GetEventReceiver
  107. //
  108. // A helper routine that navigates the tricky path from a |nsWebBrowser| to
  109. // a |nsIDOMEventTarget| via the window root and chrome event handler.
  110. //
  111. static nsresult
  112. GetDOMEventTarget( nsWebBrowser* inBrowser, nsIDOMEventTarget** aTarget)
  113. {
  114. NS_ENSURE_ARG_POINTER(inBrowser);
  115. nsCOMPtr<nsIDOMWindow> domWindow;
  116. inBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
  117. NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
  118. nsCOMPtr<nsPIDOMWindow> domWindowPrivate = do_QueryInterface(domWindow);
  119. NS_ENSURE_TRUE(domWindowPrivate, NS_ERROR_FAILURE);
  120. nsPIDOMWindow *rootWindow = domWindowPrivate->GetPrivateRoot();
  121. NS_ENSURE_TRUE(rootWindow, NS_ERROR_FAILURE);
  122. nsCOMPtr<nsIDOMEventTarget> target =
  123. rootWindow->GetChromeEventHandler();
  124. NS_ENSURE_TRUE(target, NS_ERROR_FAILURE);
  125. target.forget(aTarget);
  126. return NS_OK;
  127. }
  128. //*****************************************************************************
  129. //*** nsDocShellTreeOwner: Object Management
  130. //*****************************************************************************
  131. nsDocShellTreeOwner::nsDocShellTreeOwner() :
  132. mWebBrowser(nsnull),
  133. mTreeOwner(nsnull),
  134. mPrimaryContentShell(nsnull),
  135. mWebBrowserChrome(nsnull),
  136. mOwnerWin(nsnull),
  137. mOwnerRequestor(nsnull),
  138. mChromeTooltipListener(nsnull),
  139. mChromeContextMenuListener(nsnull)
  140. {
  141. }
  142. nsDocShellTreeOwner::~nsDocShellTreeOwner()
  143. {
  144. RemoveChromeListeners();
  145. }
  146. //*****************************************************************************
  147. // nsDocShellTreeOwner::nsISupports
  148. //*****************************************************************************
  149. NS_IMPL_ADDREF(nsDocShellTreeOwner)
  150. NS_IMPL_RELEASE(nsDocShellTreeOwner)
  151. NS_INTERFACE_MAP_BEGIN(nsDocShellTreeOwner)
  152. NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellTreeOwner)
  153. NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeOwner)
  154. NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
  155. NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
  156. NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
  157. NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
  158. NS_INTERFACE_MAP_ENTRY(nsICDocShellTreeOwner)
  159. NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
  160. NS_INTERFACE_MAP_END
  161. //*****************************************************************************
  162. // nsDocShellTreeOwner::nsIInterfaceRequestor
  163. //*****************************************************************************
  164. NS_IMETHODIMP
  165. nsDocShellTreeOwner::GetInterface(const nsIID& aIID, void** aSink)
  166. {
  167. NS_ENSURE_ARG_POINTER(aSink);
  168. if(NS_SUCCEEDED(QueryInterface(aIID, aSink)))
  169. return NS_OK;
  170. if (aIID.Equals(NS_GET_IID(nsIWebBrowserChromeFocus))) {
  171. if (mWebBrowserChromeWeak != nsnull)
  172. return mWebBrowserChromeWeak->QueryReferent(aIID, aSink);
  173. return mOwnerWin->QueryInterface(aIID, aSink);
  174. }
  175. if (aIID.Equals(NS_GET_IID(nsIPrompt))) {
  176. nsIPrompt *prompt;
  177. EnsurePrompter();
  178. prompt = mPrompter;
  179. if (prompt) {
  180. NS_ADDREF(prompt);
  181. *aSink = prompt;
  182. return NS_OK;
  183. }
  184. return NS_NOINTERFACE;
  185. }
  186. if (aIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
  187. nsIAuthPrompt *prompt;
  188. EnsureAuthPrompter();
  189. prompt = mAuthPrompter;
  190. if (prompt) {
  191. NS_ADDREF(prompt);
  192. *aSink = prompt;
  193. return NS_OK;
  194. }
  195. return NS_NOINTERFACE;
  196. }
  197. nsCOMPtr<nsIInterfaceRequestor> req = GetOwnerRequestor();
  198. if (req)
  199. return req->GetInterface(aIID, aSink);
  200. return NS_NOINTERFACE;
  201. }
  202. //*****************************************************************************
  203. // nsDocShellTreeOwner::nsIDocShellTreeOwner
  204. //*****************************************************************************
  205. NS_IMETHODIMP
  206. nsDocShellTreeOwner::FindItemWithName(const PRUnichar* aName,
  207. nsIDocShellTreeItem* aRequestor,
  208. nsIDocShellTreeItem* aOriginalRequestor,
  209. nsIDocShellTreeItem** aFoundItem)
  210. {
  211. NS_ENSURE_ARG(aName);
  212. NS_ENSURE_ARG_POINTER(aFoundItem);
  213. *aFoundItem = nsnull; // if we don't find one, we return NS_OK and a null result
  214. nsresult rv;
  215. nsAutoString name(aName);
  216. if (!mWebBrowser)
  217. return NS_OK; // stymied
  218. /* special cases */
  219. if(name.IsEmpty())
  220. return NS_OK;
  221. if(name.LowerCaseEqualsLiteral("_blank"))
  222. return NS_OK;
  223. // _main is an IE target which should be case-insensitive but isn't
  224. // see bug 217886 for details
  225. // XXXbz what if our browser isn't targetable? We need to handle that somehow.
  226. if(name.LowerCaseEqualsLiteral("_content") || name.EqualsLiteral("_main")) {
  227. *aFoundItem = mWebBrowser->mDocShellAsItem;
  228. NS_IF_ADDREF(*aFoundItem);
  229. return NS_OK;
  230. }
  231. if (!SameCOMIdentity(aRequestor, mWebBrowser->mDocShellAsItem)) {
  232. // This isn't a request coming up from our kid, so check with said kid
  233. nsISupports* thisSupports = static_cast<nsIDocShellTreeOwner*>(this);
  234. rv =
  235. mWebBrowser->mDocShellAsItem->FindItemWithName(aName, thisSupports,
  236. aOriginalRequestor, aFoundItem);
  237. if (NS_FAILED(rv) || *aFoundItem) {
  238. return rv;
  239. }
  240. }
  241. // next, if we have a parent and it isn't the requestor, ask it
  242. if(mTreeOwner) {
  243. nsCOMPtr<nsIDocShellTreeOwner> reqAsTreeOwner(do_QueryInterface(aRequestor));
  244. if (mTreeOwner != reqAsTreeOwner)
  245. return mTreeOwner->FindItemWithName(aName, mWebBrowser->mDocShellAsItem,
  246. aOriginalRequestor, aFoundItem);
  247. return NS_OK;
  248. }
  249. // finally, failing everything else, search all windows
  250. return FindItemWithNameAcrossWindows(aName, aRequestor, aOriginalRequestor,
  251. aFoundItem);
  252. }
  253. nsresult
  254. nsDocShellTreeOwner::FindItemWithNameAcrossWindows(const PRUnichar* aName,
  255. nsIDocShellTreeItem* aRequestor,
  256. nsIDocShellTreeItem* aOriginalRequestor,
  257. nsIDocShellTreeItem** aFoundItem)
  258. {
  259. // search for the item across the list of top-level windows
  260. nsCOMPtr<nsPIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
  261. if (!wwatch)
  262. return NS_OK;
  263. return wwatch->FindItemWithName(aName, aRequestor, aOriginalRequestor,
  264. aFoundItem);
  265. }
  266. void
  267. nsDocShellTreeOwner::EnsurePrompter()
  268. {
  269. if (mPrompter)
  270. return;
  271. nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
  272. if (wwatch && mWebBrowser) {
  273. nsCOMPtr<nsIDOMWindow> domWindow;
  274. mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
  275. if (domWindow)
  276. wwatch->GetNewPrompter(domWindow, getter_AddRefs(mPrompter));
  277. }
  278. }
  279. void
  280. nsDocShellTreeOwner::EnsureAuthPrompter()
  281. {
  282. if (mAuthPrompter)
  283. return;
  284. nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
  285. if (wwatch && mWebBrowser) {
  286. nsCOMPtr<nsIDOMWindow> domWindow;
  287. mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
  288. if (domWindow)
  289. wwatch->GetNewAuthPrompter(domWindow, getter_AddRefs(mAuthPrompter));
  290. }
  291. }
  292. void
  293. nsDocShellTreeOwner::AddToWatcher()
  294. {
  295. if (mWebBrowser) {
  296. nsCOMPtr<nsIDOMWindow> domWindow;
  297. mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
  298. if (domWindow) {
  299. nsCOMPtr<nsPIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
  300. if (wwatch) {
  301. nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
  302. if (webBrowserChrome)
  303. wwatch->AddWindow(domWindow, webBrowserChrome);
  304. }
  305. }
  306. }
  307. }
  308. void
  309. nsDocShellTreeOwner::RemoveFromWatcher()
  310. {
  311. if (mWebBrowser) {
  312. nsCOMPtr<nsIDOMWindow> domWindow;
  313. mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
  314. if (domWindow) {
  315. nsCOMPtr<nsPIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
  316. if (wwatch)
  317. wwatch->RemoveWindow(domWindow);
  318. }
  319. }
  320. }
  321. NS_IMETHODIMP
  322. nsDocShellTreeOwner::ContentShellAdded(nsIDocShellTreeItem* aContentShell,
  323. bool aPrimary, bool aTargetable,
  324. const nsAString& aID)
  325. {
  326. if(mTreeOwner)
  327. return mTreeOwner->ContentShellAdded(aContentShell, aPrimary,
  328. aTargetable, aID);
  329. if (aPrimary)
  330. mPrimaryContentShell = aContentShell;
  331. return NS_OK;
  332. }
  333. NS_IMETHODIMP
  334. nsDocShellTreeOwner::ContentShellRemoved(nsIDocShellTreeItem* aContentShell)
  335. {
  336. if(mTreeOwner)
  337. return mTreeOwner->ContentShellRemoved(aContentShell);
  338. if(mPrimaryContentShell == aContentShell)
  339. mPrimaryContentShell = nsnull;
  340. return NS_OK;
  341. }
  342. NS_IMETHODIMP
  343. nsDocShellTreeOwner::GetPrimaryContentShell(nsIDocShellTreeItem** aShell)
  344. {
  345. NS_ENSURE_ARG_POINTER(aShell);
  346. if(mTreeOwner)
  347. return mTreeOwner->GetPrimaryContentShell(aShell);
  348. *aShell = (mPrimaryContentShell ? mPrimaryContentShell : mWebBrowser->mDocShellAsItem.get());
  349. NS_IF_ADDREF(*aShell);
  350. return NS_OK;
  351. }
  352. NS_IMETHODIMP
  353. nsDocShellTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem,
  354. PRInt32 aCX, PRInt32 aCY)
  355. {
  356. nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
  357. NS_ENSURE_STATE(mTreeOwner || webBrowserChrome);
  358. if(mTreeOwner)
  359. return mTreeOwner->SizeShellTo(aShellItem, aCX, aCY);
  360. if(aShellItem == mWebBrowser->mDocShellAsItem)
  361. return webBrowserChrome->SizeBrowserTo(aCX, aCY);
  362. nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(aShellItem));
  363. NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
  364. nsCOMPtr<nsIDOMDocument> domDocument;
  365. webNav->GetDocument(getter_AddRefs(domDocument));
  366. NS_ENSURE_TRUE(domDocument, NS_ERROR_FAILURE);
  367. nsCOMPtr<nsIDOMElement> domElement;
  368. domDocument->GetDocumentElement(getter_AddRefs(domElement));
  369. NS_ENSURE_TRUE(domElement, NS_ERROR_FAILURE);
  370. // Set the preferred Size
  371. //XXX
  372. NS_ERROR("Implement this");
  373. /*
  374. Set the preferred size on the aShellItem.
  375. */
  376. nsRefPtr<nsPresContext> presContext;
  377. mWebBrowser->mDocShell->GetPresContext(getter_AddRefs(presContext));
  378. NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
  379. nsIPresShell *presShell = presContext->GetPresShell();
  380. NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
  381. NS_ENSURE_SUCCESS(presShell->ResizeReflow(NS_UNCONSTRAINEDSIZE,
  382. NS_UNCONSTRAINEDSIZE), NS_ERROR_FAILURE);
  383. nsRect shellArea = presContext->GetVisibleArea();
  384. PRInt32 browserCX = presContext->AppUnitsToDevPixels(shellArea.width);
  385. PRInt32 browserCY = presContext->AppUnitsToDevPixels(shellArea.height);
  386. return webBrowserChrome->SizeBrowserTo(browserCX, browserCY);
  387. }
  388. NS_IMETHODIMP
  389. nsDocShellTreeOwner::SetPersistence(bool aPersistPosition,
  390. bool aPersistSize,
  391. bool aPersistSizeMode)
  392. {
  393. return NS_ERROR_NOT_IMPLEMENTED;
  394. }
  395. NS_IMETHODIMP
  396. nsDocShellTreeOwner::GetPersistence(bool* aPersistPosition,
  397. bool* aPersistSize,
  398. bool* aPersistSizeMode)
  399. {
  400. return NS_ERROR_NOT_IMPLEMENTED;
  401. }
  402. NS_IMETHODIMP
  403. nsDocShellTreeOwner::GetTargetableShellCount(PRUint32* aResult)
  404. {
  405. if(mTreeOwner) {
  406. mTreeOwner->GetTargetableShellCount(aResult);
  407. } else {
  408. *aResult = 0;
  409. }
  410. return NS_OK;
  411. }
  412. //*****************************************************************************
  413. // nsDocShellTreeOwner::nsIBaseWindow
  414. //*****************************************************************************
  415. NS_IMETHODIMP
  416. nsDocShellTreeOwner::InitWindow(nativeWindow aParentNativeWindow,
  417. nsIWidget* aParentWidget, PRInt32 aX,
  418. PRInt32 aY, PRInt32 aCX, PRInt32 aCY)
  419. {
  420. return NS_ERROR_NULL_POINTER;
  421. }
  422. NS_IMETHODIMP
  423. nsDocShellTreeOwner::Create()
  424. {
  425. return NS_ERROR_NULL_POINTER;
  426. }
  427. NS_IMETHODIMP
  428. nsDocShellTreeOwner::Destroy()
  429. {
  430. nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
  431. if (webBrowserChrome)
  432. {
  433. return webBrowserChrome->DestroyBrowserWindow();
  434. }
  435. return NS_ERROR_NULL_POINTER;
  436. }
  437. NS_IMETHODIMP
  438. nsDocShellTreeOwner::SetPosition(PRInt32 aX, PRInt32 aY)
  439. {
  440. nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
  441. if (ownerWin)
  442. {
  443. return ownerWin->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
  444. aX, aY, 0, 0);
  445. }
  446. return NS_ERROR_NULL_POINTER;
  447. }
  448. NS_IMETHODIMP
  449. nsDocShellTreeOwner::GetPosition(PRInt32* aX, PRInt32* aY)
  450. {
  451. nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
  452. if (ownerWin)
  453. {
  454. return ownerWin->GetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
  455. aX, aY, nsnull, nsnull);
  456. }
  457. return NS_ERROR_NULL_POINTER;
  458. }
  459. NS_IMETHODIMP
  460. nsDocShellTreeOwner::SetSize(PRInt32 aCX, PRInt32 aCY, bool aRepaint)
  461. {
  462. nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
  463. if (ownerWin)
  464. {
  465. return ownerWin->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER,
  466. 0, 0, aCX, aCY);
  467. }
  468. return NS_ERROR_NULL_POINTER;
  469. }
  470. NS_IMETHODIMP
  471. nsDocShellTreeOwner::GetSize(PRInt32* aCX, PRInt32* aCY)
  472. {
  473. nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
  474. if (ownerWin)
  475. {
  476. return ownerWin->GetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER,
  477. nsnull, nsnull, aCX, aCY);
  478. }
  479. return NS_ERROR_NULL_POINTER;
  480. }
  481. NS_IMETHODIMP
  482. nsDocShellTreeOwner::SetPositionAndSize(PRInt32 aX, PRInt32 aY, PRInt32 aCX,
  483. PRInt32 aCY, bool aRepaint)
  484. {
  485. nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
  486. if (ownerWin)
  487. {
  488. return ownerWin->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER |
  489. nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
  490. aX, aY, aCX, aCY);
  491. }
  492. return NS_ERROR_NULL_POINTER;
  493. }
  494. NS_IMETHODIMP
  495. nsDocShellTreeOwner::GetPositionAndSize(PRInt32* aX, PRInt32* aY, PRInt32* aCX,
  496. PRInt32* aCY)
  497. {
  498. nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
  499. if (ownerWin)
  500. {
  501. return ownerWin->GetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER |
  502. nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
  503. aX, aY, aCX, aCY);
  504. }
  505. return NS_ERROR_NULL_POINTER;
  506. }
  507. NS_IMETHODIMP
  508. nsDocShellTreeOwner::Repaint(bool aForce)
  509. {
  510. return NS_ERROR_NULL_POINTER;
  511. }
  512. NS_IMETHODIMP
  513. nsDocShellTreeOwner::GetParentWidget(nsIWidget** aParentWidget)
  514. {
  515. return NS_ERROR_NULL_POINTER;
  516. }
  517. NS_IMETHODIMP
  518. nsDocShellTreeOwner::SetParentWidget(nsIWidget* aParentWidget)
  519. {
  520. return NS_ERROR_NULL_POINTER;
  521. }
  522. NS_IMETHODIMP
  523. nsDocShellTreeOwner::GetParentNativeWindow(nativeWindow* aParentNativeWindow)
  524. {
  525. nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
  526. if (ownerWin)
  527. {
  528. return ownerWin->GetSiteWindow(aParentNativeWindow);
  529. }
  530. return NS_ERROR_NULL_POINTER;
  531. }
  532. NS_IMETHODIMP
  533. nsDocShellTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow)
  534. {
  535. return NS_ERROR_NULL_POINTER;
  536. }
  537. NS_IMETHODIMP
  538. nsDocShellTreeOwner::GetVisibility(bool* aVisibility)
  539. {
  540. nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
  541. if (ownerWin)
  542. {
  543. return ownerWin->GetVisibility(aVisibility);
  544. }
  545. return NS_ERROR_NULL_POINTER;
  546. }
  547. NS_IMETHODIMP
  548. nsDocShellTreeOwner::SetVisibility(bool aVisibility)
  549. {
  550. nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
  551. if (ownerWin)
  552. {
  553. return ownerWin->SetVisibility(aVisibility);
  554. }
  555. return NS_ERROR_NULL_POINTER;
  556. }
  557. NS_IMETHODIMP
  558. nsDocShellTreeOwner::GetEnabled(bool *aEnabled)
  559. {
  560. NS_ENSURE_ARG_POINTER(aEnabled);
  561. *aEnabled = true;
  562. return NS_ERROR_NOT_IMPLEMENTED;
  563. }
  564. NS_IMETHODIMP
  565. nsDocShellTreeOwner::SetEnabled(bool aEnabled)
  566. {
  567. return NS_ERROR_NOT_IMPLEMENTED;
  568. }
  569. NS_IMETHODIMP
  570. nsDocShellTreeOwner::GetMainWidget(nsIWidget** aMainWidget)
  571. {
  572. return NS_ERROR_NULL_POINTER;
  573. }
  574. NS_IMETHODIMP
  575. nsDocShellTreeOwner::SetFocus()
  576. {
  577. nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
  578. if (ownerWin)
  579. {
  580. return ownerWin->SetFocus();
  581. }
  582. return NS_ERROR_NULL_POINTER;
  583. }
  584. NS_IMETHODIMP
  585. nsDocShellTreeOwner::GetTitle(PRUnichar** aTitle)
  586. {
  587. nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
  588. if (ownerWin)
  589. {
  590. return ownerWin->GetTitle(aTitle);
  591. }
  592. return NS_ERROR_NULL_POINTER;
  593. }
  594. NS_IMETHODIMP
  595. nsDocShellTreeOwner::SetTitle(const PRUnichar* aTitle)
  596. {
  597. nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
  598. if (ownerWin)
  599. {
  600. return ownerWin->SetTitle(aTitle);
  601. }
  602. return NS_ERROR_NULL_POINTER;
  603. }
  604. //*****************************************************************************
  605. // nsDocShellTreeOwner::nsIWebProgressListener
  606. //*****************************************************************************
  607. NS_IMETHODIMP
  608. nsDocShellTreeOwner::OnProgressChange(nsIWebProgress* aProgress,
  609. nsIRequest* aRequest,
  610. PRInt32 aCurSelfProgress,
  611. PRInt32 aMaxSelfProgress,
  612. PRInt32 aCurTotalProgress,
  613. PRInt32 aMaxTotalProgress)
  614. {
  615. // In the absence of DOM document creation event, this method is the
  616. // most convenient place to install the mouse listener on the
  617. // DOM document.
  618. return AddChromeListeners();
  619. }
  620. NS_IMETHODIMP
  621. nsDocShellTreeOwner::OnStateChange(nsIWebProgress* aProgress,
  622. nsIRequest* aRequest,
  623. PRUint32 aProgressStateFlags,
  624. nsresult aStatus)
  625. {
  626. return NS_OK;
  627. }
  628. NS_IMETHODIMP
  629. nsDocShellTreeOwner::OnLocationChange(nsIWebProgress* aWebProgress,
  630. nsIRequest* aRequest,
  631. nsIURI* aURI,
  632. PRUint32 aFlags)
  633. {
  634. return NS_OK;
  635. }
  636. NS_IMETHODIMP
  637. nsDocShellTreeOwner::OnStatusChange(nsIWebProgress* aWebProgress,
  638. nsIRequest* aRequest,
  639. nsresult aStatus,
  640. const PRUnichar* aMessage)
  641. {
  642. return NS_OK;
  643. }
  644. NS_IMETHODIMP
  645. nsDocShellTreeOwner::OnSecurityChange(nsIWebProgress *aWebProgress,
  646. nsIRequest *aRequest,
  647. PRUint32 state)
  648. {
  649. return NS_OK;
  650. }
  651. //*****************************************************************************
  652. // nsDocShellTreeOwner: Helpers
  653. //*****************************************************************************
  654. //*****************************************************************************
  655. // nsDocShellTreeOwner: Accessors
  656. //*****************************************************************************
  657. void
  658. nsDocShellTreeOwner::WebBrowser(nsWebBrowser* aWebBrowser)
  659. {
  660. if ( !aWebBrowser )
  661. RemoveChromeListeners();
  662. if (aWebBrowser != mWebBrowser) {
  663. mPrompter = 0;
  664. mAuthPrompter = 0;
  665. }
  666. mWebBrowser = aWebBrowser;
  667. }
  668. nsWebBrowser *
  669. nsDocShellTreeOwner::WebBrowser()
  670. {
  671. return mWebBrowser;
  672. }
  673. NS_IMETHODIMP
  674. nsDocShellTreeOwner::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner)
  675. {
  676. if(aTreeOwner) {
  677. nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome(do_GetInterface(aTreeOwner));
  678. NS_ENSURE_TRUE(webBrowserChrome, NS_ERROR_INVALID_ARG);
  679. NS_ENSURE_SUCCESS(SetWebBrowserChrome(webBrowserChrome), NS_ERROR_INVALID_ARG);
  680. mTreeOwner = aTreeOwner;
  681. }
  682. else {
  683. mTreeOwner = nsnull;
  684. nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
  685. if (!webBrowserChrome)
  686. NS_ENSURE_SUCCESS(SetWebBrowserChrome(nsnull), NS_ERROR_FAILURE);
  687. }
  688. return NS_OK;
  689. }
  690. NS_IMETHODIMP
  691. nsDocShellTreeOwner::SetWebBrowserChrome(nsIWebBrowserChrome* aWebBrowserChrome)
  692. {
  693. if(!aWebBrowserChrome) {
  694. mWebBrowserChrome = nsnull;
  695. mOwnerWin = nsnull;
  696. mOwnerRequestor = nsnull;
  697. mWebBrowserChromeWeak = 0;
  698. } else {
  699. nsCOMPtr<nsISupportsWeakReference> supportsweak =
  700. do_QueryInterface(aWebBrowserChrome);
  701. if (supportsweak) {
  702. supportsweak->GetWeakReference(getter_AddRefs(mWebBrowserChromeWeak));
  703. } else {
  704. nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin(do_QueryInterface(aWebBrowserChrome));
  705. nsCOMPtr<nsIInterfaceRequestor> requestor(do_QueryInterface(aWebBrowserChrome));
  706. // it's ok for ownerWin or requestor to be null.
  707. mWebBrowserChrome = aWebBrowserChrome;
  708. mOwnerWin = ownerWin;
  709. mOwnerRequestor = requestor;
  710. }
  711. }
  712. return NS_OK;
  713. }
  714. //
  715. // AddChromeListeners
  716. //
  717. // Hook up things to the chrome like context menus and tooltips, if the chrome
  718. // has implemented the right interfaces.
  719. //
  720. NS_IMETHODIMP
  721. nsDocShellTreeOwner::AddChromeListeners()
  722. {
  723. nsresult rv = NS_OK;
  724. nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
  725. if (!webBrowserChrome)
  726. return NS_ERROR_FAILURE;
  727. // install tooltips
  728. if ( !mChromeTooltipListener ) {
  729. nsCOMPtr<nsITooltipListener>
  730. tooltipListener(do_QueryInterface(webBrowserChrome));
  731. if ( tooltipListener ) {
  732. mChromeTooltipListener = new ChromeTooltipListener(mWebBrowser,
  733. webBrowserChrome);
  734. if ( mChromeTooltipListener ) {
  735. NS_ADDREF(mChromeTooltipListener);
  736. rv = mChromeTooltipListener->AddChromeListeners();
  737. }
  738. else
  739. rv = NS_ERROR_OUT_OF_MEMORY;
  740. }
  741. }
  742. // install context menus
  743. if ( !mChromeContextMenuListener ) {
  744. nsCOMPtr<nsIContextMenuListener2>
  745. contextListener2(do_QueryInterface(webBrowserChrome));
  746. nsCOMPtr<nsIContextMenuListener>
  747. contextListener(do_QueryInterface(webBrowserChrome));
  748. if ( contextListener2 || contextListener ) {
  749. mChromeContextMenuListener =
  750. new ChromeContextMenuListener(mWebBrowser, webBrowserChrome);
  751. if ( mChromeContextMenuListener ) {
  752. NS_ADDREF(mChromeContextMenuListener);
  753. rv = mChromeContextMenuListener->AddChromeListeners();
  754. }
  755. else
  756. rv = NS_ERROR_OUT_OF_MEMORY;
  757. }
  758. }
  759. // register dragover and drop event listeners with the listener manager
  760. nsCOMPtr<nsIDOMEventTarget> target;
  761. GetDOMEventTarget(mWebBrowser, getter_AddRefs(target));
  762. nsEventListenerManager* elmP = target->GetListenerManager(true);
  763. if (elmP) {
  764. elmP->AddEventListenerByType(this, NS_LITERAL_STRING("dragover"),
  765. NS_EVENT_FLAG_BUBBLE |
  766. NS_EVENT_FLAG_SYSTEM_EVENT);
  767. elmP->AddEventListenerByType(this, NS_LITERAL_STRING("drop"),
  768. NS_EVENT_FLAG_BUBBLE |
  769. NS_EVENT_FLAG_SYSTEM_EVENT);
  770. }
  771. return rv;
  772. } // AddChromeListeners
  773. NS_IMETHODIMP
  774. nsDocShellTreeOwner::RemoveChromeListeners()
  775. {
  776. if ( mChromeTooltipListener ) {
  777. mChromeTooltipListener->RemoveChromeListeners();
  778. NS_RELEASE(mChromeTooltipListener);
  779. }
  780. if ( mChromeContextMenuListener ) {
  781. mChromeContextMenuListener->RemoveChromeListeners();
  782. NS_RELEASE(mChromeContextMenuListener);
  783. }
  784. nsCOMPtr<nsIDOMEventTarget> piTarget;
  785. GetDOMEventTarget(mWebBrowser, getter_AddRefs(piTarget));
  786. if (!piTarget)
  787. return NS_OK;
  788. nsEventListenerManager* elmP = piTarget->GetListenerManager(true);
  789. if (elmP)
  790. {
  791. elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("dragover"),
  792. NS_EVENT_FLAG_BUBBLE |
  793. NS_EVENT_FLAG_SYSTEM_EVENT);
  794. elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("drop"),
  795. NS_EVENT_FLAG_BUBBLE |
  796. NS_EVENT_FLAG_SYSTEM_EVENT);
  797. }
  798. return NS_OK;
  799. }
  800. NS_IMETHODIMP
  801. nsDocShellTreeOwner::HandleEvent(nsIDOMEvent* aEvent)
  802. {
  803. nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
  804. NS_ENSURE_TRUE(dragEvent, NS_ERROR_INVALID_ARG);
  805. nsCOMPtr<nsIDOMNSEvent> domNSEvent = do_QueryInterface(aEvent);
  806. if (domNSEvent) {
  807. bool defaultPrevented;
  808. domNSEvent->GetPreventDefault(&defaultPrevented);
  809. if (defaultPrevented)
  810. return NS_OK;
  811. }
  812. nsCOMPtr<nsIDroppedLinkHandler> handler = do_GetService("@mozilla.org/content/dropped-link-handler;1");
  813. if (handler) {
  814. nsAutoString eventType;
  815. aEvent->GetType(eventType);
  816. if (eventType.EqualsLiteral("dragover")) {
  817. bool canDropLink;
  818. handler->CanDropLink(dragEvent, false, &canDropLink);
  819. if (canDropLink)
  820. aEvent->PreventDefault();
  821. }
  822. else if (eventType.EqualsLiteral("drop")) {
  823. nsIWebNavigation* webnav = static_cast<nsIWebNavigation *>(mWebBrowser);
  824. nsAutoString link, name;
  825. if (webnav && NS_SUCCEEDED(handler->DropLink(dragEvent, link, false, name))) {
  826. if (!link.IsEmpty()) {
  827. webnav->LoadURI(link.get(), 0, nsnull, nsnull, nsnull);
  828. }
  829. }
  830. else {
  831. aEvent->StopPropagation();
  832. aEvent->PreventDefault();
  833. }
  834. }
  835. }
  836. return NS_OK;
  837. }
  838. already_AddRefed<nsIWebBrowserChrome>
  839. nsDocShellTreeOwner::GetWebBrowserChrome()
  840. {
  841. nsCOMPtr<nsIWebBrowserChrome> chrome;
  842. if (mWebBrowserChromeWeak) {
  843. chrome = do_QueryReferent(mWebBrowserChromeWeak);
  844. } else if (mWebBrowserChrome) {
  845. chrome = mWebBrowserChrome;
  846. }
  847. return chrome.forget();
  848. }
  849. already_AddRefed<nsIEmbeddingSiteWindow>
  850. nsDocShellTreeOwner::GetOwnerWin()
  851. {
  852. nsCOMPtr<nsIEmbeddingSiteWindow> win;
  853. if (mWebBrowserChromeWeak) {
  854. win = do_QueryReferent(mWebBrowserChromeWeak);
  855. } else if (mOwnerWin) {
  856. win = mOwnerWin;
  857. }
  858. return win.forget();
  859. }
  860. already_AddRefed<nsIInterfaceRequestor>
  861. nsDocShellTreeOwner::GetOwnerRequestor()
  862. {
  863. nsCOMPtr<nsIInterfaceRequestor> req;
  864. if (mWebBrowserChromeWeak) {
  865. req = do_QueryReferent(mWebBrowserChromeWeak);
  866. } else if (mOwnerRequestor) {
  867. req = mOwnerRequestor;
  868. }
  869. return req.forget();
  870. }
  871. ///////////////////////////////////////////////////////////////////////////////
  872. // DefaultTooltipTextProvider
  873. class DefaultTooltipTextProvider : public nsITooltipTextProvider
  874. {
  875. public:
  876. DefaultTooltipTextProvider();
  877. NS_DECL_ISUPPORTS
  878. NS_DECL_NSITOOLTIPTEXTPROVIDER
  879. protected:
  880. nsCOMPtr<nsIAtom> mTag_dialog;
  881. nsCOMPtr<nsIAtom> mTag_dialogheader;
  882. nsCOMPtr<nsIAtom> mTag_window;
  883. };
  884. NS_IMPL_THREADSAFE_ISUPPORTS1(DefaultTooltipTextProvider, nsITooltipTextProvider)
  885. DefaultTooltipTextProvider::DefaultTooltipTextProvider()
  886. {
  887. // There are certain element types which we don't want to use
  888. // as tool tip text.
  889. mTag_dialog = do_GetAtom("dialog");
  890. mTag_dialogheader = do_GetAtom("dialogheader");
  891. mTag_window = do_GetAtom("window");
  892. }
  893. //
  894. // UseSVGTitle
  895. //
  896. // A helper routine that determines whether we're still interested
  897. // in SVG titles. We need to stop at the SVG root element that
  898. // has a document node parent
  899. //
  900. static bool
  901. UseSVGTitle(nsIDOMElement *currElement)
  902. {
  903. nsCOMPtr<nsIDOMSVGElement> svgContent(do_QueryInterface(currElement));
  904. if (!svgContent)
  905. return false;
  906. nsCOMPtr<nsIDOMNode> parent;
  907. currElement->GetParentNode(getter_AddRefs(parent));
  908. if (!parent)
  909. return false;
  910. PRUint16 nodeType;
  911. nsresult rv = parent->GetNodeType(&nodeType);
  912. return NS_SUCCEEDED(rv) && nodeType != nsIDOMNode::DOCUMENT_NODE;
  913. }
  914. /* void getNodeText (in nsIDOMNode aNode, out wstring aText); */
  915. NS_IMETHODIMP
  916. DefaultTooltipTextProvider::GetNodeText(nsIDOMNode *aNode, PRUnichar **aText,
  917. bool *_retval)
  918. {
  919. NS_ENSURE_ARG_POINTER(aNode);
  920. NS_ENSURE_ARG_POINTER(aText);
  921. nsString outText;
  922. bool lookingForSVGTitle = true;
  923. bool found = false;
  924. nsCOMPtr<nsIDOMNode> current ( aNode );
  925. // If the element implement the constraint validation API and has no title,
  926. // show the validation message, if any.
  927. nsCOMPtr<nsIConstraintValidation> cvElement = do_QueryInterface(current);
  928. if (cvElement) {
  929. nsCOMPtr<nsIContent> content = do_QueryInterface(cvElement);
  930. nsCOMPtr<nsIAtom> titleAtom = do_GetAtom("title");
  931. nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(content);
  932. bool formHasNoValidate = false;
  933. mozilla::dom::Element* form = formControl->GetFormElement();
  934. if (form) {
  935. nsCOMPtr<nsIAtom> noValidateAtom = do_GetAtom("novalidate");
  936. formHasNoValidate = form->HasAttr(kNameSpaceID_None, noValidateAtom);
  937. }
  938. if (!content->HasAttr(kNameSpaceID_None, titleAtom) &&
  939. !formHasNoValidate) {
  940. cvElement->GetValidationMessage(outText);
  941. found = !outText.IsEmpty();
  942. }
  943. }
  944. while ( !found && current ) {
  945. nsCOMPtr<nsIDOMElement> currElement ( do_QueryInterface(current) );
  946. if ( currElement ) {
  947. nsCOMPtr<nsIContent> content(do_QueryInterface(currElement));
  948. if (content) {
  949. nsIAtom *tagAtom = content->Tag();
  950. if (tagAtom != mTag_dialog &&
  951. tagAtom != mTag_dialogheader &&
  952. tagAtom != mTag_window) {
  953. // first try the normal title attribute...
  954. currElement->GetAttribute(NS_LITERAL_STRING("title"), outText);
  955. if ( outText.Length() )
  956. found = true;
  957. else {
  958. // ...ok, that didn't work, try it in the XLink namespace
  959. NS_NAMED_LITERAL_STRING(xlinkNS, "http://www.w3.org/1999/xlink");
  960. nsCOMPtr<mozilla::dom::Link> linkContent(do_QueryInterface(currElement));
  961. if (linkContent) {
  962. nsCOMPtr<nsIURI> uri(linkContent->GetURIExternal());
  963. if (uri) {
  964. currElement->GetAttributeNS(NS_LITERAL_STRING("http://www.w3.org/1999/xlink"), NS_LITERAL_STRING("title"), outText);
  965. if ( outText.Length() )
  966. found = true;
  967. }
  968. }
  969. else {
  970. if (lookingForSVGTitle) {
  971. lookingForSVGTitle = UseSVGTitle(currElement);
  972. }
  973. if (lookingForSVGTitle) {
  974. nsCOMPtr<nsIDOMNodeList>childNodes;
  975. aNode->GetChildNodes(getter_AddRefs(childNodes));
  976. PRUint32 childNodeCount;
  977. childNodes->GetLength(&childNodeCount);
  978. for (PRUint32 i = 0; i < childNodeCount; i++) {
  979. nsCOMPtr<nsIDOMNode>childNode;
  980. childNodes->Item(i, getter_AddRefs(childNode));
  981. nsCOMPtr<nsIDOMSVGTitleElement> titleElement(do_QueryInterface(childNode));
  982. if (titleElement) {
  983. titleElement->GetTextContent(outText);
  984. if ( outText.Length() )
  985. found = true;
  986. break;
  987. }
  988. }
  989. }
  990. }
  991. }
  992. }
  993. }
  994. }
  995. // not found here, walk up to the parent and keep trying
  996. if ( !found ) {
  997. nsCOMPtr<nsIDOMNode> temp ( current );
  998. temp->GetParentNode(getter_AddRefs(current));
  999. }
  1000. } // while not found
  1001. *_retval = found;
  1002. *aText = (found) ? ToNewUnicode(outText) : nsnull;
  1003. return NS_OK;
  1004. }
  1005. ///////////////////////////////////////////////////////////////////////////////
  1006. NS_IMPL_ISUPPORTS1(ChromeTooltipListener, nsIDOMEventListener)
  1007. //
  1008. // ChromeTooltipListener ctor
  1009. //
  1010. ChromeTooltipListener::ChromeTooltipListener(nsWebBrowser* inBrowser,
  1011. nsIWebBrowserChrome* inChrome)
  1012. : mWebBrowser(inBrowser), mWebBrowserChrome(inChrome),
  1013. mTooltipListenerInstalled(false),
  1014. mMouseClientX(0), mMouseClientY(0),
  1015. mShowingTooltip(false)
  1016. {
  1017. mTooltipTextProvider = do_GetService(NS_TOOLTIPTEXTPROVIDER_CONTRACTID);
  1018. if (!mTooltipTextProvider) {
  1019. nsISupports *pProvider = (nsISupports *) new DefaultTooltipTextProvider;
  1020. mTooltipTextProvider = do_QueryInterface(pProvider);
  1021. }
  1022. } // ctor
  1023. //
  1024. // ChromeTooltipListener dtor
  1025. //
  1026. ChromeTooltipListener::~ChromeTooltipListener()
  1027. {
  1028. } // dtor
  1029. //
  1030. // AddChromeListeners
  1031. //
  1032. // Hook up things to the chrome like context menus and tooltips, if the chrome
  1033. // has implemented the right interfaces.
  1034. //
  1035. NS_IMETHODIMP
  1036. ChromeTooltipListener::AddChromeListeners()
  1037. {
  1038. if (!mEventTarget)
  1039. GetDOMEventTarget(mWebBrowser, getter_AddRefs(mEventTarget));
  1040. // Register the appropriate events for tooltips, but only if
  1041. // the embedding chrome cares.
  1042. nsresult rv = NS_OK;
  1043. nsCOMPtr<nsITooltipListener> tooltipListener ( do_QueryInterface(mWebBrowserChrome) );
  1044. if ( tooltipListener && !mTooltipListenerInstalled ) {
  1045. rv = AddTooltipListener();
  1046. if ( NS_FAILED(rv) )
  1047. return rv;
  1048. }
  1049. return rv;
  1050. } // AddChromeListeners
  1051. //
  1052. // AddTooltipListener
  1053. //
  1054. // Subscribe to the events that will allow us to track tooltips. We need "mouse" for mouseExit,
  1055. // "mouse motion" for mouseMove, and "key" for keyDown. As we add the listeners, keep track
  1056. // of how many succeed so we can clean up correctly in Release().
  1057. //
  1058. NS_IMETHODIMP
  1059. ChromeTooltipListener::AddTooltipListener()
  1060. {
  1061. if (mEventTarget) {
  1062. nsresult rv = mEventTarget->AddEventListener(NS_LITERAL_STRING("keydown"),
  1063. this, false, false);
  1064. NS_ENSURE_SUCCESS(rv, rv);
  1065. rv = mEventTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), this,
  1066. false, false);
  1067. NS_ENSURE_SUCCESS(rv, rv);
  1068. rv = mEventTarget->AddEventListener(NS_LITERAL_STRING("mouseout"), this,
  1069. false, false);
  1070. NS_ENSURE_SUCCESS(rv, rv);
  1071. rv = mEventTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), this,
  1072. false, false);
  1073. NS_ENSURE_SUCCESS(rv, rv);
  1074. mTooltipListenerInstalled = true;
  1075. }
  1076. return NS_OK;
  1077. }
  1078. //
  1079. // RemoveChromeListeners
  1080. //
  1081. // Unsubscribe from the various things we've hooked up to the window root.
  1082. //
  1083. NS_IMETHODIMP
  1084. ChromeTooltipListener::RemoveChromeListeners ( )
  1085. {
  1086. HideTooltip();
  1087. if ( mTooltipListenerInstalled )
  1088. RemoveTooltipListener();
  1089. mEventTarget = nsnull;
  1090. // it really doesn't matter if these fail...
  1091. return NS_OK;
  1092. } // RemoveChromeTooltipListeners
  1093. //
  1094. // RemoveTooltipListener
  1095. //
  1096. // Unsubscribe from all the various tooltip events that we were listening to
  1097. //
  1098. NS_IMETHODIMP
  1099. ChromeTooltipListener::RemoveTooltipListener()
  1100. {
  1101. if (mEventTarget) {
  1102. nsresult rv =
  1103. mEventTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"), this,
  1104. false);
  1105. NS_ENSURE_SUCCESS(rv, rv);
  1106. rv = mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mousedown"),
  1107. this, false);
  1108. NS_ENSURE_SUCCESS(rv, rv);
  1109. rv = mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mouseout"), this,
  1110. false);
  1111. NS_ENSURE_SUCCESS(rv, rv);
  1112. rv = mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"),
  1113. this, false);
  1114. NS_ENSURE_SUCCESS(rv, rv);
  1115. mTooltipListenerInstalled = false;
  1116. }
  1117. return NS_OK;
  1118. }
  1119. NS_IMETHODIMP
  1120. ChromeTooltipListener::HandleEvent(nsIDOMEvent* aEvent)
  1121. {
  1122. nsAutoString eventType;
  1123. aEvent->GetType(eventType);
  1124. if (eventType.EqualsLiteral("keydown") ||
  1125. eventType.EqualsLiteral("mousedown") ||
  1126. eventType.EqualsLiteral("mouseout"))
  1127. return HideTooltip();
  1128. if (eventType.EqualsLiteral("mousemove"))
  1129. return MouseMove(aEvent);
  1130. NS_ERROR("Unexpected event type");
  1131. return NS_OK;
  1132. }
  1133. //
  1134. // MouseMove
  1135. //
  1136. // If we're a tooltip, fire off a timer to see if a tooltip should be shown. If the
  1137. // timer fires, we cache the node in |mPossibleTooltipNode|.
  1138. //
  1139. nsresult
  1140. ChromeTooltipListener::MouseMove(nsIDOMEvent* aMouseEvent)
  1141. {
  1142. nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
  1143. if (!mouseEvent)
  1144. return NS_OK;
  1145. // stash the coordinates of the event so that we can still get back to it from within the
  1146. // timer callback. On win32, we'll get a MouseMove event even when a popup goes away --
  1147. // even when the mouse doesn't change position! To get around this, we make sure the
  1148. // mouse has really moved before proceeding.
  1149. PRInt32 newMouseX, newMouseY;
  1150. mouseEvent->GetClientX(&newMouseX);
  1151. mouseEvent->GetClientY(&newMouseY);
  1152. if ( mMouseClientX == newMouseX && mMouseClientY == newMouseY )
  1153. return NS_OK;
  1154. mMouseClientX = newMouseX; mMouseClientY = newMouseY;
  1155. mouseEvent->GetScreenX(&mMouseScreenX);
  1156. mouseEvent->GetScreenY(&mMouseScreenY);
  1157. // We want to close the tip if it is being displayed and the mouse moves. Recall
  1158. // that |mShowingTooltip| is set when the popup is showing. Furthermore, as the mouse
  1159. // moves, we want to make sure we reset the timer to show it, so that the delay
  1160. // is from when the mouse stops moving, not when it enters the element.
  1161. if ( mShowingTooltip )
  1162. return HideTooltip();
  1163. if ( mTooltipTimer )
  1164. mTooltipTimer->Cancel();
  1165. mTooltipTimer = do_CreateInstance("@mozilla.org/timer;1");
  1166. if ( mTooltipTimer ) {
  1167. nsCOMPtr<nsIDOMEventTarget> eventTarget;
  1168. aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
  1169. if ( eventTarget )
  1170. mPossibleTooltipNode = do_QueryInterface(eventTarget);
  1171. if ( mPossibleTooltipNode ) {
  1172. nsresult rv =
  1173. mTooltipTimer->InitWithFuncCallback(sTooltipCallback, this,
  1174. LookAndFeel::GetInt(LookAndFeel::eIntID_TooltipDelay, 500),
  1175. nsITimer::TYPE_ONE_SHOT);
  1176. if (NS_FAILED(rv))
  1177. mPossibleTooltipNode = nsnull;
  1178. }
  1179. }
  1180. else
  1181. NS_WARNING ( "Could not create a timer for tooltip tracking" );
  1182. return NS_OK;
  1183. } // MouseMove
  1184. //
  1185. // ShowTooltip
  1186. //
  1187. // Tell the registered chrome that they should show the tooltip
  1188. //
  1189. NS_IMETHODIMP
  1190. ChromeTooltipListener::ShowTooltip(PRInt32 inXCoords, PRInt32 inYCoords,
  1191. const nsAString & inTipText)
  1192. {
  1193. nsresult rv = NS_OK;
  1194. // do the work to call the client
  1195. nsCOMPtr<nsITooltipListener> tooltipListener ( do_QueryInterface(mWebBrowserChrome) );
  1196. if ( tooltipListener ) {
  1197. rv = tooltipListener->OnShowTooltip ( inXCoords, inYCoords, PromiseFlatString(inTipText).get() );
  1198. if ( NS_SUCCEEDED(rv) )
  1199. mShowingTooltip = true;
  1200. }
  1201. return rv;
  1202. } // ShowTooltip
  1203. //
  1204. // HideTooltip
  1205. //
  1206. // Tell the registered chrome that they should rollup the tooltip
  1207. // NOTE: This routine is safe to call even if the popup is already closed.
  1208. //
  1209. NS_IMETHODIMP
  1210. ChromeTooltipListener::HideTooltip()
  1211. {
  1212. nsresult rv = NS_OK;
  1213. // shut down the relevant timers
  1214. if ( mTooltipTimer ) {
  1215. mTooltipTimer->Cancel();
  1216. mTooltipTimer = nsnull;
  1217. // release tooltip target
  1218. mPossibleTooltipNode = nsnull;
  1219. }
  1220. if ( mAutoHideTimer ) {
  1221. mAutoHideTimer->Cancel();
  1222. mAutoHideTimer = nsnull;
  1223. }
  1224. // if we're showing the tip, tell the chrome to hide it
  1225. if ( mShowingTooltip ) {
  1226. nsCOMPtr<nsITooltipListener> tooltipListener ( do_QueryInterface(mWebBrowserChrome) );
  1227. if ( tooltipListener ) {
  1228. rv = tooltipListener->OnHideTooltip ( );
  1229. if ( NS_SUCCEEDED(rv) )
  1230. mShowingTooltip = false;
  1231. }
  1232. }
  1233. return rv;
  1234. } // HideTooltip
  1235. //
  1236. // sTooltipCallback
  1237. //
  1238. // A timer callback, fired when the mouse has hovered inside of a frame for the
  1239. // appropriate amount of time. Getting to this point means that we should show the
  1240. // tooltip, but only after we determine there is an appropriate TITLE element.
  1241. //
  1242. // This relies on certain things being cached into the |aChromeTooltipListener| object passed to
  1243. // us by the timer:
  1244. // -- the x/y coordinates of the mouse (mMouseClientY, mMouseClientX)
  1245. // -- the dom node the user hovered over (mPossibleTooltipNode)
  1246. //
  1247. void
  1248. ChromeTooltipListener::sTooltipCallback(nsITimer *aTimer,
  1249. void *aChromeTooltipListener)
  1250. {
  1251. ChromeTooltipListener* self = static_cast<ChromeTooltipListener*>
  1252. (aChromeTooltipListener);
  1253. if ( self && self->mPossibleTooltipNode ){
  1254. // The actual coordinates we want to put the tooltip at are relative to the
  1255. // toplevel docshell of our mWebBrowser. We know what the screen
  1256. // coordinates of the mouse event were, which means we just need the screen
  1257. // coordinates of the docshell. Unfortunately, there is no good way to
  1258. // find those short of groveling for the presentation in that docshell and
  1259. // finding the screen coords of its toplevel widget...
  1260. nsCOMPtr<nsIDocShell> docShell =
  1261. do_GetInterface(static_cast<nsIWebBrowser*>(self->mWebBrowser));
  1262. nsCOMPtr<nsIPresShell> shell;
  1263. if (docShell) {
  1264. docShell->GetPresShell(getter_AddRefs(shell));
  1265. }
  1266. nsIWidget* widget = nsnull;
  1267. if (shell) {
  1268. nsIViewManager* vm = shell->GetViewManager();
  1269. if (vm) {
  1270. nsIView* view = vm->GetRootView();
  1271. if (view) {
  1272. nsPoint offset;
  1273. widget = view->GetNearestWidget(&offset);
  1274. }
  1275. }
  1276. }
  1277. if (!widget) {
  1278. // release tooltip target if there is one, NO MATTER WHAT
  1279. self->mPossibleTooltipNode = nsnull;
  1280. return;
  1281. }
  1282. // if there is text associated with the node, show the tip and fire
  1283. // off a timer to auto-hide it.
  1284. nsXPIDLString tooltipText;
  1285. if (self->mTooltipTextProvider) {
  1286. bool textFound = false;
  1287. self->mTooltipTextProvider->GetNodeText(
  1288. self->mPossibleTooltipNode, getter_Copies(tooltipText), &textFound);
  1289. if (textFound) {
  1290. nsString tipText(tooltipText);
  1291. self->CreateAutoHideTimer();
  1292. nsIntPoint screenDot = widget->WidgetToScreenOffset();
  1293. self->ShowTooltip (self->mMouseScreenX - screenDot.x,
  1294. self->mMouseScreenY - screenDot.y,
  1295. tipText);
  1296. }
  1297. }
  1298. // release tooltip target if there is one, NO MATTER WHAT
  1299. self->mPossibleTooltipNode = nsnull;
  1300. } // if "self" data valid
  1301. } // sTooltipCallback
  1302. //
  1303. // CreateAutoHideTimer
  1304. //
  1305. // Create a new timer to see if we should auto-hide. It's ok if this fails.
  1306. //
  1307. void
  1308. ChromeTooltipListener::CreateAutoHideTimer()
  1309. {
  1310. // just to be anal (er, safe)
  1311. if ( mAutoHideTimer ) {
  1312. mAutoHideTimer->Cancel();
  1313. mAutoHideTimer = nsnull;
  1314. }
  1315. mAutoHideTimer = do_CreateInstance("@mozilla.org/timer;1");
  1316. if ( mAutoHideTimer )
  1317. mAutoHideTimer->InitWithFuncCallback(sAutoHideCallback, this, kTooltipAutoHideTime,
  1318. nsITimer::TYPE_ONE_SHOT);
  1319. } // CreateAutoHideTimer
  1320. //
  1321. // sAutoHideCallback
  1322. //
  1323. // This fires after a tooltip has been open for a certain length of time. Just tell
  1324. // the listener to close the popup. We don't have to worry, because HideTooltip() can
  1325. // be called multiple times, even if the tip has already been closed.
  1326. //
  1327. void
  1328. ChromeTooltipListener::sAutoHideCallback(nsITimer *aTimer, void* aListener)
  1329. {
  1330. ChromeTooltipListener* self = static_cast<ChromeTooltipListener*>(aListener);
  1331. if ( self )
  1332. self->HideTooltip();
  1333. // NOTE: |aTimer| and |self->mAutoHideTimer| are invalid after calling ClosePopup();
  1334. } // sAutoHideCallback
  1335. NS_IMPL_ISUPPORTS1(ChromeContextMenuListener, nsIDOMEventListener)
  1336. //
  1337. // ChromeTooltipListener ctor
  1338. //
  1339. ChromeContextMenuListener::ChromeContextMenuListener(nsWebBrowser* inBrowser, nsIWebBrowserChrome* inChrome )
  1340. : mContextMenuListenerInstalled(false),
  1341. mWebBrowser(inBrowser),
  1342. mWebBrowserChrome(inChrome)
  1343. {
  1344. } // ctor
  1345. //
  1346. // ChromeTooltipListener dtor
  1347. //
  1348. ChromeContextMenuListener::~ChromeContextMenuListener()
  1349. {
  1350. } // dtor
  1351. //
  1352. // AddContextMenuListener
  1353. //
  1354. // Subscribe to the events that will allow us to track context menus. Bascially, this
  1355. // is just the context-menu DOM event.
  1356. //
  1357. NS_IMETHODIMP
  1358. ChromeContextMenuListener::AddContextMenuListener()
  1359. {
  1360. if (mEventTarget) {
  1361. nsresult rv =
  1362. mEventTarget->AddEventListener(NS_LITERAL_STRING("contextmenu"), this,
  1363. false, false);
  1364. NS_ENSURE_SUCCESS(rv, rv);
  1365. mContextMenuListenerInstalled = true;
  1366. }
  1367. return NS_OK;
  1368. }
  1369. //
  1370. // RemoveContextMenuListener
  1371. //
  1372. // Unsubscribe from all the various context menu events that we were listening to.
  1373. //
  1374. NS_IMETHODIMP
  1375. ChromeContextMenuListener::RemoveContextMenuListener()
  1376. {
  1377. if (mEventTarget) {
  1378. nsresult rv =
  1379. mEventTarget->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this,
  1380. false);
  1381. NS_ENSURE_SUCCESS(rv, rv);
  1382. mContextMenuListenerInstalled = false;
  1383. }
  1384. return NS_OK;
  1385. }
  1386. //
  1387. // AddChromeListeners
  1388. //
  1389. // Hook up things to the chrome like context menus and tooltips, if the chrome
  1390. // has implemented the right interfaces.
  1391. //
  1392. NS_IMETHODIMP
  1393. ChromeContextMenuListener::AddChromeListeners()
  1394. {
  1395. if (!mEventTarget)
  1396. GetDOMEventTarget(mWebBrowser, getter_AddRefs(mEventTarget));
  1397. // Register the appropriate events for context menus, but only if
  1398. // the embedding chrome cares.
  1399. nsresult rv = NS_OK;
  1400. nsCOMPtr<nsIContextMenuListener2> contextListener2 ( do_QueryInterface(mWebBrowserChrome) );
  1401. nsCOMPtr<nsIContextMenuListener> contextListener ( do_QueryInterface(mWebBrowserChrome) );
  1402. if ( (contextListener || contextListener2) && !mContextMenuListenerInstalled )
  1403. rv = AddContextMenuListener();
  1404. return rv;
  1405. } // AddChromeListeners
  1406. //
  1407. // RemoveChromeListeners
  1408. //
  1409. // Unsubscribe from the various things we've hooked up to the window root.
  1410. //
  1411. NS_IMETHODIMP
  1412. ChromeContextMenuListener::RemoveChromeListeners()
  1413. {
  1414. if ( mContextMenuListenerInstalled )
  1415. RemoveContextMenuListener();
  1416. mEventTarget = nsnull;
  1417. // it really doesn't matter if these fail...
  1418. return NS_OK;
  1419. } // RemoveChromeTooltipListeners
  1420. //
  1421. // ContextMenu
  1422. //
  1423. // We're on call to show the context menu. Dig around in the DOM to
  1424. // find the type of object we're dealing with and notify the front
  1425. // end chrome.
  1426. //
  1427. NS_IMETHODIMP
  1428. ChromeContextMenuListener::HandleEvent(nsIDOMEvent* aMouseEvent)
  1429. {
  1430. nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
  1431. NS_ENSURE_TRUE(mouseEvent, NS_ERROR_UNEXPECTED);
  1432. nsCOMPtr<nsIDOMNSEvent> domNSEvent = do_QueryInterface(aMouseEvent);
  1433. if (domNSEvent) {
  1434. bool isDefaultPrevented = false;
  1435. domNSEvent->GetPreventDefault(&isDefaultPrevented);
  1436. if (isDefaultPrevented) {
  1437. return NS_OK;
  1438. }
  1439. }
  1440. nsCOMPtr<nsIDOMEventTarget> targetNode;
  1441. nsresult res = aMouseEvent->GetTarget(getter_AddRefs(targetNode));
  1442. if (NS_FAILED(res))
  1443. return res;
  1444. if (!targetNode)
  1445. return NS_ERROR_NULL_POINTER;
  1446. nsCOMPtr<nsIDOMNode> targetDOMnode;
  1447. nsCOMPtr<nsIDOMNode> node = do_QueryInterface(targetNode);
  1448. if (!node)
  1449. return NS_OK;
  1450. // Stop the context menu event going to other windows (bug 78396)
  1451. aMouseEvent->PreventDefault();
  1452. // If the listener is a nsIContextMenuListener2, create the info object
  1453. nsCOMPtr<nsIContextMenuListener2> menuListener2(do_QueryInterface(mWebBrowserChrome));
  1454. nsContextMenuInfo *menuInfoImpl = nsnull;
  1455. nsCOMPtr<nsIContextMenuInfo> menuInfo;
  1456. if (menuListener2) {
  1457. menuInfoImpl = new nsContextMenuInfo;
  1458. if (!menuInfoImpl)
  1459. return NS_ERROR_OUT_OF_MEMORY;
  1460. menuInfo = menuInfoImpl;
  1461. }
  1462. PRUint32 flags = nsIContextMenuListener::CONTEXT_NONE;
  1463. PRUint32 flags2 = nsIContextMenuListener2::CONTEXT_NONE;
  1464. // XXX test for selected text
  1465. PRUint16 nodeType;
  1466. res = node->GetNodeType(&nodeType);
  1467. NS_ENSURE_SUCCESS(res, res);
  1468. // First, checks for nodes that never have children.
  1469. if (nodeType == nsIDOMNode::ELEMENT_NODE) {
  1470. nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(node));
  1471. if (content) {
  1472. nsCOMPtr<nsIURI> imgUri;
  1473. content->GetCurrentURI(getter_AddRefs(imgUri));
  1474. if (imgUri) {
  1475. flags |= nsIContextMenuListener::CONTEXT_IMAGE;
  1476. flags2 |= nsIContextMenuListener2::CONTEXT_IMAGE;
  1477. targetDOMnode = node;
  1478. }
  1479. }
  1480. nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(node));
  1481. if (formControl) {
  1482. if (formControl->GetType() == NS_FORM_TEXTAREA) {
  1483. flags |= nsIContextMenuListener::CONTEXT_TEXT;
  1484. flags2 |= nsIContextMenuListener2::CONTEXT_TEXT;
  1485. targetDOMnode = node;
  1486. } else {
  1487. nsCOMPtr<nsIDOMHTMLInputElement> inputElement(do_QueryInterface(formControl));
  1488. if (inputElement) {
  1489. flags |= nsIContextMenuListener::CONTEXT_INPUT;
  1490. flags2 |= nsIContextMenuListener2::CONTEXT_INPUT;
  1491. if (menuListener2) {
  1492. if (formControl->IsSingleLineTextControl(false)) {
  1493. flags2 |= nsIContextMenuListener2::CONTEXT_TEXT;
  1494. }
  1495. }
  1496. targetDOMnode = node;
  1497. }
  1498. }
  1499. }
  1500. // always consume events for plugins and Java who may throw their
  1501. // own context menus but not for image objects. Document objects
  1502. // will never be targets or ancestors of targets, so that's OK.
  1503. nsCOMPtr<nsIDOMHTMLObjectElement> objectElement;
  1504. if (!(flags & nsIContextMenuListener::CONTEXT_IMAGE))
  1505. objectElement = do_QueryInterface(node);
  1506. nsCOMPtr<nsIDOMHTMLEmbedElement> embedElement(do_QueryInterface(node));
  1507. nsCOMPtr<nsIDOMHTMLAppletElement> appletElement(do_QueryInterface(node));
  1508. if (objectElement || embedElement || appletElement)
  1509. return NS_OK;
  1510. }
  1511. // Bubble out, looking for items of interest
  1512. do {
  1513. PRUint16 nodeType;
  1514. res = node->GetNodeType(&nodeType);
  1515. NS_ENSURE_SUCCESS(res, res);
  1516. if (nodeType == nsIDOMNode::ELEMENT_NODE) {
  1517. // Test if the element has an associated link
  1518. nsCOMPtr<nsIDOMElement> element(do_QueryInterface(node));
  1519. bool hasAttr = false;
  1520. res = element->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
  1521. if (NS_SUCCEEDED(res) && hasAttr)
  1522. {
  1523. flags |= nsIContextMenuListener::CONTEXT_LINK;
  1524. flags2 |= nsIContextMenuListener2::CONTEXT_LINK;
  1525. if (!targetDOMnode)
  1526. targetDOMnode = node;
  1527. if (menuInfoImpl)
  1528. menuInfoImpl->SetAssociatedLink(node);
  1529. break; // exit do-while
  1530. }
  1531. }
  1532. // walk-up-the-tree
  1533. nsCOMPtr<nsIDOMNode> parentNode;
  1534. node->GetParentNode(getter_AddRefs(parentNode));
  1535. node = parentNode;
  1536. } while (node);
  1537. if (!flags && !flags2) {
  1538. // We found nothing of interest so far, check if we
  1539. // have at least an html document.
  1540. nsCOMPtr<nsIDOMDocument> document;
  1541. node = do_QueryInterface(targetNode);
  1542. node->GetOwnerDocument(getter_AddRefs(document));
  1543. nsCOMPtr<nsIDOMHTMLDocument> htmlDocument(do_QueryInterface(document));
  1544. if (htmlDocument) {
  1545. flags |= nsIContextMenuListener::CONTEXT_DOCUMENT;
  1546. flags2 |= nsIContextMenuListener2::CONTEXT_DOCUMENT;
  1547. targetDOMnode = node;
  1548. if (!(flags & nsIContextMenuListener::CONTEXT_IMAGE)) {
  1549. // check if this is a background image that the user was trying to click on
  1550. // and if the listener is ready for that (only nsIContextMenuListener2 and up)
  1551. if (menuInfoImpl && menuInfoImpl->HasBackgroundImage(targetDOMnode)) {
  1552. flags2 |= nsIContextMenuListener2::CONTEXT_BACKGROUND_IMAGE;
  1553. // For the embedder to get the correct background image
  1554. // targetDOMnode must point to the original node.
  1555. targetDOMnode = do_QueryInterface(targetNode);
  1556. }
  1557. }
  1558. }
  1559. }
  1560. // we need to cache the event target into the focus controller's popupNode
  1561. // so we can get at it later from command code, etc.:
  1562. // get the dom window
  1563. nsCOMPtr<nsIDOMWindow> win;
  1564. res = mWebBrowser->GetContentDOMWindow(getter_AddRefs(win));
  1565. NS_ENSURE_SUCCESS(res, res);
  1566. NS_ENSURE_TRUE(win, NS_ERROR_FAILURE);
  1567. nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(win));
  1568. NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
  1569. nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
  1570. NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
  1571. if (root) {
  1572. // set the window root's popup node to the event target
  1573. root->SetPopupNode(targetDOMnode);
  1574. }
  1575. // Tell the listener all about the event
  1576. if ( menuListener2 ) {
  1577. menuInfoImpl->SetMouseEvent(aMouseEvent);
  1578. menuInfoImpl->SetDOMNode(targetDOMnode);
  1579. menuListener2->OnShowContextMenu(flags2, menuInfo);
  1580. }
  1581. else {
  1582. nsCOMPtr<nsIContextMenuListener> menuListener(do_QueryInterface(mWebBrowserChrome));
  1583. if ( menuListener )
  1584. menuListener->OnShowContextMenu(flags, aMouseEvent, targetDOMnode);
  1585. }
  1586. return NS_OK;
  1587. } // MouseDown