1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 // Local Includes
8 #include "nsWebBrowser.h"
9 
10 // Helper Classes
11 #include "nsGfxCIID.h"
12 #include "nsWidgetsCID.h"
13 
14 #include "gfxUtils.h"
15 #include "mozilla/gfx/2D.h"
16 
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 "Layers.h"
30 #include "nsILoadContext.h"
31 #include "nsComponentManagerUtils.h"
32 #include "nsDocShell.h"
33 #include "nsServiceManagerUtils.h"
34 
35 #include "mozilla/dom/Element.h"
36 #include "mozilla/dom/BrowsingContext.h"
37 #include "mozilla/dom/LoadURIOptionsBinding.h"
38 #include "mozilla/dom/WindowGlobalChild.h"
39 
40 // for painting the background window
41 #include "mozilla/LookAndFeel.h"
42 #include "mozilla/ServoStyleConsts.h"
43 
44 // Printing Includes
45 #ifdef NS_PRINTING
46 #  include "nsIWebBrowserPrint.h"
47 #  include "nsIContentViewer.h"
48 #endif
49 
50 // PSM2 includes
51 #include "nsISecureBrowserUI.h"
52 #include "nsXULAppAPI.h"
53 
54 using namespace mozilla;
55 using namespace mozilla::gfx;
56 using namespace mozilla::layers;
57 
nsWebBrowser(int aItemType)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");
72 }
73 
~nsWebBrowser()74 nsWebBrowser::~nsWebBrowser() { InternalDestroy(); }
75 
EnsureWidget()76 nsIWidget* nsWebBrowser::EnsureWidget() {
77   if (mParentWidget) {
78     return mParentWidget;
79   }
80 
81   mInternalWidget = nsIWidget::CreateChildWindow();
82   if (NS_WARN_IF(!mInternalWidget)) {
83     return nullptr;
84   }
85 
86   nsWidgetInitData widgetInit;
87   widgetInit.clipChildren = true;
88   widgetInit.mWindowType = eWindowType_child;
89   LayoutDeviceIntRect bounds(0, 0, 0, 0);
90 
91   mInternalWidget->SetWidgetListener(&mWidgetListenerDelegate);
92   NS_ENSURE_SUCCESS(mInternalWidget->Create(nullptr, mParentNativeWindow,
93                                             bounds, &widgetInit),
94                     nullptr);
95 
96   return mInternalWidget;
97 }
98 
99 /* static */
Create(nsIWebBrowserChrome * aContainerWindow,nsIWidget * aParentWidget,dom::BrowsingContext * aBrowsingContext,dom::WindowGlobalChild * aInitialWindowChild)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);
106 
107   RefPtr<nsWebBrowser> browser = new nsWebBrowser(
108       aBrowsingContext->IsContent() ? typeContentWrapper : typeChromeWrapper);
109 
110   // nsWebBrowser::SetContainer also calls nsWebBrowser::EnsureDocShellTreeOwner
111   NS_ENSURE_SUCCESS(browser->SetContainerWindow(aContainerWindow), nullptr);
112   NS_ENSURE_SUCCESS(browser->SetParentWidget(aParentWidget), nullptr);
113 
114   nsCOMPtr<nsIWidget> docShellParentWidget = browser->EnsureWidget();
115   if (NS_WARN_IF(!docShellParentWidget)) {
116     return nullptr;
117   }
118 
119   uint64_t outerWindowId =
120       aInitialWindowChild ? aInitialWindowChild->OuterWindowId() : 0;
121 
122   RefPtr<nsDocShell> docShell =
123       nsDocShell::Create(aBrowsingContext, outerWindowId);
124   if (NS_WARN_IF(!docShell)) {
125     return nullptr;
126   }
127   browser->SetDocShell(docShell);
128   MOZ_ASSERT(browser->mDocShell == docShell);
129 
130   // get the system default window background colour
131   //
132   // TODO(emilio): Can we get the color-scheme from somewhere here?
133   browser->mBackgroundColor = LookAndFeel::Color(
134       LookAndFeel::ColorID::WindowBackground, LookAndFeel::ColorScheme::Light,
135       LookAndFeel::UseStandins::No);
136 
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);
145 
146   docShell->SetTreeOwner(docShellTreeOwner);
147 
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.
152 
153   nsresult rv = docShell->InitWindow(nullptr, docShellParentWidget, 0, 0, 0, 0);
154   if (NS_WARN_IF(NS_FAILED(rv))) {
155     return nullptr;
156   }
157 
158   docShellTreeOwner->AddToWatcher();  // evil twin of Remove in SetDocShell(0)
159   docShellTreeOwner->AddChromeListeners();
160 
161   if (aInitialWindowChild) {
162     docShell->CreateContentViewerForActor(aInitialWindowChild);
163   }
164 
165   return browser.forget();
166 }
167 
InternalDestroy()168 void nsWebBrowser::InternalDestroy() {
169   if (mInternalWidget) {
170     mInternalWidget->SetWidgetListener(nullptr);
171     mInternalWidget->Destroy();
172     mInternalWidget = nullptr;  // Force release here.
173   }
174 
175   SetDocShell(nullptr);
176 
177   if (mDocShellTreeOwner) {
178     mDocShellTreeOwner->WebBrowser(nullptr);
179     mDocShellTreeOwner = nullptr;
180   }
181 }
182 
183 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsWebBrowser)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsWebBrowser)184 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsWebBrowser)
185 
186 NS_IMPL_CYCLE_COLLECTION_WEAK(nsWebBrowser, mDocShell)
187 
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
200 
201 ///*****************************************************************************
202 // nsWebBrowser::nsIInterfaceRequestor
203 //*****************************************************************************
204 
205 NS_IMETHODIMP
206 nsWebBrowser::GetInterface(const nsIID& aIID, void** aSink) {
207   NS_ENSURE_ARG_POINTER(aSink);
208 
209   if (NS_SUCCEEDED(QueryInterface(aIID, aSink))) {
210     return NS_OK;
211   }
212 
213   if (mDocShell) {
214 #ifdef NS_PRINTING
215     if (aIID.Equals(NS_GET_IID(nsIWebBrowserPrint))) {
216       nsCOMPtr<nsIContentViewer> viewer;
217       mDocShell->GetContentViewer(getter_AddRefs(viewer));
218       if (!viewer) {
219         return NS_NOINTERFACE;
220       }
221 
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;
228     }
229 #endif
230     return mDocShell->GetInterface(aIID, aSink);
231   }
232 
233   return NS_NOINTERFACE;
234 }
235 
236 //*****************************************************************************
237 // nsWebBrowser::nsIWebBrowser
238 //*****************************************************************************
239 
240 NS_IMETHODIMP
GetContainerWindow(nsIWebBrowserChrome ** aTopWindow)241 nsWebBrowser::GetContainerWindow(nsIWebBrowserChrome** aTopWindow) {
242   NS_ENSURE_ARG_POINTER(aTopWindow);
243 
244   nsCOMPtr<nsIWebBrowserChrome> top;
245   if (mDocShellTreeOwner) {
246     top = mDocShellTreeOwner->GetWebBrowserChrome();
247   }
248 
249   top.forget(aTopWindow);
250 
251   return NS_OK;
252 }
253 
254 NS_IMETHODIMP
SetContainerWindow(nsIWebBrowserChrome * aTopWindow)255 nsWebBrowser::SetContainerWindow(nsIWebBrowserChrome* aTopWindow) {
256   EnsureDocShellTreeOwner();
257   return mDocShellTreeOwner->SetWebBrowserChrome(aTopWindow);
258 }
259 
260 NS_IMETHODIMP
GetContentDOMWindow(mozIDOMWindowProxy ** aResult)261 nsWebBrowser::GetContentDOMWindow(mozIDOMWindowProxy** aResult) {
262   if (!mDocShell) {
263     return NS_ERROR_UNEXPECTED;
264   }
265 
266   nsCOMPtr<nsPIDOMWindowOuter> retval = mDocShell->GetWindow();
267   retval.forget(aResult);
268   return *aResult ? NS_OK : NS_ERROR_FAILURE;
269 }
270 
SetOriginAttributes(const OriginAttributes & aAttrs)271 void nsWebBrowser::SetOriginAttributes(const OriginAttributes& aAttrs) {
272   mOriginAttributes = aAttrs;
273 }
274 
275 //*****************************************************************************
276 // nsWebBrowser::nsIDocShellTreeItem
277 //*****************************************************************************
278 
279 NS_IMETHODIMP
GetName(nsAString & aName)280 nsWebBrowser::GetName(nsAString& aName) {
281   if (mDocShell) {
282     mDocShell->GetName(aName);
283   }
284 
285   return NS_OK;
286 }
287 
288 NS_IMETHODIMP
SetName(const nsAString & aName)289 nsWebBrowser::SetName(const nsAString& aName) {
290   if (mDocShell) {
291     return mDocShell->SetName(aName);
292   }
293 
294   return NS_OK;
295 }
296 
297 NS_IMETHODIMP
NameEquals(const nsAString & aName,bool * aResult)298 nsWebBrowser::NameEquals(const nsAString& aName, bool* aResult) {
299   NS_ENSURE_ARG_POINTER(aResult);
300   if (mDocShell) {
301     return mDocShell->NameEquals(aName, aResult);
302   }
303 
304   return NS_OK;
305 }
306 
307 /* virtual */
ItemType()308 int32_t nsWebBrowser::ItemType() { return mContentType; }
309 
310 NS_IMETHODIMP
GetItemType(int32_t * aItemType)311 nsWebBrowser::GetItemType(int32_t* aItemType) {
312   NS_ENSURE_ARG_POINTER(aItemType);
313 
314   *aItemType = ItemType();
315   return NS_OK;
316 }
317 
318 NS_IMETHODIMP
GetInProcessParent(nsIDocShellTreeItem ** aParent)319 nsWebBrowser::GetInProcessParent(nsIDocShellTreeItem** aParent) {
320   *aParent = nullptr;
321   return NS_OK;
322 }
323 
324 NS_IMETHODIMP
GetInProcessSameTypeParent(nsIDocShellTreeItem ** aParent)325 nsWebBrowser::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) {
326   *aParent = nullptr;
327 
328   return NS_OK;
329 }
330 
331 NS_IMETHODIMP
GetInProcessRootTreeItem(nsIDocShellTreeItem ** aRootTreeItem)332 nsWebBrowser::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) {
333   NS_ENSURE_ARG_POINTER(aRootTreeItem);
334   *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
335 
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);
344   }
345   NS_ADDREF(*aRootTreeItem);
346   return NS_OK;
347 }
348 
349 NS_IMETHODIMP
GetInProcessSameTypeRootTreeItem(nsIDocShellTreeItem ** aRootTreeItem)350 nsWebBrowser::GetInProcessSameTypeRootTreeItem(
351     nsIDocShellTreeItem** aRootTreeItem) {
352   NS_ENSURE_ARG_POINTER(aRootTreeItem);
353   *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
354 
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);
363   }
364   NS_ADDREF(*aRootTreeItem);
365   return NS_OK;
366 }
367 
GetDocument()368 dom::Document* nsWebBrowser::GetDocument() {
369   return mDocShell ? mDocShell->GetDocument() : nullptr;
370 }
371 
GetWindow()372 nsPIDOMWindowOuter* nsWebBrowser::GetWindow() {
373   return mDocShell ? mDocShell->GetWindow() : nullptr;
374 }
375 
376 NS_IMETHODIMP
GetBrowsingContextXPCOM(dom::BrowsingContext ** aBrowsingContext)377 nsWebBrowser::GetBrowsingContextXPCOM(dom::BrowsingContext** aBrowsingContext) {
378   NS_ENSURE_STATE(mDocShell);
379   return mDocShell->GetBrowsingContextXPCOM(aBrowsingContext);
380 }
381 
GetBrowsingContext()382 dom::BrowsingContext* nsWebBrowser::GetBrowsingContext() {
383   return mDocShell->GetBrowsingContext();
384 }
385 
386 NS_IMETHODIMP
GetDomWindow(mozIDOMWindowProxy ** aWindow)387 nsWebBrowser::GetDomWindow(mozIDOMWindowProxy** aWindow) {
388   if (!mDocShell) return NS_ERROR_NOT_INITIALIZED;
389   return mDocShell->GetDomWindow(aWindow);
390 }
391 
392 NS_IMETHODIMP
GetTreeOwner(nsIDocShellTreeOwner ** aTreeOwner)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;
401     }
402   }
403   NS_IF_ADDREF(*aTreeOwner);
404   return NS_OK;
405 }
406 
407 NS_IMETHODIMP
SetTreeOwner(nsIDocShellTreeOwner * aTreeOwner)408 nsWebBrowser::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) {
409   EnsureDocShellTreeOwner();
410   return mDocShellTreeOwner->SetTreeOwner(aTreeOwner);
411 }
412 
413 //*****************************************************************************
414 // nsWebBrowser::nsIDocShellTreeItem
415 //*****************************************************************************
416 
417 NS_IMETHODIMP
GetInProcessChildCount(int32_t * aChildCount)418 nsWebBrowser::GetInProcessChildCount(int32_t* aChildCount) {
419   NS_ENSURE_ARG_POINTER(aChildCount);
420   *aChildCount = 0;
421   return NS_OK;
422 }
423 
424 NS_IMETHODIMP
AddChild(nsIDocShellTreeItem * aChild)425 nsWebBrowser::AddChild(nsIDocShellTreeItem* aChild) {
426   return NS_ERROR_UNEXPECTED;
427 }
428 
429 NS_IMETHODIMP
RemoveChild(nsIDocShellTreeItem * aChild)430 nsWebBrowser::RemoveChild(nsIDocShellTreeItem* aChild) {
431   return NS_ERROR_UNEXPECTED;
432 }
433 
434 NS_IMETHODIMP
GetInProcessChildAt(int32_t aIndex,nsIDocShellTreeItem ** aChild)435 nsWebBrowser::GetInProcessChildAt(int32_t aIndex,
436                                   nsIDocShellTreeItem** aChild) {
437   return NS_ERROR_UNEXPECTED;
438 }
439 
440 //*****************************************************************************
441 // nsWebBrowser::nsIWebNavigation
442 //*****************************************************************************
443 
444 NS_IMETHODIMP
GetCanGoBack(bool * aCanGoBack)445 nsWebBrowser::GetCanGoBack(bool* aCanGoBack) {
446   NS_ENSURE_STATE(mDocShell);
447 
448   return mDocShell->GetCanGoBack(aCanGoBack);
449 }
450 
451 NS_IMETHODIMP
GetCanGoForward(bool * aCanGoForward)452 nsWebBrowser::GetCanGoForward(bool* aCanGoForward) {
453   NS_ENSURE_STATE(mDocShell);
454 
455   return mDocShell->GetCanGoForward(aCanGoForward);
456 }
457 
458 NS_IMETHODIMP
GoBack(bool aRequireUserInteraction,bool aUserActivation)459 nsWebBrowser::GoBack(bool aRequireUserInteraction, bool aUserActivation) {
460   NS_ENSURE_STATE(mDocShell);
461 
462   return mDocShell->GoBack(aRequireUserInteraction, aUserActivation);
463 }
464 
465 NS_IMETHODIMP
GoForward(bool aRequireUserInteraction,bool aUserActivation)466 nsWebBrowser::GoForward(bool aRequireUserInteraction, bool aUserActivation) {
467   NS_ENSURE_STATE(mDocShell);
468 
469   return mDocShell->GoForward(aRequireUserInteraction, aUserActivation);
470 }
471 
LoadURI(const nsAString & aURI,const dom::LoadURIOptions & aLoadURIOptions)472 nsresult nsWebBrowser::LoadURI(const nsAString& aURI,
473                                const dom::LoadURIOptions& aLoadURIOptions) {
474 #ifndef ANDROID
475   MOZ_ASSERT(aLoadURIOptions.mTriggeringPrincipal,
476              "nsWebBrowser::LoadURI - Need a valid triggeringPrincipal");
477 #endif
478   NS_ENSURE_STATE(mDocShell);
479 
480   return mDocShell->LoadURI(aURI, aLoadURIOptions);
481 }
482 
483 NS_IMETHODIMP
LoadURIFromScript(const nsAString & aURI,JS::Handle<JS::Value> aLoadURIOptions,JSContext * aCx)484 nsWebBrowser::LoadURIFromScript(const nsAString& aURI,
485                                 JS::Handle<JS::Value> aLoadURIOptions,
486                                 JSContext* aCx) {
487   // generate dictionary for loadURIOptions and forward call
488   dom::LoadURIOptions loadURIOptions;
489   if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
490     return NS_ERROR_INVALID_ARG;
491   }
492   return LoadURI(aURI, loadURIOptions);
493 }
494 
495 NS_IMETHODIMP
ResumeRedirectedLoad(uint64_t aIdentifier,int32_t aHistoryIndex)496 nsWebBrowser::ResumeRedirectedLoad(uint64_t aIdentifier,
497                                    int32_t aHistoryIndex) {
498   NS_ENSURE_STATE(mDocShell);
499 
500   return mDocShell->ResumeRedirectedLoad(aIdentifier, aHistoryIndex);
501 }
502 
503 NS_IMETHODIMP
Reload(uint32_t aReloadFlags)504 nsWebBrowser::Reload(uint32_t aReloadFlags) {
505   NS_ENSURE_STATE(mDocShell);
506 
507   return mDocShell->Reload(aReloadFlags);
508 }
509 
510 NS_IMETHODIMP
GotoIndex(int32_t aIndex,bool aUserActivation)511 nsWebBrowser::GotoIndex(int32_t aIndex, bool aUserActivation) {
512   NS_ENSURE_STATE(mDocShell);
513 
514   return mDocShell->GotoIndex(aIndex, aUserActivation);
515 }
516 
517 NS_IMETHODIMP
Stop(uint32_t aStopFlags)518 nsWebBrowser::Stop(uint32_t aStopFlags) {
519   NS_ENSURE_STATE(mDocShell);
520 
521   return mDocShell->Stop(aStopFlags);
522 }
523 
524 NS_IMETHODIMP
GetCurrentURI(nsIURI ** aURI)525 nsWebBrowser::GetCurrentURI(nsIURI** aURI) {
526   NS_ENSURE_STATE(mDocShell);
527 
528   return mDocShell->GetCurrentURI(aURI);
529 }
530 
531 // XXX(nika): Consider making the mozilla::dom::ChildSHistory version the
532 // canonical one?
533 NS_IMETHODIMP
GetSessionHistoryXPCOM(nsISupports ** aSessionHistory)534 nsWebBrowser::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) {
535   NS_ENSURE_ARG_POINTER(aSessionHistory);
536   *aSessionHistory = nullptr;
537   if (mDocShell) {
538     return mDocShell->GetSessionHistoryXPCOM(aSessionHistory);
539   }
540   return NS_OK;
541 }
542 
543 NS_IMETHODIMP
GetDocument(dom::Document ** aDocument)544 nsWebBrowser::GetDocument(dom::Document** aDocument) {
545   NS_ENSURE_STATE(mDocShell);
546 
547   return mDocShell->GetDocument(aDocument);
548 }
549 
SetAllowDNSPrefetch(bool aAllowPrefetch)550 void nsWebBrowser::SetAllowDNSPrefetch(bool aAllowPrefetch) {
551   MOZ_ASSERT(mDocShell);
552   mDocShell->SetAllowDNSPrefetch(aAllowPrefetch);
553 }
554 
555 //*****************************************************************************
556 // nsWebBrowser::nsIWebProgressListener
557 //*****************************************************************************
558 
559 NS_IMETHODIMP
OnStateChange(nsIWebProgress * aWebProgress,nsIRequest * aRequest,uint32_t aStateFlags,nsresult aStatus)560 nsWebBrowser::OnStateChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
561                             uint32_t aStateFlags, nsresult aStatus) {
562   if (mPersist) {
563     mPersist->GetCurrentState(&mPersistCurrentState);
564   }
565   if (aStateFlags & STATE_IS_NETWORK && aStateFlags & STATE_STOP) {
566     mPersist = nullptr;
567   }
568   if (mProgressListener) {
569     return mProgressListener->OnStateChange(aWebProgress, aRequest, aStateFlags,
570                                             aStatus);
571   }
572   return NS_OK;
573 }
574 
575 NS_IMETHODIMP
OnProgressChange(nsIWebProgress * aWebProgress,nsIRequest * aRequest,int32_t aCurSelfProgress,int32_t aMaxSelfProgress,int32_t aCurTotalProgress,int32_t aMaxTotalProgress)576 nsWebBrowser::OnProgressChange(nsIWebProgress* aWebProgress,
577                                nsIRequest* aRequest, int32_t aCurSelfProgress,
578                                int32_t aMaxSelfProgress,
579                                int32_t aCurTotalProgress,
580                                int32_t aMaxTotalProgress) {
581   if (mPersist) {
582     mPersist->GetCurrentState(&mPersistCurrentState);
583   }
584   if (mProgressListener) {
585     return mProgressListener->OnProgressChange(
586         aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress,
587         aCurTotalProgress, aMaxTotalProgress);
588   }
589   return NS_OK;
590 }
591 
592 NS_IMETHODIMP
OnLocationChange(nsIWebProgress * aWebProgress,nsIRequest * aRequest,nsIURI * aLocation,uint32_t aFlags)593 nsWebBrowser::OnLocationChange(nsIWebProgress* aWebProgress,
594                                nsIRequest* aRequest, nsIURI* aLocation,
595                                uint32_t aFlags) {
596   if (mProgressListener) {
597     return mProgressListener->OnLocationChange(aWebProgress, aRequest,
598                                                aLocation, aFlags);
599   }
600   return NS_OK;
601 }
602 
603 NS_IMETHODIMP
OnStatusChange(nsIWebProgress * aWebProgress,nsIRequest * aRequest,nsresult aStatus,const char16_t * aMessage)604 nsWebBrowser::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
605                              nsresult aStatus, const char16_t* aMessage) {
606   if (mProgressListener) {
607     return mProgressListener->OnStatusChange(aWebProgress, aRequest, aStatus,
608                                              aMessage);
609   }
610   return NS_OK;
611 }
612 
613 NS_IMETHODIMP
OnSecurityChange(nsIWebProgress * aWebProgress,nsIRequest * aRequest,uint32_t aState)614 nsWebBrowser::OnSecurityChange(nsIWebProgress* aWebProgress,
615                                nsIRequest* aRequest, uint32_t aState) {
616   if (mProgressListener) {
617     return mProgressListener->OnSecurityChange(aWebProgress, aRequest, aState);
618   }
619   return NS_OK;
620 }
621 
622 NS_IMETHODIMP
OnContentBlockingEvent(nsIWebProgress * aWebProgress,nsIRequest * aRequest,uint32_t aEvent)623 nsWebBrowser::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
624                                      nsIRequest* aRequest, uint32_t aEvent) {
625   if (mProgressListener) {
626     return mProgressListener->OnContentBlockingEvent(aWebProgress, aRequest,
627                                                      aEvent);
628   }
629   return NS_OK;
630 }
631 
632 //*****************************************************************************
633 // nsWebBrowser::nsIWebBrowserPersist
634 //*****************************************************************************
635 
636 NS_IMETHODIMP
GetPersistFlags(uint32_t * aPersistFlags)637 nsWebBrowser::GetPersistFlags(uint32_t* aPersistFlags) {
638   NS_ENSURE_ARG_POINTER(aPersistFlags);
639   nsresult rv = NS_OK;
640   if (mPersist) {
641     rv = mPersist->GetPersistFlags(&mPersistFlags);
642   }
643   *aPersistFlags = mPersistFlags;
644   return rv;
645 }
646 
647 NS_IMETHODIMP
SetPersistFlags(uint32_t aPersistFlags)648 nsWebBrowser::SetPersistFlags(uint32_t aPersistFlags) {
649   nsresult rv = NS_OK;
650   mPersistFlags = aPersistFlags;
651   if (mPersist) {
652     rv = mPersist->SetPersistFlags(mPersistFlags);
653     mPersist->GetPersistFlags(&mPersistFlags);
654   }
655   return rv;
656 }
657 
658 NS_IMETHODIMP
GetCurrentState(uint32_t * aCurrentState)659 nsWebBrowser::GetCurrentState(uint32_t* aCurrentState) {
660   NS_ENSURE_ARG_POINTER(aCurrentState);
661   if (mPersist) {
662     mPersist->GetCurrentState(&mPersistCurrentState);
663   }
664   *aCurrentState = mPersistCurrentState;
665   return NS_OK;
666 }
667 
668 NS_IMETHODIMP
GetResult(nsresult * aResult)669 nsWebBrowser::GetResult(nsresult* aResult) {
670   NS_ENSURE_ARG_POINTER(aResult);
671   if (mPersist) {
672     mPersist->GetResult(&mPersistResult);
673   }
674   *aResult = mPersistResult;
675   return NS_OK;
676 }
677 
678 NS_IMETHODIMP
GetProgressListener(nsIWebProgressListener ** aProgressListener)679 nsWebBrowser::GetProgressListener(nsIWebProgressListener** aProgressListener) {
680   NS_ENSURE_ARG_POINTER(aProgressListener);
681   *aProgressListener = mProgressListener;
682   NS_IF_ADDREF(*aProgressListener);
683   return NS_OK;
684 }
685 
686 NS_IMETHODIMP
SetProgressListener(nsIWebProgressListener * aProgressListener)687 nsWebBrowser::SetProgressListener(nsIWebProgressListener* aProgressListener) {
688   mProgressListener = aProgressListener;
689   return NS_OK;
690 }
691 
692 NS_IMETHODIMP
SaveURI(nsIURI * aURI,nsIPrincipal * aPrincipal,uint32_t aCacheKey,nsIReferrerInfo * aReferrerInfo,nsICookieJarSettings * aCookieJarSettings,nsIInputStream * aPostData,const char * aExtraHeaders,nsISupports * aFile,nsContentPolicyType aContentPolicyType,nsILoadContext * aPrivacyContext)693 nsWebBrowser::SaveURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
694                       uint32_t aCacheKey, nsIReferrerInfo* aReferrerInfo,
695                       nsICookieJarSettings* aCookieJarSettings,
696                       nsIInputStream* aPostData, const char* aExtraHeaders,
697                       nsISupports* aFile,
698                       nsContentPolicyType aContentPolicyType,
699                       nsILoadContext* aPrivacyContext) {
700   return SavePrivacyAwareURI(
701       aURI, aPrincipal, aCacheKey, aReferrerInfo, aCookieJarSettings, aPostData,
702       aExtraHeaders, aFile, aContentPolicyType,
703       aPrivacyContext && aPrivacyContext->UsePrivateBrowsing());
704 }
705 
706 NS_IMETHODIMP
SavePrivacyAwareURI(nsIURI * aURI,nsIPrincipal * aPrincipal,uint32_t aCacheKey,nsIReferrerInfo * aReferrerInfo,nsICookieJarSettings * aCookieJarSettings,nsIInputStream * aPostData,const char * aExtraHeaders,nsISupports * aFile,nsContentPolicyType aContentPolicyType,bool aIsPrivate)707 nsWebBrowser::SavePrivacyAwareURI(
708     nsIURI* aURI, nsIPrincipal* aPrincipal, uint32_t aCacheKey,
709     nsIReferrerInfo* aReferrerInfo, nsICookieJarSettings* aCookieJarSettings,
710     nsIInputStream* aPostData, const char* aExtraHeaders, nsISupports* aFile,
711     nsContentPolicyType aContentPolicyType, bool aIsPrivate) {
712   if (mPersist) {
713     uint32_t currentState;
714     mPersist->GetCurrentState(&currentState);
715     if (currentState == PERSIST_STATE_FINISHED) {
716       mPersist = nullptr;
717     } else {
718       // You can't save again until the last save has completed
719       return NS_ERROR_FAILURE;
720     }
721   }
722 
723   nsCOMPtr<nsIURI> uri;
724   if (aURI) {
725     uri = aURI;
726   } else {
727     nsresult rv = GetCurrentURI(getter_AddRefs(uri));
728     if (NS_FAILED(rv)) {
729       return NS_ERROR_FAILURE;
730     }
731   }
732 
733   // Create a throwaway persistence object to do the work
734   nsresult rv;
735   mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv);
736   NS_ENSURE_SUCCESS(rv, rv);
737   mPersist->SetProgressListener(this);
738   mPersist->SetPersistFlags(mPersistFlags);
739   mPersist->GetCurrentState(&mPersistCurrentState);
740 
741   rv = mPersist->SavePrivacyAwareURI(
742       uri, aPrincipal, aCacheKey, aReferrerInfo, aCookieJarSettings, aPostData,
743       aExtraHeaders, aFile, aContentPolicyType, aIsPrivate);
744   if (NS_FAILED(rv)) {
745     mPersist = nullptr;
746   }
747   return rv;
748 }
749 
750 NS_IMETHODIMP
SaveChannel(nsIChannel * aChannel,nsISupports * aFile)751 nsWebBrowser::SaveChannel(nsIChannel* aChannel, nsISupports* aFile) {
752   if (mPersist) {
753     uint32_t currentState;
754     mPersist->GetCurrentState(&currentState);
755     if (currentState == PERSIST_STATE_FINISHED) {
756       mPersist = nullptr;
757     } else {
758       // You can't save again until the last save has completed
759       return NS_ERROR_FAILURE;
760     }
761   }
762 
763   // Create a throwaway persistence object to do the work
764   nsresult rv;
765   mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv);
766   NS_ENSURE_SUCCESS(rv, rv);
767   mPersist->SetProgressListener(this);
768   mPersist->SetPersistFlags(mPersistFlags);
769   mPersist->GetCurrentState(&mPersistCurrentState);
770   rv = mPersist->SaveChannel(aChannel, aFile);
771   if (NS_FAILED(rv)) {
772     mPersist = nullptr;
773   }
774   return rv;
775 }
776 
777 NS_IMETHODIMP
SaveDocument(nsISupports * aDocumentish,nsISupports * aFile,nsISupports * aDataPath,const char * aOutputContentType,uint32_t aEncodingFlags,uint32_t aWrapColumn)778 nsWebBrowser::SaveDocument(nsISupports* aDocumentish, nsISupports* aFile,
779                            nsISupports* aDataPath,
780                            const char* aOutputContentType,
781                            uint32_t aEncodingFlags, uint32_t aWrapColumn) {
782   if (mPersist) {
783     uint32_t currentState;
784     mPersist->GetCurrentState(&currentState);
785     if (currentState == PERSIST_STATE_FINISHED) {
786       mPersist = nullptr;
787     } else {
788       // You can't save again until the last save has completed
789       return NS_ERROR_FAILURE;
790     }
791   }
792 
793   // Use the specified DOM document, or if none is specified, the one
794   // attached to the web browser.
795 
796   nsCOMPtr<nsISupports> doc;
797   if (aDocumentish) {
798     doc = aDocumentish;
799   } else {
800     RefPtr<dom::Document> domDoc;
801     GetDocument(getter_AddRefs(domDoc));
802     doc = already_AddRefed<nsISupports>(ToSupports(domDoc.forget().take()));
803   }
804   if (!doc) {
805     return NS_ERROR_FAILURE;
806   }
807 
808   // Create a throwaway persistence object to do the work
809   nsresult rv;
810   mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv);
811   NS_ENSURE_SUCCESS(rv, rv);
812   mPersist->SetProgressListener(this);
813   mPersist->SetPersistFlags(mPersistFlags);
814   mPersist->GetCurrentState(&mPersistCurrentState);
815   rv = mPersist->SaveDocument(doc, aFile, aDataPath, aOutputContentType,
816                               aEncodingFlags, aWrapColumn);
817   if (NS_FAILED(rv)) {
818     mPersist = nullptr;
819   }
820   return rv;
821 }
822 
823 NS_IMETHODIMP
CancelSave()824 nsWebBrowser::CancelSave() {
825   if (mPersist) {
826     return mPersist->CancelSave();
827   }
828   return NS_OK;
829 }
830 
831 NS_IMETHODIMP
Cancel(nsresult aReason)832 nsWebBrowser::Cancel(nsresult aReason) {
833   if (mPersist) {
834     return mPersist->Cancel(aReason);
835   }
836   return NS_OK;
837 }
838 
839 //*****************************************************************************
840 // nsWebBrowser::nsIBaseWindow
841 //*****************************************************************************
842 
843 NS_IMETHODIMP
InitWindow(nativeWindow aParentNativeWindow,nsIWidget * aParentWidget,int32_t aX,int32_t aY,int32_t aCX,int32_t aCY)844 nsWebBrowser::InitWindow(nativeWindow aParentNativeWindow,
845                          nsIWidget* aParentWidget, int32_t aX, int32_t aY,
846                          int32_t aCX, int32_t aCY) {
847   // nsIBaseWindow::InitWindow and nsIBaseWindow::Create
848   // implementations have been merged into nsWebBrowser::Create
849   MOZ_DIAGNOSTIC_ASSERT(false);
850   return NS_ERROR_NULL_POINTER;
851 }
852 
853 NS_IMETHODIMP
Destroy()854 nsWebBrowser::Destroy() {
855   InternalDestroy();
856 
857   return NS_OK;
858 }
859 
860 NS_IMETHODIMP
GetUnscaledDevicePixelsPerCSSPixel(double * aScale)861 nsWebBrowser::GetUnscaledDevicePixelsPerCSSPixel(double* aScale) {
862   *aScale = mParentWidget ? mParentWidget->GetDefaultScale().scale : 1.0;
863   return NS_OK;
864 }
865 
866 NS_IMETHODIMP
GetDevicePixelsPerDesktopPixel(double * aScale)867 nsWebBrowser::GetDevicePixelsPerDesktopPixel(double* aScale) {
868   *aScale =
869       mParentWidget ? mParentWidget->GetDesktopToDeviceScale().scale : 1.0;
870   return NS_OK;
871 }
872 
873 NS_IMETHODIMP
SetPositionDesktopPix(int32_t aX,int32_t aY)874 nsWebBrowser::SetPositionDesktopPix(int32_t aX, int32_t aY) {
875   // XXX jfkthame
876   // It's not clear to me whether this will be fully correct across
877   // potential multi-screen, mixed-DPI configurations for all platforms;
878   // we might need to add code paths that make it possible to pass the
879   // desktop-pix parameters all the way through to the native widget,
880   // to avoid the risk of device-pixel coords mapping to the wrong
881   // display on OS X with mixed retina/non-retina screens.
882   double scale = 1.0;
883   GetDevicePixelsPerDesktopPixel(&scale);
884   return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
885 }
886 
887 NS_IMETHODIMP
SetPosition(int32_t aX,int32_t aY)888 nsWebBrowser::SetPosition(int32_t aX, int32_t aY) {
889   int32_t cx = 0;
890   int32_t cy = 0;
891 
892   GetSize(&cx, &cy);
893 
894   return SetPositionAndSize(aX, aY, cx, cy, 0);
895 }
896 
897 NS_IMETHODIMP
GetPosition(int32_t * aX,int32_t * aY)898 nsWebBrowser::GetPosition(int32_t* aX, int32_t* aY) {
899   return GetPositionAndSize(aX, aY, nullptr, nullptr);
900 }
901 
902 NS_IMETHODIMP
SetSize(int32_t aCX,int32_t aCY,bool aRepaint)903 nsWebBrowser::SetSize(int32_t aCX, int32_t aCY, bool aRepaint) {
904   int32_t x = 0;
905   int32_t y = 0;
906 
907   GetPosition(&x, &y);
908 
909   return SetPositionAndSize(x, y, aCX, aCY,
910                             aRepaint ? nsIBaseWindow::eRepaint : 0);
911 }
912 
913 NS_IMETHODIMP
GetSize(int32_t * aCX,int32_t * aCY)914 nsWebBrowser::GetSize(int32_t* aCX, int32_t* aCY) {
915   return GetPositionAndSize(nullptr, nullptr, aCX, aCY);
916 }
917 
918 NS_IMETHODIMP
SetPositionAndSize(int32_t aX,int32_t aY,int32_t aCX,int32_t aCY,uint32_t aFlags)919 nsWebBrowser::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aCX,
920                                  int32_t aCY, uint32_t aFlags) {
921   int32_t doc_x = aX;
922   int32_t doc_y = aY;
923 
924   // If there is an internal widget we need to make the docShell coordinates
925   // relative to the internal widget rather than the calling app's parent.
926   // We also need to resize our widget then.
927   if (mInternalWidget) {
928     doc_x = doc_y = 0;
929     mInternalWidget->Resize(aX, aY, aCX, aCY,
930                             !!(aFlags & nsIBaseWindow::eRepaint));
931   }
932   // Now reposition/ resize the doc
933   NS_ENSURE_SUCCESS(
934       mDocShell->SetPositionAndSize(doc_x, doc_y, aCX, aCY, aFlags),
935       NS_ERROR_FAILURE);
936 
937   return NS_OK;
938 }
939 
940 NS_IMETHODIMP
GetPositionAndSize(int32_t * aX,int32_t * aY,int32_t * aCX,int32_t * aCY)941 nsWebBrowser::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aCX,
942                                  int32_t* aCY) {
943   if (mInternalWidget) {
944     LayoutDeviceIntRect bounds = mInternalWidget->GetBounds();
945 
946     if (aX) {
947       *aX = bounds.X();
948     }
949     if (aY) {
950       *aY = bounds.Y();
951     }
952     if (aCX) {
953       *aCX = bounds.Width();
954     }
955     if (aCY) {
956       *aCY = bounds.Height();
957     }
958     return NS_OK;
959   } else {
960     // Can directly return this as it is the
961     // same interface, thus same returns.
962     return mDocShell->GetPositionAndSize(aX, aY, aCX, aCY);
963   }
964   return NS_OK;
965 }
966 
967 NS_IMETHODIMP
Repaint(bool aForce)968 nsWebBrowser::Repaint(bool aForce) {
969   NS_ENSURE_STATE(mDocShell);
970   // Can directly return this as it is the
971   // same interface, thus same returns.
972   return mDocShell->Repaint(aForce);
973 }
974 
975 NS_IMETHODIMP
GetParentWidget(nsIWidget ** aParentWidget)976 nsWebBrowser::GetParentWidget(nsIWidget** aParentWidget) {
977   NS_ENSURE_ARG_POINTER(aParentWidget);
978 
979   *aParentWidget = mParentWidget;
980 
981   NS_IF_ADDREF(*aParentWidget);
982 
983   return NS_OK;
984 }
985 
986 NS_IMETHODIMP
SetParentWidget(nsIWidget * aParentWidget)987 nsWebBrowser::SetParentWidget(nsIWidget* aParentWidget) {
988   NS_ENSURE_STATE(!mDocShell);
989 
990   mParentWidget = aParentWidget;
991   if (mParentWidget) {
992     mParentNativeWindow = mParentWidget->GetNativeData(NS_NATIVE_WIDGET);
993   } else {
994     mParentNativeWindow = nullptr;
995   }
996 
997   return NS_OK;
998 }
999 
1000 NS_IMETHODIMP
GetParentNativeWindow(nativeWindow * aParentNativeWindow)1001 nsWebBrowser::GetParentNativeWindow(nativeWindow* aParentNativeWindow) {
1002   NS_ENSURE_ARG_POINTER(aParentNativeWindow);
1003 
1004   *aParentNativeWindow = mParentNativeWindow;
1005 
1006   return NS_OK;
1007 }
1008 
1009 NS_IMETHODIMP
SetParentNativeWindow(nativeWindow aParentNativeWindow)1010 nsWebBrowser::SetParentNativeWindow(nativeWindow aParentNativeWindow) {
1011   NS_ENSURE_STATE(!mDocShell);
1012 
1013   mParentNativeWindow = aParentNativeWindow;
1014 
1015   return NS_OK;
1016 }
1017 
1018 NS_IMETHODIMP
GetNativeHandle(nsAString & aNativeHandle)1019 nsWebBrowser::GetNativeHandle(nsAString& aNativeHandle) {
1020   // the nativeHandle should be accessed from nsIAppWindow
1021   return NS_ERROR_NOT_IMPLEMENTED;
1022 }
1023 
1024 NS_IMETHODIMP
GetVisibility(bool * aVisibility)1025 nsWebBrowser::GetVisibility(bool* aVisibility) {
1026   NS_ENSURE_ARG_POINTER(aVisibility);
1027 
1028   if (mDocShell) {
1029     NS_ENSURE_SUCCESS(mDocShell->GetVisibility(aVisibility), NS_ERROR_FAILURE);
1030   }
1031 
1032   return NS_OK;
1033 }
1034 
1035 NS_IMETHODIMP
SetVisibility(bool aVisibility)1036 nsWebBrowser::SetVisibility(bool aVisibility) {
1037   if (mDocShell) {
1038     NS_ENSURE_SUCCESS(mDocShell->SetVisibility(aVisibility), NS_ERROR_FAILURE);
1039     if (mInternalWidget) {
1040       mInternalWidget->Show(aVisibility);
1041     }
1042   }
1043 
1044   return NS_OK;
1045 }
1046 
1047 NS_IMETHODIMP
GetEnabled(bool * aEnabled)1048 nsWebBrowser::GetEnabled(bool* aEnabled) {
1049   if (mInternalWidget) {
1050     *aEnabled = mInternalWidget->IsEnabled();
1051     return NS_OK;
1052   }
1053 
1054   return NS_ERROR_FAILURE;
1055 }
1056 
1057 NS_IMETHODIMP
SetEnabled(bool aEnabled)1058 nsWebBrowser::SetEnabled(bool aEnabled) {
1059   if (mInternalWidget) {
1060     mInternalWidget->Enable(aEnabled);
1061     return NS_OK;
1062   }
1063   return NS_ERROR_FAILURE;
1064 }
1065 
1066 NS_IMETHODIMP
GetMainWidget(nsIWidget ** aMainWidget)1067 nsWebBrowser::GetMainWidget(nsIWidget** aMainWidget) {
1068   NS_ENSURE_ARG_POINTER(aMainWidget);
1069 
1070   if (mInternalWidget) {
1071     *aMainWidget = mInternalWidget;
1072   } else {
1073     *aMainWidget = mParentWidget;
1074   }
1075 
1076   NS_IF_ADDREF(*aMainWidget);
1077 
1078   return NS_OK;
1079 }
1080 
1081 NS_IMETHODIMP
GetTitle(nsAString & aTitle)1082 nsWebBrowser::GetTitle(nsAString& aTitle) {
1083   NS_ENSURE_STATE(mDocShell);
1084 
1085   NS_ENSURE_SUCCESS(mDocShell->GetTitle(aTitle), NS_ERROR_FAILURE);
1086 
1087   return NS_OK;
1088 }
1089 
1090 NS_IMETHODIMP
SetTitle(const nsAString & aTitle)1091 nsWebBrowser::SetTitle(const nsAString& aTitle) {
1092   NS_ENSURE_STATE(mDocShell);
1093 
1094   NS_ENSURE_SUCCESS(mDocShell->SetTitle(aTitle), NS_ERROR_FAILURE);
1095 
1096   return NS_OK;
1097 }
1098 
1099 //*****************************************************************************
1100 // nsWebBrowser: Listener Helpers
1101 //*****************************************************************************
1102 
SetDocShell(nsDocShell * aDocShell)1103 void nsWebBrowser::SetDocShell(nsDocShell* aDocShell) {
1104   // We need to keep the docshell alive while we perform the changes, but we
1105   // don't need to call any methods on it.
1106   nsCOMPtr<nsIDocShell> kungFuDeathGrip(mDocShell);
1107   mozilla::Unused << kungFuDeathGrip;
1108 
1109   if (aDocShell) {
1110     MOZ_ASSERT(!mDocShell, "Should not overwrite an existing value!");
1111 
1112     mDocShell = aDocShell;
1113 
1114     // By default, do not allow DNS prefetch, so we don't break our frozen
1115     // API.  Embeddors who decide to enable it should do so manually.
1116     mDocShell->SetAllowDNSPrefetch(false);
1117   } else {
1118     if (mDocShellTreeOwner) {
1119       mDocShellTreeOwner->RemoveFromWatcher();  // evil twin of Add in Create()
1120     }
1121     if (mDocShell) {
1122       mDocShell->Destroy();
1123     }
1124     if (!mWillChangeProcess && mDocShell) {
1125       mDocShell->GetBrowsingContext()->Detach(/* aFromIPC */ true);
1126     }
1127 
1128     mDocShell = nullptr;
1129   }
1130 }
1131 
EnsureDocShellTreeOwner()1132 void nsWebBrowser::EnsureDocShellTreeOwner() {
1133   if (mDocShellTreeOwner) {
1134     return;
1135   }
1136 
1137   mDocShellTreeOwner = new nsDocShellTreeOwner();
1138   mDocShellTreeOwner->WebBrowser(this);
1139 }
1140 
DrawPaintedLayer(PaintedLayer * aLayer,gfxContext * aContext,const nsIntRegion & aRegionToDraw,const nsIntRegion & aDirtyRegion,DrawRegionClip aClip,const nsIntRegion & aRegionToInvalidate,void * aCallbackData)1141 static void DrawPaintedLayer(PaintedLayer* aLayer, gfxContext* aContext,
1142                              const nsIntRegion& aRegionToDraw,
1143                              const nsIntRegion& aDirtyRegion,
1144                              DrawRegionClip aClip,
1145                              const nsIntRegion& aRegionToInvalidate,
1146                              void* aCallbackData) {
1147   DrawTarget& aDrawTarget = *aContext->GetDrawTarget();
1148 
1149   ColorPattern color(ToDeviceColor(*static_cast<nscolor*>(aCallbackData)));
1150   nsIntRect dirtyRect = aRegionToDraw.GetBounds();
1151   aDrawTarget.FillRect(
1152       Rect(dirtyRect.X(), dirtyRect.Y(), dirtyRect.Width(), dirtyRect.Height()),
1153       color);
1154 }
1155 
WindowActivated()1156 void nsWebBrowser::WindowActivated() {
1157 #if defined(DEBUG_smaug)
1158   RefPtr<dom::Document> document = mDocShell->GetDocument();
1159   nsAutoString documentURI;
1160   document->GetDocumentURI(documentURI);
1161   printf("nsWebBrowser::NS_ACTIVATE %p %s\n", (void*)this,
1162          NS_ConvertUTF16toUTF8(documentURI).get());
1163 #endif
1164   FocusActivate(nsFocusManager::GenerateFocusActionId());
1165 }
1166 
WindowDeactivated()1167 void nsWebBrowser::WindowDeactivated() {
1168 #if defined(DEBUG_smaug)
1169   RefPtr<dom::Document> document = mDocShell->GetDocument();
1170   nsAutoString documentURI;
1171   document->GetDocumentURI(documentURI);
1172   printf("nsWebBrowser::NS_DEACTIVATE %p %s\n", (void*)this,
1173          NS_ConvertUTF16toUTF8(documentURI).get());
1174 #endif
1175   FocusDeactivate(nsFocusManager::GenerateFocusActionId());
1176 }
1177 
PaintWindow(nsIWidget * aWidget,LayoutDeviceIntRegion aRegion)1178 bool nsWebBrowser::PaintWindow(nsIWidget* aWidget,
1179                                LayoutDeviceIntRegion aRegion) {
1180   LayerManager* layerManager = aWidget->GetLayerManager();
1181   NS_ASSERTION(layerManager, "Must be in paint event");
1182 
1183   layerManager->BeginTransaction();
1184   RefPtr<PaintedLayer> root = layerManager->CreatePaintedLayer();
1185   if (root) {
1186     nsIntRect dirtyRect = aRegion.GetBounds().ToUnknownRect();
1187     root->SetVisibleRegion(LayerIntRegion::FromUnknownRegion(dirtyRect));
1188     layerManager->SetRoot(root);
1189   }
1190 
1191   layerManager->EndTransaction(DrawPaintedLayer, &mBackgroundColor);
1192   return true;
1193 }
1194 
FocusActivate(uint64_t aActionId)1195 void nsWebBrowser::FocusActivate(uint64_t aActionId) {
1196   nsFocusManager* fm = nsFocusManager::GetFocusManager();
1197   nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow();
1198   if (fm && window) {
1199     fm->WindowRaised(window, aActionId);
1200   }
1201 }
1202 
FocusDeactivate(uint64_t aActionId)1203 void nsWebBrowser::FocusDeactivate(uint64_t aActionId) {
1204   nsFocusManager* fm = nsFocusManager::GetFocusManager();
1205   nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow();
1206   if (fm && window) {
1207     fm->WindowLowered(window, aActionId);
1208   }
1209 }
1210 
SetWillChangeProcess()1211 void nsWebBrowser::SetWillChangeProcess() {
1212   mWillChangeProcess = true;
1213   if (mDocShell) {
1214     nsDocShell::Cast(mDocShell)->SetWillChangeProcess();
1215   }
1216 }
1217 
WindowActivated()1218 void nsWebBrowser::WidgetListenerDelegate::WindowActivated() {
1219   RefPtr<nsWebBrowser> holder = mWebBrowser;
1220   holder->WindowActivated();
1221 }
1222 
WindowDeactivated()1223 void nsWebBrowser::WidgetListenerDelegate::WindowDeactivated() {
1224   RefPtr<nsWebBrowser> holder = mWebBrowser;
1225   holder->WindowDeactivated();
1226 }
1227 
PaintWindow(nsIWidget * aWidget,mozilla::LayoutDeviceIntRegion aRegion)1228 bool nsWebBrowser::WidgetListenerDelegate::PaintWindow(
1229     nsIWidget* aWidget, mozilla::LayoutDeviceIntRegion aRegion) {
1230   RefPtr<nsWebBrowser> holder = mWebBrowser;
1231   return holder->PaintWindow(aWidget, aRegion);
1232 }
1233