xpfe/appshell/src/nsContentTreeOwner.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:156c29599499
1 /* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=2 sw=2 et tw=79:
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8 // Local Includes
9 #include "nsContentTreeOwner.h"
10 #include "nsXULWindow.h"
11
12 // Helper Classes
13 #include "nsIServiceManager.h"
14 #include "nsAutoPtr.h"
15
16 // Interfaces needed to be included
17 #include "nsIDOMNode.h"
18 #include "nsIDOMElement.h"
19 #include "nsIDOMNodeList.h"
20 #include "nsIDOMWindow.h"
21 #include "nsIDOMChromeWindow.h"
22 #include "nsIBrowserDOMWindow.h"
23 #include "nsIDOMXULElement.h"
24 #include "nsIEmbeddingSiteWindow.h"
25 #include "nsIPrompt.h"
26 #include "nsIAuthPrompt.h"
27 #include "nsIWindowMediator.h"
28 #include "nsIXULBrowserWindow.h"
29 #include "nsIPrincipal.h"
30 #include "nsIURIFixup.h"
31 #include "nsCDefaultURIFixup.h"
32 #include "nsIWebNavigation.h"
33 #include "nsDocShellCID.h"
34 #include "nsIExternalURLHandlerService.h"
35 #include "nsIMIMEInfo.h"
36 #include "nsIWidget.h"
37 #include "mozilla/BrowserElementParent.h"
38
39 #include "nsIDOMDocument.h"
40 #include "nsIScriptObjectPrincipal.h"
41 #include "nsIURI.h"
42 #include "nsIDocument.h"
43 #if defined(XP_MACOSX)
44 #include "nsThreadUtils.h"
45 #endif
46
47 #include "mozilla/Preferences.h"
48 #include "mozilla/dom/Element.h"
49 #include "mozilla/dom/ScriptSettings.h"
50
51 using namespace mozilla;
52
53 //*****************************************************************************
54 //*** nsSiteWindow declaration
55 //*****************************************************************************
56
57 class nsSiteWindow : public nsIEmbeddingSiteWindow
58 {
59 public:
60 nsSiteWindow(nsContentTreeOwner *aAggregator);
61 virtual ~nsSiteWindow();
62
63 NS_DECL_ISUPPORTS
64 NS_DECL_NSIEMBEDDINGSITEWINDOW
65
66 private:
67 nsContentTreeOwner *mAggregator;
68 };
69
70 //*****************************************************************************
71 //*** nsContentTreeOwner: Object Management
72 //*****************************************************************************
73
74 nsContentTreeOwner::nsContentTreeOwner(bool fPrimary) : mXULWindow(nullptr),
75 mPrimary(fPrimary), mContentTitleSetting(false)
76 {
77 // note if this fails, QI on nsIEmbeddingSiteWindow(2) will simply fail
78 mSiteWindow = new nsSiteWindow(this);
79 }
80
81 nsContentTreeOwner::~nsContentTreeOwner()
82 {
83 delete mSiteWindow;
84 }
85
86 //*****************************************************************************
87 // nsContentTreeOwner::nsISupports
88 //*****************************************************************************
89
90 NS_IMPL_ADDREF(nsContentTreeOwner)
91 NS_IMPL_RELEASE(nsContentTreeOwner)
92
93 NS_INTERFACE_MAP_BEGIN(nsContentTreeOwner)
94 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellTreeOwner)
95 NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeOwner)
96 NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
97 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
98 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2)
99 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome3)
100 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
101 NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
102 // NOTE: This is using aggregation because there are some properties and
103 // method on nsIBaseWindow (which we implement) and on
104 // nsIEmbeddingSiteWindow (which we also implement) that have the same name.
105 // And it just so happens that we want different behavior for these methods
106 // and properties depending on the interface through which they're called
107 // (SetFocus() is a good example here). If it were not for that, we could
108 // ditch the aggregation and just deal with not being able to use NS_DECL_*
109 // macros for this stuff....
110 NS_INTERFACE_MAP_ENTRY_AGGREGATED(nsIEmbeddingSiteWindow, mSiteWindow)
111 NS_INTERFACE_MAP_END
112
113 //*****************************************************************************
114 // nsContentTreeOwner::nsIInterfaceRequestor
115 //*****************************************************************************
116
117 NS_IMETHODIMP nsContentTreeOwner::GetInterface(const nsIID& aIID, void** aSink)
118 {
119 NS_ENSURE_ARG_POINTER(aSink);
120 *aSink = 0;
121
122 if(aIID.Equals(NS_GET_IID(nsIPrompt))) {
123 NS_ENSURE_STATE(mXULWindow);
124 return mXULWindow->GetInterface(aIID, aSink);
125 }
126 if(aIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
127 NS_ENSURE_STATE(mXULWindow);
128 return mXULWindow->GetInterface(aIID, aSink);
129 }
130 if (aIID.Equals(NS_GET_IID(nsIDocShellTreeItem))) {
131 NS_ENSURE_STATE(mXULWindow);
132 nsCOMPtr<nsIDocShell> shell;
133 mXULWindow->GetDocShell(getter_AddRefs(shell));
134 if (shell)
135 return shell->QueryInterface(aIID, aSink);
136 return NS_ERROR_FAILURE;
137 }
138
139 if (aIID.Equals(NS_GET_IID(nsIDOMWindow))) {
140 NS_ENSURE_STATE(mXULWindow);
141 nsCOMPtr<nsIDocShellTreeItem> shell;
142 mXULWindow->GetPrimaryContentShell(getter_AddRefs(shell));
143 if (shell) {
144 nsCOMPtr<nsIInterfaceRequestor> thing(do_QueryInterface(shell));
145 if (thing)
146 return thing->GetInterface(aIID, aSink);
147 }
148 return NS_ERROR_FAILURE;
149 }
150
151 if (aIID.Equals(NS_GET_IID(nsIXULWindow))) {
152 NS_ENSURE_STATE(mXULWindow);
153 return mXULWindow->QueryInterface(aIID, aSink);
154 }
155
156 return QueryInterface(aIID, aSink);
157 }
158
159 //*****************************************************************************
160 // nsContentTreeOwner::nsIDocShellTreeOwner
161 //*****************************************************************************
162
163 NS_IMETHODIMP nsContentTreeOwner::FindItemWithName(const char16_t* aName,
164 nsIDocShellTreeItem* aRequestor, nsIDocShellTreeItem* aOriginalRequestor,
165 nsIDocShellTreeItem** aFoundItem)
166 {
167 NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID);
168
169 NS_ENSURE_ARG_POINTER(aFoundItem);
170
171 *aFoundItem = nullptr;
172
173 bool fIs_Content = false;
174
175 /* Special Cases */
176 if (!aName || !*aName)
177 return NS_OK;
178
179 nsDependentString name(aName);
180
181 if (name.LowerCaseEqualsLiteral("_blank"))
182 return NS_OK;
183 // _main is an IE target which should be case-insensitive but isn't
184 // see bug 217886 for details
185 if (name.LowerCaseEqualsLiteral("_content") ||
186 name.EqualsLiteral("_main")) {
187 // If we're being called with an aRequestor and it's targetable, just
188 // return it -- _main and _content from inside targetable content shells
189 // should just be that content shell. Note that we don't have to worry
190 // about the case when it's not targetable because it's primary -- that
191 // will Just Work when we call GetPrimaryContentShell.
192 NS_ENSURE_STATE(mXULWindow);
193 if (aRequestor) {
194 // This better be the root item!
195 #ifdef DEBUG
196 nsCOMPtr<nsIDocShellTreeItem> debugRoot;
197 aRequestor->GetSameTypeRootTreeItem(getter_AddRefs(debugRoot));
198 NS_ASSERTION(SameCOMIdentity(debugRoot, aRequestor),
199 "Bogus aRequestor");
200 #endif
201
202 int32_t count = mXULWindow->mTargetableShells.Count();
203 for (int32_t i = 0; i < count; ++i) {
204 nsCOMPtr<nsIDocShellTreeItem> item =
205 do_QueryReferent(mXULWindow->mTargetableShells[i]);
206 if (SameCOMIdentity(item, aRequestor)) {
207 NS_ADDREF(*aFoundItem = aRequestor);
208 return NS_OK;
209 }
210 }
211 }
212 mXULWindow->GetPrimaryContentShell(aFoundItem);
213 if(*aFoundItem)
214 return NS_OK;
215 // Fall through and keep looking...
216 fIs_Content = true;
217 }
218
219 nsCOMPtr<nsIWindowMediator> windowMediator(do_GetService(kWindowMediatorCID));
220 NS_ENSURE_TRUE(windowMediator, NS_ERROR_FAILURE);
221
222 nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
223 NS_ENSURE_SUCCESS(windowMediator->GetXULWindowEnumerator(nullptr,
224 getter_AddRefs(windowEnumerator)), NS_ERROR_FAILURE);
225
226 bool more;
227
228 windowEnumerator->HasMoreElements(&more);
229 while(more) {
230 nsCOMPtr<nsISupports> nextWindow = nullptr;
231 windowEnumerator->GetNext(getter_AddRefs(nextWindow));
232 nsCOMPtr<nsIXULWindow> xulWindow(do_QueryInterface(nextWindow));
233 NS_ENSURE_TRUE(xulWindow, NS_ERROR_FAILURE);
234
235 if (fIs_Content) {
236 xulWindow->GetPrimaryContentShell(aFoundItem);
237 } else {
238 // Get all the targetable windows from xulWindow and search them
239 nsRefPtr<nsXULWindow> win;
240 xulWindow->QueryInterface(NS_GET_IID(nsXULWindow), getter_AddRefs(win));
241 if (win) {
242 int32_t count = win->mTargetableShells.Count();
243 int32_t i;
244 for (i = 0; i < count && !*aFoundItem; ++i) {
245 nsCOMPtr<nsIDocShellTreeItem> shellAsTreeItem =
246 do_QueryReferent(win->mTargetableShells[i]);
247 if (shellAsTreeItem) {
248 // Get the root tree item of same type, since roots are the only
249 // things that call into the treeowner to look for named items.
250 // XXXbz ideally we could guarantee that mTargetableShells only
251 // contains roots, but the current treeowner apis don't allow
252 // that... yet.
253 nsCOMPtr<nsIDocShellTreeItem> root;
254 shellAsTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
255 NS_ASSERTION(root, "Must have root tree item of same type");
256 shellAsTreeItem.swap(root);
257 if (aRequestor != shellAsTreeItem) {
258 // Do this so we can pass in the tree owner as the
259 // requestor so the child knows not to call back up.
260 nsCOMPtr<nsIDocShellTreeOwner> shellOwner;
261 shellAsTreeItem->GetTreeOwner(getter_AddRefs(shellOwner));
262 nsCOMPtr<nsISupports> shellOwnerSupports =
263 do_QueryInterface(shellOwner);
264
265 shellAsTreeItem->FindItemWithName(aName, shellOwnerSupports,
266 aOriginalRequestor,
267 aFoundItem);
268 }
269 }
270 }
271 }
272 }
273
274 if (*aFoundItem)
275 return NS_OK;
276
277 windowEnumerator->HasMoreElements(&more);
278 }
279 return NS_OK;
280 }
281
282 NS_IMETHODIMP
283 nsContentTreeOwner::ContentShellAdded(nsIDocShellTreeItem* aContentShell,
284 bool aPrimary, bool aTargetable,
285 const nsAString& aID)
286 {
287 NS_ENSURE_STATE(mXULWindow);
288 return mXULWindow->ContentShellAdded(aContentShell, aPrimary, aTargetable,
289 aID);
290 }
291
292 NS_IMETHODIMP
293 nsContentTreeOwner::ContentShellRemoved(nsIDocShellTreeItem* aContentShell)
294 {
295 NS_ENSURE_STATE(mXULWindow);
296 return mXULWindow->ContentShellRemoved(aContentShell);
297 }
298
299 NS_IMETHODIMP
300 nsContentTreeOwner::GetPrimaryContentShell(nsIDocShellTreeItem** aShell)
301 {
302 NS_ENSURE_STATE(mXULWindow);
303 return mXULWindow->GetPrimaryContentShell(aShell);
304 }
305
306 NS_IMETHODIMP
307 nsContentTreeOwner::GetContentWindow(JSContext* aCx,
308 JS::MutableHandle<JS::Value> aVal)
309 {
310 NS_ENSURE_STATE(mXULWindow);
311 return NS_ERROR_NOT_IMPLEMENTED;
312 }
313
314 NS_IMETHODIMP nsContentTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem,
315 int32_t aCX, int32_t aCY)
316 {
317 NS_ENSURE_STATE(mXULWindow);
318 return mXULWindow->SizeShellTo(aShellItem, aCX, aCY);
319 }
320
321 NS_IMETHODIMP
322 nsContentTreeOwner::SetPersistence(bool aPersistPosition,
323 bool aPersistSize,
324 bool aPersistSizeMode)
325 {
326 NS_ENSURE_STATE(mXULWindow);
327 nsCOMPtr<dom::Element> docShellElement = mXULWindow->GetWindowDOMElement();
328 if (!docShellElement)
329 return NS_ERROR_FAILURE;
330
331 nsAutoString persistString;
332 docShellElement->GetAttribute(NS_LITERAL_STRING("persist"), persistString);
333
334 bool saveString = false;
335 int32_t index;
336
337 // Set X
338 index = persistString.Find("screenX");
339 if (!aPersistPosition && index >= 0) {
340 persistString.Cut(index, 7);
341 saveString = true;
342 } else if (aPersistPosition && index < 0) {
343 persistString.AppendLiteral(" screenX");
344 saveString = true;
345 }
346 // Set Y
347 index = persistString.Find("screenY");
348 if (!aPersistPosition && index >= 0) {
349 persistString.Cut(index, 7);
350 saveString = true;
351 } else if (aPersistPosition && index < 0) {
352 persistString.AppendLiteral(" screenY");
353 saveString = true;
354 }
355 // Set CX
356 index = persistString.Find("width");
357 if (!aPersistSize && index >= 0) {
358 persistString.Cut(index, 5);
359 saveString = true;
360 } else if (aPersistSize && index < 0) {
361 persistString.AppendLiteral(" width");
362 saveString = true;
363 }
364 // Set CY
365 index = persistString.Find("height");
366 if (!aPersistSize && index >= 0) {
367 persistString.Cut(index, 6);
368 saveString = true;
369 } else if (aPersistSize && index < 0) {
370 persistString.AppendLiteral(" height");
371 saveString = true;
372 }
373 // Set SizeMode
374 index = persistString.Find("sizemode");
375 if (!aPersistSizeMode && (index >= 0)) {
376 persistString.Cut(index, 8);
377 saveString = true;
378 } else if (aPersistSizeMode && (index < 0)) {
379 persistString.AppendLiteral(" sizemode");
380 saveString = true;
381 }
382
383 ErrorResult rv;
384 if(saveString) {
385 docShellElement->SetAttribute(NS_LITERAL_STRING("persist"), persistString, rv);
386 }
387
388 return NS_OK;
389 }
390
391 NS_IMETHODIMP
392 nsContentTreeOwner::GetPersistence(bool* aPersistPosition,
393 bool* aPersistSize,
394 bool* aPersistSizeMode)
395 {
396 NS_ENSURE_STATE(mXULWindow);
397 nsCOMPtr<dom::Element> docShellElement = mXULWindow->GetWindowDOMElement();
398 if (!docShellElement)
399 return NS_ERROR_FAILURE;
400
401 nsAutoString persistString;
402 docShellElement->GetAttribute(NS_LITERAL_STRING("persist"), persistString);
403
404 // data structure doesn't quite match the question, but it's close enough
405 // for what we want (since this method is never actually called...)
406 if (aPersistPosition)
407 *aPersistPosition = persistString.Find("screenX") >= 0 || persistString.Find("screenY") >= 0 ? true : false;
408 if (aPersistSize)
409 *aPersistSize = persistString.Find("width") >= 0 || persistString.Find("height") >= 0 ? true : false;
410 if (aPersistSizeMode)
411 *aPersistSizeMode = persistString.Find("sizemode") >= 0 ? true : false;
412
413 return NS_OK;
414 }
415
416 NS_IMETHODIMP
417 nsContentTreeOwner::GetTargetableShellCount(uint32_t* aResult)
418 {
419 NS_ENSURE_STATE(mXULWindow);
420 *aResult = mXULWindow->mTargetableShells.Count();
421 return NS_OK;
422 }
423
424 //*****************************************************************************
425 // nsContentTreeOwner::nsIWebBrowserChrome3
426 //*****************************************************************************
427
428 NS_IMETHODIMP nsContentTreeOwner::OnBeforeLinkTraversal(const nsAString &originalTarget,
429 nsIURI *linkURI,
430 nsIDOMNode *linkNode,
431 bool isAppTab,
432 nsAString &_retval)
433 {
434 NS_ENSURE_STATE(mXULWindow);
435
436 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow;
437 mXULWindow->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow));
438
439 if (xulBrowserWindow)
440 return xulBrowserWindow->OnBeforeLinkTraversal(originalTarget, linkURI,
441 linkNode, isAppTab, _retval);
442
443 _retval = originalTarget;
444 return NS_OK;
445 }
446
447 //*****************************************************************************
448 // nsContentTreeOwner::nsIWebBrowserChrome2
449 //*****************************************************************************
450
451 NS_IMETHODIMP nsContentTreeOwner::SetStatusWithContext(uint32_t aStatusType,
452 const nsAString &aStatusText,
453 nsISupports *aStatusContext)
454 {
455 // We only allow the status to be set from the primary content shell
456 if (!mPrimary && aStatusType != STATUS_LINK)
457 return NS_OK;
458
459 NS_ENSURE_STATE(mXULWindow);
460
461 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow;
462 mXULWindow->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow));
463
464 if (xulBrowserWindow)
465 {
466 switch(aStatusType)
467 {
468 case STATUS_SCRIPT:
469 xulBrowserWindow->SetJSStatus(aStatusText);
470 break;
471 case STATUS_LINK:
472 {
473 nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aStatusContext);
474 xulBrowserWindow->SetOverLink(aStatusText, element);
475 break;
476 }
477 }
478 }
479
480 return NS_OK;
481 }
482
483 //*****************************************************************************
484 // nsContentTreeOwner::nsIWebBrowserChrome
485 //*****************************************************************************
486
487 NS_IMETHODIMP nsContentTreeOwner::SetStatus(uint32_t aStatusType,
488 const char16_t* aStatus)
489 {
490 return SetStatusWithContext(aStatusType,
491 aStatus ? static_cast<const nsString &>(nsDependentString(aStatus))
492 : EmptyString(),
493 nullptr);
494 }
495
496 NS_IMETHODIMP nsContentTreeOwner::SetWebBrowser(nsIWebBrowser* aWebBrowser)
497 {
498 NS_ERROR("Haven't Implemented this yet");
499 return NS_ERROR_FAILURE;
500 }
501
502 NS_IMETHODIMP nsContentTreeOwner::GetWebBrowser(nsIWebBrowser** aWebBrowser)
503 {
504 // Unimplemented, and probably will remain so; xpfe windows have docshells,
505 // not webbrowsers.
506 NS_ENSURE_ARG_POINTER(aWebBrowser);
507 *aWebBrowser = 0;
508 return NS_ERROR_FAILURE;
509 }
510
511 NS_IMETHODIMP nsContentTreeOwner::SetChromeFlags(uint32_t aChromeFlags)
512 {
513 NS_ENSURE_STATE(mXULWindow);
514 return mXULWindow->SetChromeFlags(aChromeFlags);
515 }
516
517 NS_IMETHODIMP nsContentTreeOwner::GetChromeFlags(uint32_t* aChromeFlags)
518 {
519 NS_ENSURE_STATE(mXULWindow);
520 return mXULWindow->GetChromeFlags(aChromeFlags);
521 }
522
523 NS_IMETHODIMP nsContentTreeOwner::DestroyBrowserWindow()
524 {
525 NS_ERROR("Haven't Implemented this yet");
526 return NS_ERROR_FAILURE;
527 }
528
529 NS_IMETHODIMP nsContentTreeOwner::SizeBrowserTo(int32_t aCX, int32_t aCY)
530 {
531 NS_ERROR("Haven't Implemented this yet");
532 return NS_ERROR_FAILURE;
533 }
534
535 NS_IMETHODIMP nsContentTreeOwner::ShowAsModal()
536 {
537 NS_ENSURE_STATE(mXULWindow);
538 return mXULWindow->ShowModal();
539 }
540
541 NS_IMETHODIMP nsContentTreeOwner::IsWindowModal(bool *_retval)
542 {
543 NS_ENSURE_STATE(mXULWindow);
544 *_retval = mXULWindow->mContinueModalLoop;
545 return NS_OK;
546 }
547
548 NS_IMETHODIMP nsContentTreeOwner::ExitModalEventLoop(nsresult aStatus)
549 {
550 NS_ENSURE_STATE(mXULWindow);
551 return mXULWindow->ExitModalLoop(aStatus);
552 }
553
554 //*****************************************************************************
555 // nsContentTreeOwner::nsIBaseWindow
556 //*****************************************************************************
557
558 NS_IMETHODIMP nsContentTreeOwner::InitWindow(nativeWindow aParentNativeWindow,
559 nsIWidget* parentWidget, int32_t x, int32_t y, int32_t cx, int32_t cy)
560 {
561 // Ignore wigdet parents for now. Don't think those are a vaild thing to call.
562 NS_ENSURE_SUCCESS(SetPositionAndSize(x, y, cx, cy, false), NS_ERROR_FAILURE);
563
564 return NS_OK;
565 }
566
567 NS_IMETHODIMP nsContentTreeOwner::Create()
568 {
569 NS_ASSERTION(false, "You can't call this");
570 return NS_ERROR_UNEXPECTED;
571 }
572
573 NS_IMETHODIMP nsContentTreeOwner::Destroy()
574 {
575 NS_ENSURE_STATE(mXULWindow);
576 return mXULWindow->Destroy();
577 }
578
579 NS_IMETHODIMP nsContentTreeOwner::GetUnscaledDevicePixelsPerCSSPixel(double* aScale)
580 {
581 NS_ENSURE_STATE(mXULWindow);
582 return mXULWindow->GetUnscaledDevicePixelsPerCSSPixel(aScale);
583 }
584
585 NS_IMETHODIMP nsContentTreeOwner::SetPosition(int32_t aX, int32_t aY)
586 {
587 NS_ENSURE_STATE(mXULWindow);
588 return mXULWindow->SetPosition(aX, aY);
589 }
590
591 NS_IMETHODIMP nsContentTreeOwner::GetPosition(int32_t* aX, int32_t* aY)
592 {
593 NS_ENSURE_STATE(mXULWindow);
594 return mXULWindow->GetPosition(aX, aY);
595 }
596
597 NS_IMETHODIMP nsContentTreeOwner::SetSize(int32_t aCX, int32_t aCY, bool aRepaint)
598 {
599 NS_ENSURE_STATE(mXULWindow);
600 return mXULWindow->SetSize(aCX, aCY, aRepaint);
601 }
602
603 NS_IMETHODIMP nsContentTreeOwner::GetSize(int32_t* aCX, int32_t* aCY)
604 {
605 NS_ENSURE_STATE(mXULWindow);
606 return mXULWindow->GetSize(aCX, aCY);
607 }
608
609 NS_IMETHODIMP nsContentTreeOwner::SetPositionAndSize(int32_t aX, int32_t aY,
610 int32_t aCX, int32_t aCY, bool aRepaint)
611 {
612 NS_ENSURE_STATE(mXULWindow);
613 return mXULWindow->SetPositionAndSize(aX, aY, aCX, aCY, aRepaint);
614 }
615
616 NS_IMETHODIMP nsContentTreeOwner::GetPositionAndSize(int32_t* aX, int32_t* aY,
617 int32_t* aCX, int32_t* aCY)
618 {
619 NS_ENSURE_STATE(mXULWindow);
620 return mXULWindow->GetPositionAndSize(aX, aY, aCX, aCY);
621 }
622
623 NS_IMETHODIMP nsContentTreeOwner::Repaint(bool aForce)
624 {
625 NS_ENSURE_STATE(mXULWindow);
626 return mXULWindow->Repaint(aForce);
627 }
628
629 NS_IMETHODIMP nsContentTreeOwner::GetParentWidget(nsIWidget** aParentWidget)
630 {
631 NS_ENSURE_STATE(mXULWindow);
632 return mXULWindow->GetParentWidget(aParentWidget);
633 }
634
635 NS_IMETHODIMP nsContentTreeOwner::SetParentWidget(nsIWidget* aParentWidget)
636 {
637 NS_ASSERTION(false, "You can't call this");
638 return NS_ERROR_NOT_IMPLEMENTED;
639 }
640
641 NS_IMETHODIMP nsContentTreeOwner::GetParentNativeWindow(nativeWindow* aParentNativeWindow)
642 {
643 NS_ENSURE_STATE(mXULWindow);
644 return mXULWindow->GetParentNativeWindow(aParentNativeWindow);
645 }
646
647 NS_IMETHODIMP nsContentTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow)
648 {
649 NS_ASSERTION(false, "You can't call this");
650 return NS_ERROR_NOT_IMPLEMENTED;
651 }
652
653 NS_IMETHODIMP nsContentTreeOwner::GetNativeHandle(nsAString& aNativeHandle)
654 {
655 NS_ENSURE_STATE(mXULWindow);
656 return mXULWindow->GetNativeHandle(aNativeHandle);
657 }
658
659 NS_IMETHODIMP nsContentTreeOwner::GetVisibility(bool* aVisibility)
660 {
661 NS_ENSURE_STATE(mXULWindow);
662 return mXULWindow->GetVisibility(aVisibility);
663 }
664
665 NS_IMETHODIMP nsContentTreeOwner::SetVisibility(bool aVisibility)
666 {
667 NS_ENSURE_STATE(mXULWindow);
668 return mXULWindow->SetVisibility(aVisibility);
669 }
670
671 NS_IMETHODIMP nsContentTreeOwner::GetEnabled(bool *aEnabled)
672 {
673 NS_ENSURE_STATE(mXULWindow);
674 return mXULWindow->GetEnabled(aEnabled);
675 }
676
677 NS_IMETHODIMP nsContentTreeOwner::SetEnabled(bool aEnable)
678 {
679 NS_ENSURE_STATE(mXULWindow);
680 return mXULWindow->SetEnabled(aEnable);
681 }
682
683 NS_IMETHODIMP nsContentTreeOwner::GetMainWidget(nsIWidget** aMainWidget)
684 {
685 NS_ENSURE_ARG_POINTER(aMainWidget);
686 NS_ENSURE_STATE(mXULWindow);
687
688 *aMainWidget = mXULWindow->mWindow;
689 NS_IF_ADDREF(*aMainWidget);
690
691 return NS_OK;
692 }
693
694 NS_IMETHODIMP nsContentTreeOwner::SetFocus()
695 {
696 NS_ENSURE_STATE(mXULWindow);
697 return mXULWindow->SetFocus();
698 }
699
700 NS_IMETHODIMP nsContentTreeOwner::GetTitle(char16_t** aTitle)
701 {
702 NS_ENSURE_ARG_POINTER(aTitle);
703 NS_ENSURE_STATE(mXULWindow);
704
705 return mXULWindow->GetTitle(aTitle);
706 }
707
708 NS_IMETHODIMP nsContentTreeOwner::SetTitle(const char16_t* aTitle)
709 {
710 // We only allow the title to be set from the primary content shell
711 if(!mPrimary || !mContentTitleSetting)
712 return NS_OK;
713
714 NS_ENSURE_STATE(mXULWindow);
715
716 nsAutoString title;
717 nsAutoString docTitle(aTitle);
718
719 if (docTitle.IsEmpty())
720 docTitle.Assign(mTitleDefault);
721
722 if (!docTitle.IsEmpty()) {
723 if (!mTitlePreface.IsEmpty()) {
724 // Title will be: "Preface: Doc Title - Mozilla"
725 title.Assign(mTitlePreface);
726 title.Append(docTitle);
727 }
728 else {
729 // Title will be: "Doc Title - Mozilla"
730 title = docTitle;
731 }
732
733 if (!mWindowTitleModifier.IsEmpty())
734 title += mTitleSeparator + mWindowTitleModifier;
735 }
736 else
737 title.Assign(mWindowTitleModifier); // Title will just be plain "Mozilla"
738
739 //
740 // if there is no location bar we modify the title to display at least
741 // the scheme and host (if any) as an anti-spoofing measure.
742 //
743 nsCOMPtr<dom::Element> docShellElement = mXULWindow->GetWindowDOMElement();
744
745 if (docShellElement) {
746 nsAutoString chromeString;
747 docShellElement->GetAttribute(NS_LITERAL_STRING("chromehidden"), chromeString);
748 if (chromeString.Find(NS_LITERAL_STRING("location")) != kNotFound) {
749 //
750 // location bar is turned off, find the browser location
751 //
752 // use the document's nsPrincipal to find the true owner
753 // in case of javascript: or data: documents
754 //
755 nsCOMPtr<nsIDocShellTreeItem> dsitem;
756 GetPrimaryContentShell(getter_AddRefs(dsitem));
757 nsCOMPtr<nsIDOMDocument> domdoc(do_GetInterface(dsitem));
758 nsCOMPtr<nsIScriptObjectPrincipal> doc(do_QueryInterface(domdoc));
759 if (doc) {
760 nsCOMPtr<nsIURI> uri;
761 nsIPrincipal* principal = doc->GetPrincipal();
762 if (principal) {
763 principal->GetURI(getter_AddRefs(uri));
764 if (uri) {
765 //
766 // remove any user:pass information
767 //
768 nsCOMPtr<nsIURIFixup> fixup(do_GetService(NS_URIFIXUP_CONTRACTID));
769 if (fixup) {
770 nsCOMPtr<nsIURI> tmpuri;
771 nsresult rv = fixup->CreateExposableURI(uri,getter_AddRefs(tmpuri));
772 if (NS_SUCCEEDED(rv) && tmpuri) {
773 // (don't bother if there's no host)
774 nsAutoCString host;
775 nsAutoCString prepath;
776 tmpuri->GetHost(host);
777 tmpuri->GetPrePath(prepath);
778 if (!host.IsEmpty()) {
779 //
780 // We have a scheme/host, update the title
781 //
782 title.Insert(NS_ConvertUTF8toUTF16(prepath) +
783 mTitleSeparator, 0);
784 }
785 }
786 }
787 }
788 }
789 }
790 }
791 nsIDocument* document = docShellElement->OwnerDoc();
792 ErrorResult rv;
793 document->SetTitle(title, rv);
794 return rv.ErrorCode();
795 }
796
797 return mXULWindow->SetTitle(title.get());
798 }
799
800 //*****************************************************************************
801 // nsContentTreeOwner: nsIWindowProvider
802 //*****************************************************************************
803 NS_IMETHODIMP
804 nsContentTreeOwner::ProvideWindow(nsIDOMWindow* aParent,
805 uint32_t aChromeFlags,
806 bool aCalledFromJS,
807 bool aPositionSpecified,
808 bool aSizeSpecified,
809 nsIURI* aURI,
810 const nsAString& aName,
811 const nsACString& aFeatures,
812 bool* aWindowIsNew,
813 nsIDOMWindow** aReturn)
814 {
815 NS_ENSURE_ARG_POINTER(aParent);
816
817 *aReturn = nullptr;
818
819 if (!mXULWindow) {
820 // Nothing to do here
821 return NS_OK;
822 }
823
824 #ifdef DEBUG
825 nsCOMPtr<nsIWebNavigation> parentNav = do_GetInterface(aParent);
826 nsCOMPtr<nsIDocShellTreeOwner> parentOwner = do_GetInterface(parentNav);
827 NS_ASSERTION(SameCOMIdentity(parentOwner,
828 static_cast<nsIDocShellTreeOwner*>(this)),
829 "Parent from wrong docshell tree?");
830 #endif
831
832 // If aParent is inside an <iframe mozbrowser> and this isn't a request to
833 // open a modal-type window, we're going to create a new <iframe mozbrowser>
834 // and return its window here.
835 nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
836 if (docshell && docshell->GetIsInBrowserOrApp() &&
837 !(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL |
838 nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
839 nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) {
840
841 BrowserElementParent::OpenWindowResult opened =
842 BrowserElementParent::OpenWindowInProcess(aParent, aURI, aName,
843 aFeatures, aReturn);
844
845 // If OpenWindowInProcess handled the open (by opening it or blocking the
846 // popup), tell our caller not to proceed trying to create a new window
847 // through other means.
848 if (opened != BrowserElementParent::OPEN_WINDOW_IGNORED) {
849 *aWindowIsNew = opened == BrowserElementParent::OPEN_WINDOW_ADDED;
850 return *aWindowIsNew ? NS_OK : NS_ERROR_ABORT;
851 }
852
853 // If we're in an app and the target is _blank, send the url to the OS
854 if (aName.LowerCaseEqualsLiteral("_blank")) {
855 nsCOMPtr<nsIExternalURLHandlerService> exUrlServ(
856 do_GetService(NS_EXTERNALURLHANDLERSERVICE_CONTRACTID));
857 if (exUrlServ) {
858
859 nsCOMPtr<nsIHandlerInfo> info;
860 bool found;
861 exUrlServ->GetURLHandlerInfoFromOS(aURI, &found, getter_AddRefs(info));
862
863 if (info && found) {
864 info->LaunchWithURI(aURI, nullptr);
865 return NS_ERROR_ABORT;
866 }
867
868 }
869 }
870 }
871
872 // the parent window is fullscreen mode or not.
873 bool isFullScreen = false;
874 if (aParent) {
875 aParent->GetFullScreen(&isFullScreen);
876 }
877
878 // Where should we open this?
879 int32_t containerPref;
880 if (NS_FAILED(Preferences::GetInt("browser.link.open_newwindow",
881 &containerPref))) {
882 return NS_OK;
883 }
884
885 bool isDisabledOpenNewWindow =
886 isFullScreen &&
887 Preferences::GetBool("browser.link.open_newwindow.disabled_in_fullscreen");
888
889 if (isDisabledOpenNewWindow && (containerPref == nsIBrowserDOMWindow::OPEN_NEWWINDOW)) {
890 containerPref = nsIBrowserDOMWindow::OPEN_NEWTAB;
891 }
892
893 if (containerPref != nsIBrowserDOMWindow::OPEN_NEWTAB &&
894 containerPref != nsIBrowserDOMWindow::OPEN_CURRENTWINDOW) {
895 // Just open a window normally
896 return NS_OK;
897 }
898
899 if (aCalledFromJS) {
900 /* Now check our restriction pref. The restriction pref is a power-user's
901 fine-tuning pref. values:
902 0: no restrictions - divert everything
903 1: don't divert window.open at all
904 2: don't divert window.open with features
905 */
906 int32_t restrictionPref =
907 Preferences::GetInt("browser.link.open_newwindow.restriction", 2);
908 if (restrictionPref < 0 || restrictionPref > 2) {
909 restrictionPref = 2; // Sane default behavior
910 }
911
912 if (isDisabledOpenNewWindow) {
913 // In browser fullscreen, the window should be opened
914 // in the current window with no features (see bug 803675)
915 restrictionPref = 0;
916 }
917
918 if (restrictionPref == 1) {
919 return NS_OK;
920 }
921
922 if (restrictionPref == 2 &&
923 // Only continue if there are no size/position features and no special
924 // chrome flags.
925 (aChromeFlags != nsIWebBrowserChrome::CHROME_ALL ||
926 aPositionSpecified || aSizeSpecified)) {
927 return NS_OK;
928 }
929 }
930
931 nsCOMPtr<nsIDOMWindow> domWin;
932 mXULWindow->GetWindowDOMWindow(getter_AddRefs(domWin));
933 nsCOMPtr<nsIDOMChromeWindow> chromeWin = do_QueryInterface(domWin);
934 if (!chromeWin) {
935 // Really odd... but whatever
936 NS_WARNING("nsXULWindow's DOMWindow is not a chrome window");
937 return NS_OK;
938 }
939
940 nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin;
941 chromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
942 if (!browserDOMWin) {
943 return NS_OK;
944 }
945
946 *aWindowIsNew = (containerPref != nsIBrowserDOMWindow::OPEN_CURRENTWINDOW);
947
948 {
949 dom::AutoNoJSAPI nojsapi;
950
951 // Get a new rendering area from the browserDOMWin. We don't want
952 // to be starting any loads here, so get it with a null URI.
953 return browserDOMWin->OpenURI(nullptr, aParent, containerPref,
954 nsIBrowserDOMWindow::OPEN_NEW, aReturn);
955 }
956 }
957
958 //*****************************************************************************
959 // nsContentTreeOwner: Accessors
960 //*****************************************************************************
961
962 #if defined(XP_MACOSX)
963 class nsContentTitleSettingEvent : public nsRunnable
964 {
965 public:
966 nsContentTitleSettingEvent(dom::Element* dse, const nsAString& wtm)
967 : mElement(dse),
968 mTitleDefault(wtm) {}
969
970 NS_IMETHOD Run()
971 {
972 ErrorResult rv;
973 mElement->SetAttribute(NS_LITERAL_STRING("titledefault"), mTitleDefault, rv);
974 mElement->RemoveAttribute(NS_LITERAL_STRING("titlemodifier"), rv);
975 return NS_OK;
976 }
977
978 private:
979 nsCOMPtr<dom::Element> mElement;
980 nsString mTitleDefault;
981 };
982 #endif
983
984 void nsContentTreeOwner::XULWindow(nsXULWindow* aXULWindow)
985 {
986 mXULWindow = aXULWindow;
987 if (mXULWindow && mPrimary) {
988 // Get the window title modifiers
989 nsCOMPtr<dom::Element> docShellElement = mXULWindow->GetWindowDOMElement();
990
991 nsAutoString contentTitleSetting;
992
993 if(docShellElement)
994 {
995 docShellElement->GetAttribute(NS_LITERAL_STRING("contenttitlesetting"), contentTitleSetting);
996 if(contentTitleSetting.EqualsLiteral("true"))
997 {
998 mContentTitleSetting = true;
999 docShellElement->GetAttribute(NS_LITERAL_STRING("titledefault"), mTitleDefault);
1000 docShellElement->GetAttribute(NS_LITERAL_STRING("titlemodifier"), mWindowTitleModifier);
1001 docShellElement->GetAttribute(NS_LITERAL_STRING("titlepreface"), mTitlePreface);
1002
1003 #if defined(XP_MACOSX)
1004 // On OS X, treat the titlemodifier like it's the titledefault, and don't ever append
1005 // the separator + appname.
1006 if (mTitleDefault.IsEmpty()) {
1007 NS_DispatchToCurrentThread(
1008 new nsContentTitleSettingEvent(docShellElement,
1009 mWindowTitleModifier));
1010 mTitleDefault = mWindowTitleModifier;
1011 mWindowTitleModifier.Truncate();
1012 }
1013 #endif
1014 docShellElement->GetAttribute(NS_LITERAL_STRING("titlemenuseparator"), mTitleSeparator);
1015 }
1016 }
1017 else
1018 {
1019 NS_ERROR("This condition should never happen. If it does, "
1020 "we just won't get a modifier, but it still shouldn't happen.");
1021 }
1022 }
1023 }
1024
1025 nsXULWindow* nsContentTreeOwner::XULWindow()
1026 {
1027 return mXULWindow;
1028 }
1029
1030 //*****************************************************************************
1031 //*** nsSiteWindow implementation
1032 //*****************************************************************************
1033
1034 nsSiteWindow::nsSiteWindow(nsContentTreeOwner *aAggregator)
1035 {
1036 mAggregator = aAggregator;
1037 }
1038
1039 nsSiteWindow::~nsSiteWindow()
1040 {
1041 }
1042
1043 NS_IMPL_ADDREF_USING_AGGREGATOR(nsSiteWindow, mAggregator)
1044 NS_IMPL_RELEASE_USING_AGGREGATOR(nsSiteWindow, mAggregator)
1045
1046 NS_INTERFACE_MAP_BEGIN(nsSiteWindow)
1047 NS_INTERFACE_MAP_ENTRY(nsISupports)
1048 NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
1049 NS_INTERFACE_MAP_END_AGGREGATED(mAggregator)
1050
1051 NS_IMETHODIMP
1052 nsSiteWindow::SetDimensions(uint32_t aFlags,
1053 int32_t aX, int32_t aY, int32_t aCX, int32_t aCY)
1054 {
1055 // XXX we're ignoring aFlags
1056 return mAggregator->SetPositionAndSize(aX, aY, aCX, aCY, true);
1057 }
1058
1059 NS_IMETHODIMP
1060 nsSiteWindow::GetDimensions(uint32_t aFlags,
1061 int32_t *aX, int32_t *aY, int32_t *aCX, int32_t *aCY)
1062 {
1063 // XXX we're ignoring aFlags
1064 return mAggregator->GetPositionAndSize(aX, aY, aCX, aCY);
1065 }
1066
1067 NS_IMETHODIMP
1068 nsSiteWindow::SetFocus(void)
1069 {
1070 #if 0
1071 /* This implementation focuses the main document and could make sense.
1072 However this method is actually being used from within
1073 nsGlobalWindow::Focus (providing a hook for MDI embedding apps)
1074 and it's better for our purposes to not pick a document and
1075 focus it, but allow nsGlobalWindow to carry on unhindered.
1076 */
1077 nsXULWindow *window = mAggregator->XULWindow();
1078 if (window) {
1079 nsCOMPtr<nsIDocShell> docshell;
1080 window->GetDocShell(getter_AddRefs(docshell));
1081 nsCOMPtr<nsIDOMWindow> domWindow(do_GetInterface(docshell));
1082 if (domWindow)
1083 domWindow->Focus();
1084 }
1085 #endif
1086 return NS_OK;
1087 }
1088
1089 /* this implementation focuses another window. if there isn't another
1090 window to focus, we do nothing. */
1091 NS_IMETHODIMP
1092 nsSiteWindow::Blur(void)
1093 {
1094 NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID);
1095
1096 nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
1097 nsCOMPtr<nsIXULWindow> xulWindow;
1098 bool more, foundUs;
1099 nsXULWindow *ourWindow = mAggregator->XULWindow();
1100
1101 {
1102 nsCOMPtr<nsIWindowMediator> windowMediator(do_GetService(kWindowMediatorCID));
1103 if (windowMediator)
1104 windowMediator->GetZOrderXULWindowEnumerator(0, true,
1105 getter_AddRefs(windowEnumerator));
1106 }
1107
1108 if (!windowEnumerator)
1109 return NS_ERROR_FAILURE;
1110
1111 // step through the top-level windows
1112 foundUs = false;
1113 windowEnumerator->HasMoreElements(&more);
1114 while (more) {
1115
1116 nsCOMPtr<nsISupports> nextWindow;
1117 nsCOMPtr<nsIXULWindow> nextXULWindow;
1118
1119 windowEnumerator->GetNext(getter_AddRefs(nextWindow));
1120 nextXULWindow = do_QueryInterface(nextWindow);
1121
1122 // got it!(?)
1123 if (foundUs) {
1124 xulWindow = nextXULWindow;
1125 break;
1126 }
1127
1128 // remember the very first one, in case we have to wrap
1129 if (!xulWindow)
1130 xulWindow = nextXULWindow;
1131
1132 // look for us
1133 if (nextXULWindow == ourWindow)
1134 foundUs = true;
1135
1136 windowEnumerator->HasMoreElements(&more);
1137 }
1138
1139 // change focus to the window we just found
1140 if (xulWindow) {
1141 nsCOMPtr<nsIDocShell> docshell;
1142 xulWindow->GetDocShell(getter_AddRefs(docshell));
1143 nsCOMPtr<nsIDOMWindow> domWindow(do_GetInterface(docshell));
1144 if (domWindow)
1145 domWindow->Focus();
1146 }
1147 return NS_OK;
1148 }
1149
1150 NS_IMETHODIMP
1151 nsSiteWindow::GetVisibility(bool *aVisibility)
1152 {
1153 return mAggregator->GetVisibility(aVisibility);
1154 }
1155
1156 NS_IMETHODIMP
1157 nsSiteWindow::SetVisibility(bool aVisibility)
1158 {
1159 return mAggregator->SetVisibility(aVisibility);
1160 }
1161
1162 NS_IMETHODIMP
1163 nsSiteWindow::GetTitle(char16_t * *aTitle)
1164 {
1165 return mAggregator->GetTitle(aTitle);
1166 }
1167
1168 NS_IMETHODIMP
1169 nsSiteWindow::SetTitle(const char16_t * aTitle)
1170 {
1171 return mAggregator->SetTitle(aTitle);
1172 }
1173
1174 NS_IMETHODIMP
1175 nsSiteWindow::GetSiteWindow(void **aSiteWindow)
1176 {
1177 return mAggregator->GetParentNativeWindow(aSiteWindow);
1178 }
1179

mercurial