Bug 1943650 - Command-line --help output misformatted after --dbus-service. r=emilio
[gecko.git] / toolkit / components / browser / nsWebBrowser.cpp
blob17cc7a6bbbac2eb90b7f022ba81035c2de811f19
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 mProgressListener(nullptr),
63 mWidgetListenerDelegate(this),
64 mBackgroundColor(0),
65 mPersistCurrentState(nsIWebBrowserPersist::PERSIST_STATE_READY),
66 mPersistResult(NS_OK),
67 mPersistFlags(nsIWebBrowserPersist::PERSIST_FLAGS_NONE),
68 mParentWidget(nullptr) {
69 mWWatch = do_GetService(NS_WINDOWWATCHER_CONTRACTID);
70 NS_ASSERTION(mWWatch, "failed to get WindowWatcher");
73 nsWebBrowser::~nsWebBrowser() { InternalDestroy(); }
75 nsIWidget* nsWebBrowser::EnsureWidget() {
76 if (mParentWidget) {
77 return mParentWidget;
80 mInternalWidget = nsIWidget::CreateChildWindow();
81 if (NS_WARN_IF(!mInternalWidget)) {
82 return nullptr;
85 widget::InitData widgetInit;
86 widgetInit.mClipChildren = true;
87 widgetInit.mWindowType = widget::WindowType::Child;
88 LayoutDeviceIntRect bounds(0, 0, 0, 0);
90 mInternalWidget->SetWidgetListener(&mWidgetListenerDelegate);
91 NS_ENSURE_SUCCESS(mInternalWidget->Create(mParentWidget, bounds, &widgetInit),
92 nullptr);
94 return mInternalWidget;
97 /* static */
98 already_AddRefed<nsWebBrowser> nsWebBrowser::Create(
99 nsIWebBrowserChrome* aContainerWindow, nsIWidget* aParentWidget,
100 dom::BrowsingContext* aBrowsingContext,
101 dom::WindowGlobalChild* aInitialWindowChild) {
102 MOZ_ASSERT_IF(aInitialWindowChild,
103 aInitialWindowChild->BrowsingContext() == aBrowsingContext);
105 RefPtr<nsWebBrowser> browser = new nsWebBrowser(
106 aBrowsingContext->IsContent() ? typeContentWrapper : typeChromeWrapper);
108 // nsWebBrowser::SetContainer also calls nsWebBrowser::EnsureDocShellTreeOwner
109 NS_ENSURE_SUCCESS(browser->SetContainerWindow(aContainerWindow), nullptr);
110 NS_ENSURE_SUCCESS(browser->SetParentWidget(aParentWidget), nullptr);
112 nsCOMPtr<nsIWidget> docShellParentWidget = browser->EnsureWidget();
113 if (NS_WARN_IF(!docShellParentWidget)) {
114 return nullptr;
117 uint64_t outerWindowId =
118 aInitialWindowChild ? aInitialWindowChild->OuterWindowId() : 0;
120 RefPtr<nsDocShell> docShell =
121 nsDocShell::Create(aBrowsingContext, outerWindowId);
122 if (NS_WARN_IF(!docShell)) {
123 return nullptr;
125 browser->SetDocShell(docShell);
126 MOZ_ASSERT(browser->mDocShell == docShell);
128 // get the system default window background colour
130 // TODO(emilio): Can we get the color-scheme from somewhere here?
131 browser->mBackgroundColor =
132 LookAndFeel::Color(LookAndFeel::ColorID::Window, ColorScheme::Light,
133 LookAndFeel::UseStandins::No);
135 // HACK ALERT - this registration registers the nsDocShellTreeOwner as a
136 // nsIWebBrowserListener so it can setup its MouseListener in one of the
137 // progress callbacks. If we can register the MouseListener another way, this
138 // registration can go away, and nsDocShellTreeOwner can stop implementing
139 // nsIWebProgressListener.
140 RefPtr<nsDocShellTreeOwner> docShellTreeOwner = browser->mDocShellTreeOwner;
141 Unused << docShell->AddProgressListener(docShellTreeOwner,
142 nsIWebProgress::NOTIFY_ALL);
144 docShell->SetTreeOwner(docShellTreeOwner);
146 // If the webbrowser is a content docshell item then we won't hear any
147 // events from subframes. To solve that we install our own chrome event
148 // handler that always gets called (even for subframes) for any bubbling
149 // event.
150 nsresult rv = docShell->InitWindow(docShellParentWidget, 0, 0, 0, 0);
151 if (NS_WARN_IF(NS_FAILED(rv))) {
152 return nullptr;
155 docShellTreeOwner->AddToWatcher(); // evil twin of Remove in SetDocShell(0)
156 docShellTreeOwner->AddChromeListeners();
158 if (aInitialWindowChild) {
159 docShell->CreateDocumentViewerForActor(aInitialWindowChild);
162 return browser.forget();
165 void nsWebBrowser::InternalDestroy() {
166 if (mInternalWidget) {
167 mInternalWidget->SetWidgetListener(nullptr);
168 mInternalWidget->Destroy();
169 mInternalWidget = nullptr; // Force release here.
172 SetDocShell(nullptr);
174 if (mDocShellTreeOwner) {
175 mDocShellTreeOwner->WebBrowser(nullptr);
176 mDocShellTreeOwner = nullptr;
180 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsWebBrowser)
181 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsWebBrowser)
183 NS_IMPL_CYCLE_COLLECTION_WEAK(nsWebBrowser, mDocShell)
185 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsWebBrowser)
186 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowser)
187 NS_INTERFACE_MAP_ENTRY(nsIWebBrowser)
188 NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)
189 NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
190 NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)
191 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
192 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPersist)
193 NS_INTERFACE_MAP_ENTRY(nsICancelable)
194 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
195 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
196 NS_INTERFACE_MAP_END
198 ///*****************************************************************************
199 // nsWebBrowser::nsIInterfaceRequestor
200 //*****************************************************************************
202 NS_IMETHODIMP
203 nsWebBrowser::GetInterface(const nsIID& aIID, void** aSink) {
204 NS_ENSURE_ARG_POINTER(aSink);
206 if (NS_SUCCEEDED(QueryInterface(aIID, aSink))) {
207 return NS_OK;
210 if (mDocShell) {
211 #ifdef NS_PRINTING
212 if (aIID.Equals(NS_GET_IID(nsIWebBrowserPrint))) {
213 nsCOMPtr<nsIDocumentViewer> viewer;
214 mDocShell->GetDocViewer(getter_AddRefs(viewer));
215 if (!viewer) {
216 return NS_NOINTERFACE;
219 nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint(do_QueryInterface(viewer));
220 nsIWebBrowserPrint* print = (nsIWebBrowserPrint*)webBrowserPrint.get();
221 NS_ASSERTION(print, "This MUST support this interface!");
222 NS_ADDREF(print);
223 *aSink = print;
224 return NS_OK;
226 #endif
227 return mDocShell->GetInterface(aIID, aSink);
230 return NS_NOINTERFACE;
233 //*****************************************************************************
234 // nsWebBrowser::nsIWebBrowser
235 //*****************************************************************************
237 NS_IMETHODIMP
238 nsWebBrowser::GetContainerWindow(nsIWebBrowserChrome** aTopWindow) {
239 NS_ENSURE_ARG_POINTER(aTopWindow);
241 nsCOMPtr<nsIWebBrowserChrome> top;
242 if (mDocShellTreeOwner) {
243 top = mDocShellTreeOwner->GetWebBrowserChrome();
246 top.forget(aTopWindow);
248 return NS_OK;
251 NS_IMETHODIMP
252 nsWebBrowser::SetContainerWindow(nsIWebBrowserChrome* aTopWindow) {
253 EnsureDocShellTreeOwner();
254 return mDocShellTreeOwner->SetWebBrowserChrome(aTopWindow);
257 NS_IMETHODIMP
258 nsWebBrowser::GetContentDOMWindow(mozIDOMWindowProxy** aResult) {
259 if (!mDocShell) {
260 return NS_ERROR_UNEXPECTED;
263 nsCOMPtr<nsPIDOMWindowOuter> retval = mDocShell->GetWindow();
264 retval.forget(aResult);
265 return *aResult ? NS_OK : NS_ERROR_FAILURE;
268 void nsWebBrowser::SetOriginAttributes(const OriginAttributes& aAttrs) {
269 mOriginAttributes = aAttrs;
272 //*****************************************************************************
273 // nsWebBrowser::nsIDocShellTreeItem
274 //*****************************************************************************
276 NS_IMETHODIMP
277 nsWebBrowser::GetName(nsAString& aName) {
278 if (mDocShell) {
279 mDocShell->GetName(aName);
282 return NS_OK;
285 NS_IMETHODIMP
286 nsWebBrowser::SetName(const nsAString& aName) {
287 if (mDocShell) {
288 return mDocShell->SetName(aName);
291 return NS_OK;
294 NS_IMETHODIMP
295 nsWebBrowser::NameEquals(const nsAString& aName, bool* aResult) {
296 NS_ENSURE_ARG_POINTER(aResult);
297 if (mDocShell) {
298 return mDocShell->NameEquals(aName, aResult);
301 return NS_OK;
304 /* virtual */
305 int32_t nsWebBrowser::ItemType() { return mContentType; }
307 NS_IMETHODIMP
308 nsWebBrowser::GetItemType(int32_t* aItemType) {
309 NS_ENSURE_ARG_POINTER(aItemType);
311 *aItemType = ItemType();
312 return NS_OK;
315 NS_IMETHODIMP
316 nsWebBrowser::GetInProcessParent(nsIDocShellTreeItem** aParent) {
317 *aParent = nullptr;
318 return NS_OK;
321 NS_IMETHODIMP
322 nsWebBrowser::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) {
323 *aParent = nullptr;
325 return NS_OK;
328 NS_IMETHODIMP
329 nsWebBrowser::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) {
330 NS_ENSURE_ARG_POINTER(aRootTreeItem);
331 *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
333 nsCOMPtr<nsIDocShellTreeItem> parent;
334 NS_ENSURE_SUCCESS(GetInProcessParent(getter_AddRefs(parent)),
335 NS_ERROR_FAILURE);
336 while (parent) {
337 *aRootTreeItem = parent;
338 NS_ENSURE_SUCCESS(
339 (*aRootTreeItem)->GetInProcessParent(getter_AddRefs(parent)),
340 NS_ERROR_FAILURE);
342 NS_ADDREF(*aRootTreeItem);
343 return NS_OK;
346 NS_IMETHODIMP
347 nsWebBrowser::GetInProcessSameTypeRootTreeItem(
348 nsIDocShellTreeItem** aRootTreeItem) {
349 NS_ENSURE_ARG_POINTER(aRootTreeItem);
350 *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
352 nsCOMPtr<nsIDocShellTreeItem> parent;
353 NS_ENSURE_SUCCESS(GetInProcessSameTypeParent(getter_AddRefs(parent)),
354 NS_ERROR_FAILURE);
355 while (parent) {
356 *aRootTreeItem = parent;
357 NS_ENSURE_SUCCESS(
358 (*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent)),
359 NS_ERROR_FAILURE);
361 NS_ADDREF(*aRootTreeItem);
362 return NS_OK;
365 dom::Document* nsWebBrowser::GetDocument() {
366 return mDocShell ? mDocShell->GetDocument() : nullptr;
369 nsPIDOMWindowOuter* nsWebBrowser::GetWindow() {
370 return mDocShell ? mDocShell->GetWindow() : nullptr;
373 NS_IMETHODIMP
374 nsWebBrowser::GetBrowsingContextXPCOM(dom::BrowsingContext** aBrowsingContext) {
375 NS_ENSURE_STATE(mDocShell);
376 return mDocShell->GetBrowsingContextXPCOM(aBrowsingContext);
379 dom::BrowsingContext* nsWebBrowser::GetBrowsingContext() {
380 return mDocShell->GetBrowsingContext();
383 NS_IMETHODIMP
384 nsWebBrowser::GetDomWindow(mozIDOMWindowProxy** aWindow) {
385 if (!mDocShell) return NS_ERROR_NOT_INITIALIZED;
386 return mDocShell->GetDomWindow(aWindow);
389 NS_IMETHODIMP
390 nsWebBrowser::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) {
391 NS_ENSURE_ARG_POINTER(aTreeOwner);
392 *aTreeOwner = nullptr;
393 if (mDocShellTreeOwner) {
394 if (mDocShellTreeOwner->mTreeOwner) {
395 *aTreeOwner = mDocShellTreeOwner->mTreeOwner;
396 } else {
397 *aTreeOwner = mDocShellTreeOwner;
400 NS_IF_ADDREF(*aTreeOwner);
401 return NS_OK;
404 NS_IMETHODIMP
405 nsWebBrowser::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) {
406 EnsureDocShellTreeOwner();
407 return mDocShellTreeOwner->SetTreeOwner(aTreeOwner);
410 //*****************************************************************************
411 // nsWebBrowser::nsIDocShellTreeItem
412 //*****************************************************************************
414 NS_IMETHODIMP
415 nsWebBrowser::GetInProcessChildCount(int32_t* aChildCount) {
416 NS_ENSURE_ARG_POINTER(aChildCount);
417 *aChildCount = 0;
418 return NS_OK;
421 NS_IMETHODIMP
422 nsWebBrowser::AddChild(nsIDocShellTreeItem* aChild) {
423 return NS_ERROR_UNEXPECTED;
426 NS_IMETHODIMP
427 nsWebBrowser::RemoveChild(nsIDocShellTreeItem* aChild) {
428 return NS_ERROR_UNEXPECTED;
431 NS_IMETHODIMP
432 nsWebBrowser::GetInProcessChildAt(int32_t aIndex,
433 nsIDocShellTreeItem** aChild) {
434 return NS_ERROR_UNEXPECTED;
437 //*****************************************************************************
438 // nsWebBrowser::nsIWebNavigation
439 //*****************************************************************************
441 NS_IMETHODIMP
442 nsWebBrowser::GetCanGoBack(bool* aCanGoBack) {
443 NS_ENSURE_STATE(mDocShell);
445 return mDocShell->GetCanGoBack(aCanGoBack);
448 NS_IMETHODIMP
449 nsWebBrowser::GetCanGoBackIgnoringUserInteraction(bool* aCanGoBack) {
450 NS_ENSURE_STATE(mDocShell);
452 return mDocShell->GetCanGoBackIgnoringUserInteraction(aCanGoBack);
455 NS_IMETHODIMP
456 nsWebBrowser::GetCanGoForward(bool* aCanGoForward) {
457 NS_ENSURE_STATE(mDocShell);
459 return mDocShell->GetCanGoForward(aCanGoForward);
462 NS_IMETHODIMP
463 nsWebBrowser::GoBack(bool aRequireUserInteraction, bool aUserActivation) {
464 NS_ENSURE_STATE(mDocShell);
466 RefPtr<nsDocShell> docShell = mDocShell;
467 return docShell->GoBack(aRequireUserInteraction, aUserActivation);
470 NS_IMETHODIMP
471 nsWebBrowser::GoForward(bool aRequireUserInteraction, bool aUserActivation) {
472 NS_ENSURE_STATE(mDocShell);
474 RefPtr<nsDocShell> docShell = mDocShell;
475 return docShell->GoForward(aRequireUserInteraction, aUserActivation);
478 nsresult nsWebBrowser::LoadURI(nsIURI* aURI,
479 const dom::LoadURIOptions& aLoadURIOptions) {
480 #ifndef ANDROID
481 MOZ_ASSERT(aLoadURIOptions.mTriggeringPrincipal,
482 "nsWebBrowser::LoadURI - Need a valid triggeringPrincipal");
483 #endif
484 NS_ENSURE_STATE(mDocShell);
486 RefPtr<nsDocShell> docShell = mDocShell;
487 return docShell->LoadURI(aURI, aLoadURIOptions);
490 NS_IMETHODIMP
491 nsWebBrowser::LoadURIFromScript(nsIURI* aURI,
492 JS::Handle<JS::Value> aLoadURIOptions,
493 JSContext* aCx) {
494 // generate dictionary for loadURIOptions and forward call
495 dom::LoadURIOptions loadURIOptions;
496 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
497 return NS_ERROR_INVALID_ARG;
499 return LoadURI(aURI, loadURIOptions);
502 nsresult nsWebBrowser::FixupAndLoadURIString(
503 const nsAString& aURI, const dom::LoadURIOptions& aLoadURIOptions) {
504 #ifndef ANDROID
505 MOZ_ASSERT(
506 aLoadURIOptions.mTriggeringPrincipal,
507 "nsWebBrowser::FixupAndLoadURIString - Need a valid triggeringPrincipal");
508 #endif
509 NS_ENSURE_STATE(mDocShell);
511 RefPtr<nsDocShell> docShell = mDocShell;
512 return docShell->FixupAndLoadURIString(aURI, aLoadURIOptions);
515 NS_IMETHODIMP
516 nsWebBrowser::FixupAndLoadURIStringFromScript(
517 const nsAString& aURI, JS::Handle<JS::Value> aLoadURIOptions,
518 JSContext* aCx) {
519 // generate dictionary for loadURIOptions and forward call
520 dom::LoadURIOptions loadURIOptions;
521 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
522 return NS_ERROR_INVALID_ARG;
524 return FixupAndLoadURIString(aURI, loadURIOptions);
527 NS_IMETHODIMP
528 nsWebBrowser::ResumeRedirectedLoad(uint64_t aIdentifier,
529 int32_t aHistoryIndex) {
530 NS_ENSURE_STATE(mDocShell);
532 return mDocShell->ResumeRedirectedLoad(aIdentifier, aHistoryIndex);
535 NS_IMETHODIMP
536 nsWebBrowser::Reload(uint32_t aReloadFlags) {
537 NS_ENSURE_STATE(mDocShell);
539 RefPtr<nsDocShell> docShell = mDocShell;
540 return docShell->Reload(aReloadFlags);
543 NS_IMETHODIMP
544 nsWebBrowser::GotoIndex(int32_t aIndex, bool aUserActivation) {
545 NS_ENSURE_STATE(mDocShell);
547 RefPtr<nsDocShell> docShell = mDocShell;
548 return docShell->GotoIndex(aIndex, aUserActivation);
551 NS_IMETHODIMP
552 nsWebBrowser::Stop(uint32_t aStopFlags) {
553 NS_ENSURE_STATE(mDocShell);
555 return mDocShell->Stop(aStopFlags);
558 NS_IMETHODIMP
559 nsWebBrowser::GetCurrentURI(nsIURI** aURI) {
560 NS_ENSURE_STATE(mDocShell);
562 return mDocShell->GetCurrentURI(aURI);
565 // XXX(nika): Consider making the mozilla::dom::ChildSHistory version the
566 // canonical one?
567 NS_IMETHODIMP
568 nsWebBrowser::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) {
569 NS_ENSURE_ARG_POINTER(aSessionHistory);
570 *aSessionHistory = nullptr;
571 if (mDocShell) {
572 return mDocShell->GetSessionHistoryXPCOM(aSessionHistory);
574 return NS_OK;
577 NS_IMETHODIMP
578 nsWebBrowser::GetDocument(dom::Document** aDocument) {
579 NS_ENSURE_STATE(mDocShell);
581 return mDocShell->GetDocument(aDocument);
584 void nsWebBrowser::SetAllowDNSPrefetch(bool aAllowPrefetch) {
585 MOZ_ASSERT(mDocShell);
586 mDocShell->SetAllowDNSPrefetch(aAllowPrefetch);
589 //*****************************************************************************
590 // nsWebBrowser::nsIWebProgressListener
591 //*****************************************************************************
593 NS_IMETHODIMP
594 nsWebBrowser::OnStateChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
595 uint32_t aStateFlags, nsresult aStatus) {
596 if (mPersist) {
597 mPersist->GetCurrentState(&mPersistCurrentState);
599 if (aStateFlags & STATE_IS_NETWORK && aStateFlags & STATE_STOP) {
600 mPersist = nullptr;
602 if (mProgressListener) {
603 return mProgressListener->OnStateChange(aWebProgress, aRequest, aStateFlags,
604 aStatus);
606 return NS_OK;
609 NS_IMETHODIMP
610 nsWebBrowser::OnProgressChange(nsIWebProgress* aWebProgress,
611 nsIRequest* aRequest, int32_t aCurSelfProgress,
612 int32_t aMaxSelfProgress,
613 int32_t aCurTotalProgress,
614 int32_t aMaxTotalProgress) {
615 if (mPersist) {
616 mPersist->GetCurrentState(&mPersistCurrentState);
618 if (mProgressListener) {
619 return mProgressListener->OnProgressChange(
620 aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress,
621 aCurTotalProgress, aMaxTotalProgress);
623 return NS_OK;
626 NS_IMETHODIMP
627 nsWebBrowser::OnLocationChange(nsIWebProgress* aWebProgress,
628 nsIRequest* aRequest, nsIURI* aLocation,
629 uint32_t aFlags) {
630 if (mProgressListener) {
631 return mProgressListener->OnLocationChange(aWebProgress, aRequest,
632 aLocation, aFlags);
634 return NS_OK;
637 NS_IMETHODIMP
638 nsWebBrowser::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
639 nsresult aStatus, const char16_t* aMessage) {
640 if (mProgressListener) {
641 return mProgressListener->OnStatusChange(aWebProgress, aRequest, aStatus,
642 aMessage);
644 return NS_OK;
647 NS_IMETHODIMP
648 nsWebBrowser::OnSecurityChange(nsIWebProgress* aWebProgress,
649 nsIRequest* aRequest, uint32_t aState) {
650 if (mProgressListener) {
651 return mProgressListener->OnSecurityChange(aWebProgress, aRequest, aState);
653 return NS_OK;
656 NS_IMETHODIMP
657 nsWebBrowser::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
658 nsIRequest* aRequest, uint32_t aEvent) {
659 if (mProgressListener) {
660 return mProgressListener->OnContentBlockingEvent(aWebProgress, aRequest,
661 aEvent);
663 return NS_OK;
666 //*****************************************************************************
667 // nsWebBrowser::nsIWebBrowserPersist
668 //*****************************************************************************
670 NS_IMETHODIMP
671 nsWebBrowser::GetPersistFlags(uint32_t* aPersistFlags) {
672 NS_ENSURE_ARG_POINTER(aPersistFlags);
673 nsresult rv = NS_OK;
674 if (mPersist) {
675 rv = mPersist->GetPersistFlags(&mPersistFlags);
677 *aPersistFlags = mPersistFlags;
678 return rv;
681 NS_IMETHODIMP
682 nsWebBrowser::SetPersistFlags(uint32_t aPersistFlags) {
683 nsresult rv = NS_OK;
684 mPersistFlags = aPersistFlags;
685 if (mPersist) {
686 rv = mPersist->SetPersistFlags(mPersistFlags);
687 mPersist->GetPersistFlags(&mPersistFlags);
689 return rv;
692 NS_IMETHODIMP
693 nsWebBrowser::GetCurrentState(uint32_t* aCurrentState) {
694 NS_ENSURE_ARG_POINTER(aCurrentState);
695 if (mPersist) {
696 mPersist->GetCurrentState(&mPersistCurrentState);
698 *aCurrentState = mPersistCurrentState;
699 return NS_OK;
702 NS_IMETHODIMP
703 nsWebBrowser::GetResult(nsresult* aResult) {
704 NS_ENSURE_ARG_POINTER(aResult);
705 if (mPersist) {
706 mPersist->GetResult(&mPersistResult);
708 *aResult = mPersistResult;
709 return NS_OK;
712 NS_IMETHODIMP
713 nsWebBrowser::GetProgressListener(nsIWebProgressListener** aProgressListener) {
714 NS_ENSURE_ARG_POINTER(aProgressListener);
715 *aProgressListener = mProgressListener;
716 NS_IF_ADDREF(*aProgressListener);
717 return NS_OK;
720 NS_IMETHODIMP
721 nsWebBrowser::SetProgressListener(nsIWebProgressListener* aProgressListener) {
722 mProgressListener = aProgressListener;
723 return NS_OK;
726 NS_IMETHODIMP
727 nsWebBrowser::SaveURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
728 uint32_t aCacheKey, nsIReferrerInfo* aReferrerInfo,
729 nsICookieJarSettings* aCookieJarSettings,
730 nsIInputStream* aPostData, const char* aExtraHeaders,
731 nsISupports* aFile,
732 nsContentPolicyType aContentPolicyType, bool aIsPrivate) {
733 if (mPersist) {
734 uint32_t currentState;
735 mPersist->GetCurrentState(&currentState);
736 if (currentState == PERSIST_STATE_FINISHED) {
737 mPersist = nullptr;
738 } else {
739 // You can't save again until the last save has completed
740 return NS_ERROR_FAILURE;
744 nsCOMPtr<nsIURI> uri;
745 if (aURI) {
746 uri = aURI;
747 } else {
748 nsresult rv = GetCurrentURI(getter_AddRefs(uri));
749 if (NS_FAILED(rv)) {
750 return NS_ERROR_FAILURE;
754 // Create a throwaway persistence object to do the work
755 nsresult rv;
756 mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv);
757 NS_ENSURE_SUCCESS(rv, rv);
758 mPersist->SetProgressListener(this);
759 mPersist->SetPersistFlags(mPersistFlags);
760 mPersist->GetCurrentState(&mPersistCurrentState);
762 rv = mPersist->SaveURI(uri, aPrincipal, aCacheKey, aReferrerInfo,
763 aCookieJarSettings, aPostData, aExtraHeaders, aFile,
764 aContentPolicyType, aIsPrivate);
765 if (NS_FAILED(rv)) {
766 mPersist = nullptr;
768 return rv;
771 NS_IMETHODIMP
772 nsWebBrowser::SaveChannel(nsIChannel* aChannel, nsISupports* aFile) {
773 if (mPersist) {
774 uint32_t currentState;
775 mPersist->GetCurrentState(&currentState);
776 if (currentState == PERSIST_STATE_FINISHED) {
777 mPersist = nullptr;
778 } else {
779 // You can't save again until the last save has completed
780 return NS_ERROR_FAILURE;
784 // Create a throwaway persistence object to do the work
785 nsresult rv;
786 mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv);
787 NS_ENSURE_SUCCESS(rv, rv);
788 mPersist->SetProgressListener(this);
789 mPersist->SetPersistFlags(mPersistFlags);
790 mPersist->GetCurrentState(&mPersistCurrentState);
791 rv = mPersist->SaveChannel(aChannel, aFile);
792 if (NS_FAILED(rv)) {
793 mPersist = nullptr;
795 return rv;
798 NS_IMETHODIMP
799 nsWebBrowser::SaveDocument(nsISupports* aDocumentish, nsISupports* aFile,
800 nsISupports* aDataPath,
801 const char* aOutputContentType,
802 uint32_t aEncodingFlags, uint32_t aWrapColumn) {
803 if (mPersist) {
804 uint32_t currentState;
805 mPersist->GetCurrentState(&currentState);
806 if (currentState == PERSIST_STATE_FINISHED) {
807 mPersist = nullptr;
808 } else {
809 // You can't save again until the last save has completed
810 return NS_ERROR_FAILURE;
814 // Use the specified DOM document, or if none is specified, the one
815 // attached to the web browser.
817 nsCOMPtr<nsISupports> doc;
818 if (aDocumentish) {
819 doc = aDocumentish;
820 } else {
821 RefPtr<dom::Document> domDoc;
822 GetDocument(getter_AddRefs(domDoc));
823 doc = already_AddRefed<nsISupports>(ToSupports(domDoc.forget().take()));
825 if (!doc) {
826 return NS_ERROR_FAILURE;
829 // Create a throwaway persistence object to do the work
830 nsresult rv;
831 mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv);
832 NS_ENSURE_SUCCESS(rv, rv);
833 RefPtr<nsIWebBrowserPersist> localPersist(mPersist);
834 Unused << localPersist;
835 mPersist->SetProgressListener(this);
836 mPersist->SetPersistFlags(mPersistFlags);
837 mPersist->GetCurrentState(&mPersistCurrentState);
838 rv = mPersist->SaveDocument(doc, aFile, aDataPath, aOutputContentType,
839 aEncodingFlags, aWrapColumn);
840 if (NS_FAILED(rv)) {
841 mPersist = nullptr;
843 return rv;
846 NS_IMETHODIMP
847 nsWebBrowser::CancelSave() {
848 if (mPersist) {
849 return mPersist->CancelSave();
851 return NS_OK;
854 NS_IMETHODIMP
855 nsWebBrowser::Cancel(nsresult aReason) {
856 if (mPersist) {
857 return mPersist->Cancel(aReason);
859 return NS_OK;
862 //*****************************************************************************
863 // nsWebBrowser::nsIBaseWindow
864 //*****************************************************************************
866 NS_IMETHODIMP
867 nsWebBrowser::InitWindow(nsIWidget* aParentWidget, int32_t aX, int32_t aY,
868 int32_t aCX, int32_t aCY) {
869 // nsIBaseWindow::InitWindow and nsIBaseWindow::Create
870 // implementations have been merged into nsWebBrowser::Create
871 MOZ_DIAGNOSTIC_CRASH("Superceded by nsWebBrowser::Create()");
872 return NS_ERROR_NULL_POINTER;
875 NS_IMETHODIMP
876 nsWebBrowser::Destroy() {
877 InternalDestroy();
879 return NS_OK;
882 double nsWebBrowser::GetWidgetCSSToDeviceScale() {
883 return mParentWidget ? mParentWidget->GetDefaultScale().scale : 1.0;
886 NS_IMETHODIMP
887 nsWebBrowser::GetDevicePixelsPerDesktopPixel(double* aScale) {
888 *aScale =
889 mParentWidget ? mParentWidget->GetDesktopToDeviceScale().scale : 1.0;
890 return NS_OK;
893 NS_IMETHODIMP
894 nsWebBrowser::SetPositionDesktopPix(int32_t aX, int32_t aY) {
895 // XXX jfkthame
896 // It's not clear to me whether this will be fully correct across
897 // potential multi-screen, mixed-DPI configurations for all platforms;
898 // we might need to add code paths that make it possible to pass the
899 // desktop-pix parameters all the way through to the native widget,
900 // to avoid the risk of device-pixel coords mapping to the wrong
901 // display on OS X with mixed retina/non-retina screens.
902 double scale = 1.0;
903 GetDevicePixelsPerDesktopPixel(&scale);
904 return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
907 NS_IMETHODIMP
908 nsWebBrowser::SetPosition(int32_t aX, int32_t aY) {
909 int32_t cx = 0;
910 int32_t cy = 0;
912 GetSize(&cx, &cy);
914 return SetPositionAndSize(aX, aY, cx, cy, 0);
917 NS_IMETHODIMP
918 nsWebBrowser::GetPosition(int32_t* aX, int32_t* aY) {
919 return GetPositionAndSize(aX, aY, nullptr, nullptr);
922 NS_IMETHODIMP
923 nsWebBrowser::SetSize(int32_t aCX, int32_t aCY, bool aRepaint) {
924 int32_t x = 0;
925 int32_t y = 0;
927 GetPosition(&x, &y);
929 return SetPositionAndSize(x, y, aCX, aCY,
930 aRepaint ? nsIBaseWindow::eRepaint : 0);
933 NS_IMETHODIMP
934 nsWebBrowser::GetSize(int32_t* aCX, int32_t* aCY) {
935 return GetPositionAndSize(nullptr, nullptr, aCX, aCY);
938 NS_IMETHODIMP
939 nsWebBrowser::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aCX,
940 int32_t aCY, uint32_t aFlags) {
941 int32_t doc_x = aX;
942 int32_t doc_y = aY;
944 // If there is an internal widget we need to make the docShell coordinates
945 // relative to the internal widget rather than the calling app's parent.
946 // We also need to resize our widget then.
947 if (mInternalWidget) {
948 doc_x = doc_y = 0;
949 mInternalWidget->Resize(aX, aY, aCX, aCY,
950 !!(aFlags & nsIBaseWindow::eRepaint));
952 // Now reposition/ resize the doc
953 NS_ENSURE_SUCCESS(
954 mDocShell->SetPositionAndSize(doc_x, doc_y, aCX, aCY, aFlags),
955 NS_ERROR_FAILURE);
957 return NS_OK;
960 NS_IMETHODIMP
961 nsWebBrowser::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aCX,
962 int32_t* aCY) {
963 if (mInternalWidget) {
964 LayoutDeviceIntRect bounds = mInternalWidget->GetBounds();
966 if (aX) {
967 *aX = bounds.X();
969 if (aY) {
970 *aY = bounds.Y();
972 if (aCX) {
973 *aCX = bounds.Width();
975 if (aCY) {
976 *aCY = bounds.Height();
978 return NS_OK;
981 // Can directly return this as it is the
982 // same interface, thus same returns.
983 return mDocShell->GetPositionAndSize(aX, aY, aCX, aCY);
986 NS_IMETHODIMP
987 nsWebBrowser::SetDimensions(DimensionRequest&& aRequest) {
988 return NS_ERROR_NOT_IMPLEMENTED;
991 NS_IMETHODIMP
992 nsWebBrowser::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
993 int32_t* aY, int32_t* aCX, int32_t* aCY) {
994 return NS_ERROR_NOT_IMPLEMENTED;
997 NS_IMETHODIMP
998 nsWebBrowser::Repaint(bool aForce) {
999 NS_ENSURE_STATE(mDocShell);
1000 // Can directly return this as it is the
1001 // same interface, thus same returns.
1002 return mDocShell->Repaint(aForce);
1005 NS_IMETHODIMP
1006 nsWebBrowser::GetParentWidget(nsIWidget** aParentWidget) {
1007 NS_ENSURE_ARG_POINTER(aParentWidget);
1009 *aParentWidget = mParentWidget;
1011 NS_IF_ADDREF(*aParentWidget);
1013 return NS_OK;
1016 NS_IMETHODIMP
1017 nsWebBrowser::SetParentWidget(nsIWidget* aParentWidget) {
1018 NS_ENSURE_STATE(!mDocShell);
1019 mParentWidget = aParentWidget;
1020 return NS_OK;
1023 NS_IMETHODIMP
1024 nsWebBrowser::GetNativeHandle(nsAString& aNativeHandle) {
1025 // the nativeHandle should be accessed from nsIAppWindow
1026 return NS_ERROR_NOT_IMPLEMENTED;
1029 NS_IMETHODIMP
1030 nsWebBrowser::GetVisibility(bool* aVisibility) {
1031 NS_ENSURE_ARG_POINTER(aVisibility);
1033 if (mDocShell) {
1034 NS_ENSURE_SUCCESS(mDocShell->GetVisibility(aVisibility), NS_ERROR_FAILURE);
1037 return NS_OK;
1040 NS_IMETHODIMP
1041 nsWebBrowser::SetVisibility(bool aVisibility) {
1042 if (mDocShell) {
1043 NS_ENSURE_SUCCESS(mDocShell->SetVisibility(aVisibility), NS_ERROR_FAILURE);
1044 if (mInternalWidget) {
1045 mInternalWidget->Show(aVisibility);
1049 return NS_OK;
1052 NS_IMETHODIMP
1053 nsWebBrowser::GetEnabled(bool* aEnabled) {
1054 if (mInternalWidget) {
1055 *aEnabled = mInternalWidget->IsEnabled();
1056 return NS_OK;
1059 return NS_ERROR_FAILURE;
1062 NS_IMETHODIMP
1063 nsWebBrowser::SetEnabled(bool aEnabled) {
1064 if (mInternalWidget) {
1065 mInternalWidget->Enable(aEnabled);
1066 return NS_OK;
1068 return NS_ERROR_FAILURE;
1071 NS_IMETHODIMP
1072 nsWebBrowser::GetMainWidget(nsIWidget** aMainWidget) {
1073 NS_ENSURE_ARG_POINTER(aMainWidget);
1075 if (mInternalWidget) {
1076 *aMainWidget = mInternalWidget;
1077 } else {
1078 *aMainWidget = mParentWidget;
1081 NS_IF_ADDREF(*aMainWidget);
1083 return NS_OK;
1086 NS_IMETHODIMP
1087 nsWebBrowser::GetTitle(nsAString& aTitle) {
1088 NS_ENSURE_STATE(mDocShell);
1090 NS_ENSURE_SUCCESS(mDocShell->GetTitle(aTitle), NS_ERROR_FAILURE);
1092 return NS_OK;
1095 NS_IMETHODIMP
1096 nsWebBrowser::SetTitle(const nsAString& aTitle) {
1097 NS_ENSURE_STATE(mDocShell);
1099 NS_ENSURE_SUCCESS(mDocShell->SetTitle(aTitle), NS_ERROR_FAILURE);
1101 return NS_OK;
1104 //*****************************************************************************
1105 // nsWebBrowser: Listener Helpers
1106 //*****************************************************************************
1108 void nsWebBrowser::SetDocShell(nsDocShell* aDocShell) {
1109 // We need to keep the docshell alive while we perform the changes, but we
1110 // don't need to call any methods on it.
1111 nsCOMPtr<nsIDocShell> kungFuDeathGrip(mDocShell);
1112 mozilla::Unused << kungFuDeathGrip;
1114 if (aDocShell) {
1115 MOZ_ASSERT(!mDocShell, "Should not overwrite an existing value!");
1117 mDocShell = aDocShell;
1119 // By default, do not allow DNS prefetch, so we don't break our frozen
1120 // API. Embeddors who decide to enable it should do so manually.
1121 mDocShell->SetAllowDNSPrefetch(false);
1122 } else {
1123 if (mDocShellTreeOwner) {
1124 mDocShellTreeOwner->RemoveFromWatcher(); // evil twin of Add in Create()
1126 if (mDocShell) {
1127 mDocShell->Destroy();
1129 if (!mWillChangeProcess && mDocShell) {
1130 mDocShell->GetBrowsingContext()->Detach(/* aFromIPC */ true);
1133 mDocShell = nullptr;
1137 void nsWebBrowser::EnsureDocShellTreeOwner() {
1138 if (mDocShellTreeOwner) {
1139 return;
1142 mDocShellTreeOwner = new nsDocShellTreeOwner();
1143 mDocShellTreeOwner->WebBrowser(this);
1146 void nsWebBrowser::WindowActivated() {
1147 #if defined(DEBUG_smaug)
1148 RefPtr<dom::Document> document = mDocShell->GetDocument();
1149 nsAutoString documentURI;
1150 document->GetDocumentURI(documentURI);
1151 printf("nsWebBrowser::NS_ACTIVATE %p %s\n", (void*)this,
1152 NS_ConvertUTF16toUTF8(documentURI).get());
1153 #endif
1154 FocusActivate(nsFocusManager::GenerateFocusActionId());
1157 void nsWebBrowser::WindowDeactivated() {
1158 #if defined(DEBUG_smaug)
1159 RefPtr<dom::Document> document = mDocShell->GetDocument();
1160 nsAutoString documentURI;
1161 document->GetDocumentURI(documentURI);
1162 printf("nsWebBrowser::NS_DEACTIVATE %p %s\n", (void*)this,
1163 NS_ConvertUTF16toUTF8(documentURI).get());
1164 #endif
1165 FocusDeactivate(nsFocusManager::GenerateFocusActionId());
1168 bool nsWebBrowser::PaintWindow(nsIWidget* aWidget,
1169 LayoutDeviceIntRegion aRegion) {
1170 WindowRenderer* renderer = aWidget->GetWindowRenderer();
1171 NS_ASSERTION(renderer, "Must be in paint event");
1172 if (FallbackRenderer* fallback = renderer->AsFallback()) {
1173 if (fallback->BeginTransaction()) {
1174 fallback->EndTransactionWithColor(aRegion.GetBounds().ToUnknownRect(),
1175 ToDeviceColor(mBackgroundColor));
1177 return true;
1179 return false;
1182 void nsWebBrowser::FocusActivate(uint64_t aActionId) {
1183 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
1184 if (nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow()) {
1185 fm->WindowRaised(window, aActionId);
1190 void nsWebBrowser::FocusDeactivate(uint64_t aActionId) {
1191 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
1192 if (nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow()) {
1193 fm->WindowLowered(window, aActionId);
1198 void nsWebBrowser::SetWillChangeProcess() {
1199 mWillChangeProcess = true;
1200 if (mDocShell) {
1201 nsDocShell::Cast(mDocShell)->SetWillChangeProcess();
1205 void nsWebBrowser::WidgetListenerDelegate::WindowActivated() {
1206 RefPtr<nsWebBrowser> holder = mWebBrowser;
1207 holder->WindowActivated();
1210 void nsWebBrowser::WidgetListenerDelegate::WindowDeactivated() {
1211 RefPtr<nsWebBrowser> holder = mWebBrowser;
1212 holder->WindowDeactivated();
1215 bool nsWebBrowser::WidgetListenerDelegate::PaintWindow(
1216 nsIWidget* aWidget, mozilla::LayoutDeviceIntRegion aRegion) {
1217 RefPtr<nsWebBrowser> holder = mWebBrowser;
1218 return holder->PaintWindow(aWidget, aRegion);