Source code

Revision control

Other Tools

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 "nsSize.h"
14
#include "mozilla/ReflowInput.h"
15
#include "nsComponentManagerUtils.h"
16
#include "nsString.h"
17
#include "nsAtom.h"
18
#include "nsReadableUtils.h"
19
#include "nsUnicharUtils.h"
20
#include "mozilla/LookAndFeel.h"
21
22
// Interfaces needed to be included
23
#include "nsPresContext.h"
24
#include "nsITooltipListener.h"
25
#include "nsINode.h"
26
#include "Link.h"
27
#include "mozilla/dom/Element.h"
28
#include "mozilla/dom/MouseEvent.h"
29
#include "mozilla/dom/SVGTitleElement.h"
30
#include "nsIFormControl.h"
31
#include "nsIWebNavigation.h"
32
#include "nsPIDOMWindow.h"
33
#include "nsPIWindowRoot.h"
34
#include "nsIWindowWatcher.h"
35
#include "nsPIWindowWatcher.h"
36
#include "nsIPrompt.h"
37
#include "nsIRemoteTab.h"
38
#include "nsIBrowserChild.h"
39
#include "nsRect.h"
40
#include "nsIWebBrowserChromeFocus.h"
41
#include "nsIContent.h"
42
#include "nsViewManager.h"
43
#include "nsView.h"
44
#include "nsIConstraintValidation.h"
45
#include "mozilla/Attributes.h"
46
#include "mozilla/EventListenerManager.h"
47
#include "mozilla/dom/DragEvent.h"
48
#include "mozilla/dom/Event.h" // for Event
49
#include "mozilla/dom/File.h" // for input type=file
50
#include "mozilla/dom/FileList.h" // for input type=file
51
#include "mozilla/dom/LoadURIOptionsBinding.h"
52
#include "mozilla/PresShell.h"
53
#include "mozilla/TextEvents.h"
54
55
using namespace mozilla;
56
using namespace mozilla::dom;
57
58
// A helper routine that navigates the tricky path from a |nsWebBrowser| to
59
// a |EventTarget| via the window root and chrome event handler.
60
static nsresult GetDOMEventTarget(nsWebBrowser* aInBrowser,
61
EventTarget** aTarget) {
62
if (!aInBrowser) {
63
return NS_ERROR_INVALID_POINTER;
64
}
65
66
nsCOMPtr<mozIDOMWindowProxy> domWindow;
67
aInBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
68
if (!domWindow) {
69
return NS_ERROR_FAILURE;
70
}
71
72
auto* outerWindow = nsPIDOMWindowOuter::From(domWindow);
73
nsPIDOMWindowOuter* rootWindow = outerWindow->GetPrivateRoot();
74
NS_ENSURE_TRUE(rootWindow, NS_ERROR_FAILURE);
75
nsCOMPtr<EventTarget> target = rootWindow->GetChromeEventHandler();
76
NS_ENSURE_TRUE(target, NS_ERROR_FAILURE);
77
target.forget(aTarget);
78
79
return NS_OK;
80
}
81
82
nsDocShellTreeOwner::nsDocShellTreeOwner()
83
: mWebBrowser(nullptr),
84
mTreeOwner(nullptr),
85
mPrimaryContentShell(nullptr),
86
mWebBrowserChrome(nullptr),
87
mOwnerWin(nullptr),
88
mOwnerRequestor(nullptr) {}
89
90
nsDocShellTreeOwner::~nsDocShellTreeOwner() { RemoveChromeListeners(); }
91
92
NS_IMPL_ADDREF(nsDocShellTreeOwner)
93
NS_IMPL_RELEASE(nsDocShellTreeOwner)
94
95
NS_INTERFACE_MAP_BEGIN(nsDocShellTreeOwner)
96
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellTreeOwner)
97
NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeOwner)
98
NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
99
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
100
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
101
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
102
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
103
NS_INTERFACE_MAP_END
104
105
//*****************************************************************************
106
// nsDocShellTreeOwner::nsIInterfaceRequestor
107
//*****************************************************************************
108
109
NS_IMETHODIMP
110
nsDocShellTreeOwner::GetInterface(const nsIID& aIID, void** aSink) {
111
NS_ENSURE_ARG_POINTER(aSink);
112
113
if (NS_SUCCEEDED(QueryInterface(aIID, aSink))) {
114
return NS_OK;
115
}
116
117
if (aIID.Equals(NS_GET_IID(nsIWebBrowserChromeFocus))) {
118
if (mWebBrowserChromeWeak != nullptr) {
119
return mWebBrowserChromeWeak->QueryReferent(aIID, aSink);
120
}
121
return mOwnerWin->QueryInterface(aIID, aSink);
122
}
123
124
if (aIID.Equals(NS_GET_IID(nsIPrompt))) {
125
nsCOMPtr<nsIPrompt> prompt;
126
EnsurePrompter();
127
prompt = mPrompter;
128
if (prompt) {
129
prompt.forget(aSink);
130
return NS_OK;
131
}
132
return NS_NOINTERFACE;
133
}
134
135
if (aIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
136
nsCOMPtr<nsIAuthPrompt> prompt;
137
EnsureAuthPrompter();
138
prompt = mAuthPrompter;
139
if (prompt) {
140
prompt.forget(aSink);
141
return NS_OK;
142
}
143
return NS_NOINTERFACE;
144
}
145
146
nsCOMPtr<nsIInterfaceRequestor> req = GetOwnerRequestor();
147
if (req) {
148
return req->GetInterface(aIID, aSink);
149
}
150
151
return NS_NOINTERFACE;
152
}
153
154
//*****************************************************************************
155
// nsDocShellTreeOwner::nsIDocShellTreeOwner
156
//*****************************************************************************
157
158
void nsDocShellTreeOwner::EnsurePrompter() {
159
if (mPrompter) {
160
return;
161
}
162
163
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
164
if (wwatch && mWebBrowser) {
165
nsCOMPtr<mozIDOMWindowProxy> domWindow;
166
mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
167
if (domWindow) {
168
wwatch->GetNewPrompter(domWindow, getter_AddRefs(mPrompter));
169
}
170
}
171
}
172
173
void nsDocShellTreeOwner::EnsureAuthPrompter() {
174
if (mAuthPrompter) {
175
return;
176
}
177
178
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
179
if (wwatch && mWebBrowser) {
180
nsCOMPtr<mozIDOMWindowProxy> domWindow;
181
mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
182
if (domWindow) {
183
wwatch->GetNewAuthPrompter(domWindow, getter_AddRefs(mAuthPrompter));
184
}
185
}
186
}
187
188
void nsDocShellTreeOwner::AddToWatcher() {
189
if (mWebBrowser) {
190
nsCOMPtr<mozIDOMWindowProxy> domWindow;
191
mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
192
if (domWindow) {
193
nsCOMPtr<nsPIWindowWatcher> wwatch(
194
do_GetService(NS_WINDOWWATCHER_CONTRACTID));
195
if (wwatch) {
196
nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
197
if (webBrowserChrome) {
198
wwatch->AddWindow(domWindow, webBrowserChrome);
199
}
200
}
201
}
202
}
203
}
204
205
void nsDocShellTreeOwner::RemoveFromWatcher() {
206
if (mWebBrowser) {
207
nsCOMPtr<mozIDOMWindowProxy> domWindow;
208
mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
209
if (domWindow) {
210
nsCOMPtr<nsPIWindowWatcher> wwatch(
211
do_GetService(NS_WINDOWWATCHER_CONTRACTID));
212
if (wwatch) {
213
wwatch->RemoveWindow(domWindow);
214
}
215
}
216
}
217
}
218
219
void nsDocShellTreeOwner::EnsureContentTreeOwner() {
220
if (mContentTreeOwner) {
221
return;
222
}
223
224
mContentTreeOwner = new nsDocShellTreeOwner();
225
nsCOMPtr<nsIWebBrowserChrome> browserChrome = GetWebBrowserChrome();
226
if (browserChrome) {
227
mContentTreeOwner->SetWebBrowserChrome(browserChrome);
228
}
229
230
if (mWebBrowser) {
231
mContentTreeOwner->WebBrowser(mWebBrowser);
232
}
233
}
234
235
NS_IMETHODIMP
236
nsDocShellTreeOwner::ContentShellAdded(nsIDocShellTreeItem* aContentShell,
237
bool aPrimary) {
238
if (mTreeOwner) return mTreeOwner->ContentShellAdded(aContentShell, aPrimary);
239
240
EnsureContentTreeOwner();
241
aContentShell->SetTreeOwner(mContentTreeOwner);
242
243
if (aPrimary) {
244
mPrimaryContentShell = aContentShell;
245
mPrimaryRemoteTab = nullptr;
246
}
247
return NS_OK;
248
}
249
250
NS_IMETHODIMP
251
nsDocShellTreeOwner::ContentShellRemoved(nsIDocShellTreeItem* aContentShell) {
252
if (mTreeOwner) {
253
return mTreeOwner->ContentShellRemoved(aContentShell);
254
}
255
256
if (mPrimaryContentShell == aContentShell) {
257
mPrimaryContentShell = nullptr;
258
}
259
260
return NS_OK;
261
}
262
263
NS_IMETHODIMP
264
nsDocShellTreeOwner::GetPrimaryContentShell(nsIDocShellTreeItem** aShell) {
265
NS_ENSURE_ARG_POINTER(aShell);
266
267
if (mTreeOwner) {
268
return mTreeOwner->GetPrimaryContentShell(aShell);
269
}
270
271
nsCOMPtr<nsIDocShellTreeItem> shell;
272
if (!mPrimaryRemoteTab) {
273
shell =
274
mPrimaryContentShell ? mPrimaryContentShell : mWebBrowser->mDocShell;
275
}
276
shell.forget(aShell);
277
278
return NS_OK;
279
}
280
281
NS_IMETHODIMP
282
nsDocShellTreeOwner::RemoteTabAdded(nsIRemoteTab* aTab, bool aPrimary) {
283
if (mTreeOwner) {
284
return mTreeOwner->RemoteTabAdded(aTab, aPrimary);
285
}
286
287
if (aPrimary) {
288
mPrimaryRemoteTab = aTab;
289
mPrimaryContentShell = nullptr;
290
} else if (mPrimaryRemoteTab == aTab) {
291
mPrimaryRemoteTab = nullptr;
292
}
293
294
return NS_OK;
295
}
296
297
NS_IMETHODIMP
298
nsDocShellTreeOwner::RemoteTabRemoved(nsIRemoteTab* aTab) {
299
if (mTreeOwner) {
300
return mTreeOwner->RemoteTabRemoved(aTab);
301
}
302
303
if (aTab == mPrimaryRemoteTab) {
304
mPrimaryRemoteTab = nullptr;
305
}
306
307
return NS_OK;
308
}
309
310
NS_IMETHODIMP
311
nsDocShellTreeOwner::GetPrimaryRemoteTab(nsIRemoteTab** aTab) {
312
if (mTreeOwner) {
313
return mTreeOwner->GetPrimaryRemoteTab(aTab);
314
}
315
316
nsCOMPtr<nsIRemoteTab> tab = mPrimaryRemoteTab;
317
tab.forget(aTab);
318
return NS_OK;
319
}
320
321
NS_IMETHODIMP
322
nsDocShellTreeOwner::GetPrimaryContentSize(int32_t* aWidth, int32_t* aHeight) {
323
return NS_ERROR_NOT_IMPLEMENTED;
324
}
325
326
NS_IMETHODIMP
327
nsDocShellTreeOwner::SetPrimaryContentSize(int32_t aWidth, int32_t aHeight) {
328
return NS_ERROR_NOT_IMPLEMENTED;
329
}
330
331
NS_IMETHODIMP
332
nsDocShellTreeOwner::GetRootShellSize(int32_t* aWidth, int32_t* aHeight) {
333
return NS_ERROR_NOT_IMPLEMENTED;
334
}
335
336
NS_IMETHODIMP
337
nsDocShellTreeOwner::SetRootShellSize(int32_t aWidth, int32_t aHeight) {
338
return NS_ERROR_NOT_IMPLEMENTED;
339
}
340
341
NS_IMETHODIMP
342
nsDocShellTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem, int32_t aCX,
343
int32_t aCY) {
344
nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
345
346
NS_ENSURE_STATE(mTreeOwner || webBrowserChrome);
347
348
if (nsCOMPtr<nsIDocShellTreeOwner> treeOwner = mTreeOwner) {
349
return treeOwner->SizeShellTo(aShellItem, aCX, aCY);
350
}
351
352
if (aShellItem == mWebBrowser->mDocShell) {
353
nsCOMPtr<nsIBrowserChild> browserChild =
354
do_QueryInterface(webBrowserChrome);
355
if (browserChild) {
356
// The XUL window to resize is in the parent process, but there we
357
// won't be able to get aShellItem to do the hack in
358
// AppWindow::SizeShellTo, so let's send the width and height of
359
// aShellItem too.
360
nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(aShellItem));
361
NS_ENSURE_TRUE(shellAsWin, NS_ERROR_FAILURE);
362
363
int32_t width = 0;
364
int32_t height = 0;
365
shellAsWin->GetSize(&width, &height);
366
return browserChild->RemoteSizeShellTo(aCX, aCY, width, height);
367
}
368
// XXX: this is weird, but we used to call a method here
369
// (webBrowserChrome->SizeBrowserTo()) whose implementations all failed
370
// like this, so...
371
return NS_ERROR_NOT_IMPLEMENTED;
372
}
373
374
NS_ENSURE_TRUE(aShellItem, NS_ERROR_FAILURE);
375
376
RefPtr<Document> document = aShellItem->GetDocument();
377
NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
378
379
NS_ENSURE_TRUE(document->GetDocumentElement(), NS_ERROR_FAILURE);
380
381
// Set the preferred Size
382
// XXX
383
NS_ERROR("Implement this");
384
/*
385
Set the preferred size on the aShellItem.
386
*/
387
388
RefPtr<nsPresContext> presContext = mWebBrowser->mDocShell->GetPresContext();
389
NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
390
391
RefPtr<PresShell> presShell = presContext->GetPresShell();
392
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
393
394
NS_ENSURE_SUCCESS(
395
presShell->ResizeReflow(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE),
396
NS_ERROR_FAILURE);
397
398
// XXX: this is weird, but we used to call a method here
399
// (webBrowserChrome->SizeBrowserTo()) whose implementations all failed like
400
// this, so...
401
return NS_ERROR_NOT_IMPLEMENTED;
402
}
403
404
NS_IMETHODIMP
405
nsDocShellTreeOwner::SetPersistence(bool aPersistPosition, bool aPersistSize,
406
bool aPersistSizeMode) {
407
return NS_ERROR_NOT_IMPLEMENTED;
408
}
409
410
NS_IMETHODIMP
411
nsDocShellTreeOwner::GetPersistence(bool* aPersistPosition, bool* aPersistSize,
412
bool* aPersistSizeMode) {
413
return NS_ERROR_NOT_IMPLEMENTED;
414
}
415
416
NS_IMETHODIMP
417
nsDocShellTreeOwner::GetTabCount(uint32_t* aResult) {
418
if (mTreeOwner) {
419
return mTreeOwner->GetTabCount(aResult);
420
}
421
422
*aResult = 0;
423
return NS_OK;
424
}
425
426
NS_IMETHODIMP
427
nsDocShellTreeOwner::GetHasPrimaryContent(bool* aResult) {
428
*aResult = mPrimaryRemoteTab || mPrimaryContentShell;
429
return NS_OK;
430
}
431
432
//*****************************************************************************
433
// nsDocShellTreeOwner::nsIBaseWindow
434
//*****************************************************************************
435
436
NS_IMETHODIMP
437
nsDocShellTreeOwner::InitWindow(nativeWindow aParentNativeWindow,
438
nsIWidget* aParentWidget, int32_t aX,
439
int32_t aY, int32_t aCX, int32_t aCY) {
440
return NS_ERROR_NULL_POINTER;
441
}
442
443
NS_IMETHODIMP
444
nsDocShellTreeOwner::Create() { return NS_ERROR_NULL_POINTER; }
445
446
NS_IMETHODIMP
447
nsDocShellTreeOwner::Destroy() {
448
nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
449
if (webBrowserChrome) {
450
// XXX: this is weird, but we used to call a method here
451
// (webBrowserChrome->DestroyBrowserWindow()) whose implementations all
452
// failed like this, so...
453
return NS_ERROR_NOT_IMPLEMENTED;
454
}
455
456
return NS_ERROR_NULL_POINTER;
457
}
458
459
NS_IMETHODIMP
460
nsDocShellTreeOwner::GetUnscaledDevicePixelsPerCSSPixel(double* aScale) {
461
if (mWebBrowser) {
462
return mWebBrowser->GetUnscaledDevicePixelsPerCSSPixel(aScale);
463
}
464
465
*aScale = 1.0;
466
return NS_OK;
467
}
468
469
NS_IMETHODIMP
470
nsDocShellTreeOwner::GetDevicePixelsPerDesktopPixel(double* aScale) {
471
if (mWebBrowser) {
472
return mWebBrowser->GetDevicePixelsPerDesktopPixel(aScale);
473
}
474
475
*aScale = 1.0;
476
return NS_OK;
477
}
478
479
NS_IMETHODIMP
480
nsDocShellTreeOwner::SetPositionDesktopPix(int32_t aX, int32_t aY) {
481
if (mWebBrowser) {
482
nsresult rv = mWebBrowser->SetPositionDesktopPix(aX, aY);
483
NS_ENSURE_SUCCESS(rv, rv);
484
}
485
486
double scale = 1.0;
487
GetDevicePixelsPerDesktopPixel(&scale);
488
return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
489
}
490
491
NS_IMETHODIMP
492
nsDocShellTreeOwner::SetPosition(int32_t aX, int32_t aY) {
493
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
494
if (ownerWin) {
495
return ownerWin->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
496
aX, aY, 0, 0);
497
}
498
return NS_ERROR_NULL_POINTER;
499
}
500
501
NS_IMETHODIMP
502
nsDocShellTreeOwner::GetPosition(int32_t* aX, int32_t* aY) {
503
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
504
if (ownerWin) {
505
return ownerWin->GetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
506
aX, aY, nullptr, nullptr);
507
}
508
return NS_ERROR_NULL_POINTER;
509
}
510
511
NS_IMETHODIMP
512
nsDocShellTreeOwner::SetSize(int32_t aCX, int32_t aCY, bool aRepaint) {
513
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
514
if (ownerWin) {
515
return ownerWin->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER,
516
0, 0, aCX, aCY);
517
}
518
return NS_ERROR_NULL_POINTER;
519
}
520
521
NS_IMETHODIMP
522
nsDocShellTreeOwner::GetSize(int32_t* aCX, int32_t* aCY) {
523
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
524
if (ownerWin) {
525
return ownerWin->GetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER,
526
nullptr, nullptr, aCX, aCY);
527
}
528
return NS_ERROR_NULL_POINTER;
529
}
530
531
NS_IMETHODIMP
532
nsDocShellTreeOwner::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aCX,
533
int32_t aCY, uint32_t aFlags) {
534
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
535
if (ownerWin) {
536
return ownerWin->SetDimensions(
537
nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER |
538
nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
539
aX, aY, aCX, aCY);
540
}
541
return NS_ERROR_NULL_POINTER;
542
}
543
544
NS_IMETHODIMP
545
nsDocShellTreeOwner::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aCX,
546
int32_t* aCY) {
547
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
548
if (ownerWin) {
549
return ownerWin->GetDimensions(
550
nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER |
551
nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
552
aX, aY, aCX, aCY);
553
}
554
return NS_ERROR_NULL_POINTER;
555
}
556
557
NS_IMETHODIMP
558
nsDocShellTreeOwner::Repaint(bool aForce) { return NS_ERROR_NULL_POINTER; }
559
560
NS_IMETHODIMP
561
nsDocShellTreeOwner::GetParentWidget(nsIWidget** aParentWidget) {
562
return NS_ERROR_NULL_POINTER;
563
}
564
565
NS_IMETHODIMP
566
nsDocShellTreeOwner::SetParentWidget(nsIWidget* aParentWidget) {
567
return NS_ERROR_NULL_POINTER;
568
}
569
570
NS_IMETHODIMP
571
nsDocShellTreeOwner::GetParentNativeWindow(nativeWindow* aParentNativeWindow) {
572
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
573
if (ownerWin) {
574
return ownerWin->GetSiteWindow(aParentNativeWindow);
575
}
576
return NS_ERROR_NULL_POINTER;
577
}
578
579
NS_IMETHODIMP
580
nsDocShellTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow) {
581
return NS_ERROR_NULL_POINTER;
582
}
583
584
NS_IMETHODIMP
585
nsDocShellTreeOwner::GetNativeHandle(nsAString& aNativeHandle) {
586
// the nativeHandle should be accessed from nsIAppWindow
587
return NS_ERROR_NOT_IMPLEMENTED;
588
}
589
590
NS_IMETHODIMP
591
nsDocShellTreeOwner::GetVisibility(bool* aVisibility) {
592
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
593
if (ownerWin) {
594
return ownerWin->GetVisibility(aVisibility);
595
}
596
return NS_ERROR_NULL_POINTER;
597
}
598
599
NS_IMETHODIMP
600
nsDocShellTreeOwner::SetVisibility(bool aVisibility) {
601
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
602
if (ownerWin) {
603
return ownerWin->SetVisibility(aVisibility);
604
}
605
return NS_ERROR_NULL_POINTER;
606
}
607
608
NS_IMETHODIMP
609
nsDocShellTreeOwner::GetEnabled(bool* aEnabled) {
610
NS_ENSURE_ARG_POINTER(aEnabled);
611
*aEnabled = true;
612
return NS_ERROR_NOT_IMPLEMENTED;
613
}
614
615
NS_IMETHODIMP
616
nsDocShellTreeOwner::SetEnabled(bool aEnabled) {
617
return NS_ERROR_NOT_IMPLEMENTED;
618
}
619
620
NS_IMETHODIMP
621
nsDocShellTreeOwner::GetMainWidget(nsIWidget** aMainWidget) {
622
return NS_ERROR_NULL_POINTER;
623
}
624
625
NS_IMETHODIMP
626
nsDocShellTreeOwner::SetFocus() {
627
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
628
if (ownerWin) {
629
return ownerWin->SetFocus();
630
}
631
return NS_ERROR_NULL_POINTER;
632
}
633
634
NS_IMETHODIMP
635
nsDocShellTreeOwner::GetTitle(nsAString& aTitle) {
636
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
637
if (ownerWin) {
638
return ownerWin->GetTitle(aTitle);
639
}
640
return NS_ERROR_NULL_POINTER;
641
}
642
643
NS_IMETHODIMP
644
nsDocShellTreeOwner::SetTitle(const nsAString& aTitle) {
645
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
646
if (ownerWin) {
647
return ownerWin->SetTitle(aTitle);
648
}
649
return NS_ERROR_NULL_POINTER;
650
}
651
652
//*****************************************************************************
653
// nsDocShellTreeOwner::nsIWebProgressListener
654
//*****************************************************************************
655
656
NS_IMETHODIMP
657
nsDocShellTreeOwner::OnProgressChange(nsIWebProgress* aProgress,
658
nsIRequest* aRequest,
659
int32_t aCurSelfProgress,
660
int32_t aMaxSelfProgress,
661
int32_t aCurTotalProgress,
662
int32_t aMaxTotalProgress) {
663
// In the absence of DOM document creation event, this method is the
664
// most convenient place to install the mouse listener on the
665
// DOM document.
666
return AddChromeListeners();
667
}
668
669
NS_IMETHODIMP
670
nsDocShellTreeOwner::OnStateChange(nsIWebProgress* aProgress,
671
nsIRequest* aRequest,
672
uint32_t aProgressStateFlags,
673
nsresult aStatus) {
674
return NS_OK;
675
}
676
677
NS_IMETHODIMP
678
nsDocShellTreeOwner::OnLocationChange(nsIWebProgress* aWebProgress,
679
nsIRequest* aRequest, nsIURI* aURI,
680
uint32_t aFlags) {
681
if (mChromeTooltipListener && aWebProgress &&
682
!(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT) &&
683
mChromeTooltipListener->WebProgressShowedTooltip(aWebProgress)) {
684
mChromeTooltipListener->HideTooltip();
685
}
686
return NS_OK;
687
}
688
689
NS_IMETHODIMP
690
nsDocShellTreeOwner::OnStatusChange(nsIWebProgress* aWebProgress,
691
nsIRequest* aRequest, nsresult aStatus,
692
const char16_t* aMessage) {
693
return NS_OK;
694
}
695
696
NS_IMETHODIMP
697
nsDocShellTreeOwner::OnSecurityChange(nsIWebProgress* aWebProgress,
698
nsIRequest* aRequest, uint32_t aState) {
699
return NS_OK;
700
}
701
702
NS_IMETHODIMP
703
nsDocShellTreeOwner::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
704
nsIRequest* aRequest,
705
uint32_t aEvent) {
706
return NS_OK;
707
}
708
709
//*****************************************************************************
710
// nsDocShellTreeOwner: Accessors
711
//*****************************************************************************
712
713
void nsDocShellTreeOwner::WebBrowser(nsWebBrowser* aWebBrowser) {
714
if (!aWebBrowser) {
715
RemoveChromeListeners();
716
}
717
if (aWebBrowser != mWebBrowser) {
718
mPrompter = nullptr;
719
mAuthPrompter = nullptr;
720
}
721
722
mWebBrowser = aWebBrowser;
723
724
if (mContentTreeOwner) {
725
mContentTreeOwner->WebBrowser(aWebBrowser);
726
if (!aWebBrowser) {
727
mContentTreeOwner = nullptr;
728
}
729
}
730
}
731
732
nsWebBrowser* nsDocShellTreeOwner::WebBrowser() { return mWebBrowser; }
733
734
NS_IMETHODIMP
735
nsDocShellTreeOwner::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) {
736
if (aTreeOwner) {
737
nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome(do_GetInterface(aTreeOwner));
738
NS_ENSURE_TRUE(webBrowserChrome, NS_ERROR_INVALID_ARG);
739
NS_ENSURE_SUCCESS(SetWebBrowserChrome(webBrowserChrome),
740
NS_ERROR_INVALID_ARG);
741
mTreeOwner = aTreeOwner;
742
} else {
743
mTreeOwner = nullptr;
744
nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
745
if (!webBrowserChrome) {
746
NS_ENSURE_SUCCESS(SetWebBrowserChrome(nullptr), NS_ERROR_FAILURE);
747
}
748
}
749
750
return NS_OK;
751
}
752
753
NS_IMETHODIMP
754
nsDocShellTreeOwner::SetWebBrowserChrome(
755
nsIWebBrowserChrome* aWebBrowserChrome) {
756
if (!aWebBrowserChrome) {
757
mWebBrowserChrome = nullptr;
758
mOwnerWin = nullptr;
759
mOwnerRequestor = nullptr;
760
mWebBrowserChromeWeak = nullptr;
761
} else {
762
nsCOMPtr<nsISupportsWeakReference> supportsweak =
763
do_QueryInterface(aWebBrowserChrome);
764
if (supportsweak) {
765
supportsweak->GetWeakReference(getter_AddRefs(mWebBrowserChromeWeak));
766
} else {
767
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin(
768
do_QueryInterface(aWebBrowserChrome));
769
nsCOMPtr<nsIInterfaceRequestor> requestor(
770
do_QueryInterface(aWebBrowserChrome));
771
772
// it's ok for ownerWin or requestor to be null.
773
mWebBrowserChrome = aWebBrowserChrome;
774
mOwnerWin = ownerWin;
775
mOwnerRequestor = requestor;
776
}
777
}
778
779
if (mContentTreeOwner) {
780
mContentTreeOwner->SetWebBrowserChrome(aWebBrowserChrome);
781
}
782
783
return NS_OK;
784
}
785
786
// Hook up things to the chrome like context menus and tooltips, if the chrome
787
// has implemented the right interfaces.
788
NS_IMETHODIMP
789
nsDocShellTreeOwner::AddChromeListeners() {
790
nsresult rv = NS_OK;
791
792
nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
793
if (!webBrowserChrome) {
794
return NS_ERROR_FAILURE;
795
}
796
797
// install tooltips
798
if (!mChromeTooltipListener) {
799
nsCOMPtr<nsITooltipListener> tooltipListener(
800
do_QueryInterface(webBrowserChrome));
801
if (tooltipListener) {
802
mChromeTooltipListener =
803
new ChromeTooltipListener(mWebBrowser, webBrowserChrome);
804
rv = mChromeTooltipListener->AddChromeListeners();
805
}
806
}
807
808
// register dragover and drop event listeners with the listener manager
809
nsCOMPtr<EventTarget> target;
810
GetDOMEventTarget(mWebBrowser, getter_AddRefs(target));
811
812
EventListenerManager* elmP = target->GetOrCreateListenerManager();
813
if (elmP) {
814
elmP->AddEventListenerByType(this, NS_LITERAL_STRING("dragover"),
815
TrustedEventsAtSystemGroupBubble());
816
elmP->AddEventListenerByType(this, NS_LITERAL_STRING("drop"),
817
TrustedEventsAtSystemGroupBubble());
818
}
819
820
return rv;
821
}
822
823
NS_IMETHODIMP
824
nsDocShellTreeOwner::RemoveChromeListeners() {
825
if (mChromeTooltipListener) {
826
mChromeTooltipListener->RemoveChromeListeners();
827
mChromeTooltipListener = nullptr;
828
}
829
830
nsCOMPtr<EventTarget> piTarget;
831
GetDOMEventTarget(mWebBrowser, getter_AddRefs(piTarget));
832
if (!piTarget) {
833
return NS_OK;
834
}
835
836
EventListenerManager* elmP = piTarget->GetOrCreateListenerManager();
837
if (elmP) {
838
elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("dragover"),
839
TrustedEventsAtSystemGroupBubble());
840
elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("drop"),
841
TrustedEventsAtSystemGroupBubble());
842
}
843
844
return NS_OK;
845
}
846
847
NS_IMETHODIMP
848
nsDocShellTreeOwner::HandleEvent(Event* aEvent) {
849
DragEvent* dragEvent = aEvent ? aEvent->AsDragEvent() : nullptr;
850
if (NS_WARN_IF(!dragEvent)) {
851
return NS_ERROR_INVALID_ARG;
852
}
853
854
if (dragEvent->DefaultPrevented()) {
855
return NS_OK;
856
}
857
858
nsCOMPtr<nsIDroppedLinkHandler> handler =
859
do_GetService("@mozilla.org/content/dropped-link-handler;1");
860
if (!handler) {
861
return NS_OK;
862
}
863
864
nsAutoString eventType;
865
aEvent->GetType(eventType);
866
if (eventType.EqualsLiteral("dragover")) {
867
bool canDropLink = false;
868
handler->CanDropLink(dragEvent, false, &canDropLink);
869
if (canDropLink) {
870
aEvent->PreventDefault();
871
}
872
} else if (eventType.EqualsLiteral("drop")) {
873
nsIWebNavigation* webnav = static_cast<nsIWebNavigation*>(mWebBrowser);
874
875
nsTArray<RefPtr<nsIDroppedLinkItem>> links;
876
if (webnav && NS_SUCCEEDED(handler->DropLinks(dragEvent, true, links))) {
877
if (links.Length() >= 1) {
878
nsCOMPtr<nsIPrincipal> triggeringPrincipal;
879
handler->GetTriggeringPrincipal(dragEvent,
880
getter_AddRefs(triggeringPrincipal));
881
if (triggeringPrincipal) {
882
nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome =
883
GetWebBrowserChrome();
884
if (webBrowserChrome) {
885
nsCOMPtr<nsIBrowserChild> browserChild =
886
do_QueryInterface(webBrowserChrome);
887
if (browserChild) {
888
nsresult rv = browserChild->RemoteDropLinks(links);
889
return rv;
890
}
891
}
892
nsAutoString url;
893
if (NS_SUCCEEDED(links[0]->GetUrl(url))) {
894
if (!url.IsEmpty()) {
895
#ifndef ANDROID
896
MOZ_ASSERT(triggeringPrincipal,
897
"nsDocShellTreeOwner::HandleEvent: Need a valid "
898
"triggeringPrincipal");
899
#endif
900
LoadURIOptions loadURIOptions;
901
loadURIOptions.mTriggeringPrincipal = triggeringPrincipal;
902
nsCOMPtr<nsIContentSecurityPolicy> csp;
903
handler->GetCSP(dragEvent, getter_AddRefs(csp));
904
loadURIOptions.mCsp = csp;
905
webnav->LoadURI(url, loadURIOptions);
906
}
907
}
908
}
909
}
910
} else {
911
aEvent->StopPropagation();
912
aEvent->PreventDefault();
913
}
914
}
915
916
return NS_OK;
917
}
918
919
already_AddRefed<nsIWebBrowserChrome>
920
nsDocShellTreeOwner::GetWebBrowserChrome() {
921
nsCOMPtr<nsIWebBrowserChrome> chrome;
922
if (mWebBrowserChromeWeak) {
923
chrome = do_QueryReferent(mWebBrowserChromeWeak);
924
} else if (mWebBrowserChrome) {
925
chrome = mWebBrowserChrome;
926
}
927
return chrome.forget();
928
}
929
930
already_AddRefed<nsIEmbeddingSiteWindow> nsDocShellTreeOwner::GetOwnerWin() {
931
nsCOMPtr<nsIEmbeddingSiteWindow> win;
932
if (mWebBrowserChromeWeak) {
933
win = do_QueryReferent(mWebBrowserChromeWeak);
934
} else if (mOwnerWin) {
935
win = mOwnerWin;
936
}
937
return win.forget();
938
}
939
940
already_AddRefed<nsIInterfaceRequestor>
941
nsDocShellTreeOwner::GetOwnerRequestor() {
942
nsCOMPtr<nsIInterfaceRequestor> req;
943
if (mWebBrowserChromeWeak) {
944
req = do_QueryReferent(mWebBrowserChromeWeak);
945
} else if (mOwnerRequestor) {
946
req = mOwnerRequestor;
947
}
948
return req.forget();
949
}
950
951
NS_IMPL_ISUPPORTS(ChromeTooltipListener, nsIDOMEventListener)
952
953
ChromeTooltipListener::ChromeTooltipListener(nsWebBrowser* aInBrowser,
954
nsIWebBrowserChrome* aInChrome)
955
: mWebBrowser(aInBrowser),
956
mWebBrowserChrome(aInChrome),
957
mTooltipListenerInstalled(false),
958
mMouseClientX(0),
959
mMouseClientY(0),
960
mMouseScreenX(0),
961
mMouseScreenY(0),
962
mShowingTooltip(false),
963
mTooltipShownOnce(false) {}
964
965
ChromeTooltipListener::~ChromeTooltipListener() {}
966
967
nsITooltipTextProvider* ChromeTooltipListener::GetTooltipTextProvider() {
968
if (!mTooltipTextProvider) {
969
mTooltipTextProvider = do_GetService(NS_TOOLTIPTEXTPROVIDER_CONTRACTID);
970
}
971
972
if (!mTooltipTextProvider) {
973
mTooltipTextProvider =
974
do_GetService(NS_DEFAULTTOOLTIPTEXTPROVIDER_CONTRACTID);
975
}
976
977
return mTooltipTextProvider;
978
}
979
980
// Hook up things to the chrome like context menus and tooltips, if the chrome
981
// has implemented the right interfaces.
982
NS_IMETHODIMP
983
ChromeTooltipListener::AddChromeListeners() {
984
if (!mEventTarget) {
985
GetDOMEventTarget(mWebBrowser, getter_AddRefs(mEventTarget));
986
}
987
988
// Register the appropriate events for tooltips, but only if
989
// the embedding chrome cares.
990
nsresult rv = NS_OK;
991
nsCOMPtr<nsITooltipListener> tooltipListener(
992
do_QueryInterface(mWebBrowserChrome));
993
if (tooltipListener && !mTooltipListenerInstalled) {
994
rv = AddTooltipListener();
995
if (NS_FAILED(rv)) {
996
return rv;
997
}
998
}
999
1000
return rv;
1001
}
1002
1003
// Subscribe to the events that will allow us to track tooltips. We need "mouse"
1004
// for mouseExit, "mouse motion" for mouseMove, and "key" for keyDown. As we
1005
// add the listeners, keep track of how many succeed so we can clean up
1006
// correctly in Release().
1007
NS_IMETHODIMP
1008
ChromeTooltipListener::AddTooltipListener() {
1009
if (mEventTarget) {
1010
nsresult rv = NS_OK;
1011
#ifndef XP_WIN
1012
rv = mEventTarget->AddSystemEventListener(NS_LITERAL_STRING("keydown"),
1013
this, false, false);
1014
NS_ENSURE_SUCCESS(rv, rv);
1015
#endif
1016
rv = mEventTarget->AddSystemEventListener(NS_LITERAL_STRING("mousedown"),
1017
this, false, false);
1018
NS_ENSURE_SUCCESS(rv, rv);
1019
rv = mEventTarget->AddSystemEventListener(NS_LITERAL_STRING("mouseout"),
1020
this, false, false);
1021
NS_ENSURE_SUCCESS(rv, rv);
1022
rv = mEventTarget->AddSystemEventListener(NS_LITERAL_STRING("mousemove"),
1023
this, false, false);
1024
NS_ENSURE_SUCCESS(rv, rv);
1025
1026
mTooltipListenerInstalled = true;
1027
}
1028
1029
return NS_OK;
1030
}
1031
1032
// Unsubscribe from the various things we've hooked up to the window root.
1033
NS_IMETHODIMP
1034
ChromeTooltipListener::RemoveChromeListeners() {
1035
HideTooltip();
1036
1037
if (mTooltipListenerInstalled) {
1038
RemoveTooltipListener();
1039
}
1040
1041
mEventTarget = nullptr;
1042
1043
// it really doesn't matter if these fail...
1044
return NS_OK;
1045
}
1046
1047
// Unsubscribe from all the various tooltip events that we were listening to.
1048
NS_IMETHODIMP
1049
ChromeTooltipListener::RemoveTooltipListener() {
1050
if (mEventTarget) {
1051
#ifndef XP_WIN
1052
mEventTarget->RemoveSystemEventListener(NS_LITERAL_STRING("keydown"), this,
1053
false);
1054
#endif
1055
mEventTarget->RemoveSystemEventListener(NS_LITERAL_STRING("mousedown"),
1056
this, false);
1057
mEventTarget->RemoveSystemEventListener(NS_LITERAL_STRING("mouseout"), this,
1058
false);
1059
mEventTarget->RemoveSystemEventListener(NS_LITERAL_STRING("mousemove"),
1060
this, false);
1061
mTooltipListenerInstalled = false;
1062
}
1063
1064
return NS_OK;
1065
}
1066
1067
NS_IMETHODIMP
1068
ChromeTooltipListener::HandleEvent(Event* aEvent) {
1069
nsAutoString eventType;
1070
aEvent->GetType(eventType);
1071
1072
if (eventType.EqualsLiteral("mousedown")) {
1073
return HideTooltip();
1074
} else if (eventType.EqualsLiteral("keydown")) {
1075
WidgetKeyboardEvent* keyEvent = aEvent->WidgetEventPtr()->AsKeyboardEvent();
1076
if (!keyEvent->IsModifierKeyEvent()) {
1077
return HideTooltip();
1078
}
1079
1080
return NS_OK;
1081
} else if (eventType.EqualsLiteral("mouseout")) {
1082
// Reset flag so that tooltip will display on the next MouseMove
1083
mTooltipShownOnce = false;
1084
return HideTooltip();
1085
} else if (eventType.EqualsLiteral("mousemove")) {
1086
return MouseMove(aEvent);
1087
}
1088
1089
NS_ERROR("Unexpected event type");
1090
return NS_OK;
1091
}
1092
1093
// If we're a tooltip, fire off a timer to see if a tooltip should be shown. If
1094
// the timer fires, we cache the node in |mPossibleTooltipNode|.
1095
nsresult ChromeTooltipListener::MouseMove(Event* aMouseEvent) {
1096
MouseEvent* mouseEvent = aMouseEvent->AsMouseEvent();
1097
if (!mouseEvent) {
1098
return NS_OK;
1099
}
1100
1101
// stash the coordinates of the event so that we can still get back to it from
1102
// within the timer callback. On win32, we'll get a MouseMove event even when
1103
// a popup goes away -- even when the mouse doesn't change position! To get
1104
// around this, we make sure the mouse has really moved before proceeding.
1105
int32_t newMouseX = mouseEvent->ClientX();
1106
int32_t newMouseY = mouseEvent->ClientY();
1107
if (mMouseClientX == newMouseX && mMouseClientY == newMouseY) {
1108
return NS_OK;
1109
}
1110
1111
// Filter out minor mouse movements.
1112
if (mShowingTooltip &&
1113
(abs(mMouseClientX - newMouseX) <= kTooltipMouseMoveTolerance) &&
1114
(abs(mMouseClientY - newMouseY) <= kTooltipMouseMoveTolerance)) {
1115
return NS_OK;
1116
}
1117
1118
mMouseClientX = newMouseX;
1119
mMouseClientY = newMouseY;
1120
mMouseScreenX = mouseEvent->ScreenX(CallerType::System);
1121
mMouseScreenY = mouseEvent->ScreenY(CallerType::System);
1122
1123
if (mTooltipTimer) {
1124
mTooltipTimer->Cancel();
1125
mTooltipTimer = nullptr;
1126
}
1127
1128
if (!mShowingTooltip) {
1129
nsIEventTarget* target = nullptr;
1130
if (nsCOMPtr<EventTarget> eventTarget = aMouseEvent->GetComposedTarget()) {
1131
mPossibleTooltipNode = do_QueryInterface(eventTarget);
1132
nsCOMPtr<nsIGlobalObject> global(eventTarget->GetOwnerGlobal());
1133
if (global) {
1134
target = global->EventTargetFor(TaskCategory::UI);
1135
}
1136
}
1137
1138
if (mPossibleTooltipNode) {
1139
nsresult rv = NS_NewTimerWithFuncCallback(
1140
getter_AddRefs(mTooltipTimer), sTooltipCallback, this,
1141
LookAndFeel::GetInt(LookAndFeel::eIntID_TooltipDelay, 500),
1142
nsITimer::TYPE_ONE_SHOT, "ChromeTooltipListener::MouseMove", target);
1143
if (NS_FAILED(rv)) {
1144
mPossibleTooltipNode = nullptr;
1145
NS_WARNING("Could not create a timer for tooltip tracking");
1146
}
1147
}
1148
} else {
1149
mTooltipShownOnce = true;
1150
return HideTooltip();
1151
}
1152
1153
return NS_OK;
1154
}
1155
1156
// Tell the registered chrome that they should show the tooltip.
1157
NS_IMETHODIMP
1158
ChromeTooltipListener::ShowTooltip(int32_t aInXCoords, int32_t aInYCoords,
1159
const nsAString& aInTipText,
1160
const nsAString& aTipDir) {
1161
nsresult rv = NS_OK;
1162
1163
// do the work to call the client
1164
nsCOMPtr<nsITooltipListener> tooltipListener(
1165
do_QueryInterface(mWebBrowserChrome));
1166
if (tooltipListener) {
1167
rv = tooltipListener->OnShowTooltip(aInXCoords, aInYCoords, aInTipText,
1168
aTipDir);
1169
if (NS_SUCCEEDED(rv)) {
1170
mShowingTooltip = true;
1171
}
1172
}
1173
1174
return rv;
1175
}
1176
1177
// Tell the registered chrome that they should rollup the tooltip
1178
// NOTE: This routine is safe to call even if the popup is already closed.
1179
NS_IMETHODIMP
1180
ChromeTooltipListener::HideTooltip() {
1181
nsresult rv = NS_OK;
1182
1183
// shut down the relevant timers
1184
if (mTooltipTimer) {
1185
mTooltipTimer->Cancel();
1186
mTooltipTimer = nullptr;
1187
// release tooltip target
1188
mPossibleTooltipNode = nullptr;
1189
mLastDocshell = nullptr;
1190
}
1191
1192
// if we're showing the tip, tell the chrome to hide it
1193
if (mShowingTooltip) {
1194
nsCOMPtr<nsITooltipListener> tooltipListener(
1195
do_QueryInterface(mWebBrowserChrome));
1196
if (tooltipListener) {
1197
rv = tooltipListener->OnHideTooltip();
1198
if (NS_SUCCEEDED(rv)) {
1199
mShowingTooltip = false;
1200
}
1201
}
1202
}
1203
1204
return rv;
1205
}
1206
1207
bool ChromeTooltipListener::WebProgressShowedTooltip(
1208
nsIWebProgress* aWebProgress) {
1209
nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(aWebProgress);
1210
nsCOMPtr<nsIDocShell> lastUsed = do_QueryReferent(mLastDocshell);
1211
while (lastUsed) {
1212
if (lastUsed == docshell) {
1213
return true;
1214
}
1215
// We can't use the docshell hierarchy here, because when the parent
1216
// docshell is navigated, the child docshell is disconnected (ie its
1217
// references to the parent are nulled out) despite it still being
1218
// alive here. So we use the document hierarchy instead:
1219
Document* document = lastUsed->GetDocument();
1220
if (document) {
1221
document = document->GetInProcessParentDocument();
1222
}
1223
if (!document) {
1224
break;
1225
}
1226
lastUsed = document->GetDocShell();
1227
}
1228
return false;
1229
}
1230
1231
// A timer callback, fired when the mouse has hovered inside of a frame for the
1232
// appropriate amount of time. Getting to this point means that we should show
1233
// the tooltip, but only after we determine there is an appropriate TITLE
1234
// element.
1235
//
1236
// This relies on certain things being cached into the |aChromeTooltipListener|
1237
// object passed to us by the timer:
1238
// -- the x/y coordinates of the mouse (mMouseClientY, mMouseClientX)
1239
// -- the dom node the user hovered over (mPossibleTooltipNode)
1240
void ChromeTooltipListener::sTooltipCallback(nsITimer* aTimer,
1241
void* aChromeTooltipListener) {
1242
auto self = static_cast<ChromeTooltipListener*>(aChromeTooltipListener);
1243
if (self && self->mPossibleTooltipNode) {
1244
if (!self->mPossibleTooltipNode->IsInComposedDoc()) {
1245
// release tooltip target if there is one, NO MATTER WHAT
1246
self->mPossibleTooltipNode = nullptr;
1247
return;
1248
}
1249
1250
// The actual coordinates we want to put the tooltip at are relative to the
1251
// toplevel docshell of our mWebBrowser. We know what the screen
1252
// coordinates of the mouse event were, which means we just need the screen
1253
// coordinates of the docshell. Unfortunately, there is no good way to
1254
// find those short of groveling for the presentation in that docshell and
1255
// finding the screen coords of its toplevel widget...
1256
nsCOMPtr<nsIDocShell> docShell =
1257
do_GetInterface(static_cast<nsIWebBrowser*>(self->mWebBrowser));
1258
RefPtr<PresShell> presShell = docShell ? docShell->GetPresShell() : nullptr;
1259
1260
nsIWidget* widget = nullptr;
1261
if (presShell) {
1262
nsViewManager* vm = presShell->GetViewManager();
1263
if (vm) {
1264
nsView* view = vm->GetRootView();
1265
if (view) {
1266
nsPoint offset;
1267
widget = view->GetNearestWidget(&offset);
1268
}
1269
}
1270
}
1271
1272
if (!widget || !docShell || !docShell->GetIsActive()) {
1273
// release tooltip target if there is one, NO MATTER WHAT
1274
self->mPossibleTooltipNode = nullptr;
1275
return;
1276
}
1277
1278
// if there is text associated with the node, show the tip and fire
1279
// off a timer to auto-hide it.
1280
nsITooltipTextProvider* tooltipProvider = self->GetTooltipTextProvider();
1281
if (tooltipProvider) {
1282
nsString tooltipText;
1283
nsString directionText;
1284
bool textFound = false;
1285
tooltipProvider->GetNodeText(self->mPossibleTooltipNode,
1286
getter_Copies(tooltipText),
1287
getter_Copies(directionText), &textFound);
1288
1289
if (textFound && (!self->mTooltipShownOnce ||
1290
tooltipText != self->mLastShownTooltipText)) {
1291
LayoutDeviceIntPoint screenDot = widget->WidgetToScreenOffset();
1292
double scaleFactor = 1.0;
1293
if (presShell->GetPresContext()) {
1294
nsDeviceContext* dc = presShell->GetPresContext()->DeviceContext();
1295
scaleFactor = double(AppUnitsPerCSSPixel()) /
1296
dc->AppUnitsPerDevPixelAtUnitFullZoom();
1297
}
1298
// ShowTooltip expects widget-relative position.
1299
self->ShowTooltip(self->mMouseScreenX - screenDot.x / scaleFactor,
1300
self->mMouseScreenY - screenDot.y / scaleFactor,
1301
tooltipText, directionText);
1302
self->mLastShownTooltipText = std::move(tooltipText);
1303
self->mLastDocshell = do_GetWeakReference(
1304
self->mPossibleTooltipNode->OwnerDoc()->GetDocShell());
1305
}
1306
}
1307
1308
// release tooltip target if there is one, NO MATTER WHAT
1309
self->mPossibleTooltipNode = nullptr;
1310
}
1311
}