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