Bug 1870926 [wpt PR 43734] - Remove experimental ::details-summary pseudo-element...
[gecko.git] / toolkit / components / browser / nsWebBrowser.cpp
blobdb63cdedb5e1a27d2c5c2cb51c836b33eaf4eedf
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/. */
7 // Local Includes
8 #include "nsWebBrowser.h"
10 // Helper Classes
11 #include "nsGfxCIID.h"
12 #include "nsWidgetsCID.h"
14 #include "gfxUtils.h"
15 #include "mozilla/gfx/2D.h"
17 // Interfaces Needed
18 #include "gfxContext.h"
19 #include "nsReadableUtils.h"
20 #include "nsIInterfaceRequestor.h"
21 #include "nsIInterfaceRequestorUtils.h"
22 #include "nsIWebBrowserChrome.h"
23 #include "nsPIDOMWindow.h"
24 #include "nsIWebProgress.h"
25 #include "nsIWebProgressListener.h"
26 #include "nsIURI.h"
27 #include "nsIWebBrowserPersist.h"
28 #include "nsFocusManager.h"
29 #include "nsILoadContext.h"
30 #include "nsComponentManagerUtils.h"
31 #include "nsDocShell.h"
32 #include "nsServiceManagerUtils.h"
33 #include "WindowRenderer.h"
35 #include "mozilla/dom/Element.h"
36 #include "mozilla/dom/BrowsingContext.h"
37 #include "mozilla/dom/LoadURIOptionsBinding.h"
38 #include "mozilla/dom/WindowGlobalChild.h"
40 // for painting the background window
41 #include "mozilla/LookAndFeel.h"
42 #include "mozilla/ServoStyleConsts.h"
44 // Printing Includes
45 #ifdef NS_PRINTING
46 # include "nsIWebBrowserPrint.h"
47 # include "nsIDocumentViewer.h"
48 #endif
50 // PSM2 includes
51 #include "nsISecureBrowserUI.h"
52 #include "nsXULAppAPI.h"
54 using namespace mozilla;
55 using namespace mozilla::gfx;
56 using namespace mozilla::layers;
58 nsWebBrowser::nsWebBrowser(int aItemType)
59 : mContentType(aItemType),
60 mShouldEnableHistory(true),
61 mWillChangeProcess(false),
62 mParentNativeWindow(nullptr),
63 mProgressListener(nullptr),
64 mWidgetListenerDelegate(this),
65 mBackgroundColor(0),
66 mPersistCurrentState(nsIWebBrowserPersist::PERSIST_STATE_READY),
67 mPersistResult(NS_OK),
68 mPersistFlags(nsIWebBrowserPersist::PERSIST_FLAGS_NONE),
69 mParentWidget(nullptr) {
70 mWWatch = do_GetService(NS_WINDOWWATCHER_CONTRACTID);
71 NS_ASSERTION(mWWatch, "failed to get WindowWatcher");
74 nsWebBrowser::~nsWebBrowser() { InternalDestroy(); }
76 nsIWidget* nsWebBrowser::EnsureWidget() {
77 if (mParentWidget) {
78 return mParentWidget;
81 mInternalWidget = nsIWidget::CreateChildWindow();
82 if (NS_WARN_IF(!mInternalWidget)) {
83 return nullptr;
86 widget::InitData widgetInit;
87 widgetInit.mClipChildren = true;
88 widgetInit.mWindowType = widget::WindowType::Child;
89 LayoutDeviceIntRect bounds(0, 0, 0, 0);
91 mInternalWidget->SetWidgetListener(&mWidgetListenerDelegate);
92 NS_ENSURE_SUCCESS(mInternalWidget->Create(nullptr, mParentNativeWindow,
93 bounds, &widgetInit),
94 nullptr);
96 return mInternalWidget;
99 /* static */
100 already_AddRefed<nsWebBrowser> nsWebBrowser::Create(
101 nsIWebBrowserChrome* aContainerWindow, nsIWidget* aParentWidget,
102 dom::BrowsingContext* aBrowsingContext,
103 dom::WindowGlobalChild* aInitialWindowChild) {
104 MOZ_ASSERT_IF(aInitialWindowChild,
105 aInitialWindowChild->BrowsingContext() == aBrowsingContext);
107 RefPtr<nsWebBrowser> browser = new nsWebBrowser(
108 aBrowsingContext->IsContent() ? typeContentWrapper : typeChromeWrapper);
110 // nsWebBrowser::SetContainer also calls nsWebBrowser::EnsureDocShellTreeOwner
111 NS_ENSURE_SUCCESS(browser->SetContainerWindow(aContainerWindow), nullptr);
112 NS_ENSURE_SUCCESS(browser->SetParentWidget(aParentWidget), nullptr);
114 nsCOMPtr<nsIWidget> docShellParentWidget = browser->EnsureWidget();
115 if (NS_WARN_IF(!docShellParentWidget)) {
116 return nullptr;
119 uint64_t outerWindowId =
120 aInitialWindowChild ? aInitialWindowChild->OuterWindowId() : 0;
122 RefPtr<nsDocShell> docShell =
123 nsDocShell::Create(aBrowsingContext, outerWindowId);
124 if (NS_WARN_IF(!docShell)) {
125 return nullptr;
127 browser->SetDocShell(docShell);
128 MOZ_ASSERT(browser->mDocShell == docShell);
130 // get the system default window background colour
132 // TODO(emilio): Can we get the color-scheme from somewhere here?
133 browser->mBackgroundColor =
134 LookAndFeel::Color(LookAndFeel::ColorID::Window, ColorScheme::Light,
135 LookAndFeel::UseStandins::No);
137 // HACK ALERT - this registration registers the nsDocShellTreeOwner as a
138 // nsIWebBrowserListener so it can setup its MouseListener in one of the
139 // progress callbacks. If we can register the MouseListener another way, this
140 // registration can go away, and nsDocShellTreeOwner can stop implementing
141 // nsIWebProgressListener.
142 RefPtr<nsDocShellTreeOwner> docShellTreeOwner = browser->mDocShellTreeOwner;
143 Unused << docShell->AddProgressListener(docShellTreeOwner,
144 nsIWebProgress::NOTIFY_ALL);
146 docShell->SetTreeOwner(docShellTreeOwner);
148 // If the webbrowser is a content docshell item then we won't hear any
149 // events from subframes. To solve that we install our own chrome event
150 // handler that always gets called (even for subframes) for any bubbling
151 // event.
153 nsresult rv = docShell->InitWindow(nullptr, docShellParentWidget, 0, 0, 0, 0);
154 if (NS_WARN_IF(NS_FAILED(rv))) {
155 return nullptr;
158 docShellTreeOwner->AddToWatcher(); // evil twin of Remove in SetDocShell(0)
159 docShellTreeOwner->AddChromeListeners();
161 if (aInitialWindowChild) {
162 docShell->CreateDocumentViewerForActor(aInitialWindowChild);
165 return browser.forget();
168 void nsWebBrowser::InternalDestroy() {
169 if (mInternalWidget) {
170 mInternalWidget->SetWidgetListener(nullptr);
171 mInternalWidget->Destroy();
172 mInternalWidget = nullptr; // Force release here.
175 SetDocShell(nullptr);
177 if (mDocShellTreeOwner) {
178 mDocShellTreeOwner->WebBrowser(nullptr);
179 mDocShellTreeOwner = nullptr;
183 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsWebBrowser)
184 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsWebBrowser)
186 NS_IMPL_CYCLE_COLLECTION_WEAK(nsWebBrowser, mDocShell)
188 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsWebBrowser)
189 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowser)
190 NS_INTERFACE_MAP_ENTRY(nsIWebBrowser)
191 NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)
192 NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
193 NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)
194 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
195 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPersist)
196 NS_INTERFACE_MAP_ENTRY(nsICancelable)
197 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
198 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
199 NS_INTERFACE_MAP_END
201 ///*****************************************************************************
202 // nsWebBrowser::nsIInterfaceRequestor
203 //*****************************************************************************
205 NS_IMETHODIMP
206 nsWebBrowser::GetInterface(const nsIID& aIID, void** aSink) {
207 NS_ENSURE_ARG_POINTER(aSink);
209 if (NS_SUCCEEDED(QueryInterface(aIID, aSink))) {
210 return NS_OK;
213 if (mDocShell) {
214 #ifdef NS_PRINTING
215 if (aIID.Equals(NS_GET_IID(nsIWebBrowserPrint))) {
216 nsCOMPtr<nsIDocumentViewer> viewer;
217 mDocShell->GetDocViewer(getter_AddRefs(viewer));
218 if (!viewer) {
219 return NS_NOINTERFACE;
222 nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint(do_QueryInterface(viewer));
223 nsIWebBrowserPrint* print = (nsIWebBrowserPrint*)webBrowserPrint.get();
224 NS_ASSERTION(print, "This MUST support this interface!");
225 NS_ADDREF(print);
226 *aSink = print;
227 return NS_OK;
229 #endif
230 return mDocShell->GetInterface(aIID, aSink);
233 return NS_NOINTERFACE;
236 //*****************************************************************************
237 // nsWebBrowser::nsIWebBrowser
238 //*****************************************************************************
240 NS_IMETHODIMP
241 nsWebBrowser::GetContainerWindow(nsIWebBrowserChrome** aTopWindow) {
242 NS_ENSURE_ARG_POINTER(aTopWindow);
244 nsCOMPtr<nsIWebBrowserChrome> top;
245 if (mDocShellTreeOwner) {
246 top = mDocShellTreeOwner->GetWebBrowserChrome();
249 top.forget(aTopWindow);
251 return NS_OK;
254 NS_IMETHODIMP
255 nsWebBrowser::SetContainerWindow(nsIWebBrowserChrome* aTopWindow) {
256 EnsureDocShellTreeOwner();
257 return mDocShellTreeOwner->SetWebBrowserChrome(aTopWindow);
260 NS_IMETHODIMP
261 nsWebBrowser::GetContentDOMWindow(mozIDOMWindowProxy** aResult) {
262 if (!mDocShell) {
263 return NS_ERROR_UNEXPECTED;
266 nsCOMPtr<nsPIDOMWindowOuter> retval = mDocShell->GetWindow();
267 retval.forget(aResult);
268 return *aResult ? NS_OK : NS_ERROR_FAILURE;
271 void nsWebBrowser::SetOriginAttributes(const OriginAttributes& aAttrs) {
272 mOriginAttributes = aAttrs;
275 //*****************************************************************************
276 // nsWebBrowser::nsIDocShellTreeItem
277 //*****************************************************************************
279 NS_IMETHODIMP
280 nsWebBrowser::GetName(nsAString& aName) {
281 if (mDocShell) {
282 mDocShell->GetName(aName);
285 return NS_OK;
288 NS_IMETHODIMP
289 nsWebBrowser::SetName(const nsAString& aName) {
290 if (mDocShell) {
291 return mDocShell->SetName(aName);
294 return NS_OK;
297 NS_IMETHODIMP
298 nsWebBrowser::NameEquals(const nsAString& aName, bool* aResult) {
299 NS_ENSURE_ARG_POINTER(aResult);
300 if (mDocShell) {
301 return mDocShell->NameEquals(aName, aResult);
304 return NS_OK;
307 /* virtual */
308 int32_t nsWebBrowser::ItemType() { return mContentType; }
310 NS_IMETHODIMP
311 nsWebBrowser::GetItemType(int32_t* aItemType) {
312 NS_ENSURE_ARG_POINTER(aItemType);
314 *aItemType = ItemType();
315 return NS_OK;
318 NS_IMETHODIMP
319 nsWebBrowser::GetInProcessParent(nsIDocShellTreeItem** aParent) {
320 *aParent = nullptr;
321 return NS_OK;
324 NS_IMETHODIMP
325 nsWebBrowser::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) {
326 *aParent = nullptr;
328 return NS_OK;
331 NS_IMETHODIMP
332 nsWebBrowser::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) {
333 NS_ENSURE_ARG_POINTER(aRootTreeItem);
334 *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
336 nsCOMPtr<nsIDocShellTreeItem> parent;
337 NS_ENSURE_SUCCESS(GetInProcessParent(getter_AddRefs(parent)),
338 NS_ERROR_FAILURE);
339 while (parent) {
340 *aRootTreeItem = parent;
341 NS_ENSURE_SUCCESS(
342 (*aRootTreeItem)->GetInProcessParent(getter_AddRefs(parent)),
343 NS_ERROR_FAILURE);
345 NS_ADDREF(*aRootTreeItem);
346 return NS_OK;
349 NS_IMETHODIMP
350 nsWebBrowser::GetInProcessSameTypeRootTreeItem(
351 nsIDocShellTreeItem** aRootTreeItem) {
352 NS_ENSURE_ARG_POINTER(aRootTreeItem);
353 *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
355 nsCOMPtr<nsIDocShellTreeItem> parent;
356 NS_ENSURE_SUCCESS(GetInProcessSameTypeParent(getter_AddRefs(parent)),
357 NS_ERROR_FAILURE);
358 while (parent) {
359 *aRootTreeItem = parent;
360 NS_ENSURE_SUCCESS(
361 (*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent)),
362 NS_ERROR_FAILURE);
364 NS_ADDREF(*aRootTreeItem);
365 return NS_OK;
368 dom::Document* nsWebBrowser::GetDocument() {
369 return mDocShell ? mDocShell->GetDocument() : nullptr;
372 nsPIDOMWindowOuter* nsWebBrowser::GetWindow() {
373 return mDocShell ? mDocShell->GetWindow() : nullptr;
376 NS_IMETHODIMP
377 nsWebBrowser::GetBrowsingContextXPCOM(dom::BrowsingContext** aBrowsingContext) {
378 NS_ENSURE_STATE(mDocShell);
379 return mDocShell->GetBrowsingContextXPCOM(aBrowsingContext);
382 dom::BrowsingContext* nsWebBrowser::GetBrowsingContext() {
383 return mDocShell->GetBrowsingContext();
386 NS_IMETHODIMP
387 nsWebBrowser::GetDomWindow(mozIDOMWindowProxy** aWindow) {
388 if (!mDocShell) return NS_ERROR_NOT_INITIALIZED;
389 return mDocShell->GetDomWindow(aWindow);
392 NS_IMETHODIMP
393 nsWebBrowser::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) {
394 NS_ENSURE_ARG_POINTER(aTreeOwner);
395 *aTreeOwner = nullptr;
396 if (mDocShellTreeOwner) {
397 if (mDocShellTreeOwner->mTreeOwner) {
398 *aTreeOwner = mDocShellTreeOwner->mTreeOwner;
399 } else {
400 *aTreeOwner = mDocShellTreeOwner;
403 NS_IF_ADDREF(*aTreeOwner);
404 return NS_OK;
407 NS_IMETHODIMP
408 nsWebBrowser::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) {
409 EnsureDocShellTreeOwner();
410 return mDocShellTreeOwner->SetTreeOwner(aTreeOwner);
413 //*****************************************************************************
414 // nsWebBrowser::nsIDocShellTreeItem
415 //*****************************************************************************
417 NS_IMETHODIMP
418 nsWebBrowser::GetInProcessChildCount(int32_t* aChildCount) {
419 NS_ENSURE_ARG_POINTER(aChildCount);
420 *aChildCount = 0;
421 return NS_OK;
424 NS_IMETHODIMP
425 nsWebBrowser::AddChild(nsIDocShellTreeItem* aChild) {
426 return NS_ERROR_UNEXPECTED;
429 NS_IMETHODIMP
430 nsWebBrowser::RemoveChild(nsIDocShellTreeItem* aChild) {
431 return NS_ERROR_UNEXPECTED;
434 NS_IMETHODIMP
435 nsWebBrowser::GetInProcessChildAt(int32_t aIndex,
436 nsIDocShellTreeItem** aChild) {
437 return NS_ERROR_UNEXPECTED;
440 //*****************************************************************************
441 // nsWebBrowser::nsIWebNavigation
442 //*****************************************************************************
444 NS_IMETHODIMP
445 nsWebBrowser::GetCanGoBack(bool* aCanGoBack) {
446 NS_ENSURE_STATE(mDocShell);
448 return mDocShell->GetCanGoBack(aCanGoBack);
451 NS_IMETHODIMP
452 nsWebBrowser::GetCanGoForward(bool* aCanGoForward) {
453 NS_ENSURE_STATE(mDocShell);
455 return mDocShell->GetCanGoForward(aCanGoForward);
458 NS_IMETHODIMP
459 nsWebBrowser::GoBack(bool aRequireUserInteraction, bool aUserActivation) {
460 NS_ENSURE_STATE(mDocShell);
462 RefPtr<nsDocShell> docShell = mDocShell;
463 return docShell->GoBack(aRequireUserInteraction, aUserActivation);
466 NS_IMETHODIMP
467 nsWebBrowser::GoForward(bool aRequireUserInteraction, bool aUserActivation) {
468 NS_ENSURE_STATE(mDocShell);
470 RefPtr<nsDocShell> docShell = mDocShell;
471 return docShell->GoForward(aRequireUserInteraction, aUserActivation);
474 nsresult nsWebBrowser::LoadURI(nsIURI* aURI,
475 const dom::LoadURIOptions& aLoadURIOptions) {
476 #ifndef ANDROID
477 MOZ_ASSERT(aLoadURIOptions.mTriggeringPrincipal,
478 "nsWebBrowser::LoadURI - Need a valid triggeringPrincipal");
479 #endif
480 NS_ENSURE_STATE(mDocShell);
482 RefPtr<nsDocShell> docShell = mDocShell;
483 return docShell->LoadURI(aURI, aLoadURIOptions);
486 NS_IMETHODIMP
487 nsWebBrowser::LoadURIFromScript(nsIURI* aURI,
488 JS::Handle<JS::Value> aLoadURIOptions,
489 JSContext* aCx) {
490 // generate dictionary for loadURIOptions and forward call
491 dom::LoadURIOptions loadURIOptions;
492 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
493 return NS_ERROR_INVALID_ARG;
495 return LoadURI(aURI, loadURIOptions);
498 nsresult nsWebBrowser::FixupAndLoadURIString(
499 const nsAString& aURI, const dom::LoadURIOptions& aLoadURIOptions) {
500 #ifndef ANDROID
501 MOZ_ASSERT(
502 aLoadURIOptions.mTriggeringPrincipal,
503 "nsWebBrowser::FixupAndLoadURIString - Need a valid triggeringPrincipal");
504 #endif
505 NS_ENSURE_STATE(mDocShell);
507 RefPtr<nsDocShell> docShell = mDocShell;
508 return docShell->FixupAndLoadURIString(aURI, aLoadURIOptions);
511 NS_IMETHODIMP
512 nsWebBrowser::FixupAndLoadURIStringFromScript(
513 const nsAString& aURI, JS::Handle<JS::Value> aLoadURIOptions,
514 JSContext* aCx) {
515 // generate dictionary for loadURIOptions and forward call
516 dom::LoadURIOptions loadURIOptions;
517 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
518 return NS_ERROR_INVALID_ARG;
520 return FixupAndLoadURIString(aURI, loadURIOptions);
523 NS_IMETHODIMP
524 nsWebBrowser::ResumeRedirectedLoad(uint64_t aIdentifier,
525 int32_t aHistoryIndex) {
526 NS_ENSURE_STATE(mDocShell);
528 return mDocShell->ResumeRedirectedLoad(aIdentifier, aHistoryIndex);
531 NS_IMETHODIMP
532 nsWebBrowser::Reload(uint32_t aReloadFlags) {
533 NS_ENSURE_STATE(mDocShell);
535 RefPtr<nsDocShell> docShell = mDocShell;
536 return docShell->Reload(aReloadFlags);
539 NS_IMETHODIMP
540 nsWebBrowser::GotoIndex(int32_t aIndex, bool aUserActivation) {
541 NS_ENSURE_STATE(mDocShell);
543 RefPtr<nsDocShell> docShell = mDocShell;
544 return docShell->GotoIndex(aIndex, aUserActivation);
547 NS_IMETHODIMP
548 nsWebBrowser::Stop(uint32_t aStopFlags) {
549 NS_ENSURE_STATE(mDocShell);
551 return mDocShell->Stop(aStopFlags);
554 NS_IMETHODIMP
555 nsWebBrowser::GetCurrentURI(nsIURI** aURI) {
556 NS_ENSURE_STATE(mDocShell);
558 return mDocShell->GetCurrentURI(aURI);
561 // XXX(nika): Consider making the mozilla::dom::ChildSHistory version the
562 // canonical one?
563 NS_IMETHODIMP
564 nsWebBrowser::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) {
565 NS_ENSURE_ARG_POINTER(aSessionHistory);
566 *aSessionHistory = nullptr;
567 if (mDocShell) {
568 return mDocShell->GetSessionHistoryXPCOM(aSessionHistory);
570 return NS_OK;
573 NS_IMETHODIMP
574 nsWebBrowser::GetDocument(dom::Document** aDocument) {
575 NS_ENSURE_STATE(mDocShell);
577 return mDocShell->GetDocument(aDocument);
580 void nsWebBrowser::SetAllowDNSPrefetch(bool aAllowPrefetch) {
581 MOZ_ASSERT(mDocShell);
582 mDocShell->SetAllowDNSPrefetch(aAllowPrefetch);
585 //*****************************************************************************
586 // nsWebBrowser::nsIWebProgressListener
587 //*****************************************************************************
589 NS_IMETHODIMP
590 nsWebBrowser::OnStateChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
591 uint32_t aStateFlags, nsresult aStatus) {
592 if (mPersist) {
593 mPersist->GetCurrentState(&mPersistCurrentState);
595 if (aStateFlags & STATE_IS_NETWORK && aStateFlags & STATE_STOP) {
596 mPersist = nullptr;
598 if (mProgressListener) {
599 return mProgressListener->OnStateChange(aWebProgress, aRequest, aStateFlags,
600 aStatus);
602 return NS_OK;
605 NS_IMETHODIMP
606 nsWebBrowser::OnProgressChange(nsIWebProgress* aWebProgress,
607 nsIRequest* aRequest, int32_t aCurSelfProgress,
608 int32_t aMaxSelfProgress,
609 int32_t aCurTotalProgress,
610 int32_t aMaxTotalProgress) {
611 if (mPersist) {
612 mPersist->GetCurrentState(&mPersistCurrentState);
614 if (mProgressListener) {
615 return mProgressListener->OnProgressChange(
616 aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress,
617 aCurTotalProgress, aMaxTotalProgress);
619 return NS_OK;
622 NS_IMETHODIMP
623 nsWebBrowser::OnLocationChange(nsIWebProgress* aWebProgress,
624 nsIRequest* aRequest, nsIURI* aLocation,
625 uint32_t aFlags) {
626 if (mProgressListener) {
627 return mProgressListener->OnLocationChange(aWebProgress, aRequest,
628 aLocation, aFlags);
630 return NS_OK;
633 NS_IMETHODIMP
634 nsWebBrowser::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
635 nsresult aStatus, const char16_t* aMessage) {
636 if (mProgressListener) {
637 return mProgressListener->OnStatusChange(aWebProgress, aRequest, aStatus,
638 aMessage);
640 return NS_OK;
643 NS_IMETHODIMP
644 nsWebBrowser::OnSecurityChange(nsIWebProgress* aWebProgress,
645 nsIRequest* aRequest, uint32_t aState) {
646 if (mProgressListener) {
647 return mProgressListener->OnSecurityChange(aWebProgress, aRequest, aState);
649 return NS_OK;
652 NS_IMETHODIMP
653 nsWebBrowser::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
654 nsIRequest* aRequest, uint32_t aEvent) {
655 if (mProgressListener) {
656 return mProgressListener->OnContentBlockingEvent(aWebProgress, aRequest,
657 aEvent);
659 return NS_OK;
662 //*****************************************************************************
663 // nsWebBrowser::nsIWebBrowserPersist
664 //*****************************************************************************
666 NS_IMETHODIMP
667 nsWebBrowser::GetPersistFlags(uint32_t* aPersistFlags) {
668 NS_ENSURE_ARG_POINTER(aPersistFlags);
669 nsresult rv = NS_OK;
670 if (mPersist) {
671 rv = mPersist->GetPersistFlags(&mPersistFlags);
673 *aPersistFlags = mPersistFlags;
674 return rv;
677 NS_IMETHODIMP
678 nsWebBrowser::SetPersistFlags(uint32_t aPersistFlags) {
679 nsresult rv = NS_OK;
680 mPersistFlags = aPersistFlags;
681 if (mPersist) {
682 rv = mPersist->SetPersistFlags(mPersistFlags);
683 mPersist->GetPersistFlags(&mPersistFlags);
685 return rv;
688 NS_IMETHODIMP
689 nsWebBrowser::GetCurrentState(uint32_t* aCurrentState) {
690 NS_ENSURE_ARG_POINTER(aCurrentState);
691 if (mPersist) {
692 mPersist->GetCurrentState(&mPersistCurrentState);
694 *aCurrentState = mPersistCurrentState;
695 return NS_OK;
698 NS_IMETHODIMP
699 nsWebBrowser::GetResult(nsresult* aResult) {
700 NS_ENSURE_ARG_POINTER(aResult);
701 if (mPersist) {
702 mPersist->GetResult(&mPersistResult);
704 *aResult = mPersistResult;
705 return NS_OK;
708 NS_IMETHODIMP
709 nsWebBrowser::GetProgressListener(nsIWebProgressListener** aProgressListener) {
710 NS_ENSURE_ARG_POINTER(aProgressListener);
711 *aProgressListener = mProgressListener;
712 NS_IF_ADDREF(*aProgressListener);
713 return NS_OK;
716 NS_IMETHODIMP
717 nsWebBrowser::SetProgressListener(nsIWebProgressListener* aProgressListener) {
718 mProgressListener = aProgressListener;
719 return NS_OK;
722 NS_IMETHODIMP
723 nsWebBrowser::SaveURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
724 uint32_t aCacheKey, nsIReferrerInfo* aReferrerInfo,
725 nsICookieJarSettings* aCookieJarSettings,
726 nsIInputStream* aPostData, const char* aExtraHeaders,
727 nsISupports* aFile,
728 nsContentPolicyType aContentPolicyType, bool aIsPrivate) {
729 if (mPersist) {
730 uint32_t currentState;
731 mPersist->GetCurrentState(&currentState);
732 if (currentState == PERSIST_STATE_FINISHED) {
733 mPersist = nullptr;
734 } else {
735 // You can't save again until the last save has completed
736 return NS_ERROR_FAILURE;
740 nsCOMPtr<nsIURI> uri;
741 if (aURI) {
742 uri = aURI;
743 } else {
744 nsresult rv = GetCurrentURI(getter_AddRefs(uri));
745 if (NS_FAILED(rv)) {
746 return NS_ERROR_FAILURE;
750 // Create a throwaway persistence object to do the work
751 nsresult rv;
752 mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv);
753 NS_ENSURE_SUCCESS(rv, rv);
754 mPersist->SetProgressListener(this);
755 mPersist->SetPersistFlags(mPersistFlags);
756 mPersist->GetCurrentState(&mPersistCurrentState);
758 rv = mPersist->SaveURI(uri, aPrincipal, aCacheKey, aReferrerInfo,
759 aCookieJarSettings, aPostData, aExtraHeaders, aFile,
760 aContentPolicyType, aIsPrivate);
761 if (NS_FAILED(rv)) {
762 mPersist = nullptr;
764 return rv;
767 NS_IMETHODIMP
768 nsWebBrowser::SaveChannel(nsIChannel* aChannel, nsISupports* aFile) {
769 if (mPersist) {
770 uint32_t currentState;
771 mPersist->GetCurrentState(&currentState);
772 if (currentState == PERSIST_STATE_FINISHED) {
773 mPersist = nullptr;
774 } else {
775 // You can't save again until the last save has completed
776 return NS_ERROR_FAILURE;
780 // Create a throwaway persistence object to do the work
781 nsresult rv;
782 mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv);
783 NS_ENSURE_SUCCESS(rv, rv);
784 mPersist->SetProgressListener(this);
785 mPersist->SetPersistFlags(mPersistFlags);
786 mPersist->GetCurrentState(&mPersistCurrentState);
787 rv = mPersist->SaveChannel(aChannel, aFile);
788 if (NS_FAILED(rv)) {
789 mPersist = nullptr;
791 return rv;
794 NS_IMETHODIMP
795 nsWebBrowser::SaveDocument(nsISupports* aDocumentish, nsISupports* aFile,
796 nsISupports* aDataPath,
797 const char* aOutputContentType,
798 uint32_t aEncodingFlags, uint32_t aWrapColumn) {
799 if (mPersist) {
800 uint32_t currentState;
801 mPersist->GetCurrentState(&currentState);
802 if (currentState == PERSIST_STATE_FINISHED) {
803 mPersist = nullptr;
804 } else {
805 // You can't save again until the last save has completed
806 return NS_ERROR_FAILURE;
810 // Use the specified DOM document, or if none is specified, the one
811 // attached to the web browser.
813 nsCOMPtr<nsISupports> doc;
814 if (aDocumentish) {
815 doc = aDocumentish;
816 } else {
817 RefPtr<dom::Document> domDoc;
818 GetDocument(getter_AddRefs(domDoc));
819 doc = already_AddRefed<nsISupports>(ToSupports(domDoc.forget().take()));
821 if (!doc) {
822 return NS_ERROR_FAILURE;
825 // Create a throwaway persistence object to do the work
826 nsresult rv;
827 mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv);
828 NS_ENSURE_SUCCESS(rv, rv);
829 RefPtr<nsIWebBrowserPersist> localPersist(mPersist);
830 Unused << localPersist;
831 mPersist->SetProgressListener(this);
832 mPersist->SetPersistFlags(mPersistFlags);
833 mPersist->GetCurrentState(&mPersistCurrentState);
834 rv = mPersist->SaveDocument(doc, aFile, aDataPath, aOutputContentType,
835 aEncodingFlags, aWrapColumn);
836 if (NS_FAILED(rv)) {
837 mPersist = nullptr;
839 return rv;
842 NS_IMETHODIMP
843 nsWebBrowser::CancelSave() {
844 if (mPersist) {
845 return mPersist->CancelSave();
847 return NS_OK;
850 NS_IMETHODIMP
851 nsWebBrowser::Cancel(nsresult aReason) {
852 if (mPersist) {
853 return mPersist->Cancel(aReason);
855 return NS_OK;
858 //*****************************************************************************
859 // nsWebBrowser::nsIBaseWindow
860 //*****************************************************************************
862 NS_IMETHODIMP
863 nsWebBrowser::InitWindow(nativeWindow aParentNativeWindow,
864 nsIWidget* aParentWidget, int32_t aX, int32_t aY,
865 int32_t aCX, int32_t aCY) {
866 // nsIBaseWindow::InitWindow and nsIBaseWindow::Create
867 // implementations have been merged into nsWebBrowser::Create
868 MOZ_DIAGNOSTIC_ASSERT(false);
869 return NS_ERROR_NULL_POINTER;
872 NS_IMETHODIMP
873 nsWebBrowser::Destroy() {
874 InternalDestroy();
876 return NS_OK;
879 double nsWebBrowser::GetWidgetCSSToDeviceScale() {
880 return mParentWidget ? mParentWidget->GetDefaultScale().scale : 1.0;
883 NS_IMETHODIMP
884 nsWebBrowser::GetDevicePixelsPerDesktopPixel(double* aScale) {
885 *aScale =
886 mParentWidget ? mParentWidget->GetDesktopToDeviceScale().scale : 1.0;
887 return NS_OK;
890 NS_IMETHODIMP
891 nsWebBrowser::SetPositionDesktopPix(int32_t aX, int32_t aY) {
892 // XXX jfkthame
893 // It's not clear to me whether this will be fully correct across
894 // potential multi-screen, mixed-DPI configurations for all platforms;
895 // we might need to add code paths that make it possible to pass the
896 // desktop-pix parameters all the way through to the native widget,
897 // to avoid the risk of device-pixel coords mapping to the wrong
898 // display on OS X with mixed retina/non-retina screens.
899 double scale = 1.0;
900 GetDevicePixelsPerDesktopPixel(&scale);
901 return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
904 NS_IMETHODIMP
905 nsWebBrowser::SetPosition(int32_t aX, int32_t aY) {
906 int32_t cx = 0;
907 int32_t cy = 0;
909 GetSize(&cx, &cy);
911 return SetPositionAndSize(aX, aY, cx, cy, 0);
914 NS_IMETHODIMP
915 nsWebBrowser::GetPosition(int32_t* aX, int32_t* aY) {
916 return GetPositionAndSize(aX, aY, nullptr, nullptr);
919 NS_IMETHODIMP
920 nsWebBrowser::SetSize(int32_t aCX, int32_t aCY, bool aRepaint) {
921 int32_t x = 0;
922 int32_t y = 0;
924 GetPosition(&x, &y);
926 return SetPositionAndSize(x, y, aCX, aCY,
927 aRepaint ? nsIBaseWindow::eRepaint : 0);
930 NS_IMETHODIMP
931 nsWebBrowser::GetSize(int32_t* aCX, int32_t* aCY) {
932 return GetPositionAndSize(nullptr, nullptr, aCX, aCY);
935 NS_IMETHODIMP
936 nsWebBrowser::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aCX,
937 int32_t aCY, uint32_t aFlags) {
938 int32_t doc_x = aX;
939 int32_t doc_y = aY;
941 // If there is an internal widget we need to make the docShell coordinates
942 // relative to the internal widget rather than the calling app's parent.
943 // We also need to resize our widget then.
944 if (mInternalWidget) {
945 doc_x = doc_y = 0;
946 mInternalWidget->Resize(aX, aY, aCX, aCY,
947 !!(aFlags & nsIBaseWindow::eRepaint));
949 // Now reposition/ resize the doc
950 NS_ENSURE_SUCCESS(
951 mDocShell->SetPositionAndSize(doc_x, doc_y, aCX, aCY, aFlags),
952 NS_ERROR_FAILURE);
954 return NS_OK;
957 NS_IMETHODIMP
958 nsWebBrowser::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aCX,
959 int32_t* aCY) {
960 if (mInternalWidget) {
961 LayoutDeviceIntRect bounds = mInternalWidget->GetBounds();
963 if (aX) {
964 *aX = bounds.X();
966 if (aY) {
967 *aY = bounds.Y();
969 if (aCX) {
970 *aCX = bounds.Width();
972 if (aCY) {
973 *aCY = bounds.Height();
975 return NS_OK;
978 // Can directly return this as it is the
979 // same interface, thus same returns.
980 return mDocShell->GetPositionAndSize(aX, aY, aCX, aCY);
983 NS_IMETHODIMP
984 nsWebBrowser::SetDimensions(DimensionRequest&& aRequest) {
985 return NS_ERROR_NOT_IMPLEMENTED;
988 NS_IMETHODIMP
989 nsWebBrowser::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
990 int32_t* aY, int32_t* aCX, int32_t* aCY) {
991 return NS_ERROR_NOT_IMPLEMENTED;
994 NS_IMETHODIMP
995 nsWebBrowser::Repaint(bool aForce) {
996 NS_ENSURE_STATE(mDocShell);
997 // Can directly return this as it is the
998 // same interface, thus same returns.
999 return mDocShell->Repaint(aForce);
1002 NS_IMETHODIMP
1003 nsWebBrowser::GetParentWidget(nsIWidget** aParentWidget) {
1004 NS_ENSURE_ARG_POINTER(aParentWidget);
1006 *aParentWidget = mParentWidget;
1008 NS_IF_ADDREF(*aParentWidget);
1010 return NS_OK;
1013 NS_IMETHODIMP
1014 nsWebBrowser::SetParentWidget(nsIWidget* aParentWidget) {
1015 NS_ENSURE_STATE(!mDocShell);
1017 mParentWidget = aParentWidget;
1018 if (mParentWidget) {
1019 mParentNativeWindow = mParentWidget->GetNativeData(NS_NATIVE_WIDGET);
1020 } else {
1021 mParentNativeWindow = nullptr;
1024 return NS_OK;
1027 NS_IMETHODIMP
1028 nsWebBrowser::GetParentNativeWindow(nativeWindow* aParentNativeWindow) {
1029 NS_ENSURE_ARG_POINTER(aParentNativeWindow);
1031 *aParentNativeWindow = mParentNativeWindow;
1033 return NS_OK;
1036 NS_IMETHODIMP
1037 nsWebBrowser::SetParentNativeWindow(nativeWindow aParentNativeWindow) {
1038 NS_ENSURE_STATE(!mDocShell);
1040 mParentNativeWindow = aParentNativeWindow;
1042 return NS_OK;
1045 NS_IMETHODIMP
1046 nsWebBrowser::GetNativeHandle(nsAString& aNativeHandle) {
1047 // the nativeHandle should be accessed from nsIAppWindow
1048 return NS_ERROR_NOT_IMPLEMENTED;
1051 NS_IMETHODIMP
1052 nsWebBrowser::GetVisibility(bool* aVisibility) {
1053 NS_ENSURE_ARG_POINTER(aVisibility);
1055 if (mDocShell) {
1056 NS_ENSURE_SUCCESS(mDocShell->GetVisibility(aVisibility), NS_ERROR_FAILURE);
1059 return NS_OK;
1062 NS_IMETHODIMP
1063 nsWebBrowser::SetVisibility(bool aVisibility) {
1064 if (mDocShell) {
1065 NS_ENSURE_SUCCESS(mDocShell->SetVisibility(aVisibility), NS_ERROR_FAILURE);
1066 if (mInternalWidget) {
1067 mInternalWidget->Show(aVisibility);
1071 return NS_OK;
1074 NS_IMETHODIMP
1075 nsWebBrowser::GetEnabled(bool* aEnabled) {
1076 if (mInternalWidget) {
1077 *aEnabled = mInternalWidget->IsEnabled();
1078 return NS_OK;
1081 return NS_ERROR_FAILURE;
1084 NS_IMETHODIMP
1085 nsWebBrowser::SetEnabled(bool aEnabled) {
1086 if (mInternalWidget) {
1087 mInternalWidget->Enable(aEnabled);
1088 return NS_OK;
1090 return NS_ERROR_FAILURE;
1093 NS_IMETHODIMP
1094 nsWebBrowser::GetMainWidget(nsIWidget** aMainWidget) {
1095 NS_ENSURE_ARG_POINTER(aMainWidget);
1097 if (mInternalWidget) {
1098 *aMainWidget = mInternalWidget;
1099 } else {
1100 *aMainWidget = mParentWidget;
1103 NS_IF_ADDREF(*aMainWidget);
1105 return NS_OK;
1108 NS_IMETHODIMP
1109 nsWebBrowser::GetTitle(nsAString& aTitle) {
1110 NS_ENSURE_STATE(mDocShell);
1112 NS_ENSURE_SUCCESS(mDocShell->GetTitle(aTitle), NS_ERROR_FAILURE);
1114 return NS_OK;
1117 NS_IMETHODIMP
1118 nsWebBrowser::SetTitle(const nsAString& aTitle) {
1119 NS_ENSURE_STATE(mDocShell);
1121 NS_ENSURE_SUCCESS(mDocShell->SetTitle(aTitle), NS_ERROR_FAILURE);
1123 return NS_OK;
1126 //*****************************************************************************
1127 // nsWebBrowser: Listener Helpers
1128 //*****************************************************************************
1130 void nsWebBrowser::SetDocShell(nsDocShell* aDocShell) {
1131 // We need to keep the docshell alive while we perform the changes, but we
1132 // don't need to call any methods on it.
1133 nsCOMPtr<nsIDocShell> kungFuDeathGrip(mDocShell);
1134 mozilla::Unused << kungFuDeathGrip;
1136 if (aDocShell) {
1137 MOZ_ASSERT(!mDocShell, "Should not overwrite an existing value!");
1139 mDocShell = aDocShell;
1141 // By default, do not allow DNS prefetch, so we don't break our frozen
1142 // API. Embeddors who decide to enable it should do so manually.
1143 mDocShell->SetAllowDNSPrefetch(false);
1144 } else {
1145 if (mDocShellTreeOwner) {
1146 mDocShellTreeOwner->RemoveFromWatcher(); // evil twin of Add in Create()
1148 if (mDocShell) {
1149 mDocShell->Destroy();
1151 if (!mWillChangeProcess && mDocShell) {
1152 mDocShell->GetBrowsingContext()->Detach(/* aFromIPC */ true);
1155 mDocShell = nullptr;
1159 void nsWebBrowser::EnsureDocShellTreeOwner() {
1160 if (mDocShellTreeOwner) {
1161 return;
1164 mDocShellTreeOwner = new nsDocShellTreeOwner();
1165 mDocShellTreeOwner->WebBrowser(this);
1168 void nsWebBrowser::WindowActivated() {
1169 #if defined(DEBUG_smaug)
1170 RefPtr<dom::Document> document = mDocShell->GetDocument();
1171 nsAutoString documentURI;
1172 document->GetDocumentURI(documentURI);
1173 printf("nsWebBrowser::NS_ACTIVATE %p %s\n", (void*)this,
1174 NS_ConvertUTF16toUTF8(documentURI).get());
1175 #endif
1176 FocusActivate(nsFocusManager::GenerateFocusActionId());
1179 void nsWebBrowser::WindowDeactivated() {
1180 #if defined(DEBUG_smaug)
1181 RefPtr<dom::Document> document = mDocShell->GetDocument();
1182 nsAutoString documentURI;
1183 document->GetDocumentURI(documentURI);
1184 printf("nsWebBrowser::NS_DEACTIVATE %p %s\n", (void*)this,
1185 NS_ConvertUTF16toUTF8(documentURI).get());
1186 #endif
1187 FocusDeactivate(nsFocusManager::GenerateFocusActionId());
1190 bool nsWebBrowser::PaintWindow(nsIWidget* aWidget,
1191 LayoutDeviceIntRegion aRegion) {
1192 WindowRenderer* renderer = aWidget->GetWindowRenderer();
1193 NS_ASSERTION(renderer, "Must be in paint event");
1194 if (FallbackRenderer* fallback = renderer->AsFallback()) {
1195 if (fallback->BeginTransaction()) {
1196 fallback->EndTransactionWithColor(aRegion.GetBounds().ToUnknownRect(),
1197 ToDeviceColor(mBackgroundColor));
1199 return true;
1201 return false;
1204 void nsWebBrowser::FocusActivate(uint64_t aActionId) {
1205 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
1206 if (nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow()) {
1207 fm->WindowRaised(window, aActionId);
1212 void nsWebBrowser::FocusDeactivate(uint64_t aActionId) {
1213 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
1214 if (nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow()) {
1215 fm->WindowLowered(window, aActionId);
1220 void nsWebBrowser::SetWillChangeProcess() {
1221 mWillChangeProcess = true;
1222 if (mDocShell) {
1223 nsDocShell::Cast(mDocShell)->SetWillChangeProcess();
1227 void nsWebBrowser::WidgetListenerDelegate::WindowActivated() {
1228 RefPtr<nsWebBrowser> holder = mWebBrowser;
1229 holder->WindowActivated();
1232 void nsWebBrowser::WidgetListenerDelegate::WindowDeactivated() {
1233 RefPtr<nsWebBrowser> holder = mWebBrowser;
1234 holder->WindowDeactivated();
1237 bool nsWebBrowser::WidgetListenerDelegate::PaintWindow(
1238 nsIWidget* aWidget, mozilla::LayoutDeviceIntRegion aRegion) {
1239 RefPtr<nsWebBrowser> holder = mWebBrowser;
1240 return holder->PaintWindow(aWidget, aRegion);