Bug 1416384 - Part 3: Remove nsPIDOMWindow<nsISupports>, r=smaug
This was needed before as the base to nsGlobalWindow, but now that
nsGlobalWindow doesn't exist, and we only have specific versions, we no longer
need this type.
MozReview-Commit-ID: 6IJmJtnSkMr

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* vim: set ts=8 sts=2 et sw=2 tw=80: *//* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */nsGlobalWindowInner::InnerWindowByIdTable*nsGlobalWindowInner::sInnerWindowsById=nullptr;/** * An indirect observer object that means we don't have to implement nsIObserver * on nsGlobalWindow, where any script could see it. */classnsGlobalWindowObserverfinal:publicnsIObserver,publicnsIInterfaceRequestor,publicStorageNotificationObserver{public:explicitnsGlobalWindowObserver(nsGlobalWindowInner*aWindow):mWindow(aWindow){}NS_DECL_ISUPPORTSNS_IMETHODObserve(nsISupports*aSubject,constchar*aTopic,constchar16_t*aData)override{if(!mWindow)returnNS_OK;returnmWindow->Observe(aSubject,aTopic,aData);}voidForget(){mWindow=nullptr;}NS_IMETHODGetInterface(constnsIID&aIID,void**aResult)override{if(mWindow&&aIID.Equals(NS_GET_IID(nsIDOMWindow))&&mWindow){returnmWindow->QueryInterface(aIID,aResult);}returnNS_NOINTERFACE;}voidObserveStorageNotification(StorageEvent*aEvent,constchar16_t*aStorageType,boolaPrivateBrowsing)override{if(mWindow){mWindow->ObserveStorageNotification(aEvent,aStorageType,aPrivateBrowsing);}}nsIPrincipal*GetPrincipal()constoverride{returnmWindow?mWindow->GetPrincipal():nullptr;}boolIsPrivateBrowsing()constoverride{returnmWindow?mWindow->IsPrivateBrowsing():false;}nsIEventTarget*GetEventTarget()constoverride{returnmWindow?mWindow->EventTargetFor(TaskCategory::Other):nullptr;}private:~nsGlobalWindowObserver()=default;// This reference is non-owning and safe because it's cleared by// nsGlobalWindowInner::CleanUp().nsGlobalWindowInner*MOZ_NON_OWNING_REFmWindow;};NS_IMPL_ISUPPORTS(nsGlobalWindowObserver,nsIObserver,nsIInterfaceRequestor)classIdleRequestExecutor;classIdleRequestExecutorTimeoutHandlerfinal:publicTimeoutHandler{public:explicitIdleRequestExecutorTimeoutHandler(IdleRequestExecutor*aExecutor):mExecutor(aExecutor){}NS_DECL_ISUPPORTS_INHERITEDNS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IdleRequestExecutorTimeoutHandler,TimeoutHandler)nsresultCall()override;private:~IdleRequestExecutorTimeoutHandler()override{}RefPtr<IdleRequestExecutor>mExecutor;};NS_IMPL_CYCLE_COLLECTION_INHERITED(IdleRequestExecutorTimeoutHandler,TimeoutHandler,mExecutor)NS_IMPL_ADDREF_INHERITED(IdleRequestExecutorTimeoutHandler,TimeoutHandler)NS_IMPL_RELEASE_INHERITED(IdleRequestExecutorTimeoutHandler,TimeoutHandler)NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutorTimeoutHandler)NS_INTERFACE_MAP_END_INHERITING(TimeoutHandler)classIdleRequestExecutorfinal:publicnsIRunnable,publicnsICancelableRunnable,publicnsINamed,publicnsIIdleRunnable{public:explicitIdleRequestExecutor(nsGlobalWindowInner*aWindow):mDispatched(false),mDeadline(TimeStamp::Now()),mWindow(aWindow){MOZ_DIAGNOSTIC_ASSERT(mWindow);MOZ_DIAGNOSTIC_ASSERT(mWindow->IsInnerWindow());mIdlePeriodLimit={mDeadline,mWindow->LastIdleRequestHandle()};mDelayedExecutorDispatcher=newIdleRequestExecutorTimeoutHandler(this);}NS_DECL_CYCLE_COLLECTING_ISUPPORTSNS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IdleRequestExecutor,nsIRunnable)NS_DECL_NSIRUNNABLENS_DECL_NSINAMEDnsresultCancel()override;voidSetDeadline(TimeStampaDeadline)override;boolIsCancelled()const{return!mWindow||mWindow->AsInner()->InnerObjectsFreed();}// Checks if aRequest shouldn't execute in the current idle period// since it has been queued from a chained call to// requestIdleCallback from within a running idle callback.boolIneligibleForCurrentIdlePeriod(IdleRequest*aRequest)const{returnaRequest->Handle()>=mIdlePeriodLimit.mLastRequestIdInIdlePeriod&&TimeStamp::Now()<=mIdlePeriodLimit.mEndOfIdlePeriod;}voidMaybeUpdateIdlePeriodLimit();// Maybe dispatch the IdleRequestExecutor. MabyeDispatch will// schedule a delayed dispatch if the associated window is in the// background or if given a time to wait until dispatching.voidMaybeDispatch(TimeStampaDelayUntil=TimeStamp());voidScheduleDispatch();private:structIdlePeriodLimit{TimeStampmEndOfIdlePeriod;uint32_tmLastRequestIdInIdlePeriod;};voidDelayedDispatch(uint32_taDelay);~IdleRequestExecutor()override{}boolmDispatched;TimeStampmDeadline;IdlePeriodLimitmIdlePeriodLimit;RefPtr<nsGlobalWindowInner>mWindow;// The timeout handler responsible for dispatching this executor in// the case of immediate dispatch to the idle queue isn't// desirable. This is used if we've dispatched all idle callbacks// that are allowed to run in the current idle period, or if the// associated window is currently in the background.nsCOMPtr<nsITimeoutHandler>mDelayedExecutorDispatcher;// If not Nothing() then this value is the handle to the currently// scheduled delayed executor dispatcher. This is needed to be able// to cancel the timeout handler in case of the executor being// cancelled.Maybe<int32_t>mDelayedExecutorHandle;};NS_IMPL_CYCLE_COLLECTION_CLASS(IdleRequestExecutor)NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequestExecutor)NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequestExecutor)NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IdleRequestExecutor)NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)NS_IMPL_CYCLE_COLLECTION_UNLINK(mDelayedExecutorDispatcher)NS_IMPL_CYCLE_COLLECTION_UNLINK_ENDNS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IdleRequestExecutor)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDelayedExecutorDispatcher)NS_IMPL_CYCLE_COLLECTION_TRAVERSE_ENDNS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutor)NS_INTERFACE_MAP_ENTRY(nsIRunnable)NS_INTERFACE_MAP_ENTRY(nsICancelableRunnable)NS_INTERFACE_MAP_ENTRY(nsINamed)NS_INTERFACE_MAP_ENTRY(nsIIdleRunnable)NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports,nsIRunnable)NS_INTERFACE_MAP_ENDNS_IMETHODIMPIdleRequestExecutor::GetName(nsACString&aName){aName.AssignASCII("IdleRequestExecutor");returnNS_OK;}NS_IMETHODIMPIdleRequestExecutor::Run(){MOZ_ASSERT(NS_IsMainThread());mDispatched=false;if(mWindow){returnmWindow->ExecuteIdleRequest(mDeadline);}returnNS_OK;}nsresultIdleRequestExecutor::Cancel(){MOZ_ASSERT(NS_IsMainThread());if(mDelayedExecutorHandle&&mWindow){mWindow->AsInner()->TimeoutManager().ClearTimeout(mDelayedExecutorHandle.value(),Timeout::Reason::eIdleCallbackTimeout);}mWindow=nullptr;returnNS_OK;}voidIdleRequestExecutor::SetDeadline(TimeStampaDeadline){MOZ_ASSERT(NS_IsMainThread());if(!mWindow){return;}mDeadline=aDeadline;}voidIdleRequestExecutor::MaybeUpdateIdlePeriodLimit(){if(TimeStamp::Now()>mIdlePeriodLimit.mEndOfIdlePeriod){mIdlePeriodLimit={mDeadline,mWindow->LastIdleRequestHandle()};}}voidIdleRequestExecutor::MaybeDispatch(TimeStampaDelayUntil){// If we've already dispatched the executor we don't want to do it// again. Also, if we've called IdleRequestExecutor::Cancel mWindow// will be null, which indicates that we shouldn't dispatch this// executor either.if(mDispatched||IsCancelled()){return;}mDispatched=true;nsPIDOMWindowOuter*outer=mWindow->GetOuterWindow();if(outer&&outer->AsOuter()->IsBackground()){// Set a timeout handler with a timeout of 0 ms to throttle idle// callback requests coming from a backround window using// background timeout throttling.DelayedDispatch(0);return;}TimeStampnow=TimeStamp::Now();if(!aDelayUntil||aDelayUntil<now){ScheduleDispatch();return;}TimeDurationdelay=aDelayUntil-now;DelayedDispatch(static_cast<uint32_t>(delay.ToMilliseconds()));}voidIdleRequestExecutor::ScheduleDispatch(){MOZ_ASSERT(mWindow);mDelayedExecutorHandle=Nothing();RefPtr<IdleRequestExecutor>request=this;NS_IdleDispatchToCurrentThread(request.forget());}voidIdleRequestExecutor::DelayedDispatch(uint32_taDelay){MOZ_ASSERT(mWindow);MOZ_ASSERT(mDelayedExecutorHandle.isNothing());int32_thandle;mWindow->AsInner()->TimeoutManager().SetTimeout(mDelayedExecutorDispatcher,aDelay,false,Timeout::Reason::eIdleCallbackTimeout,&handle);mDelayedExecutorHandle=Some(handle);}nsresultIdleRequestExecutorTimeoutHandler::Call(){if(!mExecutor->IsCancelled()){mExecutor->ScheduleDispatch();}returnNS_OK;}voidnsGlobalWindowInner::ScheduleIdleRequestDispatch(){AssertIsOnMainThread();if(!mIdleRequestExecutor){mIdleRequestExecutor=newIdleRequestExecutor(AssertInner());}mIdleRequestExecutor->MaybeDispatch();}voidnsGlobalWindowInner::SuspendIdleRequests(){if(mIdleRequestExecutor){mIdleRequestExecutor->Cancel();mIdleRequestExecutor=nullptr;}}voidnsGlobalWindowInner::ResumeIdleRequests(){MOZ_ASSERT(!mIdleRequestExecutor);ScheduleIdleRequestDispatch();}voidnsGlobalWindowInner::InsertIdleCallback(IdleRequest*aRequest){AssertIsOnMainThread();mIdleRequestCallbacks.insertBack(aRequest);aRequest->AddRef();}voidnsGlobalWindowInner::RemoveIdleCallback(mozilla::dom::IdleRequest*aRequest){AssertIsOnMainThread();if(aRequest->HasTimeout()){mTimeoutManager->ClearTimeout(aRequest->GetTimeoutHandle(),Timeout::Reason::eIdleCallbackTimeout);}aRequest->removeFrom(mIdleRequestCallbacks);aRequest->Release();}nsresultnsGlobalWindowInner::RunIdleRequest(IdleRequest*aRequest,DOMHighResTimeStampaDeadline,boolaDidTimeout){AssertIsOnMainThread();RefPtr<IdleRequest>request(aRequest);RemoveIdleCallback(request);returnrequest->IdleRun(AsInner(),aDeadline,aDidTimeout);}nsresultnsGlobalWindowInner::ExecuteIdleRequest(TimeStampaDeadline){AssertIsOnMainThread();RefPtr<IdleRequest>request=mIdleRequestCallbacks.getFirst();if(!request){// There are no more idle requests, so stop scheduling idle// request callbacks.returnNS_OK;}// If the request that we're trying to execute has been queued// during the current idle period, then dispatch it again at the end// of the idle period.if(mIdleRequestExecutor->IneligibleForCurrentIdlePeriod(request)){mIdleRequestExecutor->MaybeDispatch(aDeadline);returnNS_OK;}DOMHighResTimeStampdeadline=0.0;if(Performance*perf=GetPerformance()){deadline=perf->GetDOMTiming()->TimeStampToDOMHighRes(aDeadline);}mIdleRequestExecutor->MaybeUpdateIdlePeriodLimit();nsresultresult=RunIdleRequest(request,deadline,false);// Running the idle callback could've suspended the window, in which// case mIdleRequestExecutor will be null.if(mIdleRequestExecutor){mIdleRequestExecutor->MaybeDispatch();}returnresult;}classIdleRequestTimeoutHandlerfinal:publicTimeoutHandler{public:IdleRequestTimeoutHandler(JSContext*aCx,IdleRequest*aIdleRequest,nsPIDOMWindowInner*aWindow):TimeoutHandler(aCx),mIdleRequest(aIdleRequest),mWindow(aWindow){}NS_DECL_ISUPPORTS_INHERITEDNS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IdleRequestTimeoutHandler,TimeoutHandler)nsresultCall()override{returnnsGlobalWindowInner::Cast(mWindow)->RunIdleRequest(mIdleRequest,0.0,true);}private:~IdleRequestTimeoutHandler()override{}RefPtr<IdleRequest>mIdleRequest;nsCOMPtr<nsPIDOMWindowInner>mWindow;};NS_IMPL_CYCLE_COLLECTION_INHERITED(IdleRequestTimeoutHandler,TimeoutHandler,mIdleRequest,mWindow)NS_IMPL_ADDREF_INHERITED(IdleRequestTimeoutHandler,TimeoutHandler)NS_IMPL_RELEASE_INHERITED(IdleRequestTimeoutHandler,TimeoutHandler)NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestTimeoutHandler)NS_INTERFACE_MAP_END_INHERITING(TimeoutHandler)uint32_tnsGlobalWindowInner::RequestIdleCallback(JSContext*aCx,IdleRequestCallback&aCallback,constIdleRequestOptions&aOptions,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());AssertIsOnMainThread();uint32_thandle=mIdleRequestCallbackCounter++;RefPtr<IdleRequest>request=newIdleRequest(&aCallback,handle);if(aOptions.mTimeout.WasPassed()){int32_ttimeoutHandle;nsCOMPtr<nsITimeoutHandler>handler(newIdleRequestTimeoutHandler(aCx,request,AsInner()));nsresultrv=mTimeoutManager->SetTimeout(handler,aOptions.mTimeout.Value(),false,Timeout::Reason::eIdleCallbackTimeout,&timeoutHandle);if(NS_WARN_IF(NS_FAILED(rv))){return0;}request->SetTimeoutHandle(timeoutHandle);}// mIdleRequestCallbacks now owns requestInsertIdleCallback(request);if(!IsSuspended()){ScheduleIdleRequestDispatch();}returnhandle;}voidnsGlobalWindowInner::CancelIdleCallback(uint32_taHandle){MOZ_RELEASE_ASSERT(IsInnerWindow());for(IdleRequest*r:mIdleRequestCallbacks){if(r->Handle()==aHandle){RemoveIdleCallback(r);break;}}}voidnsGlobalWindowInner::DisableIdleCallbackRequests(){if(mIdleRequestExecutor){mIdleRequestExecutor->Cancel();mIdleRequestExecutor=nullptr;}while(!mIdleRequestCallbacks.isEmpty()){RefPtr<IdleRequest>request=mIdleRequestCallbacks.getFirst();RemoveIdleCallback(request);}}boolnsGlobalWindowInner::IsBackgroundInternal()const{return!mOuterWindow||mOuterWindow->IsBackground();}//*****************************************************************************//*** nsGlobalWindowInner: Object Management//*****************************************************************************nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter*aOuterWindow):nsPIDOMWindowInner(aOuterWindow->AsOuter()),mIdleFuzzFactor(0),mIdleCallbackIndex(-1),mCurrentlyIdle(false),mAddActiveEventFuzzTime(true),mFullScreen(false),mFullscreenMode(false),mIsClosed(false),mInClose(false),mHavePendingClose(false),mHadOriginalOpener(false),mOriginalOpenerWasSecureContext(false),mIsPopupSpam(false),mBlockScriptedClosingFlag(false),mWasOffline(false),mHasHadSlowScript(false),mNotifyIdleObserversIdleOnThaw(false),mNotifyIdleObserversActiveOnThaw(false),mCreatingInnerWindow(false),mIsChrome(false),mCleanMessageManager(false),mNeedsFocus(true),mHasFocus(false),mShowFocusRingForContent(false),mFocusByKeyOccurred(false),mHasGamepad(false),mHasVREvents(false),mHasVRDisplayActivateEvents(false),mHasSeenGamepadInput(false),mNotifiedIDDestroyed(false),mAllowScriptsToClose(false),mTopLevelOuterContentWindow(false),mSuspendDepth(0),mFreezeDepth(0),mFocusMethod(0),mSerial(0),mIdleRequestCallbackCounter(1),mIdleRequestExecutor(nullptr),#ifdef DEBUGmSetOpenerWindowCalled(false),#endifmCleanedUp(false),mDialogAbuseCount(0),mAreDialogsEnabled(true),#ifdef DEBUGmIsValidatingTabGroup(false),#endifmCanSkipCCGeneration(0),mAutoActivateVRDisplayID(0),mBeforeUnloadListenerCount(0){AssertIsOnMainThread();nsLayoutStatics::AddRef();// Initialize the PRCList (this).PR_INIT_CLIST(this);if(aOuterWindow){// |this| is an inner window, add this inner window to the outer// window list of inners.PR_INSERT_AFTER(this,aOuterWindow);mObserver=newnsGlobalWindowObserver(AssertInner());if(mObserver){nsCOMPtr<nsIObserverService>os=mozilla::services::GetObserverService();if(os){// Watch for online/offline status changes so we can fire events. Use// a strong reference.os->AddObserver(mObserver,NS_IOSERVICE_OFFLINE_STATUS_TOPIC,false);os->AddObserver(mObserver,MEMORY_PRESSURE_OBSERVER_TOPIC,false);}Preferences::AddStrongObserver(mObserver,"intl.accept_languages");// Watch for storage notifications so we can fire storage events.RefPtr<StorageNotifierService>sns=StorageNotifierService::GetOrCreate();if(sns){sns->Register(mObserver);}}}else{// |this| is an outer window. Outer windows start out frozen and// remain frozen until they get an inner window.MOZ_ASSERT(IsFrozen());}if(XRE_IsContentProcess()){nsCOMPtr<nsIDocShell>docShell=GetDocShell();if(docShell){mTabChild=docShell->GetTabChild();}}// We could have failed the first time through trying// to create the entropy collector, so we should// try to get one until we succeed.gRefCnt++;EnsurePrefCaches();if(gDumpFile==nullptr){nsAutoCStringfname;Preferences::GetCString("browser.dom.window.dump.file",fname);if(!fname.IsEmpty()){// If this fails to open, Dump() knows to just go to stdout on null.gDumpFile=fopen(fname.get(),"wb+");}else{gDumpFile=stdout;}}mSerial=++gSerialCounter;#ifdef DEBUGif(!PR_GetEnv("MOZ_QUIET")){printf_stderr("++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n",gRefCnt,static_cast<void*>(ToCanonicalSupports(this)),getpid(),gSerialCounter,static_cast<void*>(ToCanonicalSupports(aOuterWindow)));}#endifMOZ_LOG(gDOMLeakPRLog,LogLevel::Debug,("DOMWINDOW %p created outer=%p",this,aOuterWindow));// Add ourselves to the inner windows list.MOZ_ASSERT(sInnerWindowsById,"Inner Windows hash table must be created!");MOZ_ASSERT(!sInnerWindowsById->Get(mWindowID),"This window shouldn't be in the hash table yet!");// We seem to see crashes in release builds because of null |sInnerWindowsById|.if(sInnerWindowsById){sInnerWindowsById->Put(mWindowID,AssertInner());}}#ifdef DEBUG/* static */voidnsGlobalWindowInner::AssertIsOnMainThread(){MOZ_ASSERT(NS_IsMainThread());}#endif // DEBUG/* static */voidnsGlobalWindowInner::Init(){AssertIsOnMainThread();NS_ASSERTION(gDOMLeakPRLog,"gDOMLeakPRLog should have been initialized!");sInnerWindowsById=newInnerWindowByIdTable();}nsGlobalWindowInner::~nsGlobalWindowInner(){AssertIsOnMainThread();if(IsChromeWindow()){MOZ_ASSERT(mCleanMessageManager,"chrome windows may always disconnect the msg manager");DisconnectAndClearGroupMessageManagers();if(mChromeFields.mMessageManager){static_cast<nsFrameMessageManager*>(mChromeFields.mMessageManager.get())->Disconnect();}mCleanMessageManager=false;}DisconnectEventTargetObjects();if(IsOuterWindow()){if(nsGlobalWindowOuter::sOuterWindowsById){MOZ_ASSERT(nsGlobalWindowOuter::sOuterWindowsById->Get(mWindowID),"This window should be in the hash table");nsGlobalWindowOuter::sOuterWindowsById->Remove(mWindowID);}}else{if(nsGlobalWindowInner::sInnerWindowsById){MOZ_ASSERT(nsGlobalWindowInner::sInnerWindowsById->Get(mWindowID),"This window should be in the hash table");nsGlobalWindowInner::sInnerWindowsById->Remove(mWindowID);}}--gRefCnt;#ifdef DEBUGif(!PR_GetEnv("MOZ_QUIET")){nsAutoCStringurl;if(mLastOpenedURI){url=mLastOpenedURI->GetSpecOrDefault();// Data URLs can be very long, so truncate to avoid flooding the log.constuint32_tmaxURLLength=1000;if(url.Length()>maxURLLength){url.Truncate(maxURLLength);}}nsGlobalWindowOuter*outer=nsGlobalWindowOuter::Cast(mOuterWindow);printf_stderr("--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = %s]\n",gRefCnt,static_cast<void*>(ToCanonicalSupports(this)),getpid(),mSerial,static_cast<void*>(ToCanonicalSupports(outer)),url.get());}#endifMOZ_LOG(gDOMLeakPRLog,LogLevel::Debug,("DOMWINDOW %p destroyed",this));if(IsOuterWindow()){JSObject*proxy=GetWrapperMaybeDead();if(proxy){js::SetProxyReservedSlot(proxy,0,js::PrivateValue(nullptr));}// An outer window is destroyed with inner windows still possibly// alive, iterate through the inner windows and null out their// back pointer to this outer, and pull them out of the list of// inner windows.//// Our linked list of inner windows both contains (an nsGlobalWindowOuter),// and our inner windows (nsGlobalWindowInners). This means that we need to// use PRCList*. We can then compare that PRCList* to `this` to see if its an// inner or outer window.PRCList*w;while((w=PR_LIST_HEAD(this))!=this){PR_REMOVE_AND_INIT_LINK(w);}DropOuterWindowDocs();}else{Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,mMutationBits?1:0);if(mListenerManager){mListenerManager->Disconnect();mListenerManager=nullptr;}// An inner window is destroyed, pull it out of the outer window's// list if inner windows.PR_REMOVE_LINK(this);// If our outer window's inner window is this window, null out the// outer window's reference to this window that's being deleted.nsGlobalWindowOuter*outer=GetOuterWindowInternal();if(outer){outer->MaybeClearInnerWindow(AssertInner());}}// We don't have to leave the tab group if we are an inner window.if(mTabGroup&&IsOuterWindow()){mTabGroup->Leave(AsOuter());}// Outer windows are always supposed to call CleanUp before letting themselves// be destroyed. And while CleanUp generally seems to be intended to clean up// outers, we've historically called it for both. Changing this would probably// involve auditing all of the references that inners and outers can have, and// separating the handling into CleanUp() and FreeInnerObjects.if(IsInnerWindow()){CleanUp();}else{MOZ_ASSERT(mCleanedUp);}nsCOMPtr<nsIDeviceSensors>ac=do_GetService(NS_DEVICE_SENSORS_CONTRACTID);if(ac)ac->RemoveWindowAsListener(this);nsLayoutStatics::Release();}voidnsGlobalWindowInner::AddEventTargetObject(DOMEventTargetHelper*aObject){MOZ_ASSERT(IsInnerWindow());mEventTargetObjects.PutEntry(aObject);}voidnsGlobalWindowInner::RemoveEventTargetObject(DOMEventTargetHelper*aObject){MOZ_ASSERT(IsInnerWindow());mEventTargetObjects.RemoveEntry(aObject);}voidnsGlobalWindowInner::DisconnectEventTargetObjects(){for(autoiter=mEventTargetObjects.ConstIter();!iter.Done();iter.Next()){RefPtr<DOMEventTargetHelper>target=iter.Get()->GetKey();target->DisconnectFromOwner();}mEventTargetObjects.Clear();}// staticvoidnsGlobalWindowInner::ShutDown(){AssertIsOnMainThread();// nsGlobalWindowOuter::ShutDown() handles closing gDumpFile.deletesInnerWindowsById;sInnerWindowsById=nullptr;}// staticvoidnsGlobalWindowInner::CleanupCachedXBLHandlers(){if(mCachedXBLPrototypeHandlers&&mCachedXBLPrototypeHandlers->Count()>0){mCachedXBLPrototypeHandlers->Clear();}}voidnsGlobalWindowInner::MaybeForgiveSpamCount(){if(IsOuterWindow()&&IsPopupSpamWindow()){SetIsPopupSpamWindow(false);}}voidnsGlobalWindowInner::SetIsPopupSpamWindow(boolaIsPopupSpam){MOZ_ASSERT(IsOuterWindow());mIsPopupSpam=aIsPopupSpam;if(aIsPopupSpam){++gOpenPopupSpamCount;}else{--gOpenPopupSpamCount;NS_ASSERTION(gOpenPopupSpamCount>=0,"Unbalanced decrement of gOpenPopupSpamCount");}}voidnsGlobalWindowInner::DropOuterWindowDocs(){MOZ_ASSERT(IsOuterWindow());MOZ_ASSERT_IF(mDoc,!mDoc->EventHandlingSuppressed());mDoc=nullptr;mSuspendedDoc=nullptr;}voidnsGlobalWindowInner::CleanUp(){// Guarantee idempotence.if(mCleanedUp)return;mCleanedUp=true;StartDying();DisconnectEventTargetObjects();if(mObserver){nsCOMPtr<nsIObserverService>os=mozilla::services::GetObserverService();if(os){os->RemoveObserver(mObserver,NS_IOSERVICE_OFFLINE_STATUS_TOPIC);os->RemoveObserver(mObserver,MEMORY_PRESSURE_OBSERVER_TOPIC);}RefPtr<StorageNotifierService>sns=StorageNotifierService::GetOrCreate();if(sns){sns->Unregister(mObserver);}if(mIdleService){mIdleService->RemoveIdleObserver(mObserver,MIN_IDLE_NOTIFICATION_TIME_S);}Preferences::RemoveObserver(mObserver,"intl.accept_languages");// Drop its reference to this dying window, in case for some bogus reason// the object stays around.mObserver->Forget();}if(mNavigator){mNavigator->Invalidate();mNavigator=nullptr;}mScreen=nullptr;mMenubar=nullptr;mToolbar=nullptr;mLocationbar=nullptr;mPersonalbar=nullptr;mStatusbar=nullptr;mScrollbars=nullptr;mHistory=nullptr;mCustomElements=nullptr;mFrames=nullptr;mWindowUtils=nullptr;mApplicationCache=nullptr;mIndexedDB=nullptr;mConsole=nullptr;mAudioWorklet=nullptr;mPaintWorklet=nullptr;mExternal=nullptr;mMozSelfSupport=nullptr;mPerformance=nullptr;#ifdef MOZ_WEBSPEECHmSpeechSynthesis=nullptr;#endif#if defined(MOZ_WIDGET_ANDROID)mOrientationChangeObserver=nullptr;#endifClearControllers();mOpener=nullptr;// Forces Releaseif(mContext){mContext=nullptr;// Forces Release}mChromeEventHandler=nullptr;// Forces ReleasemParentTarget=nullptr;if(IsOuterWindow()){nsGlobalWindowInner*inner=GetCurrentInnerWindowInternal();if(inner){inner->CleanUp();}}if(IsInnerWindow()){DisableGamepadUpdates();mHasGamepad=false;DisableVRUpdates();mHasVREvents=false;mHasVRDisplayActivateEvents=false;DisableIdleCallbackRequests();}else{MOZ_ASSERT(!mHasGamepad);MOZ_ASSERT(!mHasVREvents);MOZ_ASSERT(!mHasVRDisplayActivateEvents);}if(mCleanMessageManager){MOZ_ASSERT(mIsChrome,"only chrome should have msg manager cleaned");if(mChromeFields.mMessageManager){static_cast<nsFrameMessageManager*>(mChromeFields.mMessageManager.get())->Disconnect();}}mArguments=nullptr;CleanupCachedXBLHandlers();for(uint32_ti=0;i<mAudioContexts.Length();++i){mAudioContexts[i]->Shutdown();}mAudioContexts.Clear();if(mIdleTimer){mIdleTimer->Cancel();mIdleTimer=nullptr;}mServiceWorkerRegistrationTable.Clear();mIntlUtils=nullptr;}voidnsGlobalWindowInner::ClearControllers(){if(mControllers){uint32_tcount;mControllers->GetControllerCount(&count);while(count--){nsCOMPtr<nsIController>controller;mControllers->GetControllerAt(count,getter_AddRefs(controller));nsCOMPtr<nsIControllerContext>context=do_QueryInterface(controller);if(context)context->SetCommandContext(nullptr);}mControllers=nullptr;}}voidnsGlobalWindowInner::FreeInnerObjects(){NS_ASSERTION(IsInnerWindow(),"Don't free inner objects on an outer window");// Make sure that this is called before we null out the document and// other members that the window destroyed observers could// re-create.NotifyDOMWindowDestroyed(AssertInner());if(auto*reporter=nsWindowMemoryReporter::Get()){reporter->ObserveDOMWindowDetached(AssertInner());}mInnerObjectsFreed=true;// Kill all of the workers for this window.mozilla::dom::workers::CancelWorkersForWindow(AsInner());if(mTimeoutManager){mTimeoutManager->ClearAllTimeouts();}if(mIdleTimer){mIdleTimer->Cancel();mIdleTimer=nullptr;}mIdleObservers.Clear();DisableIdleCallbackRequests();mChromeEventHandler=nullptr;if(mListenerManager){mListenerManager->Disconnect();mListenerManager=nullptr;}mHistory=nullptr;mCustomElements=nullptr;if(mNavigator){mNavigator->OnNavigation();mNavigator->Invalidate();mNavigator=nullptr;}if(mScreen){mScreen=nullptr;}#if defined(MOZ_WIDGET_ANDROID)mOrientationChangeObserver=nullptr;#endifif(mDoc){// Remember the document's principal and URI.mDocumentPrincipal=mDoc->NodePrincipal();mDocumentURI=mDoc->GetDocumentURI();mDocBaseURI=mDoc->GetDocBaseURI();while(mDoc->EventHandlingSuppressed()){mDoc->UnsuppressEventHandlingAndFireEvents(false);}}// Remove our reference to the document and the document principal.mFocusedNode=nullptr;if(mApplicationCache){static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())->Disconnect();mApplicationCache=nullptr;}mIndexedDB=nullptr;UnlinkHostObjectURIs();NotifyWindowIDDestroyed("inner-window-destroyed");CleanupCachedXBLHandlers();for(uint32_ti=0;i<mAudioContexts.Length();++i){mAudioContexts[i]->Shutdown();}mAudioContexts.Clear();DisableGamepadUpdates();mHasGamepad=false;mGamepads.Clear();DisableVRUpdates();mHasVREvents=false;mHasVRDisplayActivateEvents=false;mVRDisplays.Clear();if(mTabChild){while(mBeforeUnloadListenerCount-->0){mTabChild->BeforeUnloadRemoved();}}}//*****************************************************************************// nsGlobalWindowInner::nsISupports//*****************************************************************************// QueryInterface implementation for nsGlobalWindowInnerNS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindowInner)NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY// Make sure this matches the cast in nsGlobalWindowInner::FromWrapper()NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports,nsIDOMEventTarget)NS_INTERFACE_MAP_ENTRY(nsIDOMWindow)NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)NS_INTERFACE_MAP_ENTRY(mozilla::dom::EventTarget)if(aIID.Equals(NS_GET_IID(nsPIDOMWindowInner))){foundInterface=AsInner();}elseif(aIID.Equals(NS_GET_IID(mozIDOMWindow))&&IsInnerWindow()){foundInterface=AsInner();}elseif(aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter))){foundInterface=AsOuter();}elseif(aIID.Equals(NS_GET_IID(mozIDOMWindowProxy))&&IsOuterWindow()){foundInterface=AsOuter();}elseif(aIID.Equals(NS_GET_IID(nsIDOMChromeWindow))&&IsChromeWindow()){foundInterface=static_cast<nsIDOMChromeWindow*>(this);}elseNS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)NS_INTERFACE_MAP_ENDNS_IMPL_CYCLE_COLLECTING_ADDREF(nsGlobalWindowInner)NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGlobalWindowInner)NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindowInner)if(tmp->IsBlackForCC(false)){if(nsCCUncollectableMarker::InGeneration(tmp->mCanSkipCCGeneration)){returntrue;}tmp->mCanSkipCCGeneration=nsCCUncollectableMarker::sGeneration;if(tmp->mCachedXBLPrototypeHandlers){for(autoiter=tmp->mCachedXBLPrototypeHandlers->Iter();!iter.Done();iter.Next()){iter.Data().exposeToActiveJS();}}if(EventListenerManager*elm=tmp->GetExistingListenerManager()){elm->MarkForCC();}if(tmp->mTimeoutManager){tmp->mTimeoutManager->UnmarkGrayTimers();}returntrue;}NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_ENDNS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGlobalWindowInner)returntmp->IsBlackForCC(true);NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_ENDNS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsGlobalWindowInner)returntmp->IsBlackForCC(false);NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_ENDNS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindowInner)NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowInner)if(MOZ_UNLIKELY(cb.WantDebugInfo())){charname[512];nsAutoCStringuri;if(tmp->mDoc&&tmp->mDoc->GetDocumentURI()){uri=tmp->mDoc->GetDocumentURI()->GetSpecOrDefault();}SprintfLiteral(name,"nsGlobalWindowInner # %"PRIu64" %s %s",tmp->mWindowID,tmp->IsInnerWindow()?"inner":"outer",uri.get());cb.DescribeRefCountedNode(tmp->mRefCnt.get(),name);}else{NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindowInner,tmp->mRefCnt.get())}NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArguments)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReturnValue)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerRegistrationTable)#ifdef MOZ_WEBSPEECHNS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSpeechSynthesis)#endifNS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOuterWindow)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTopInnerWindow)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager)if(tmp->mTimeoutManager){tmp->mTimeoutManager->ForEachUnorderedTimeout([&cb](Timeout*timeout){cb.NoteNativeChild(timeout,NS_CYCLE_COLLECTION_PARTICIPANT(Timeout));});}NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHistory)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCustomElements)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStorage)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStorage)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mApplicationCache)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSuspendedDoc)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChild)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleService)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWakeLock)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleRequestExecutor)for(IdleRequest*request:tmp->mIdleRequestCallbacks){cb.NoteNativeChild(request,NS_CYCLE_COLLECTION_PARTICIPANT(IdleRequest));}NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleObservers)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepads)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRDisplays)// Traverse stuff from nsPIDOMWindowNS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameElement)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedNode)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMenubar)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mToolbar)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocationbar)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPersonalbar)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusbar)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScrollbars)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mU2F)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioWorklet)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPaintWorklet)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExternal)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMozSelfSupport)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntlUtils)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)tmp->TraverseHostObjectURIs(cb);NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mBrowserDOMWindow)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mMessageManager)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mGroupMessageManagers)NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mOpenerForInitialContentBrowser)NS_IMPL_CYCLE_COLLECTION_TRAVERSE_ENDNS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)tmp->CleanupCachedXBLHandlers();NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)NS_IMPL_CYCLE_COLLECTION_UNLINK(mArguments)NS_IMPL_CYCLE_COLLECTION_UNLINK(mReturnValue)NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)NS_IMPL_CYCLE_COLLECTION_UNLINK(mServiceWorkerRegistrationTable)#ifdef MOZ_WEBSPEECHNS_IMPL_CYCLE_COLLECTION_UNLINK(mSpeechSynthesis)#endifif(tmp->mOuterWindow){nsGlobalWindowOuter::Cast(tmp->mOuterWindow)->MaybeClearInnerWindow(tmp->AssertInner());NS_IMPL_CYCLE_COLLECTION_UNLINK(mOuterWindow)}if(tmp->mListenerManager){tmp->mListenerManager->Disconnect();NS_IMPL_CYCLE_COLLECTION_UNLINK(mListenerManager)}tmp->UpdateTopInnerWindow();NS_IMPL_CYCLE_COLLECTION_UNLINK(mTopInnerWindow)NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)NS_IMPL_CYCLE_COLLECTION_UNLINK(mHistory)NS_IMPL_CYCLE_COLLECTION_UNLINK(mCustomElements)NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStorage)if(tmp->mApplicationCache){static_cast<nsDOMOfflineResourceList*>(tmp->mApplicationCache.get())->Disconnect();NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplicationCache)}NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuspendedDoc)NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChild)NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleService)NS_IMPL_CYCLE_COLLECTION_UNLINK(mWakeLock)NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleObservers)NS_IMPL_CYCLE_COLLECTION_UNLINK(mGamepads)NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDisplays)// Unlink stuff from nsPIDOMWindowNS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameElement)NS_IMPL_CYCLE_COLLECTION_UNLINK(mFocusedNode)NS_IMPL_CYCLE_COLLECTION_UNLINK(mMenubar)NS_IMPL_CYCLE_COLLECTION_UNLINK(mToolbar)NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocationbar)NS_IMPL_CYCLE_COLLECTION_UNLINK(mPersonalbar)NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusbar)NS_IMPL_CYCLE_COLLECTION_UNLINK(mScrollbars)NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)NS_IMPL_CYCLE_COLLECTION_UNLINK(mU2F)NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioWorklet)NS_IMPL_CYCLE_COLLECTION_UNLINK(mPaintWorklet)NS_IMPL_CYCLE_COLLECTION_UNLINK(mExternal)NS_IMPL_CYCLE_COLLECTION_UNLINK(mMozSelfSupport)NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntlUtils)NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)tmp->UnlinkHostObjectURIs();NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor)tmp->DisableIdleCallbackRequests();if(tmp->IsChromeWindow()){NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mBrowserDOMWindow)if(tmp->mChromeFields.mMessageManager){static_cast<nsFrameMessageManager*>(tmp->mChromeFields.mMessageManager.get())->Disconnect();NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mMessageManager)}tmp->DisconnectAndClearGroupMessageManagers();NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mGroupMessageManagers)NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mOpenerForInitialContentBrowser)}NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPERNS_IMPL_CYCLE_COLLECTION_UNLINK_END#ifdef DEBUGvoidnsGlobalWindowInner::RiskyUnlink(){NS_CYCLE_COLLECTION_INNERNAME.Unlink(this);}#endifNS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindowInner)if(tmp->mCachedXBLPrototypeHandlers){for(autoiter=tmp->mCachedXBLPrototypeHandlers->Iter();!iter.Done();iter.Next()){aCallbacks.Trace(&iter.Data(),"Cached XBL prototype handler",aClosure);}}NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPERNS_IMPL_CYCLE_COLLECTION_TRACE_ENDboolnsGlobalWindowInner::IsBlackForCC(boolaTracingNeeded){if(!nsCCUncollectableMarker::sGeneration){returnfalse;}return(nsCCUncollectableMarker::InGeneration(GetMarkedCCGeneration())||HasKnownLiveWrapper())&&(!aTracingNeeded||HasNothingToTrace(static_cast<nsIDOMEventTarget*>(this)));}//*****************************************************************************// nsGlobalWindowInner::nsIScriptGlobalObject//*****************************************************************************nsresultnsGlobalWindowInner::EnsureScriptEnvironment(){nsGlobalWindowOuter*outer=GetOuterWindowInternal();if(!outer){NS_WARNING("No outer window available!");returnNS_ERROR_FAILURE;}if(outer->GetWrapperPreserveColor()){returnNS_OK;}NS_ASSERTION(!outer->GetCurrentInnerWindowInternal(),"No cached wrapper, but we have an inner window?");// If this window is a [i]frame, don't bother GC'ing when the frame's context// is destroyed since a GC will happen when the frameset or host document is// destroyed anyway.nsCOMPtr<nsIScriptContext>context=newnsJSContext(!IsFrame(),outer);NS_ASSERTION(!outer->mContext,"Will overwrite mContext!");// should probably assert the context is clean???context->WillInitializeContext();nsresultrv=context->InitContext();NS_ENSURE_SUCCESS(rv,rv);outer->mContext=context;returnNS_OK;}nsIScriptContext*nsGlobalWindowInner::GetScriptContext(){nsGlobalWindowOuter*outer=GetOuterWindowInternal();if(!outer){returnnullptr;}returnouter->mContext;}JSObject*nsGlobalWindowInner::GetGlobalJSObject(){returnFastGetGlobalJSObject();}voidnsGlobalWindowInner::TraceGlobalJSObject(JSTracer*aTrc){TraceWrapper(aTrc,"active window global");}boolnsGlobalWindowInner::WouldReuseInnerWindow(nsIDocument*aNewDocument){MOZ_ASSERT(IsOuterWindow());// We reuse the inner window when:// a. We are currently at our original document.// b. At least one of the following conditions are true:// -- The new document is the same as the old document. This means that we're// getting called from document.open().// -- The new document has the same origin as what we have loaded right now.if(!mDoc||!aNewDocument){returnfalse;}if(!mDoc->IsInitialDocument()){returnfalse;}#ifdef DEBUG{nsCOMPtr<nsIURI>uri;mDoc->GetDocumentURI()->CloneIgnoringRef(getter_AddRefs(uri));NS_ASSERTION(NS_IsAboutBlank(uri),"How'd this happen?");}#endif// Great, we're the original document, check for one of the other// conditions.if(mDoc==aNewDocument){returntrue;}boolequal;if(NS_SUCCEEDED(mDoc->NodePrincipal()->Equals(aNewDocument->NodePrincipal(),&equal))&&equal){// The origin is the same.returntrue;}returnfalse;}voidnsGlobalWindowInner::SetInitialPrincipalToSubject(){MOZ_ASSERT(IsOuterWindow());// First, grab the subject principal.nsCOMPtr<nsIPrincipal>newWindowPrincipal=nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();// We should never create windows with an expanded principal.// If we have a system principal, make sure we're not using it for a content// docshell.// NOTE: Please keep this logic in sync with nsWebShellWindow::Initialize().if(nsContentUtils::IsExpandedPrincipal(newWindowPrincipal)||(nsContentUtils::IsSystemPrincipal(newWindowPrincipal)&&GetDocShell()->ItemType()!=nsIDocShellTreeItem::typeChrome)){newWindowPrincipal=nullptr;}// If there's an existing document, bail if it either:if(mDoc){// (a) is not an initial about:blank document, orif(!mDoc->IsInitialDocument())return;// (b) already has the correct principal.if(mDoc->NodePrincipal()==newWindowPrincipal)return;#ifdef DEBUG// If we have a document loaded at this point, it had better be about:blank.// Otherwise, something is really weird. An about:blank page has a// NullPrincipal.boolisNullPrincipal;MOZ_ASSERT(NS_SUCCEEDED(mDoc->NodePrincipal()->GetIsNullPrincipal(&isNullPrincipal))&&isNullPrincipal);#endif}GetDocShell()->CreateAboutBlankContentViewer(newWindowPrincipal);if(mDoc){mDoc->SetIsInitialDocument(true);}nsCOMPtr<nsIPresShell>shell=GetDocShell()->GetPresShell();if(shell&&!shell->DidInitialize()){// Ensure that if someone plays with this document they will get// layout happening.nsRectr=shell->GetPresContext()->GetVisibleArea();shell->Initialize(r.Width(),r.Height());}}PopupControlStatensGlobalWindowInner::PushPopupControlState(PopupControlStateaState,boolaForce)const{return::PushPopupControlState(aState,aForce);}voidnsGlobalWindowInner::PopPopupControlState(PopupControlStateaState)const{::PopPopupControlState(aState);}PopupControlStatensGlobalWindowInner::GetPopupControlState()const{MOZ_ASSERT(NS_IsMainThread());returngPopupControlState;}boolnsGlobalWindowInner::ComputeIsSecureContext(nsIDocument*aDocument,SecureContextFlagsaFlags){MOZ_CRASH("Outer Window Only - notbuilding");}nsresultnsGlobalWindowInner::SetNewDocument(nsIDocument*aDocument,nsISupports*aState,boolaForceReuseInnerWindow){NS_PRECONDITION(mDocumentPrincipal==nullptr,"mDocumentPrincipal prematurely set!");MOZ_ASSERT(aDocument);if(!mOuterWindow){returnNS_ERROR_NOT_INITIALIZED;}// Refuse to set a new document if the call came from an inner// window that's not the current inner window.if(mOuterWindow->GetCurrentInnerWindow()!=AsInner()){returnNS_ERROR_NOT_AVAILABLE;}returnGetOuterWindowInternal()->SetNewDocument(aDocument,aState,aForceReuseInnerWindow);}voidnsGlobalWindowInner::PreloadLocalStorage(){MOZ_ASSERT(IsOuterWindow());if(!Preferences::GetBool(kStorageEnabled)){return;}if(IsChromeWindow()){return;}nsIPrincipal*principal=GetPrincipal();if(!principal){return;}nsresultrv;nsCOMPtr<nsIDOMStorageManager>storageManager=do_GetService("@mozilla.org/dom/localStorage-manager;1",&rv);if(NS_FAILED(rv)){return;}// private browsing windows do not persist local storage to disk so we should// only try to precache storage when we're not a private browsing window.if(principal->GetPrivateBrowsingId()==0){nsCOMPtr<nsIDOMStorage>storage;rv=storageManager->PrecacheStorage(principal,getter_AddRefs(storage));if(NS_SUCCEEDED(rv)){mLocalStorage=static_cast<Storage*>(storage.get());}}}voidnsGlobalWindowInner::DispatchDOMWindowCreated(){MOZ_ASSERT(IsOuterWindow());if(!mDoc){return;}// Fire DOMWindowCreated at chrome event listenersnsContentUtils::DispatchChromeEvent(mDoc,mDoc,NS_LITERAL_STRING("DOMWindowCreated"),true/* bubbles */,false/* not cancellable */);nsCOMPtr<nsIObserverService>observerService=mozilla::services::GetObserverService();// The event dispatching could possibly cause docshell destory, and// consequently cause mDoc to be set to nullptr by DropOuterWindowDocs(),// so check it again here.if(observerService&&mDoc){nsAutoStringorigin;nsIPrincipal*principal=mDoc->NodePrincipal();nsContentUtils::GetUTFOrigin(principal,origin);observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),nsContentUtils::IsSystemPrincipal(principal)?"chrome-document-global-created":"content-document-global-created",origin.get());}}voidnsGlobalWindowInner::ClearStatus(){SetStatusOuter(EmptyString());}voidnsGlobalWindowInner::InnerSetNewDocument(JSContext*aCx,nsIDocument*aDocument){NS_PRECONDITION(IsInnerWindow(),"Must only be called on inner windows");MOZ_ASSERT(aDocument);if(MOZ_LOG_TEST(gDOMLeakPRLog,LogLevel::Debug)){nsIURI*uri=aDocument->GetDocumentURI();MOZ_LOG(gDOMLeakPRLog,LogLevel::Debug,("DOMWINDOW %p SetNewDocument %s",this,uri?uri->GetSpecOrDefault().get():""));}mDoc=aDocument;ClearDocumentDependentSlots(aCx);mFocusedNode=nullptr;mLocalStorage=nullptr;mSessionStorage=nullptr;#ifdef DEBUGmLastOpenedURI=aDocument->GetDocumentURI();#endifTelemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,mMutationBits?1:0);// Clear our mutation bitfield.mMutationBits=0;}voidnsGlobalWindowInner::SetDocShell(nsIDocShell*aDocShell){MOZ_CRASH("Outer Window Only");}voidnsGlobalWindowInner::DetachFromDocShell(){NS_ASSERTION(IsOuterWindow(),"Uh, DetachFromDocShell() called on inner window!");// DetachFromDocShell means the window is being torn down. Drop our// reference to the script context, allowing it to be deleted// later. Meanwhile, keep our weak reference to the script object// so that it can be retrieved later (until it is finalized by the JS GC).// Call FreeInnerObjects on all inner windows, not just the current// one, since some could be held by WindowStateHolder objects that// are GC-owned.RefPtr<nsGlobalWindowInner>inner;for(PRCList*node=PR_LIST_HEAD(this);node!=this;node=PR_NEXT_LINK(inner)){// This cast is safe because `node != this`. Non-this nodes are inner windows.inner=static_cast<nsGlobalWindowInner*>(node);MOZ_ASSERT(inner->IsInnerWindow());MOZ_ASSERT(!inner->mOuterWindow||inner->mOuterWindow==AsOuter());inner->FreeInnerObjects();}// Don't report that we were detached to the nsWindowMemoryReporter, as it// only tracks inner windows.NotifyWindowIDDestroyed("outer-window-destroyed");nsGlobalWindowInner*currentInner=GetCurrentInnerWindowInternal();if(currentInner){NS_ASSERTION(mDoc,"Must have doc!");// Remember the document's principal and URI.mDocumentPrincipal=mDoc->NodePrincipal();mDocumentURI=mDoc->GetDocumentURI();mDocBaseURI=mDoc->GetDocBaseURI();// Release our document referenceDropOuterWindowDocs();mFocusedNode=nullptr;}ClearControllers();mChromeEventHandler=nullptr;// force release nowif(mContext){// When we're about to destroy a top level content window// (for example a tab), we trigger a full GC by passing null as the last// param. We also trigger a full GC for chrome windows.nsJSContext::PokeGC(JS::gcreason::SET_DOC_SHELL,(mTopLevelOuterContentWindow||mIsChrome)?nullptr:GetWrapperPreserveColor());mContext=nullptr;}mDocShell=nullptr;// Weak ReferenceNS_ASSERTION(!mNavigator,"Non-null mNavigator in outer window!");if(mFrames){mFrames->SetDocShell(nullptr);}MaybeForgiveSpamCount();CleanUp();}voidnsGlobalWindowInner::SetOpenerWindow(nsPIDOMWindowOuter*aOpener,boolaOriginalOpener){FORWARD_TO_OUTER_VOID(SetOpenerWindow,(aOpener,aOriginalOpener));nsWeakPtropener=do_GetWeakReference(aOpener);if(opener==mOpener){return;}NS_ASSERTION(!aOriginalOpener||!mSetOpenerWindowCalled,"aOriginalOpener is true, but not first call to ""SetOpenerWindow!");NS_ASSERTION(aOpener||!aOriginalOpener,"Shouldn't set mHadOriginalOpener if aOpener is null");mOpener=opener.forget();NS_ASSERTION(mOpener||!aOpener,"Opener must support weak references!");// Check that the js visible opener matches! We currently don't depend on this// being true outside of nightly, so we disable the assertion in optimized// release / beta builds.nsPIDOMWindowOuter*contentOpener=GetSanitizedOpener(aOpener);// contentOpener is not used when the DIAGNOSTIC_ASSERT is compiled out.mozilla::Unused<<contentOpener;MOZ_DIAGNOSTIC_ASSERT(!contentOpener||!mTabGroup||mTabGroup==nsGlobalWindowOuter::Cast(contentOpener)->mTabGroup);if(aOriginalOpener){MOZ_ASSERT(!mHadOriginalOpener,"Probably too late to call ComputeIsSecureContext again");mHadOriginalOpener=true;mOriginalOpenerWasSecureContext=aOpener->GetCurrentInnerWindow()->IsSecureContext();}#ifdef DEBUGmSetOpenerWindowCalled=true;#endif}voidnsGlobalWindowInner::UpdateParentTarget(){// Try to get our frame element's tab child global (its in-process message// manager). If that fails, fall back to the chrome event handler's tab// child global, and if it doesn't have one, just use the chrome event// handler itself.nsCOMPtr<Element>frameElement=GetOuterWindow()->GetFrameElementInternal();nsCOMPtr<EventTarget>eventTarget=TryGetTabChildGlobalAsEventTarget(frameElement);if(!eventTarget){nsGlobalWindowOuter*topWin=GetScriptableTopInternal();if(topWin){frameElement=topWin->AsOuter()->GetFrameElementInternal();eventTarget=TryGetTabChildGlobalAsEventTarget(frameElement);}}if(!eventTarget){eventTarget=TryGetTabChildGlobalAsEventTarget(mChromeEventHandler);}if(!eventTarget){eventTarget=mChromeEventHandler;}mParentTarget=eventTarget;}EventTarget*nsGlobalWindowInner::GetTargetForDOMEvent(){returnGetOuterWindowInternal();}EventTarget*nsGlobalWindowInner::GetTargetForEventTargetChain(){returnIsInnerWindow()?this:GetCurrentInnerWindowInternal();}nsresultnsGlobalWindowInner::WillHandleEvent(EventChainPostVisitor&aVisitor){returnNS_OK;}nsresultnsGlobalWindowInner::GetEventTargetParent(EventChainPreVisitor&aVisitor){NS_PRECONDITION(IsInnerWindow(),"GetEventTargetParent is used on outer window!?");EventMessagemsg=aVisitor.mEvent->mMessage;aVisitor.mCanHandle=true;aVisitor.mForceContentDispatch=true;//FIXME! Bug 329119if(msg==eResize&&aVisitor.mEvent->IsTrusted()){// QIing to window so that we can keep the old behavior also in case// a child window is handling resize.nsCOMPtr<nsPIDOMWindowInner>window=do_QueryInterface(aVisitor.mEvent->mOriginalTarget);if(window){mIsHandlingResizeEvent=true;}}elseif(msg==eMouseDown&&aVisitor.mEvent->IsTrusted()){gMouseDown=true;}elseif((msg==eMouseUp||msg==eDragEnd)&&aVisitor.mEvent->IsTrusted()){gMouseDown=false;if(gDragServiceDisabled){nsCOMPtr<nsIDragService>ds=do_GetService("@mozilla.org/widget/dragservice;1");if(ds){gDragServiceDisabled=false;ds->Unsuppress();}}}aVisitor.mParentTarget=GetParentTarget();// Handle 'active' event.if(!mIdleObservers.IsEmpty()&&aVisitor.mEvent->IsTrusted()&&(aVisitor.mEvent->HasMouseEventMessage()||aVisitor.mEvent->HasDragEventMessage())){mAddActiveEventFuzzTime=false;}returnNS_OK;}boolnsGlobalWindowInner::ShouldPromptToBlockDialogs(){MOZ_ASSERT(IsOuterWindow());nsGlobalWindowOuter*topWindowOuter=GetScriptableTopInternal();if(!topWindowOuter){NS_ASSERTION(!mDocShell,"ShouldPromptToBlockDialogs() called without a top window?");returntrue;}nsGlobalWindowInner*topWindow=topWindowOuter->GetCurrentInnerWindowInternal();if(!topWindow){returntrue;}returntopWindow->DialogsAreBeingAbused();}boolnsGlobalWindowInner::AreDialogsEnabled(){MOZ_ASSERT(IsOuterWindow());nsGlobalWindowOuter*topWindowOuter=GetScriptableTopInternal();if(!topWindowOuter){NS_ERROR("AreDialogsEnabled() called without a top window?");returnfalse;}// TODO: Warn if no top window?nsGlobalWindowInner*topWindow=topWindowOuter->GetCurrentInnerWindowInternal();if(!topWindow){returnfalse;}// Dialogs are blocked if the content viewer is hiddenif(mDocShell){nsCOMPtr<nsIContentViewer>cv;mDocShell->GetContentViewer(getter_AddRefs(cv));boolisHidden;cv->GetIsHidden(&isHidden);if(isHidden){returnfalse;}}// Dialogs are also blocked if the document is sandboxed with SANDBOXED_MODALS// (or if we have no document, of course). Which document? Who knows; the// spec is daft. See <https://github.com/whatwg/html/issues/1206>. For now// just go ahead and check mDoc, since in everything except edge cases in// which a frame is allow-same-origin but not allow-scripts and is being poked// at by some other window this should be the right thing anyway.if(!mDoc||(mDoc->GetSandboxFlags()&SANDBOXED_MODALS)){returnfalse;}returntopWindow->mAreDialogsEnabled;}boolnsGlobalWindowInner::DialogsAreBeingAbused(){MOZ_ASSERT(IsInnerWindow());NS_ASSERTION(GetScriptableTopInternal()&&GetScriptableTopInternal()->GetCurrentInnerWindowInternal()==this,"DialogsAreBeingAbused called with invalid window");if(mLastDialogQuitTime.IsNull()||nsContentUtils::IsCallerChrome()){returnfalse;}TimeDurationdialogInterval(TimeStamp::Now()-mLastDialogQuitTime);if(dialogInterval.ToSeconds()<Preferences::GetInt("dom.successive_dialog_time_limit",DEFAULT_SUCCESSIVE_DIALOG_TIME_LIMIT)){mDialogAbuseCount++;returnGetPopupControlState()>openAllowed||mDialogAbuseCount>MAX_SUCCESSIVE_DIALOG_COUNT;}// Reset the abuse countermDialogAbuseCount=0;returnfalse;}boolnsGlobalWindowInner::ConfirmDialogIfNeeded(){MOZ_ASSERT(IsOuterWindow());NS_ENSURE_TRUE(mDocShell,false);nsCOMPtr<nsIPromptService>promptSvc=do_GetService("@mozilla.org/embedcomp/prompt-service;1");if(!promptSvc){returntrue;}// Reset popup state while opening a modal dialog, and firing events// about the dialog, to prevent the current state from being active// the whole time a modal dialog is open.nsAutoPopupStatePusherpopupStatePusher(openAbused,true);booldisableDialog=false;nsAutoStringlabel,title;nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,"ScriptDialogLabel",label);nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,"ScriptDialogPreventTitle",title);promptSvc->Confirm(AsOuter(),title.get(),label.get(),&disableDialog);if(disableDialog){DisableDialogs();returnfalse;}returntrue;}voidnsGlobalWindowInner::DisableDialogs(){nsGlobalWindowOuter*topWindowOuter=GetScriptableTopInternal();if(!topWindowOuter){NS_ERROR("DisableDialogs() called without a top window?");return;}nsGlobalWindowInner*topWindow=topWindowOuter->GetCurrentInnerWindowInternal();// TODO: Warn if no top window?if(topWindow){topWindow->mAreDialogsEnabled=false;}}voidnsGlobalWindowInner::EnableDialogs(){nsGlobalWindowOuter*topWindowOuter=GetScriptableTopInternal();if(!topWindowOuter){NS_ERROR("EnableDialogs() called without a top window?");return;}// TODO: Warn if no top window?nsGlobalWindowInner*topWindow=topWindowOuter->GetCurrentInnerWindowInternal();if(topWindow){topWindow->mAreDialogsEnabled=true;}}nsresultnsGlobalWindowInner::PostHandleEvent(EventChainPostVisitor&aVisitor){NS_PRECONDITION(IsInnerWindow(),"PostHandleEvent is used on outer window!?");// Return early if there is nothing to do.switch(aVisitor.mEvent->mMessage){caseeResize:caseeUnload:caseeLoad:break;default:returnNS_OK;}/* mChromeEventHandler and mContext go dangling in the middle of this function under some circumstances (events that destroy the window) without this addref. */nsCOMPtr<nsIDOMEventTarget>kungFuDeathGrip1(mChromeEventHandler);mozilla::Unused<<kungFuDeathGrip1;// These aren't referred to through the functionnsCOMPtr<nsIScriptContext>kungFuDeathGrip2(GetContextInternal());mozilla::Unused<<kungFuDeathGrip2;// These aren't referred to through the functionif(aVisitor.mEvent->mMessage==eResize){mIsHandlingResizeEvent=false;}elseif(aVisitor.mEvent->mMessage==eUnload&&aVisitor.mEvent->IsTrusted()){// If any VR display presentation is active at unload, the next page// will receive a vrdisplayactive event to indicate that it should// immediately begin vr presentation. This should occur when navigating// forwards, navigating backwards, and on page reload.for(constauto&display:mVRDisplays){if(display->IsPresenting()){// Save this VR display ID to trigger vrdisplayactivate event// after the next load event.nsGlobalWindowOuter*outer=GetOuterWindowInternal();if(outer){outer->SetAutoActivateVRDisplayID(display->DisplayId());}// XXX The WebVR 1.1 spec does not define which of multiple VR// presenting VR displays will be chosen during navigation.// As the underlying platform VR API's currently only allow a single// VR display, it is safe to choose the first VR display for now.break;}}// Execute bindingdetached handlers before we tear ourselves// down.if(mDoc){mDoc->BindingManager()->ExecuteDetachedHandlers();}mIsDocumentLoaded=false;}elseif(aVisitor.mEvent->mMessage==eLoad&&aVisitor.mEvent->IsTrusted()){// This is page load event since load events don't propagate to |window|.// @see nsDocument::GetEventTargetParent.mIsDocumentLoaded=true;mTimeoutManager->OnDocumentLoaded();nsCOMPtr<Element>element=GetOuterWindow()->GetFrameElementInternal();nsIDocShell*docShell=GetDocShell();if(element&&GetParentInternal()&&docShell&&docShell->ItemType()!=nsIDocShellTreeItem::typeChrome){// If we're not in chrome, or at a chrome boundary, fire the// onload event for the frame element.nsEventStatusstatus=nsEventStatus_eIgnore;WidgetEventevent(aVisitor.mEvent->IsTrusted(),eLoad);event.mFlags.mBubbles=false;event.mFlags.mCancelable=false;// Most of the time we could get a pres context to pass in here,// but not always (i.e. if this window is not shown there won't// be a pres context available). Since we're not firing a GUI// event we don't need a pres context anyway so we just pass// null as the pres context all the time here.EventDispatcher::Dispatch(element,nullptr,&event,nullptr,&status);}uint32_tautoActivateVRDisplayID=0;nsGlobalWindowOuter*outer=GetOuterWindowInternal();if(outer){autoActivateVRDisplayID=outer->GetAutoActivateVRDisplayID();}if(autoActivateVRDisplayID){DispatchVRDisplayActivate(autoActivateVRDisplayID,VRDisplayEventReason::Navigation);}}returnNS_OK;}voidnsGlobalWindowInner::PoisonOuterWindowProxy(JSObject*aObject){MOZ_ASSERT(IsOuterWindow());if(aObject==GetWrapperMaybeDead()){PoisonWrapper();}}nsresultnsGlobalWindowInner::SetArguments(nsIArray*aArguments){MOZ_ASSERT(IsOuterWindow());nsresultrv;// Historically, we've used the same machinery to handle openDialog arguments// (exposed via window.arguments) and showModalDialog arguments (exposed via// window.dialogArguments), even though the former is XUL-only and uses an XPCOM// array while the latter is web-exposed and uses an arbitrary JS value.// Moreover, per-spec |dialogArguments| is a property of the browsing context// (outer), whereas |arguments| lives on the inner.//// We've now mostly separated them, but the difference is still opaque to// nsWindowWatcher (the caller of SetArguments in this little back-and-forth// embedding waltz we do here).//// So we need to demultiplex the two cases here.nsGlobalWindowInner*currentInner=GetCurrentInnerWindowInternal();mArguments=aArguments;rv=currentInner->DefineArgumentsProperty(aArguments);NS_ENSURE_SUCCESS(rv,rv);returnNS_OK;}nsresultnsGlobalWindowInner::DefineArgumentsProperty(nsIArray*aArguments){MOZ_ASSERT(IsInnerWindow());nsIScriptContext*ctx=GetOuterWindowInternal()->mContext;NS_ENSURE_TRUE(aArguments&&ctx,NS_ERROR_NOT_INITIALIZED);JS::Rooted<JSObject*>obj(RootingCx(),GetWrapperPreserveColor());returnctx->SetProperty(obj,"arguments",aArguments);}//*****************************************************************************// nsGlobalWindowInner::nsIScriptObjectPrincipal//*****************************************************************************nsIPrincipal*nsGlobalWindowInner::GetPrincipal(){if(mDoc){// If we have a document, get the principal from the documentreturnmDoc->NodePrincipal();}if(mDocumentPrincipal){returnmDocumentPrincipal;}// If we don't have a principal and we don't have a document we// ask the parent window for the principal. This can happen when// loading a frameset that has a <frame src="javascript:xxx">, in// that case the global window is used in JS before we've loaded// a document into the window.nsCOMPtr<nsIScriptObjectPrincipal>objPrincipal=do_QueryInterface(GetParentInternal());if(objPrincipal){returnobjPrincipal->GetPrincipal();}returnnullptr;}//*****************************************************************************// nsGlobalWindowInner::nsIDOMWindow//*****************************************************************************boolnsPIDOMWindowInner::AddAudioContext(AudioContext*aAudioContext){MOZ_ASSERT(IsInnerWindow());mAudioContexts.AppendElement(aAudioContext);// Return true if the context should be muted and false if not.nsIDocShell*docShell=GetDocShell();returndocShell&&!docShell->GetAllowMedia()&&!aAudioContext->IsOffline();}voidnsPIDOMWindowInner::RemoveAudioContext(AudioContext*aAudioContext){MOZ_ASSERT(IsInnerWindow());mAudioContexts.RemoveElement(aAudioContext);}voidnsPIDOMWindowInner::MuteAudioContexts(){MOZ_ASSERT(IsInnerWindow());for(uint32_ti=0;i<mAudioContexts.Length();++i){if(!mAudioContexts[i]->IsOffline()){mAudioContexts[i]->Mute();}}}voidnsPIDOMWindowInner::UnmuteAudioContexts(){MOZ_ASSERT(IsInnerWindow());for(uint32_ti=0;i<mAudioContexts.Length();++i){if(!mAudioContexts[i]->IsOffline()){mAudioContexts[i]->Unmute();}}}nsGlobalWindowInner*nsGlobalWindowInner::Window(){returnAssertInner();}nsGlobalWindowInner*nsGlobalWindowInner::Self(){returnAssertInner();}Navigator*nsGlobalWindowInner::Navigator(){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mNavigator){mNavigator=newmozilla::dom::Navigator(AsInner());}returnmNavigator;}nsIDOMNavigator*nsGlobalWindowInner::GetNavigator(){FORWARD_TO_INNER(GetNavigator,(),nullptr);returnNavigator();}nsScreen*nsGlobalWindowInner::GetScreen(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mScreen){mScreen=nsScreen::Create(AsInner());if(!mScreen){aError.Throw(NS_ERROR_UNEXPECTED);returnnullptr;}}returnmScreen;}nsIDOMScreen*nsGlobalWindowInner::GetScreen(){FORWARD_TO_INNER(GetScreen,(),nullptr);ErrorResultdummy;nsIDOMScreen*screen=GetScreen(dummy);dummy.SuppressException();returnscreen;}nsHistory*nsGlobalWindowInner::GetHistory(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mHistory){mHistory=newnsHistory(AsInner());}returnmHistory;}CustomElementRegistry*nsGlobalWindowInner::CustomElements(){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mCustomElements){mCustomElements=newCustomElementRegistry(AsInner());}returnmCustomElements;}Performance*nsPIDOMWindowInner::GetPerformance(){MOZ_ASSERT(IsInnerWindow());CreatePerformanceObjectIfNeeded();returnmPerformance;}Performance*nsGlobalWindowInner::GetPerformance(){returnAsInner()->GetPerformance();}voidnsPIDOMWindowInner::CreatePerformanceObjectIfNeeded(){MOZ_ASSERT(IsInnerWindow());if(mPerformance||!mDoc){return;}RefPtr<nsDOMNavigationTiming>timing=mDoc->GetNavigationTiming();nsCOMPtr<nsITimedChannel>timedChannel(do_QueryInterface(mDoc->GetChannel()));booltimingEnabled=false;if(!timedChannel||!NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled))||!timingEnabled){timedChannel=nullptr;}if(timing){mPerformance=Performance::CreateForMainThread(this,timing,timedChannel);}}boolnsPIDOMWindowInner::IsSecureContext()const{returnnsGlobalWindowInner::Cast(this)->IsSecureContext();}boolnsPIDOMWindowInner::IsSecureContextIfOpenerIgnored()const{returnnsGlobalWindowInner::Cast(this)->IsSecureContextIfOpenerIgnored();}voidnsPIDOMWindowInner::Suspend(){nsGlobalWindowInner::Cast(this)->Suspend();}voidnsPIDOMWindowInner::Resume(){nsGlobalWindowInner::Cast(this)->Resume();}voidnsPIDOMWindowInner::Freeze(){nsGlobalWindowInner::Cast(this)->Freeze();}voidnsPIDOMWindowInner::Thaw(){nsGlobalWindowInner::Cast(this)->Thaw();}voidnsPIDOMWindowInner::SyncStateFromParentWindow(){nsGlobalWindowInner::Cast(this)->SyncStateFromParentWindow();}voidnsGlobalWindowInner::UpdateTopInnerWindow(){if(!IsInnerWindow()||AsInner()->IsTopInnerWindow()||!mTopInnerWindow){return;}mTopInnerWindow->UpdateWebSocketCount(-(int32_t)mNumOfOpenWebSockets);}voidnsPIDOMWindowInner::AddPeerConnection(){MOZ_ASSERT(NS_IsMainThread());MOZ_ASSERT(IsInnerWindow());mTopInnerWindow?mTopInnerWindow->mActivePeerConnections++:mActivePeerConnections++;}voidnsPIDOMWindowInner::RemovePeerConnection(){MOZ_ASSERT(NS_IsMainThread());MOZ_ASSERT(IsInnerWindow());MOZ_ASSERT(mTopInnerWindow?mTopInnerWindow->mActivePeerConnections:mActivePeerConnections);mTopInnerWindow?mTopInnerWindow->mActivePeerConnections--:mActivePeerConnections--;}boolnsPIDOMWindowInner::HasActivePeerConnections(){MOZ_ASSERT(NS_IsMainThread());MOZ_ASSERT(IsInnerWindow());returnmTopInnerWindow?mTopInnerWindow->mActivePeerConnections:mActivePeerConnections;}boolnsPIDOMWindowInner::IsPlayingAudio(){for(uint32_ti=0;i<mAudioContexts.Length();i++){if(mAudioContexts[i]->IsRunning()){returntrue;}}RefPtr<AudioChannelService>acs=AudioChannelService::Get();if(!acs){returnfalse;}autoouter=GetOuterWindow();if(!outer){// We've been unlinked and are about to die. Not a good time to pretend to// be playing audio.returnfalse;}returnacs->IsWindowActive(outer);}boolnsPIDOMWindowInner::IsDocumentLoaded()const{returnmIsDocumentLoaded;}mozilla::dom::TimeoutManager&nsPIDOMWindowInner::TimeoutManager(){return*mTimeoutManager;}boolnsPIDOMWindowInner::IsRunningTimeout(){returnTimeoutManager().IsRunningTimeout();}voidnsPIDOMWindowInner::TryToCacheTopInnerWindow(){if(mHasTriedToCacheTopInnerWindow){return;}MOZ_ASSERT(!mInnerObjectsFreed);mHasTriedToCacheTopInnerWindow=true;nsGlobalWindowInner*window=nsGlobalWindowInner::Cast(AsInner());MOZ_ASSERT(window);if(nsCOMPtr<nsPIDOMWindowOuter>topOutter=window->GetScriptableTop()){mTopInnerWindow=topOutter->GetCurrentInnerWindow();}}voidnsPIDOMWindowInner::UpdateActiveIndexedDBTransactionCount(int32_taDelta){MOZ_ASSERT(NS_IsMainThread());if(aDelta==0){return;}TabGroup()->IndexedDBTransactionCounter()+=aDelta;}voidnsPIDOMWindowInner::UpdateActiveIndexedDBDatabaseCount(int32_taDelta){MOZ_ASSERT(NS_IsMainThread());if(aDelta==0){return;}// We count databases but not transactions because only active databases// could block throttling.uint32_t&counter=mTopInnerWindow?mTopInnerWindow->mNumOfIndexedDBDatabases:mNumOfIndexedDBDatabases;counter+=aDelta;TabGroup()->IndexedDBDatabaseCounter()+=aDelta;}boolnsPIDOMWindowInner::HasActiveIndexedDBDatabases(){MOZ_ASSERT(NS_IsMainThread());returnmTopInnerWindow?mTopInnerWindow->mNumOfIndexedDBDatabases>0:mNumOfIndexedDBDatabases>0;}voidnsPIDOMWindowInner::UpdateWebSocketCount(int32_taDelta){MOZ_ASSERT(NS_IsMainThread());if(aDelta==0){return;}if(mTopInnerWindow&&!IsTopInnerWindow()){mTopInnerWindow->UpdateWebSocketCount(aDelta);}MOZ_DIAGNOSTIC_ASSERT(aDelta>0||((aDelta+mNumOfOpenWebSockets)<mNumOfOpenWebSockets));mNumOfOpenWebSockets+=aDelta;}boolnsPIDOMWindowInner::HasOpenWebSockets()const{MOZ_ASSERT(NS_IsMainThread());returnmNumOfOpenWebSockets||(mTopInnerWindow&&mTopInnerWindow->mNumOfOpenWebSockets);}boolnsPIDOMWindowInner::GetAudioCaptured()const{MOZ_ASSERT(IsInnerWindow());returnmAudioCaptured;}nsresultnsPIDOMWindowInner::SetAudioCapture(boolaCapture){MOZ_ASSERT(IsInnerWindow());mAudioCaptured=aCapture;RefPtr<AudioChannelService>service=AudioChannelService::GetOrCreate();if(service){service->SetWindowAudioCaptured(GetOuterWindow(),mWindowID,aCapture);}returnNS_OK;}// nsISpeechSynthesisGetter#ifdef MOZ_WEBSPEECHSpeechSynthesis*nsGlobalWindowInner::GetSpeechSynthesis(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mSpeechSynthesis){mSpeechSynthesis=newSpeechSynthesis(AsInner());}returnmSpeechSynthesis;}boolnsGlobalWindowInner::HasActiveSpeechSynthesis(){MOZ_ASSERT(IsInnerWindow());if(mSpeechSynthesis){return!mSpeechSynthesis->HasEmptyQueue();}returnfalse;}#endifalready_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::GetParentOuter(){MOZ_RELEASE_ASSERT(IsOuterWindow());if(!mDocShell){returnnullptr;}nsCOMPtr<nsPIDOMWindowOuter>parent;if(mDocShell->GetIsMozBrowser()){parent=AsOuter();}else{parent=GetParent();}returnparent.forget();}already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::GetParent(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetParentOuter,(),aError,nullptr);}/** * GetScriptableParent is called when script reads window.parent. * * In contrast to GetRealParent, GetScriptableParent respects <iframe * mozbrowser> boundaries, so if |this| is contained by an <iframe * mozbrowser>, we will return |this| as its own parent. */nsPIDOMWindowOuter*nsGlobalWindowInner::GetScriptableParent(){FORWARD_TO_OUTER(GetScriptableParent,(),nullptr);nsCOMPtr<nsPIDOMWindowOuter>parent=GetParentOuter();returnparent.get();}/** * Behavies identically to GetScriptableParent extept that it returns null * if GetScriptableParent would return this window. */nsPIDOMWindowOuter*nsGlobalWindowInner::GetScriptableParentOrNull(){FORWARD_TO_OUTER(GetScriptableParentOrNull,(),nullptr);MOZ_CRASH("Should be in outer by now");}/** * nsPIDOMWindow::GetParent (when called from C++) is just a wrapper around * GetRealParent. */already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::GetParent(){MOZ_ASSERT(IsOuterWindow());if(!mDocShell){returnnullptr;}nsCOMPtr<nsIDocShell>parent;mDocShell->GetSameTypeParentIgnoreBrowserBoundaries(getter_AddRefs(parent));if(parent){nsCOMPtr<nsPIDOMWindowOuter>win=parent->GetWindow();returnwin.forget();}nsCOMPtr<nsPIDOMWindowOuter>win(AsOuter());returnwin.forget();}/** * GetScriptableTop is called when script reads window.top. * * In contrast to GetRealTop, GetScriptableTop respects <iframe mozbrowser> * boundaries. If we encounter a window owned by an <iframe mozbrowser> while * walking up the window hierarchy, we'll stop and return that window. */nsPIDOMWindowOuter*nsGlobalWindowInner::GetScriptableTop(){FORWARD_TO_OUTER(GetScriptableTop,(),nullptr);MOZ_CRASH("Outer window expected!");}already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::GetTop(){MOZ_CRASH("Outer window only");}voidnsGlobalWindowInner::GetContentOuter(JSContext*aCx,JS::MutableHandle<JSObject*>aRetval,CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());nsCOMPtr<nsPIDOMWindowOuter>content=GetContentInternal(aError,aCallerType);if(aError.Failed()){return;}if(content){JS::Rooted<JS::Value>val(aCx);aError=nsContentUtils::WrapNative(aCx,content,&val);if(aError.Failed()){return;}aRetval.set(&val.toObject());return;}aRetval.set(nullptr);}voidnsGlobalWindowInner::GetContent(JSContext*aCx,JS::MutableHandle<JSObject*>aRetval,CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetContentOuter,(aCx,aRetval,aCallerType,aError),aError,);}already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::GetContentInternal(ErrorResult&aError,CallerTypeaCallerType){MOZ_ASSERT(IsOuterWindow());// First check for a named frame named "content"nsCOMPtr<nsPIDOMWindowOuter>domWindow=GetChildWindow(NS_LITERAL_STRING("content"));if(domWindow){returndomWindow.forget();}// If we're contained in <iframe mozbrowser>, then GetContent is the same as// window.top.if(mDocShell&&mDocShell->GetIsInMozBrowser()){returnGetTopOuter();}nsCOMPtr<nsIDocShellTreeItem>primaryContent;if(aCallerType!=CallerType::System){if(mDoc){mDoc->WarnOnceAbout(nsIDocument::eWindowContentUntrusted);}// If we're called by non-chrome code, make sure we don't return// the primary content window if the calling tab is hidden. In// such a case we return the same-type root in the hidden tab,// which is "good enough", for now.nsCOMPtr<nsIBaseWindow>baseWin(do_QueryInterface(mDocShell));if(baseWin){boolvisible=false;baseWin->GetVisibility(&visible);if(!visible){mDocShell->GetSameTypeRootTreeItem(getter_AddRefs(primaryContent));}}}if(!primaryContent){nsCOMPtr<nsIDocShellTreeOwner>treeOwner=GetTreeOwner();if(!treeOwner){aError.Throw(NS_ERROR_FAILURE);returnnullptr;}treeOwner->GetPrimaryContentShell(getter_AddRefs(primaryContent));}if(!primaryContent){returnnullptr;}domWindow=primaryContent->GetWindow();returndomWindow.forget();}MozSelfSupport*nsGlobalWindowInner::GetMozSelfSupport(ErrorResult&aError){MOZ_ASSERT(IsInnerWindow());if(mMozSelfSupport){returnmMozSelfSupport;}// We're called from JS and want to use out existing JSContext (and,// importantly, its compartment!) here.AutoJSContextcx;GlobalObjectglobal(cx,FastGetGlobalJSObject());mMozSelfSupport=MozSelfSupport::Constructor(global,cx,aError);returnmMozSelfSupport;}nsresultnsGlobalWindowInner::GetPrompter(nsIPrompt**aPrompt){if(IsInnerWindow()){nsGlobalWindowOuter*outer=GetOuterWindowInternal();if(!outer){NS_WARNING("No outer window available!");returnNS_ERROR_NOT_INITIALIZED;}returnouter->GetPrompter(aPrompt);}if(!mDocShell)returnNS_ERROR_FAILURE;nsCOMPtr<nsIPrompt>prompter(do_GetInterface(mDocShell));NS_ENSURE_TRUE(prompter,NS_ERROR_NO_INTERFACE);prompter.forget(aPrompt);returnNS_OK;}BarProp*nsGlobalWindowInner::GetMenubar(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mMenubar){mMenubar=newMenubarProp(AssertInner());}returnmMenubar;}BarProp*nsGlobalWindowInner::GetToolbar(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mToolbar){mToolbar=newToolbarProp(AssertInner());}returnmToolbar;}BarProp*nsGlobalWindowInner::GetLocationbar(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mLocationbar){mLocationbar=newLocationbarProp(AssertInner());}returnmLocationbar;}BarProp*nsGlobalWindowInner::GetPersonalbar(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mPersonalbar){mPersonalbar=newPersonalbarProp(AssertInner());}returnmPersonalbar;}BarProp*nsGlobalWindowInner::GetStatusbar(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mStatusbar){mStatusbar=newStatusbarProp(AssertInner());}returnmStatusbar;}BarProp*nsGlobalWindowInner::GetScrollbars(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mScrollbars){mScrollbars=newScrollbarsProp(AssertInner());}returnmScrollbars;}boolnsGlobalWindowInner::GetClosedOuter(){MOZ_RELEASE_ASSERT(IsOuterWindow());// If someone called close(), or if we don't have a docshell, we're closed.returnmIsClosed||!mDocShell;}boolnsGlobalWindowInner::GetClosed(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetClosedOuter,(),aError,false);}boolnsGlobalWindowInner::Closed(){MOZ_ASSERT(IsOuterWindow());returnGetClosedOuter();}nsDOMWindowList*nsGlobalWindowInner::GetWindowList(){MOZ_ASSERT(IsOuterWindow());if(!mFrames&&mDocShell){mFrames=newnsDOMWindowList(mDocShell);}returnmFrames;}already_AddRefed<nsIDOMWindowCollection>nsGlobalWindowInner::GetFrames(){FORWARD_TO_OUTER(GetFrames,(),nullptr);nsCOMPtr<nsIDOMWindowCollection>frames=GetWindowList();returnframes.forget();}already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::IndexedGetterOuter(uint32_taIndex){MOZ_RELEASE_ASSERT(IsOuterWindow());nsDOMWindowList*windows=GetWindowList();NS_ENSURE_TRUE(windows,nullptr);returnwindows->IndexedGetter(aIndex);}already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::IndexedGetter(uint32_taIndex){FORWARD_TO_OUTER(IndexedGetterOuter,(aIndex),nullptr);MOZ_CRASH();}boolnsGlobalWindowInner::DoResolve(JSContext*aCx,JS::Handle<JSObject*>aObj,JS::Handle<jsid>aId,JS::MutableHandle<JS::PropertyDescriptor>aDesc){MOZ_ASSERT(IsInnerWindow());// Note: Keep this in sync with MayResolve.// Note: The infallibleInit call in GlobalResolve depends on this check.if(!JSID_IS_STRING(aId)){returntrue;}boolfound;if(!WebIDLGlobalNameHash::DefineIfEnabled(aCx,aObj,aId,aDesc,&found)){returnfalse;}if(found){returntrue;}nsresultrv=nsWindowSH::GlobalResolve(AssertInner(),aCx,aObj,aId,aDesc);if(NS_FAILED(rv)){returnThrow(aCx,rv);}returntrue;}/* static */boolnsGlobalWindowInner::MayResolve(jsidaId){// Note: This function does not fail and may not have any side-effects.// Note: Keep this in sync with DoResolve.if(!JSID_IS_STRING(aId)){returnfalse;}if(aId==XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_COMPONENTS)){returntrue;}if(aId==XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS)||aId==XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS_CLASS)){// We only resolve .controllers/.Controllers in release builds and on non-chrome// windows, but let's not worry about any of that stuff.returntrue;}if(WebIDLGlobalNameHash::MayResolve(aId)){returntrue;}nsScriptNameSpaceManager*nameSpaceManager=PeekNameSpaceManager();if(!nameSpaceManager){// Really shouldn't happen. Fail safe.returntrue;}nsAutoStringname;AssignJSFlatString(name,JSID_TO_FLAT_STRING(aId));returnnameSpaceManager->LookupName(name);}voidnsGlobalWindowInner::GetOwnPropertyNames(JSContext*aCx,JS::AutoIdVector&aNames,boolaEnumerableOnly,ErrorResult&aRv){if(aEnumerableOnly){// The names we would return from here get defined on the window via one of// two codepaths. The ones coming from the WebIDLGlobalNameHash will end up// in the DefineConstructor function in BindingUtils, which always defines// things as non-enumerable. The ones coming from the script namespace// manager get defined by nsDOMClassInfo::PostCreatePrototype calling// ResolvePrototype and using the resulting descriptot to define the// property. ResolvePrototype always passes 0 to the FillPropertyDescriptor// for the property attributes, so all those are non-enumerable as well.//// So in the aEnumerableOnly case we have nothing to do.return;}MOZ_ASSERT(IsInnerWindow());// "Components" is marked as enumerable but only resolved on demand :-/.//aNames.AppendElement(NS_LITERAL_STRING("Components"));nsScriptNameSpaceManager*nameSpaceManager=GetNameSpaceManager();if(nameSpaceManager){JS::Rooted<JSObject*>wrapper(aCx,GetWrapper());// There are actually two ways we can get called here: For normal// enumeration or for Xray enumeration. In the latter case, we want to// return all possible WebIDL names, because we don't really support// deleting these names off our Xray; trying to resolve them will just make// them come back. In the former case, we want to avoid returning deleted// names. But the JS engine already knows about the non-deleted// already-resolved names, so we can just return the so-far-unresolved ones.//// We can tell which case we're in by whether aCx is in our wrapper's// compartment. If not, we're in the Xray case.WebIDLGlobalNameHash::NameTypenameType=js::IsObjectInContextCompartment(wrapper,aCx)?WebIDLGlobalNameHash::UnresolvedNamesOnly:WebIDLGlobalNameHash::AllNames;if(!WebIDLGlobalNameHash::GetNames(aCx,wrapper,nameType,aNames)){aRv.NoteJSContextException(aCx);}for(autoi=nameSpaceManager->GlobalNameIter();!i.Done();i.Next()){constGlobalNameMapEntry*entry=i.Get();if(nsWindowSH::NameStructEnabled(aCx,AssertInner(),entry->mKey,entry->mGlobalName)){// Just append all of these; even if they get deleted our resolve hook// just goes ahead and recreates them.JSString*str=JS_AtomizeUCStringN(aCx,entry->mKey.BeginReading(),entry->mKey.Length());if(!str||!aNames.append(NON_INTEGER_ATOM_TO_JSID(str))){aRv.NoteJSContextException(aCx);return;}}}}}/* static */boolnsGlobalWindowInner::IsPrivilegedChromeWindow(JSContext*aCx,JSObject*aObj){// For now, have to deal with XPConnect objects here.returnxpc::WindowOrNull(aObj)->IsChromeWindow()&&nsContentUtils::ObjectPrincipal(aObj)==nsContentUtils::GetSystemPrincipal();}/* static */boolnsGlobalWindowInner::IsRequestIdleCallbackEnabled(JSContext*aCx,JSObject*aObj){// The requestIdleCallback should always be enabled for system code.returnnsContentUtils::RequestIdleCallbackEnabled()||nsContentUtils::IsSystemCaller(aCx);}nsIDOMOfflineResourceList*nsGlobalWindowInner::GetApplicationCache(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mApplicationCache){nsCOMPtr<nsIWebNavigation>webNav(do_QueryInterface(GetDocShell()));if(!webNav||!mDoc){aError.Throw(NS_ERROR_FAILURE);returnnullptr;}nsCOMPtr<nsIURI>uri;aError=webNav->GetCurrentURI(getter_AddRefs(uri));if(aError.Failed()){returnnullptr;}nsCOMPtr<nsIURI>manifestURI;nsContentUtils::GetOfflineAppManifest(mDoc,getter_AddRefs(manifestURI));RefPtr<nsDOMOfflineResourceList>applicationCache=newnsDOMOfflineResourceList(manifestURI,uri,mDoc->NodePrincipal(),AsInner());applicationCache->Init();mApplicationCache=applicationCache;}returnmApplicationCache;}already_AddRefed<nsIDOMOfflineResourceList>nsGlobalWindowInner::GetApplicationCache(){FORWARD_TO_INNER(GetApplicationCache,(),nullptr);ErrorResultdummy;nsCOMPtr<nsIDOMOfflineResourceList>applicationCache=GetApplicationCache(dummy);dummy.SuppressException();returnapplicationCache.forget();}Crypto*nsGlobalWindowInner::GetCrypto(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mCrypto){mCrypto=newCrypto();mCrypto->Init(this);}returnmCrypto;}mozilla::dom::U2F*nsGlobalWindowInner::GetU2f(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mU2F){RefPtr<U2F>u2f=newU2F(AsInner());u2f->Init(aError);if(NS_WARN_IF(aError.Failed())){returnnullptr;}mU2F=u2f;}returnmU2F;}nsIControllers*nsGlobalWindowInner::GetControllersOuter(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());if(!mControllers){nsresultrv;mControllers=do_CreateInstance(kXULControllersCID,&rv);if(NS_FAILED(rv)){aError.Throw(rv);returnnullptr;}// Add in the default controllernsCOMPtr<nsIController>controller=do_CreateInstance(NS_WINDOWCONTROLLER_CONTRACTID,&rv);if(NS_FAILED(rv)){aError.Throw(rv);returnnullptr;}mControllers->InsertControllerAt(0,controller);nsCOMPtr<nsIControllerContext>controllerContext=do_QueryInterface(controller);if(!controllerContext){aError.Throw(NS_ERROR_FAILURE);returnnullptr;}controllerContext->SetCommandContext(static_cast<nsIDOMWindow*>(this));}returnmControllers;}nsIControllers*nsGlobalWindowInner::GetControllers(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetControllersOuter,(aError),aError,nullptr);}nsresultnsGlobalWindowInner::GetControllers(nsIControllers**aResult){FORWARD_TO_INNER(GetControllers,(aResult),NS_ERROR_UNEXPECTED);ErrorResultrv;nsCOMPtr<nsIControllers>controllers=GetControllers(rv);controllers.forget(aResult);returnrv.StealNSResult();}nsPIDOMWindowOuter*nsGlobalWindowInner::GetSanitizedOpener(nsPIDOMWindowOuter*aOpener){if(!aOpener){returnnullptr;}nsGlobalWindowOuter*win=nsGlobalWindowOuter::Cast(aOpener);// First, ensure that we're not handing back a chrome window to content:if(win->IsChromeWindow()){returnnullptr;}// We don't want to reveal the opener if the opener is a mail window,// because opener can be used to spoof the contents of a message (bug 105050).// So, we look in the opener's root docshell to see if it's a mail window.nsCOMPtr<nsIDocShell>openerDocShell=aOpener->GetDocShell();if(openerDocShell){nsCOMPtr<nsIDocShellTreeItem>openerRootItem;openerDocShell->GetRootTreeItem(getter_AddRefs(openerRootItem));nsCOMPtr<nsIDocShell>openerRootDocShell(do_QueryInterface(openerRootItem));if(openerRootDocShell){uint32_tappType;nsresultrv=openerRootDocShell->GetAppType(&appType);if(NS_SUCCEEDED(rv)&&appType!=nsIDocShell::APP_TYPE_MAIL){returnaOpener;}}}returnnullptr;}nsPIDOMWindowOuter*nsGlobalWindowInner::GetOpenerWindowOuter(){MOZ_RELEASE_ASSERT(IsOuterWindow());nsCOMPtr<nsPIDOMWindowOuter>opener=do_QueryReferent(mOpener);if(!opener){returnnullptr;}// First, check if we were called from a privileged chrome scriptif(nsContentUtils::LegacyIsCallerChromeOrNativeCode()){// Catch the case where we're chrome but the opener is not...if(GetPrincipal()==nsContentUtils::GetSystemPrincipal()&&nsGlobalWindowOuter::Cast(opener)->GetPrincipal()!=nsContentUtils::GetSystemPrincipal()){returnnullptr;}returnopener;}returnGetSanitizedOpener(opener);}nsPIDOMWindowOuter*nsGlobalWindowInner::GetOpenerWindow(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetOpenerWindowOuter,(),aError,nullptr);}voidnsGlobalWindowInner::GetOpener(JSContext*aCx,JS::MutableHandle<JS::Value>aRetval,ErrorResult&aError){MOZ_ASSERT(IsInnerWindow());nsCOMPtr<nsPIDOMWindowOuter>opener=GetOpenerWindow(aError);if(aError.Failed()||!opener){aRetval.setNull();return;}aError=nsContentUtils::WrapNative(aCx,opener,aRetval);}already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::GetOpener(){FORWARD_TO_OUTER(GetOpener,(),nullptr);nsCOMPtr<nsPIDOMWindowOuter>opener=GetOpenerWindowOuter();returnopener.forget();}voidnsGlobalWindowInner::SetOpener(JSContext*aCx,JS::Handle<JS::Value>aOpener,ErrorResult&aError){// Check if we were called from a privileged chrome script. If not, and if// aOpener is not null, just define aOpener on our inner window's JS object,// wrapped into the current compartment so that for Xrays we define on the// Xray expando object, but don't set it on the outer window, so that it'll// get reset on navigation. This is just like replaceable properties, but// we're not quite readonly.if(!aOpener.isNull()&&!nsContentUtils::IsCallerChrome()){RedefineProperty(aCx,"opener",aOpener,aError);return;}if(!aOpener.isObjectOrNull()){// Chrome code trying to set some random value as openeraError.Throw(NS_ERROR_INVALID_ARG);return;}nsPIDOMWindowInner*win=nullptr;if(aOpener.isObject()){JSObject*unwrapped=js::CheckedUnwrap(&aOpener.toObject(),/* stopAtWindowProxy = */false);if(!unwrapped){aError.Throw(NS_ERROR_DOM_SECURITY_ERR);return;}auto*globalWindow=xpc::WindowOrNull(unwrapped);if(!globalWindow){// Wasn't a windowaError.Throw(NS_ERROR_INVALID_ARG);return;}win=globalWindow->AsInner();}nsPIDOMWindowOuter*outer=nullptr;if(win){if(!win->IsCurrentInnerWindow()){aError.Throw(NS_ERROR_FAILURE);return;}outer=win->GetOuterWindow();}SetOpenerWindow(outer,false);}voidnsGlobalWindowInner::GetStatusOuter(nsAString&aStatus){MOZ_RELEASE_ASSERT(IsOuterWindow());aStatus=mStatus;}voidnsGlobalWindowInner::GetStatus(nsAString&aStatus,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetStatusOuter,(aStatus),aError,);}voidnsGlobalWindowInner::SetStatusOuter(constnsAString&aStatus){MOZ_RELEASE_ASSERT(IsOuterWindow());mStatus=aStatus;/* * If caller is not chrome and dom.disable_window_status_change is true, * prevent propagating window.status to the UI by exiting early */if(!CanSetProperty("dom.disable_window_status_change")){return;}nsCOMPtr<nsIWebBrowserChrome>browserChrome=GetWebBrowserChrome();if(browserChrome){browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT,PromiseFlatString(aStatus).get());}}voidnsGlobalWindowInner::SetStatus(constnsAString&aStatus,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(SetStatusOuter,(aStatus),aError,);}voidnsGlobalWindowInner::GetNameOuter(nsAString&aName){MOZ_RELEASE_ASSERT(IsOuterWindow());if(mDocShell){mDocShell->GetName(aName);}}voidnsGlobalWindowInner::GetName(nsAString&aName,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetNameOuter,(aName),aError,);}voidnsGlobalWindowInner::SetNameOuter(constnsAString&aName,mozilla::ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());if(mDocShell){aError=mDocShell->SetName(aName);}}voidnsGlobalWindowInner::SetName(constnsAString&aName,mozilla::ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(SetNameOuter,(aName,aError),aError,);}// Helper functions used by many methods below.int32_tnsGlobalWindowInner::DevToCSSIntPixels(int32_tpx){if(!mDocShell)returnpx;// assume 1:1RefPtr<nsPresContext>presContext;mDocShell->GetPresContext(getter_AddRefs(presContext));if(!presContext)returnpx;returnpresContext->DevPixelsToIntCSSPixels(px);}int32_tnsGlobalWindowInner::CSSToDevIntPixels(int32_tpx){if(!mDocShell)returnpx;// assume 1:1RefPtr<nsPresContext>presContext;mDocShell->GetPresContext(getter_AddRefs(presContext));if(!presContext)returnpx;returnpresContext->CSSPixelsToDevPixels(px);}nsIntSizensGlobalWindowInner::DevToCSSIntPixels(nsIntSizepx){if(!mDocShell)returnpx;// assume 1:1RefPtr<nsPresContext>presContext;mDocShell->GetPresContext(getter_AddRefs(presContext));if(!presContext)returnpx;returnnsIntSize(presContext->DevPixelsToIntCSSPixels(px.width),presContext->DevPixelsToIntCSSPixels(px.height));}nsIntSizensGlobalWindowInner::CSSToDevIntPixels(nsIntSizepx){if(!mDocShell)returnpx;// assume 1:1RefPtr<nsPresContext>presContext;mDocShell->GetPresContext(getter_AddRefs(presContext));if(!presContext)returnpx;returnnsIntSize(presContext->CSSPixelsToDevPixels(px.width),presContext->CSSPixelsToDevPixels(px.height));}nsresultnsGlobalWindowInner::GetInnerSize(CSSIntSize&aSize){MOZ_ASSERT(IsOuterWindow());EnsureSizeAndPositionUpToDate();NS_ENSURE_STATE(mDocShell);RefPtr<nsPresContext>presContext;mDocShell->GetPresContext(getter_AddRefs(presContext));RefPtr<nsIPresShell>presShell=mDocShell->GetPresShell();if(!presContext||!presShell){aSize=CSSIntSize(0,0);returnNS_OK;}/* * On platforms with resolution-based zooming, the CSS viewport * and visual viewport may not be the same. The inner size should * be the visual viewport, but we fall back to the CSS viewport * if it is not set. */if(presShell->IsScrollPositionClampingScrollPortSizeSet()){aSize=CSSIntRect::FromAppUnitsRounded(presShell->GetScrollPositionClampingScrollPortSize());}else{RefPtr<nsViewManager>viewManager=presShell->GetViewManager();if(viewManager){viewManager->FlushDelayedResize(false);}aSize=CSSIntRect::FromAppUnitsRounded(presContext->GetVisibleArea().Size());}returnNS_OK;}int32_tnsGlobalWindowInner::GetInnerWidthOuter(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());CSSIntSizesize;aError=GetInnerSize(size);returnsize.width;}int32_tnsGlobalWindowInner::GetInnerWidth(CallerTypeaCallerType,ErrorResult&aError){// We ignore aCallerType; we only have that argument because some other things// called by GetReplaceableWindowCoord need it. If this ever changes, fix// nsresult nsGlobalWindowInner::GetInnerWidth(int32_t* aInnerWidth)// to actually take a useful CallerType and pass it in here.FORWARD_TO_OUTER_OR_THROW(GetInnerWidthOuter,(aError),aError,0);}voidnsGlobalWindowInner::GetInnerWidth(JSContext*aCx,JS::MutableHandle<JS::Value>aValue,CallerTypeaCallerType,ErrorResult&aError){GetReplaceableWindowCoord(aCx,&nsGlobalWindowInner::GetInnerWidth,aValue,aCallerType,aError);}nsresultnsGlobalWindowInner::GetInnerWidth(int32_t*aInnerWidth){FORWARD_TO_INNER(GetInnerWidth,(aInnerWidth),NS_ERROR_UNEXPECTED);ErrorResultrv;// Callee doesn't care about the caller type, but play it safe.*aInnerWidth=GetInnerWidth(CallerType::NonSystem,rv);returnrv.StealNSResult();}voidnsGlobalWindowInner::SetInnerWidthOuter(int32_taInnerWidth,CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());if(!mDocShell){aError.Throw(NS_ERROR_UNEXPECTED);return;}CheckSecurityWidthAndHeight(&aInnerWidth,nullptr,aCallerType);RefPtr<nsIPresShell>presShell=mDocShell->GetPresShell();if(presShell&&presShell->GetIsViewportOverridden()){nscoordheight=0;RefPtr<nsPresContext>presContext;presContext=presShell->GetPresContext();nsRectshellArea=presContext->GetVisibleArea();height=shellArea.Height();SetCSSViewportWidthAndHeight(nsPresContext::CSSPixelsToAppUnits(aInnerWidth),height);return;}int32_theight=0;int32_tunused=0;nsCOMPtr<nsIBaseWindow>docShellAsWin(do_QueryInterface(mDocShell));docShellAsWin->GetSize(&unused,&height);aError=SetDocShellWidthAndHeight(CSSToDevIntPixels(aInnerWidth),height);}voidnsGlobalWindowInner::SetInnerWidth(int32_taInnerWidth,CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(SetInnerWidthOuter,(aInnerWidth,aCallerType,aError),aError,);}voidnsGlobalWindowInner::SetInnerWidth(JSContext*aCx,JS::Handle<JS::Value>aValue,CallerTypeaCallerType,ErrorResult&aError){SetReplaceableWindowCoord(aCx,&nsGlobalWindowInner::SetInnerWidth,aValue,"innerWidth",aCallerType,aError);}int32_tnsGlobalWindowInner::GetInnerHeightOuter(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());CSSIntSizesize;aError=GetInnerSize(size);returnsize.height;}int32_tnsGlobalWindowInner::GetInnerHeight(CallerTypeaCallerType,ErrorResult&aError){// We ignore aCallerType; we only have that argument because some other things// called by GetReplaceableWindowCoord need it. If this ever changes, fix// nsresult nsGlobalWindowInner::GetInnerHeight(int32_t* aInnerWidth)// to actually take a useful CallerType and pass it in here.FORWARD_TO_OUTER_OR_THROW(GetInnerHeightOuter,(aError),aError,0);}voidnsGlobalWindowInner::GetInnerHeight(JSContext*aCx,JS::MutableHandle<JS::Value>aValue,CallerTypeaCallerType,ErrorResult&aError){GetReplaceableWindowCoord(aCx,&nsGlobalWindowInner::GetInnerHeight,aValue,aCallerType,aError);}nsresultnsGlobalWindowInner::GetInnerHeight(int32_t*aInnerHeight){FORWARD_TO_INNER(GetInnerHeight,(aInnerHeight),NS_ERROR_UNEXPECTED);ErrorResultrv;// Callee doesn't care about the caller type, but play it safe.*aInnerHeight=GetInnerHeight(CallerType::NonSystem,rv);returnrv.StealNSResult();}voidnsGlobalWindowInner::SetInnerHeightOuter(int32_taInnerHeight,CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());if(!mDocShell){aError.Throw(NS_ERROR_UNEXPECTED);return;}RefPtr<nsIPresShell>presShell=mDocShell->GetPresShell();if(presShell&&presShell->GetIsViewportOverridden()){RefPtr<nsPresContext>presContext;presContext=presShell->GetPresContext();nsRectshellArea=presContext->GetVisibleArea();nscoordheight=aInnerHeight;nscoordwidth=shellArea.Width();CheckSecurityWidthAndHeight(nullptr,&height,aCallerType);SetCSSViewportWidthAndHeight(width,nsPresContext::CSSPixelsToAppUnits(height));return;}int32_theight=0;int32_twidth=0;nsCOMPtr<nsIBaseWindow>docShellAsWin(do_QueryInterface(mDocShell));docShellAsWin->GetSize(&width,&height);CheckSecurityWidthAndHeight(nullptr,&aInnerHeight,aCallerType);aError=SetDocShellWidthAndHeight(width,CSSToDevIntPixels(aInnerHeight));}voidnsGlobalWindowInner::SetInnerHeight(int32_taInnerHeight,CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(SetInnerHeightOuter,(aInnerHeight,aCallerType,aError),aError,);}voidnsGlobalWindowInner::SetInnerHeight(JSContext*aCx,JS::Handle<JS::Value>aValue,CallerTypeaCallerType,ErrorResult&aError){SetReplaceableWindowCoord(aCx,&nsGlobalWindowInner::SetInnerHeight,aValue,"innerHeight",aCallerType,aError);}nsIntSizensGlobalWindowInner::GetOuterSize(CallerTypeaCallerType,ErrorResult&aError){MOZ_ASSERT(IsOuterWindow());if(nsContentUtils::ResistFingerprinting(aCallerType)){CSSIntSizesize;aError=GetInnerSize(size);returnnsIntSize(size.width,size.height);}nsCOMPtr<nsIBaseWindow>treeOwnerAsWin=GetTreeOwnerWindow();if(!treeOwnerAsWin){aError.Throw(NS_ERROR_FAILURE);returnnsIntSize(0,0);}nsIntSizesizeDevPixels;aError=treeOwnerAsWin->GetSize(&sizeDevPixels.width,&sizeDevPixels.height);if(aError.Failed()){returnnsIntSize();}returnDevToCSSIntPixels(sizeDevPixels);}int32_tnsGlobalWindowInner::GetOuterWidthOuter(CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());returnGetOuterSize(aCallerType,aError).width;}int32_tnsGlobalWindowInner::GetOuterWidth(CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetOuterWidthOuter,(aCallerType,aError),aError,0);}voidnsGlobalWindowInner::GetOuterWidth(JSContext*aCx,JS::MutableHandle<JS::Value>aValue,CallerTypeaCallerType,ErrorResult&aError){GetReplaceableWindowCoord(aCx,&nsGlobalWindowInner::GetOuterWidth,aValue,aCallerType,aError);}int32_tnsGlobalWindowInner::GetOuterHeightOuter(CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());returnGetOuterSize(aCallerType,aError).height;}int32_tnsGlobalWindowInner::GetOuterHeight(CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetOuterHeightOuter,(aCallerType,aError),aError,0);}voidnsGlobalWindowInner::GetOuterHeight(JSContext*aCx,JS::MutableHandle<JS::Value>aValue,CallerTypeaCallerType,ErrorResult&aError){GetReplaceableWindowCoord(aCx,&nsGlobalWindowInner::GetOuterHeight,aValue,aCallerType,aError);}voidnsGlobalWindowInner::SetOuterSize(int32_taLengthCSSPixels,boolaIsWidth,CallerTypeaCallerType,ErrorResult&aError){MOZ_ASSERT(IsOuterWindow());nsCOMPtr<nsIBaseWindow>treeOwnerAsWin=GetTreeOwnerWindow();if(!treeOwnerAsWin){aError.Throw(NS_ERROR_FAILURE);return;}CheckSecurityWidthAndHeight(aIsWidth?&aLengthCSSPixels:nullptr,aIsWidth?nullptr:&aLengthCSSPixels,aCallerType);int32_twidth,height;aError=treeOwnerAsWin->GetSize(&width,&height);if(aError.Failed()){return;}int32_tlengthDevPixels=CSSToDevIntPixels(aLengthCSSPixels);if(aIsWidth){width=lengthDevPixels;}else{height=lengthDevPixels;}aError=treeOwnerAsWin->SetSize(width,height,true);CheckForDPIChange();}voidnsGlobalWindowInner::SetOuterWidthOuter(int32_taOuterWidth,CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());SetOuterSize(aOuterWidth,true,aCallerType,aError);}voidnsGlobalWindowInner::SetOuterWidth(int32_taOuterWidth,CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(SetOuterWidthOuter,(aOuterWidth,aCallerType,aError),aError,);}voidnsGlobalWindowInner::SetOuterWidth(JSContext*aCx,JS::Handle<JS::Value>aValue,CallerTypeaCallerType,ErrorResult&aError){SetReplaceableWindowCoord(aCx,&nsGlobalWindowInner::SetOuterWidth,aValue,"outerWidth",aCallerType,aError);}voidnsGlobalWindowInner::SetOuterHeightOuter(int32_taOuterHeight,CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());SetOuterSize(aOuterHeight,false,aCallerType,aError);}voidnsGlobalWindowInner::SetOuterHeight(int32_taOuterHeight,CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(SetOuterHeightOuter,(aOuterHeight,aCallerType,aError),aError,);}voidnsGlobalWindowInner::SetOuterHeight(JSContext*aCx,JS::Handle<JS::Value>aValue,CallerTypeaCallerType,ErrorResult&aError){SetReplaceableWindowCoord(aCx,&nsGlobalWindowInner::SetOuterHeight,aValue,"outerHeight",aCallerType,aError);}CSSIntPointnsGlobalWindowInner::GetScreenXY(CallerTypeaCallerType,ErrorResult&aError){MOZ_ASSERT(IsOuterWindow());// When resisting fingerprinting, always return (0,0)if(nsContentUtils::ResistFingerprinting(aCallerType)){returnCSSIntPoint(0,0);}nsCOMPtr<nsIBaseWindow>treeOwnerAsWin=GetTreeOwnerWindow();if(!treeOwnerAsWin){aError.Throw(NS_ERROR_FAILURE);returnCSSIntPoint(0,0);}int32_tx=0,y=0;aError=treeOwnerAsWin->GetPosition(&x,&y);// LayoutDevice px valuesRefPtr<nsPresContext>presContext;mDocShell->GetPresContext(getter_AddRefs(presContext));if(!presContext){returnCSSIntPoint(x,y);}// Find the global desktop coordinate of the top-left of the screen.// We'll use this as a "fake origin" when converting to CSS px units,// to avoid overlapping coordinates in cases such as a hi-dpi screen// placed to the right of a lo-dpi screen on Windows. (Instead, there// may be "gaps" in the resulting CSS px coordinates in some cases.)nsDeviceContext*dc=presContext->DeviceContext();nsRectscreenRect;dc->GetRect(screenRect);LayoutDeviceRectscreenRectDev=LayoutDevicePixel::FromAppUnits(screenRect,dc->AppUnitsPerDevPixel());DesktopToLayoutDeviceScalescale=dc->GetDesktopToDeviceScale();DesktopRectscreenRectDesk=screenRectDev/scale;CSSPointcssPt=LayoutDevicePoint(x-screenRectDev.x,y-screenRectDev.y)/presContext->CSSToDevPixelScale();cssPt.x+=screenRectDesk.x;cssPt.y+=screenRectDesk.y;returnCSSIntPoint(NSToIntRound(cssPt.x),NSToIntRound(cssPt.y));}int32_tnsGlobalWindowInner::GetScreenXOuter(CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());returnGetScreenXY(aCallerType,aError).x;}int32_tnsGlobalWindowInner::GetScreenX(CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetScreenXOuter,(aCallerType,aError),aError,0);}voidnsGlobalWindowInner::GetScreenX(JSContext*aCx,JS::MutableHandle<JS::Value>aValue,CallerTypeaCallerType,ErrorResult&aError){GetReplaceableWindowCoord(aCx,&nsGlobalWindowInner::GetScreenX,aValue,aCallerType,aError);}nsRectnsGlobalWindowInner::GetInnerScreenRect(){MOZ_ASSERT(IsOuterWindow());if(!mDocShell){returnnsRect();}EnsureSizeAndPositionUpToDate();if(!mDocShell){returnnsRect();}nsCOMPtr<nsIPresShell>presShell=mDocShell->GetPresShell();if(!presShell){returnnsRect();}nsIFrame*rootFrame=presShell->GetRootFrame();if(!rootFrame){returnnsRect();}returnrootFrame->GetScreenRectInAppUnits();}floatnsGlobalWindowInner::GetMozInnerScreenXOuter(CallerTypeaCallerType){MOZ_RELEASE_ASSERT(IsOuterWindow());// When resisting fingerprinting, always return 0.if(nsContentUtils::ResistFingerprinting(aCallerType)){return0.0;}nsRectr=GetInnerScreenRect();returnnsPresContext::AppUnitsToFloatCSSPixels(r.x);}floatnsGlobalWindowInner::GetMozInnerScreenX(CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenXOuter,(aCallerType),aError,0);}floatnsGlobalWindowInner::GetMozInnerScreenYOuter(CallerTypeaCallerType){MOZ_RELEASE_ASSERT(IsOuterWindow());// Return 0 to prevent fingerprinting.if(nsContentUtils::ResistFingerprinting(aCallerType)){return0.0;}nsRectr=GetInnerScreenRect();returnnsPresContext::AppUnitsToFloatCSSPixels(r.y);}floatnsGlobalWindowInner::GetMozInnerScreenY(CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenYOuter,(aCallerType),aError,0);}doublensGlobalWindowInner::GetDevicePixelRatioOuter(CallerTypeaCallerType){MOZ_RELEASE_ASSERT(IsOuterWindow());if(!mDocShell){return1.0;}RefPtr<nsPresContext>presContext;mDocShell->GetPresContext(getter_AddRefs(presContext));if(!presContext){return1.0;}if(nsContentUtils::ResistFingerprinting(aCallerType)){return1.0;}floatoverrideDPPX=presContext->GetOverrideDPPX();if(overrideDPPX>0){returnoverrideDPPX;}returndouble(nsPresContext::AppUnitsPerCSSPixel())/double(presContext->AppUnitsPerDevPixel());}doublensGlobalWindowInner::GetDevicePixelRatio(CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetDevicePixelRatioOuter,(aCallerType),aError,0.0);}uint64_tnsGlobalWindowInner::GetMozPaintCountOuter(){MOZ_RELEASE_ASSERT(IsOuterWindow());if(!mDocShell){return0;}nsCOMPtr<nsIPresShell>presShell=mDocShell->GetPresShell();returnpresShell?presShell->GetPaintCount():0;}uint64_tnsGlobalWindowInner::GetMozPaintCount(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetMozPaintCountOuter,(),aError,0);}int32_tnsGlobalWindowInner::RequestAnimationFrame(FrameRequestCallback&aCallback,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mDoc){return0;}if(GetWrapperPreserveColor()){js::NotifyAnimationActivity(GetWrapperPreserveColor());}int32_thandle;aError=mDoc->ScheduleFrameRequestCallback(aCallback,&handle);returnhandle;}voidnsGlobalWindowInner::CancelAnimationFrame(int32_taHandle,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsInnerWindow());if(!mDoc){return;}mDoc->CancelFrameRequestCallback(aHandle);}already_AddRefed<MediaQueryList>nsGlobalWindowInner::MatchMediaOuter(constnsAString&aMediaQueryList,CallerTypeaCallerType){MOZ_RELEASE_ASSERT(IsOuterWindow());if(!mDoc){returnnullptr;}returnmDoc->MatchMedia(aMediaQueryList,aCallerType);}already_AddRefed<MediaQueryList>nsGlobalWindowInner::MatchMedia(constnsAString&aMediaQueryList,CallerTypeaCallerType,ErrorResult&aError){// FIXME: This whole forward-to-outer and then get a pres// shell/context off the docshell dance is sort of silly; it'd make// more sense to forward to the inner, but it's what everyone else// (GetSelection, GetScrollXY, etc.) does around here.FORWARD_TO_OUTER_OR_THROW(MatchMediaOuter,(aMediaQueryList,aCallerType),aError,nullptr);}voidnsGlobalWindowInner::SetScreenXOuter(int32_taScreenX,CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());nsCOMPtr<nsIBaseWindow>treeOwnerAsWin=GetTreeOwnerWindow();if(!treeOwnerAsWin){aError.Throw(NS_ERROR_FAILURE);return;}int32_tx,y;aError=treeOwnerAsWin->GetPosition(&x,&y);if(aError.Failed()){return;}CheckSecurityLeftAndTop(&aScreenX,nullptr,aCallerType);x=CSSToDevIntPixels(aScreenX);aError=treeOwnerAsWin->SetPosition(x,y);CheckForDPIChange();}voidnsGlobalWindowInner::SetScreenX(int32_taScreenX,CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(SetScreenXOuter,(aScreenX,aCallerType,aError),aError,);}voidnsGlobalWindowInner::SetScreenX(JSContext*aCx,JS::Handle<JS::Value>aValue,CallerTypeaCallerType,ErrorResult&aError){SetReplaceableWindowCoord(aCx,&nsGlobalWindowInner::SetScreenX,aValue,"screenX",aCallerType,aError);}int32_tnsGlobalWindowInner::GetScreenYOuter(CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());returnGetScreenXY(aCallerType,aError).y;}int32_tnsGlobalWindowInner::GetScreenY(CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetScreenYOuter,(aCallerType,aError),aError,0);}voidnsGlobalWindowInner::GetScreenY(JSContext*aCx,JS::MutableHandle<JS::Value>aValue,CallerTypeaCallerType,ErrorResult&aError){GetReplaceableWindowCoord(aCx,&nsGlobalWindowInner::GetScreenY,aValue,aCallerType,aError);}voidnsGlobalWindowInner::SetScreenYOuter(int32_taScreenY,CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());nsCOMPtr<nsIBaseWindow>treeOwnerAsWin=GetTreeOwnerWindow();if(!treeOwnerAsWin){aError.Throw(NS_ERROR_FAILURE);return;}int32_tx,y;aError=treeOwnerAsWin->GetPosition(&x,&y);if(aError.Failed()){return;}CheckSecurityLeftAndTop(nullptr,&aScreenY,aCallerType);y=CSSToDevIntPixels(aScreenY);aError=treeOwnerAsWin->SetPosition(x,y);CheckForDPIChange();}voidnsGlobalWindowInner::SetScreenY(int32_taScreenY,CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(SetScreenYOuter,(aScreenY,aCallerType,aError),aError,);}voidnsGlobalWindowInner::SetScreenY(JSContext*aCx,JS::Handle<JS::Value>aValue,CallerTypeaCallerType,ErrorResult&aError){SetReplaceableWindowCoord(aCx,&nsGlobalWindowInner::SetScreenY,aValue,"screenY",aCallerType,aError);}// NOTE: Arguments to this function should have values scaled to// CSS pixels, not device pixels.voidnsGlobalWindowInner::CheckSecurityWidthAndHeight(int32_t*aWidth,int32_t*aHeight,CallerTypeaCallerType){MOZ_ASSERT(IsOuterWindow());#ifdef MOZ_XULif(aCallerType!=CallerType::System){// if attempting to resize the window, hide any open popupsnsContentUtils::HidePopupsInDocument(mDoc);}#endif// This one is easy. Just ensure the variable is greater than 100;if((aWidth&&*aWidth<100)||(aHeight&&*aHeight<100)){// Check security state for use in determing window dimensionsif(aCallerType!=CallerType::System){//sec check failedif(aWidth&&*aWidth<100){*aWidth=100;}if(aHeight&&*aHeight<100){*aHeight=100;}}}}// NOTE: Arguments to this function should have values in device pixelsnsresultnsGlobalWindowInner::SetDocShellWidthAndHeight(int32_taInnerWidth,int32_taInnerHeight){MOZ_ASSERT(IsOuterWindow());NS_ENSURE_TRUE(mDocShell,NS_ERROR_FAILURE);nsCOMPtr<nsIDocShellTreeOwner>treeOwner;mDocShell->GetTreeOwner(getter_AddRefs(treeOwner));NS_ENSURE_TRUE(treeOwner,NS_ERROR_FAILURE);NS_ENSURE_SUCCESS(treeOwner->SizeShellTo(mDocShell,aInnerWidth,aInnerHeight),NS_ERROR_FAILURE);returnNS_OK;}// NOTE: Arguments to this function should have values in app unitsvoidnsGlobalWindowInner::SetCSSViewportWidthAndHeight(nscoordaInnerWidth,nscoordaInnerHeight){MOZ_ASSERT(IsOuterWindow());RefPtr<nsPresContext>presContext;mDocShell->GetPresContext(getter_AddRefs(presContext));nsRectshellArea=presContext->GetVisibleArea();shellArea.SetHeight(aInnerHeight);shellArea.SetWidth(aInnerWidth);presContext->SetVisibleArea(shellArea);}// NOTE: Arguments to this function should have values scaled to// CSS pixels, not device pixels.voidnsGlobalWindowInner::CheckSecurityLeftAndTop(int32_t*aLeft,int32_t*aTop,CallerTypeaCallerType){MOZ_ASSERT(IsOuterWindow());// This one is harder. We have to get the screen size and window dimensions.// Check security state for use in determing window dimensionsif(aCallerType!=CallerType::System){#ifdef MOZ_XUL// if attempting to move the window, hide any open popupsnsContentUtils::HidePopupsInDocument(mDoc);#endifif(nsGlobalWindowOuter*rootWindow=nsGlobalWindowOuter::Cast(GetPrivateRoot())){rootWindow->FlushPendingNotifications(FlushType::Layout);}nsCOMPtr<nsIBaseWindow>treeOwner=GetTreeOwnerWindow();nsCOMPtr<nsIDOMScreen>screen=GetScreen();if(treeOwner&&screen){int32_tscreenLeft,screenTop,screenWidth,screenHeight;int32_twinLeft,winTop,winWidth,winHeight;// Get the window sizetreeOwner->GetPositionAndSize(&winLeft,&winTop,&winWidth,&winHeight);// convert those values to CSS pixels// XXX four separate retrievals of the prescontextwinLeft=DevToCSSIntPixels(winLeft);winTop=DevToCSSIntPixels(winTop);winWidth=DevToCSSIntPixels(winWidth);winHeight=DevToCSSIntPixels(winHeight);// Get the screen dimensions// XXX This should use nsIScreenManager once it's fully fleshed out.screen->GetAvailLeft(&screenLeft);screen->GetAvailWidth(&screenWidth);screen->GetAvailHeight(&screenHeight);#if defined(XP_MACOSX)/* The mac's coordinate system is different from the assumed Windows' system. It offsets by the height of the menubar so that a window placed at (0,0) will be entirely visible. Unfortunately that correction is made elsewhere (in Widget) and the meaning of the Avail... coordinates is overloaded. Here we allow a window to be placed at (0,0) because it does make sense to do so. */screen->GetTop(&screenTop);#elsescreen->GetAvailTop(&screenTop);#endifif(aLeft){if(screenLeft+screenWidth<*aLeft+winWidth)*aLeft=screenLeft+screenWidth-winWidth;if(screenLeft>*aLeft)*aLeft=screenLeft;}if(aTop){if(screenTop+screenHeight<*aTop+winHeight)*aTop=screenTop+screenHeight-winHeight;if(screenTop>*aTop)*aTop=screenTop;}}else{if(aLeft)*aLeft=0;if(aTop)*aTop=0;}}}int32_tnsGlobalWindowInner::GetScrollBoundaryOuter(SideaSide){MOZ_RELEASE_ASSERT(IsOuterWindow());FlushPendingNotifications(FlushType::Layout);if(nsIScrollableFrame*sf=GetScrollFrame()){returnnsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().Edge(aSide));}return0;}int32_tnsGlobalWindowInner::GetScrollMinX(ErrorResult&aError){MOZ_ASSERT(IsInnerWindow());FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter,(eSideLeft),aError,0);}int32_tnsGlobalWindowInner::GetScrollMinY(ErrorResult&aError){MOZ_ASSERT(IsInnerWindow());FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter,(eSideTop),aError,0);}int32_tnsGlobalWindowInner::GetScrollMaxX(ErrorResult&aError){MOZ_ASSERT(IsInnerWindow());FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter,(eSideRight),aError,0);}int32_tnsGlobalWindowInner::GetScrollMaxY(ErrorResult&aError){MOZ_ASSERT(IsInnerWindow());FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter,(eSideBottom),aError,0);}CSSPointnsGlobalWindowInner::GetScrollXY(boolaDoFlush){MOZ_ASSERT(IsOuterWindow());if(aDoFlush){FlushPendingNotifications(FlushType::Layout);}else{EnsureSizeAndPositionUpToDate();}nsIScrollableFrame*sf=GetScrollFrame();if(!sf){returnCSSIntPoint(0,0);}nsPointscrollPos=sf->GetScrollPosition();if(scrollPos!=nsPoint(0,0)&&!aDoFlush){// Oh, well. This is the expensive case -- the window is scrolled and we// didn't actually flush yet. Repeat, but with a flush, since the content// may get shorter and hence our scroll position may decrease.returnGetScrollXY(true);}returnCSSPoint::FromAppUnits(scrollPos);}doublensGlobalWindowInner::GetScrollXOuter(){MOZ_RELEASE_ASSERT(IsOuterWindow());returnGetScrollXY(false).x;}doublensGlobalWindowInner::GetScrollX(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetScrollXOuter,(),aError,0);}doublensGlobalWindowInner::GetScrollYOuter(){MOZ_RELEASE_ASSERT(IsOuterWindow());returnGetScrollXY(false).y;}doublensGlobalWindowInner::GetScrollY(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetScrollYOuter,(),aError,0);}uint32_tnsGlobalWindowInner::Length(){FORWARD_TO_OUTER(Length,(),0);nsDOMWindowList*windows=GetWindowList();returnwindows?windows->GetLength():0;}already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::GetTopOuter(){MOZ_ASSERT(IsOuterWindow());nsCOMPtr<nsPIDOMWindowOuter>top=GetScriptableTop();returntop.forget();}already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::GetTop(mozilla::ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetTopOuter,(),aError,nullptr);}nsPIDOMWindowOuter*nsGlobalWindowInner::GetChildWindow(constnsAString&aName){nsCOMPtr<nsIDocShell>docShell(GetDocShell());NS_ENSURE_TRUE(docShell,nullptr);nsCOMPtr<nsIDocShellTreeItem>child;docShell->FindChildWithName(aName,false,true,nullptr,nullptr,getter_AddRefs(child));returnchild?child->GetWindow():nullptr;}boolnsGlobalWindowInner::DispatchCustomEvent(constnsAString&aEventName){MOZ_ASSERT(IsOuterWindow());booldefaultActionEnabled=true;nsContentUtils::DispatchTrustedEvent(mDoc,ToSupports(this),aEventName,true,true,&defaultActionEnabled);returndefaultActionEnabled;}boolnsGlobalWindowInner::DispatchResizeEvent(constCSSIntSize&aSize){MOZ_ASSERT(IsOuterWindow());ErrorResultres;RefPtr<Event>domEvent=mDoc->CreateEvent(NS_LITERAL_STRING("CustomEvent"),CallerType::System,res);if(res.Failed()){returnfalse;}// We don't init the AutoJSAPI with ourselves because we don't want it// reporting errors to our onerror handlers.AutoJSAPIjsapi;jsapi.Init();JSContext*cx=jsapi.cx();JSAutoCompartmentac(cx,GetWrapperPreserveColor());DOMWindowResizeEventDetaildetail;detail.mWidth=aSize.width;detail.mHeight=aSize.height;JS::Rooted<JS::Value>detailValue(cx);if(!ToJSValue(cx,detail,&detailValue)){returnfalse;}CustomEvent*customEvent=static_cast<CustomEvent*>(domEvent.get());customEvent->InitCustomEvent(cx,NS_LITERAL_STRING("DOMWindowResize"),/* aCanBubble = */true,/* aCancelable = */true,detailValue,res);if(res.Failed()){returnfalse;}domEvent->SetTrusted(true);domEvent->WidgetEventPtr()->mFlags.mOnlyChromeDispatch=true;nsCOMPtr<EventTarget>target=do_QueryInterface(GetOuterWindow());domEvent->SetTarget(target);booldefaultActionEnabled=true;target->DispatchEvent(domEvent,&defaultActionEnabled);returndefaultActionEnabled;}voidnsGlobalWindowInner::RefreshCompartmentPrincipal(){MOZ_ASSERT(IsInnerWindow());JS_SetCompartmentPrincipals(js::GetObjectCompartment(GetWrapperPreserveColor()),nsJSPrincipals::get(mDoc->NodePrincipal()));}boolnsGlobalWindowInner::WindowExists(constnsAString&aName,boolaForceNoOpener,boolaLookForCallerOnJSStack){MOZ_CRASH("Outer window only");}already_AddRefed<nsIWidget>nsGlobalWindowInner::GetMainWidget(){FORWARD_TO_OUTER(GetMainWidget,(),nullptr);nsCOMPtr<nsIBaseWindow>treeOwnerAsWin=GetTreeOwnerWindow();nsCOMPtr<nsIWidget>widget;if(treeOwnerAsWin){treeOwnerAsWin->GetMainWidget(getter_AddRefs(widget));}returnwidget.forget();}nsIWidget*nsGlobalWindowInner::GetNearestWidget()const{nsIDocShell*docShell=GetDocShell();NS_ENSURE_TRUE(docShell,nullptr);nsCOMPtr<nsIPresShell>presShell=docShell->GetPresShell();NS_ENSURE_TRUE(presShell,nullptr);nsIFrame*rootFrame=presShell->GetRootFrame();NS_ENSURE_TRUE(rootFrame,nullptr);returnrootFrame->GetView()->GetNearestWidget(nullptr);}voidnsGlobalWindowInner::SetFullScreenOuter(boolaFullScreen,mozilla::ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());aError=SetFullscreenInternal(FullscreenReason::ForFullscreenMode,aFullScreen);}voidnsGlobalWindowInner::SetFullScreen(boolaFullScreen,mozilla::ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(SetFullScreenOuter,(aFullScreen,aError),aError,/* void */);}nsresultnsGlobalWindowInner::SetFullScreen(boolaFullScreen){FORWARD_TO_OUTER(SetFullScreen,(aFullScreen),NS_ERROR_NOT_INITIALIZED);returnSetFullscreenInternal(FullscreenReason::ForFullscreenMode,aFullScreen);}nsresultnsGlobalWindowInner::SetFullscreenInternal(FullscreenReasonaReason,boolaFullScreen){MOZ_CRASH("Outer window only");}boolnsGlobalWindowInner::SetWidgetFullscreen(FullscreenReasonaReason,boolaIsFullscreen,nsIWidget*aWidget,nsIScreen*aScreen){MOZ_CRASH("Only callable on the outer window");}/* virtual */voidnsGlobalWindowInner::FullscreenWillChange(boolaIsFullscreen){if(aIsFullscreen){DispatchCustomEvent(NS_LITERAL_STRING("willenterfullscreen"));}else{DispatchCustomEvent(NS_LITERAL_STRING("willexitfullscreen"));}}/* virtual */voidnsGlobalWindowInner::FinishFullscreenChange(boolaIsFullscreen){MOZ_CRASH("Outer window only");}boolnsGlobalWindowInner::FullScreen()const{MOZ_ASSERT(IsOuterWindow());NS_ENSURE_TRUE(mDocShell,mFullScreen);// Get the fullscreen value of the root window, to always have the value// accurate, even when called from content.nsCOMPtr<nsIDocShellTreeItem>rootItem;mDocShell->GetRootTreeItem(getter_AddRefs(rootItem));if(rootItem==mDocShell){if(!XRE_IsContentProcess()){// We are the root window. Return our internal value.returnmFullScreen;}if(nsCOMPtr<nsIWidget>widget=GetNearestWidget()){// We are in content process, figure out the value from// the sizemode of the puppet widget.returnwidget->SizeMode()==nsSizeMode_Fullscreen;}returnfalse;}nsCOMPtr<nsPIDOMWindowOuter>window=rootItem->GetWindow();NS_ENSURE_TRUE(window,mFullScreen);returnnsGlobalWindowOuter::Cast(window)->FullScreen();}boolnsGlobalWindowInner::GetFullScreenOuter(){MOZ_RELEASE_ASSERT(IsOuterWindow());returnFullScreen();}boolnsGlobalWindowInner::GetFullScreen(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetFullScreenOuter,(),aError,false);}boolnsGlobalWindowInner::GetFullScreen(){FORWARD_TO_INNER(GetFullScreen,(),false);ErrorResultdummy;boolfullscreen=GetFullScreen(dummy);dummy.SuppressException();returnfullscreen;}voidnsGlobalWindowInner::Dump(constnsAString&aStr){if(!nsContentUtils::DOMWindowDumpEnabled()){return;}char*cstr=ToNewUTF8String(aStr);#if defined(XP_MACOSX)// have to convert \r to \n so that printing to the console workschar*c=cstr,*cEnd=cstr+strlen(cstr);while(c<cEnd){if(*c=='\r')*c='\n';c++;}#endifif(cstr){MOZ_LOG(nsContentUtils::DOMDumpLog(),LogLevel::Debug,("[Window.Dump] %s",cstr));#ifdef XP_WINPrintToDebugger(cstr);#endif#ifdef ANDROID__android_log_write(ANDROID_LOG_INFO,"GeckoDump",cstr);#endifFILE*fp=gDumpFile?gDumpFile:stdout;fputs(cstr,fp);fflush(fp);free(cstr);}}voidnsGlobalWindowInner::EnsureReflowFlushAndPaint(){MOZ_ASSERT(IsOuterWindow());NS_ASSERTION(mDocShell,"EnsureReflowFlushAndPaint() called with no ""docshell!");if(!mDocShell)return;nsCOMPtr<nsIPresShell>presShell=mDocShell->GetPresShell();if(!presShell)return;// Flush pending reflows.if(mDoc){mDoc->FlushPendingNotifications(FlushType::Layout);}// Unsuppress painting.presShell->UnsuppressPainting();}// staticvoidnsGlobalWindowInner::MakeScriptDialogTitle(nsAString&aOutTitle,nsIPrincipal*aSubjectPrincipal){MOZ_ASSERT(aSubjectPrincipal);aOutTitle.Truncate();// Try to get a host from the running principal -- this will do the// right thing for javascript: and data: documents.nsCOMPtr<nsIURI>uri;nsresultrv=aSubjectPrincipal->GetURI(getter_AddRefs(uri));// Note - The check for the current JSContext here isn't necessarily sensical.// It's just designed to preserve existing behavior during a mass-conversion// patch.if(NS_SUCCEEDED(rv)&&uri&&nsContentUtils::GetCurrentJSContext()){// remove user:pass for privacy and spoof preventionnsCOMPtr<nsIURIFixup>fixup(do_GetService(NS_URIFIXUP_CONTRACTID));if(fixup){nsCOMPtr<nsIURI>fixedURI;rv=fixup->CreateExposableURI(uri,getter_AddRefs(fixedURI));if(NS_SUCCEEDED(rv)&&fixedURI){nsAutoCStringhost;fixedURI->GetHost(host);if(!host.IsEmpty()){// if this URI has a host we'll show it. For other// schemes (e.g. file:) we fall back to the localized// generic stringnsAutoCStringprepath;fixedURI->GetDisplayPrePath(prepath);NS_ConvertUTF8toUTF16ucsPrePath(prepath);constchar16_t*formatStrings[]={ucsPrePath.get()};nsContentUtils::FormatLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,"ScriptDlgHeading",formatStrings,aOutTitle);}}}}if(aOutTitle.IsEmpty()){// We didn't find a host so use the generic headingnsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,"ScriptDlgGenericHeading",aOutTitle);}// Just in caseif(aOutTitle.IsEmpty()){NS_WARNING("could not get ScriptDlgGenericHeading string from string bundle");aOutTitle.AssignLiteral("[Script]");}}boolnsGlobalWindowInner::CanMoveResizeWindows(CallerTypeaCallerType){MOZ_ASSERT(IsOuterWindow());// When called from chrome, we can avoid the following checks.if(aCallerType!=CallerType::System){// Don't allow scripts to move or resize windows that were not opened by a// script.if(!mHadOriginalOpener){returnfalse;}if(!CanSetProperty("dom.disable_window_move_resize")){returnfalse;}// Ignore the request if we have more than one tab in the window.uint32_titemCount=0;if(XRE_IsContentProcess()){nsCOMPtr<nsIDocShell>docShell=GetDocShell();if(docShell){nsCOMPtr<nsITabChild>child=docShell->GetTabChild();if(child){child->SendGetTabCount(&itemCount);}}}else{nsCOMPtr<nsIDocShellTreeOwner>treeOwner=GetTreeOwner();if(!treeOwner||NS_FAILED(treeOwner->GetTabCount(&itemCount))){itemCount=0;}}if(itemCount>1){returnfalse;}}if(mDocShell){boolallow;nsresultrv=mDocShell->GetAllowWindowControl(&allow);if(NS_SUCCEEDED(rv)&&!allow)returnfalse;}if(gMouseDown&&!gDragServiceDisabled){nsCOMPtr<nsIDragService>ds=do_GetService("@mozilla.org/widget/dragservice;1");if(ds){gDragServiceDisabled=true;ds->Suppress();}}returntrue;}boolnsGlobalWindowInner::AlertOrConfirm(boolaAlert,constnsAString&aMessage,nsIPrincipal&aSubjectPrincipal,ErrorResult&aError){// XXX This method is very similar to nsGlobalWindowInner::Prompt, make// sure any modifications here don't need to happen over there!MOZ_ASSERT(IsOuterWindow());if(!AreDialogsEnabled()){// Just silently return. In the case of alert(), the return value is// ignored. In the case of confirm(), returning false is the same thing as// would happen if the user cancels.returnfalse;}// Reset popup state while opening a modal dialog, and firing events// about the dialog, to prevent the current state from being active// the whole time a modal dialog is open.nsAutoPopupStatePusherpopupStatePusher(openAbused,true);// Before bringing up the window, unsuppress painting and flush// pending reflows.EnsureReflowFlushAndPaint();nsAutoStringtitle;MakeScriptDialogTitle(title,&aSubjectPrincipal);// Remove non-terminating null characters from the// string. See bug #310037.nsAutoStringfinal;nsContentUtils::StripNullChars(aMessage,final);nsresultrv;nsCOMPtr<nsIPromptFactory>promptFac=do_GetService("@mozilla.org/prompter;1",&rv);if(NS_FAILED(rv)){aError.Throw(rv);returnfalse;}nsCOMPtr<nsIPrompt>prompt;aError=promptFac->GetPrompt(AsOuter(),NS_GET_IID(nsIPrompt),getter_AddRefs(prompt));if(aError.Failed()){returnfalse;}// Always allow tab modal prompts for alert and confirm.if(nsCOMPtr<nsIWritablePropertyBag2>promptBag=do_QueryInterface(prompt)){promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"),true);}boolresult=false;nsAutoSyncOperationsync(mDoc);if(ShouldPromptToBlockDialogs()){booldisallowDialog=false;nsAutoStringlabel;nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,"ScriptDialogLabel",label);aError=aAlert?prompt->AlertCheck(title.get(),final.get(),label.get(),&disallowDialog):prompt->ConfirmCheck(title.get(),final.get(),label.get(),&disallowDialog,&result);if(disallowDialog)DisableDialogs();}else{aError=aAlert?prompt->Alert(title.get(),final.get()):prompt->Confirm(title.get(),final.get(),&result);}returnresult;}voidnsGlobalWindowInner::Alert(nsIPrincipal&aSubjectPrincipal,ErrorResult&aError){MOZ_ASSERT(IsInnerWindow());Alert(EmptyString(),aSubjectPrincipal,aError);}voidnsGlobalWindowInner::AlertOuter(constnsAString&aMessage,nsIPrincipal&aSubjectPrincipal,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());AlertOrConfirm(/* aAlert = */true,aMessage,aSubjectPrincipal,aError);}voidnsGlobalWindowInner::Alert(constnsAString&aMessage,nsIPrincipal&aSubjectPrincipal,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(AlertOuter,(aMessage,aSubjectPrincipal,aError),aError,);}boolnsGlobalWindowInner::ConfirmOuter(constnsAString&aMessage,nsIPrincipal&aSubjectPrincipal,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());returnAlertOrConfirm(/* aAlert = */false,aMessage,aSubjectPrincipal,aError);}boolnsGlobalWindowInner::Confirm(constnsAString&aMessage,nsIPrincipal&aSubjectPrincipal,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(ConfirmOuter,(aMessage,aSubjectPrincipal,aError),aError,false);}already_AddRefed<Promise>nsGlobalWindowInner::Fetch(constRequestOrUSVString&aInput,constRequestInit&aInit,CallerTypeaCallerType,ErrorResult&aRv){returnFetchRequest(this,aInput,aInit,aCallerType,aRv);}voidnsGlobalWindowInner::PromptOuter(constnsAString&aMessage,constnsAString&aInitial,nsAString&aReturn,nsIPrincipal&aSubjectPrincipal,ErrorResult&aError){// XXX This method is very similar to nsGlobalWindowInner::AlertOrConfirm, make// sure any modifications here don't need to happen over there!MOZ_RELEASE_ASSERT(IsOuterWindow());SetDOMStringToNull(aReturn);if(!AreDialogsEnabled()){// Return null, as if the user just canceled the prompt.return;}// Reset popup state while opening a modal dialog, and firing events// about the dialog, to prevent the current state from being active// the whole time a modal dialog is open.nsAutoPopupStatePusherpopupStatePusher(openAbused,true);// Before bringing up the window, unsuppress painting and flush// pending reflows.EnsureReflowFlushAndPaint();nsAutoStringtitle;MakeScriptDialogTitle(title,&aSubjectPrincipal);// Remove non-terminating null characters from the// string. See bug #310037.nsAutoStringfixedMessage,fixedInitial;nsContentUtils::StripNullChars(aMessage,fixedMessage);nsContentUtils::StripNullChars(aInitial,fixedInitial);nsresultrv;nsCOMPtr<nsIPromptFactory>promptFac=do_GetService("@mozilla.org/prompter;1",&rv);if(NS_FAILED(rv)){aError.Throw(rv);return;}nsCOMPtr<nsIPrompt>prompt;aError=promptFac->GetPrompt(AsOuter(),NS_GET_IID(nsIPrompt),getter_AddRefs(prompt));if(aError.Failed()){return;}// Always allow tab modal prompts for prompt.if(nsCOMPtr<nsIWritablePropertyBag2>promptBag=do_QueryInterface(prompt)){promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"),true);}// Pass in the default value, if any.char16_t*inoutValue=ToNewUnicode(fixedInitial);booldisallowDialog=false;nsAutoStringlabel;label.SetIsVoid(true);if(ShouldPromptToBlockDialogs()){nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,"ScriptDialogLabel",label);}nsAutoSyncOperationsync(mDoc);boolok;aError=prompt->Prompt(title.get(),fixedMessage.get(),&inoutValue,label.IsVoid()?nullptr:label.get(),&disallowDialog,&ok);if(disallowDialog){DisableDialogs();}if(aError.Failed()){return;}nsStringoutValue;outValue.Adopt(inoutValue);if(ok&&inoutValue){aReturn.Assign(outValue);}}voidnsGlobalWindowInner::Prompt(constnsAString&aMessage,constnsAString&aInitial,nsAString&aReturn,nsIPrincipal&aSubjectPrincipal,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(PromptOuter,(aMessage,aInitial,aReturn,aSubjectPrincipal,aError),aError,);}voidnsGlobalWindowInner::FocusOuter(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());nsIFocusManager*fm=nsFocusManager::GetFocusManager();if(!fm){return;}nsCOMPtr<nsIBaseWindow>baseWin=do_QueryInterface(mDocShell);boolisVisible=false;if(baseWin){baseWin->GetVisibility(&isVisible);}if(!isVisible){// A hidden tab is being focused, ignore this call.return;}nsCOMPtr<nsPIDOMWindowInner>caller=do_QueryInterface(GetEntryGlobal());nsPIDOMWindowOuter*callerOuter=caller?caller->GetOuterWindow():nullptr;nsCOMPtr<nsPIDOMWindowOuter>opener=GetOpener();// Enforce dom.disable_window_flip (for non-chrome), but still allow the// window which opened us to raise us at times when popups are allowed// (bugs 355482 and 369306).boolcanFocus=CanSetProperty("dom.disable_window_flip")||(opener==callerOuter&&RevisePopupAbuseLevel(gPopupControlState)<openBlocked);nsCOMPtr<mozIDOMWindowProxy>activeDOMWindow;fm->GetActiveWindow(getter_AddRefs(activeDOMWindow));nsCOMPtr<nsIDocShellTreeItem>rootItem;mDocShell->GetRootTreeItem(getter_AddRefs(rootItem));nsCOMPtr<nsPIDOMWindowOuter>rootWin=rootItem?rootItem->GetWindow():nullptr;auto*activeWindow=nsPIDOMWindowOuter::From(activeDOMWindow);boolisActive=(rootWin==activeWindow);nsCOMPtr<nsIBaseWindow>treeOwnerAsWin=GetTreeOwnerWindow();if(treeOwnerAsWin&&(canFocus||isActive)){boolisEnabled=true;if(NS_SUCCEEDED(treeOwnerAsWin->GetEnabled(&isEnabled))&&!isEnabled){NS_WARNING("Should not try to set the focus on a disabled window");return;}// XXXndeakin not sure what this is for or if it should go somewhere elsensCOMPtr<nsIEmbeddingSiteWindow>embeddingWin(do_GetInterface(treeOwnerAsWin));if(embeddingWin)embeddingWin->SetFocus();}if(!mDocShell){return;}nsCOMPtr<nsIPresShell>presShell;// Don't look for a presshell if we're a root chrome window that's got// about:blank loaded. We don't want to focus our widget in that case.// XXXbz should we really be checking for IsInitialDocument() instead?boollookForPresShell=true;if(mDocShell->ItemType()==nsIDocShellTreeItem::typeChrome&&GetPrivateRoot()==AsOuter()&&mDoc){nsIURI*ourURI=mDoc->GetDocumentURI();if(ourURI){lookForPresShell=!NS_IsAboutBlank(ourURI);}}if(lookForPresShell){mDocShell->GetEldestPresShell(getter_AddRefs(presShell));}nsCOMPtr<nsIDocShellTreeItem>parentDsti;mDocShell->GetParent(getter_AddRefs(parentDsti));// set the parent's current focus to the frame containing this window.nsCOMPtr<nsPIDOMWindowOuter>parent=parentDsti?parentDsti->GetWindow():nullptr;if(parent){nsCOMPtr<nsIDocument>parentdoc=parent->GetDoc();if(!parentdoc){return;}nsIContent*frame=parentdoc->FindContentForSubDocument(mDoc);nsCOMPtr<nsIDOMElement>frameElement=do_QueryInterface(frame);if(frameElement){uint32_tflags=nsIFocusManager::FLAG_NOSCROLL;if(canFocus)flags|=nsIFocusManager::FLAG_RAISE;aError=fm->SetFocus(frameElement,flags);}return;}if(canFocus){// if there is no parent, this must be a toplevel window, so raise the// window if canFocus is true. If this is a child process, the raise// window request will get forwarded to the parent by the puppet widget.aError=fm->SetActiveWindow(AsOuter());}}voidnsGlobalWindowInner::Focus(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(FocusOuter,(aError),aError,);}nsresultnsGlobalWindowInner::Focus(){FORWARD_TO_INNER(Focus,(),NS_ERROR_UNEXPECTED);ErrorResultrv;Focus(rv);returnrv.StealNSResult();}voidnsGlobalWindowInner::BlurOuter(){MOZ_RELEASE_ASSERT(IsOuterWindow());// If dom.disable_window_flip == true, then content should not be allowed// to call this function (this would allow popunders, bug 369306)if(!CanSetProperty("dom.disable_window_flip")){return;}// If embedding apps don't implement nsIEmbeddingSiteWindow, we// shouldn't throw exceptions to web content.nsCOMPtr<nsIDocShellTreeOwner>treeOwner=GetTreeOwner();nsCOMPtr<nsIEmbeddingSiteWindow>siteWindow(do_GetInterface(treeOwner));if(siteWindow){// This method call may cause mDocShell to become nullptr.siteWindow->Blur();// if the root is focused, clear the focusnsIFocusManager*fm=nsFocusManager::GetFocusManager();if(fm&&mDoc){nsCOMPtr<nsIDOMElement>element;fm->GetFocusedElementForWindow(AsOuter(),false,nullptr,getter_AddRefs(element));nsCOMPtr<nsIContent>content=do_QueryInterface(element);if(content==mDoc->GetRootElement()){fm->ClearFocus(AsOuter());}}}}voidnsGlobalWindowInner::Blur(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(BlurOuter,(),aError,);}voidnsGlobalWindowInner::BackOuter(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());nsCOMPtr<nsIWebNavigation>webNav(do_QueryInterface(mDocShell));if(!webNav){aError.Throw(NS_ERROR_FAILURE);return;}aError=webNav->GoBack();}voidnsGlobalWindowInner::Back(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(BackOuter,(aError),aError,);}voidnsGlobalWindowInner::ForwardOuter(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());nsCOMPtr<nsIWebNavigation>webNav(do_QueryInterface(mDocShell));if(!webNav){aError.Throw(NS_ERROR_FAILURE);return;}aError=webNav->GoForward();}voidnsGlobalWindowInner::Forward(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(ForwardOuter,(aError),aError,);}voidnsGlobalWindowInner::HomeOuter(nsIPrincipal&aSubjectPrincipal,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());if(!mDocShell){return;}nsAutoStringhomeURL;Preferences::GetLocalizedString(PREF_BROWSER_STARTUP_HOMEPAGE,homeURL);if(homeURL.IsEmpty()){// if all else fails, use this#ifdef DEBUG_sethprintf("all else failed. using %s as the home page\n",DEFAULT_HOME_PAGE);#endifCopyASCIItoUTF16(DEFAULT_HOME_PAGE,homeURL);}#ifdef MOZ_PHOENIX{// Firefox lets the user specify multiple home pages to open in// individual tabs by separating them with '|'. Since we don't// have the machinery in place to easily open new tabs from here,// simply truncate the homeURL at the first '|' character to// prevent any possibilities of leaking the users list of home// pages to the first home page.//// Once bug https://bugzilla.mozilla.org/show_bug.cgi?id=221445 is// fixed we can revisit this.int32_tfirstPipe=homeURL.FindChar('|');if(firstPipe>0){homeURL.Truncate(firstPipe);}}#endifnsCOMPtr<nsIWebNavigation>webNav(do_QueryInterface(mDocShell));if(!webNav){aError.Throw(NS_ERROR_FAILURE);return;}aError=webNav->LoadURI(homeURL.get(),nsIWebNavigation::LOAD_FLAGS_NONE,nullptr,nullptr,nullptr,&aSubjectPrincipal);}voidnsGlobalWindowInner::Home(nsIPrincipal&aSubjectPrincipal,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(HomeOuter,(aSubjectPrincipal,aError),aError,);}voidnsGlobalWindowInner::StopOuter(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());nsCOMPtr<nsIWebNavigation>webNav(do_QueryInterface(mDocShell));if(webNav){aError=webNav->Stop(nsIWebNavigation::STOP_ALL);}}voidnsGlobalWindowInner::Stop(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(StopOuter,(aError),aError,);}/* static */boolnsGlobalWindowInner::IsWindowPrintEnabled(JSContext*,JSObject*){staticboolcalled=false;staticboolprintDisabled=false;if(!called){called=true;Preferences::AddBoolVarCache(&printDisabled,"dom.disable_window_print");}return!printDisabled;}voidnsGlobalWindowInner::PrintOuter(ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());#ifdef NS_PRINTINGif(!AreDialogsEnabled()){// We probably want to keep throwing here; silently doing nothing is a bit// weird given the typical use cases of print().aError.Throw(NS_ERROR_NOT_AVAILABLE);return;}if(ShouldPromptToBlockDialogs()&&!ConfirmDialogIfNeeded()){aError.Throw(NS_ERROR_NOT_AVAILABLE);return;}nsCOMPtr<nsIWebBrowserPrint>webBrowserPrint;if(NS_SUCCEEDED(GetInterface(NS_GET_IID(nsIWebBrowserPrint),getter_AddRefs(webBrowserPrint)))){nsAutoSyncOperationsync(GetCurrentInnerWindowInternal()?GetCurrentInnerWindowInternal()->mDoc.get():nullptr);nsCOMPtr<nsIPrintSettingsService>printSettingsService=do_GetService("@mozilla.org/gfx/printsettings-service;1");nsCOMPtr<nsIPrintSettings>printSettings;if(printSettingsService){boolprintSettingsAreGlobal=Preferences::GetBool("print.use_global_printsettings",false);if(printSettingsAreGlobal){printSettingsService->GetGlobalPrintSettings(getter_AddRefs(printSettings));nsAutoStringprinterName;printSettings->GetPrinterName(printerName);boolshouldGetDefaultPrinterName=printerName.IsEmpty();#ifdef MOZ_X11// In Linux, GTK backend does not support per printer settings.// Calling GetDefaultPrinterName causes a sandbox violation (see Bug 1329216).// The printer name is not needed anywhere else on Linux before it gets to the parent.// In the parent, we will then query the default printer name if no name is set.// Unless we are in the parent, we will skip this part.if(!XRE_IsParentProcess()){shouldGetDefaultPrinterName=false;}#endifif(shouldGetDefaultPrinterName){printSettingsService->GetDefaultPrinterName(printerName);printSettings->SetPrinterName(printerName);}printSettingsService->InitPrintSettingsFromPrinter(printerName,printSettings);printSettingsService->InitPrintSettingsFromPrefs(printSettings,true,nsIPrintSettings::kInitSaveAll);}else{printSettingsService->GetNewPrintSettings(getter_AddRefs(printSettings));}EnterModalState();webBrowserPrint->Print(printSettings,nullptr);LeaveModalState();boolsavePrintSettings=Preferences::GetBool("print.save_print_settings",false);if(printSettingsAreGlobal&&savePrintSettings){printSettingsService->SavePrintSettingsToPrefs(printSettings,true,nsIPrintSettings::kInitSaveAll);printSettingsService->SavePrintSettingsToPrefs(printSettings,false,nsIPrintSettings::kInitSavePrinterName);}}else{webBrowserPrint->GetGlobalPrintSettings(getter_AddRefs(printSettings));webBrowserPrint->Print(printSettings,nullptr);}}#endif //NS_PRINTING}voidnsGlobalWindowInner::Print(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(PrintOuter,(aError),aError,);}voidnsGlobalWindowInner::MoveToOuter(int32_taXPos,int32_taYPos,CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());/* * If caller is not chrome and the user has not explicitly exempted the site, * prevent window.moveTo() by exiting early */if(!CanMoveResizeWindows(aCallerType)||IsFrame()){return;}nsCOMPtr<nsIBaseWindow>treeOwnerAsWin=GetTreeOwnerWindow();if(!treeOwnerAsWin){aError.Throw(NS_ERROR_FAILURE);return;}nsCOMPtr<nsIScreenManager>screenMgr=do_GetService("@mozilla.org/gfx/screenmanager;1");nsCOMPtr<nsIScreen>screen;if(screenMgr){CSSIntSizesize;GetInnerSize(size);screenMgr->ScreenForRect(aXPos,aYPos,size.width,size.height,getter_AddRefs(screen));}if(screen){// On secondary displays, the "CSS px" coordinates are offset so that they// share their origin with global desktop pixels, to avoid ambiguities in// the coordinate space when there are displays with different DPIs.// (See the corresponding code in GetScreenXY() above.)int32_tscreenLeftDeskPx,screenTopDeskPx,w,h;screen->GetRectDisplayPix(&screenLeftDeskPx,&screenTopDeskPx,&w,&h);CSSIntPointcssPos(aXPos-screenLeftDeskPx,aYPos-screenTopDeskPx);CheckSecurityLeftAndTop(&cssPos.x,&cssPos.y,aCallerType);doublescale;screen->GetDefaultCSSScaleFactor(&scale);LayoutDevicePointdevPos=cssPos*CSSToLayoutDeviceScale(scale);screen->GetContentsScaleFactor(&scale);DesktopPointdeskPos=devPos/DesktopToLayoutDeviceScale(scale);aError=treeOwnerAsWin->SetPositionDesktopPix(screenLeftDeskPx+deskPos.x,screenTopDeskPx+deskPos.y);}else{// We couldn't find a screen? Just assume a 1:1 mapping.CSSIntPointcssPos(aXPos,aXPos);CheckSecurityLeftAndTop(&cssPos.x,&cssPos.y,aCallerType);LayoutDevicePointdevPos=cssPos*CSSToLayoutDeviceScale(1.0);aError=treeOwnerAsWin->SetPosition(devPos.x,devPos.y);}CheckForDPIChange();}voidnsGlobalWindowInner::MoveTo(int32_taXPos,int32_taYPos,CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(MoveToOuter,(aXPos,aYPos,aCallerType,aError),aError,);}voidnsGlobalWindowInner::MoveByOuter(int32_taXDif,int32_taYDif,CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());/* * If caller is not chrome and the user has not explicitly exempted the site, * prevent window.moveBy() by exiting early */if(!CanMoveResizeWindows(aCallerType)||IsFrame()){return;}nsCOMPtr<nsIBaseWindow>treeOwnerAsWin=GetTreeOwnerWindow();if(!treeOwnerAsWin){aError.Throw(NS_ERROR_FAILURE);return;}// To do this correctly we have to convert what we get from GetPosition// into CSS pixels, add the arguments, do the security check, and// then convert back to device pixels for the call to SetPosition.int32_tx,y;aError=treeOwnerAsWin->GetPosition(&x,&y);if(aError.Failed()){return;}// mild abuse of a "size" object so we don't need more helper functionsnsIntSizecssPos(DevToCSSIntPixels(nsIntSize(x,y)));cssPos.width+=aXDif;cssPos.height+=aYDif;CheckSecurityLeftAndTop(&cssPos.width,&cssPos.height,aCallerType);nsIntSizenewDevPos(CSSToDevIntPixels(cssPos));aError=treeOwnerAsWin->SetPosition(newDevPos.width,newDevPos.height);CheckForDPIChange();}voidnsGlobalWindowInner::MoveBy(int32_taXDif,int32_taYDif,CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(MoveByOuter,(aXDif,aYDif,aCallerType,aError),aError,);}nsresultnsGlobalWindowInner::MoveBy(int32_taXDif,int32_taYDif){FORWARD_TO_OUTER(MoveBy,(aXDif,aYDif),NS_ERROR_UNEXPECTED);ErrorResultrv;MoveByOuter(aXDif,aYDif,CallerType::System,rv);returnrv.StealNSResult();}voidnsGlobalWindowInner::ResizeToOuter(int32_taWidth,int32_taHeight,CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());/* * If caller is a browser-element then dispatch a resize event to * the embedder. */if(mDocShell&&mDocShell->GetIsMozBrowser()){CSSIntSizesize(aWidth,aHeight);if(!DispatchResizeEvent(size)){// The embedder chose to prevent the default action for this// event, so let's not resize this window after all...return;}}/* * If caller is not chrome and the user has not explicitly exempted the site, * prevent window.resizeTo() by exiting early */if(!CanMoveResizeWindows(aCallerType)||IsFrame()){return;}nsCOMPtr<nsIBaseWindow>treeOwnerAsWin=GetTreeOwnerWindow();if(!treeOwnerAsWin){aError.Throw(NS_ERROR_FAILURE);return;}nsIntSizecssSize(aWidth,aHeight);CheckSecurityWidthAndHeight(&cssSize.width,&cssSize.height,aCallerType);nsIntSizedevSz(CSSToDevIntPixels(cssSize));aError=treeOwnerAsWin->SetSize(devSz.width,devSz.height,true);CheckForDPIChange();}voidnsGlobalWindowInner::ResizeTo(int32_taWidth,int32_taHeight,CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(ResizeToOuter,(aWidth,aHeight,aCallerType,aError),aError,);}voidnsGlobalWindowInner::ResizeByOuter(int32_taWidthDif,int32_taHeightDif,CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());/* * If caller is a browser-element then dispatch a resize event to * parent. */if(mDocShell&&mDocShell->GetIsMozBrowser()){CSSIntSizesize;if(NS_FAILED(GetInnerSize(size))){return;}size.width+=aWidthDif;size.height+=aHeightDif;if(!DispatchResizeEvent(size)){// The embedder chose to prevent the default action for this// event, so let's not resize this window after all...return;}}/* * If caller is not chrome and the user has not explicitly exempted the site, * prevent window.resizeBy() by exiting early */if(!CanMoveResizeWindows(aCallerType)||IsFrame()){return;}nsCOMPtr<nsIBaseWindow>treeOwnerAsWin=GetTreeOwnerWindow();if(!treeOwnerAsWin){aError.Throw(NS_ERROR_FAILURE);return;}int32_twidth,height;aError=treeOwnerAsWin->GetSize(&width,&height);if(aError.Failed()){return;}// To do this correctly we have to convert what we got from GetSize// into CSS pixels, add the arguments, do the security check, and// then convert back to device pixels for the call to SetSize.nsIntSizecssSize(DevToCSSIntPixels(nsIntSize(width,height)));cssSize.width+=aWidthDif;cssSize.height+=aHeightDif;CheckSecurityWidthAndHeight(&cssSize.width,&cssSize.height,aCallerType);nsIntSizenewDevSize(CSSToDevIntPixels(cssSize));aError=treeOwnerAsWin->SetSize(newDevSize.width,newDevSize.height,true);CheckForDPIChange();}voidnsGlobalWindowInner::ResizeBy(int32_taWidthDif,int32_taHeightDif,CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(ResizeByOuter,(aWidthDif,aHeightDif,aCallerType,aError),aError,);}voidnsGlobalWindowInner::SizeToContentOuter(CallerTypeaCallerType,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());if(!mDocShell){return;}/* * If caller is not chrome and the user has not explicitly exempted the site, * prevent window.sizeToContent() by exiting early */if(!CanMoveResizeWindows(aCallerType)||IsFrame()){return;}// The content viewer does a check to make sure that it's a content// viewer for a toplevel docshell.nsCOMPtr<nsIContentViewer>cv;mDocShell->GetContentViewer(getter_AddRefs(cv));if(!cv){aError.Throw(NS_ERROR_FAILURE);return;}int32_twidth,height;aError=cv->GetContentSize(&width,&height);if(aError.Failed()){return;}// Make sure the new size is following the CheckSecurityWidthAndHeight// rules.nsCOMPtr<nsIDocShellTreeOwner>treeOwner=GetTreeOwner();if(!treeOwner){aError.Throw(NS_ERROR_FAILURE);return;}nsIntSizecssSize(DevToCSSIntPixels(nsIntSize(width,height)));CheckSecurityWidthAndHeight(&cssSize.width,&cssSize.height,aCallerType);nsIntSizenewDevSize(CSSToDevIntPixels(cssSize));aError=treeOwner->SizeShellTo(mDocShell,newDevSize.width,newDevSize.height);}voidnsGlobalWindowInner::SizeToContent(CallerTypeaCallerType,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(SizeToContentOuter,(aCallerType,aError),aError,);}already_AddRefed<nsPIWindowRoot>nsGlobalWindowInner::GetTopWindowRoot(){nsPIDOMWindowOuter*piWin=GetPrivateRoot();if(!piWin){returnnullptr;}nsCOMPtr<nsPIWindowRoot>window=do_QueryInterface(piWin->GetChromeEventHandler());returnwindow.forget();}voidnsGlobalWindowInner::Scroll(doubleaXScroll,doubleaYScroll){// Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.autoscrollPos=CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScroll),mozilla::ToZeroIfNonfinite(aYScroll));ScrollTo(scrollPos,ScrollOptions());}voidnsGlobalWindowInner::ScrollTo(doubleaXScroll,doubleaYScroll){// Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.autoscrollPos=CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScroll),mozilla::ToZeroIfNonfinite(aYScroll));ScrollTo(scrollPos,ScrollOptions());}voidnsGlobalWindowInner::ScrollTo(constScrollToOptions&aOptions){// When scrolling to a non-zero offset, we need to determine whether that// position is within our scrollable range, so we need updated layout// information which requires a layout flush, otherwise all we need is to// flush frames to be able to access our scrollable frame here.FlushTypeflushType=((aOptions.mLeft.WasPassed()&&aOptions.mLeft.Value()>0)||(aOptions.mTop.WasPassed()&&aOptions.mTop.Value()>0))?FlushType::Layout:FlushType::Frames;FlushPendingNotifications(flushType);nsIScrollableFrame*sf=GetScrollFrame();if(sf){CSSIntPointscrollPos=sf->GetScrollPositionCSSPixels();if(aOptions.mLeft.WasPassed()){scrollPos.x=mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value());}if(aOptions.mTop.WasPassed()){scrollPos.y=mozilla::ToZeroIfNonfinite(aOptions.mTop.Value());}ScrollTo(scrollPos,aOptions);}}voidnsGlobalWindowInner::Scroll(constScrollToOptions&aOptions){ScrollTo(aOptions);}voidnsGlobalWindowInner::ScrollTo(constCSSIntPoint&aScroll,constScrollOptions&aOptions){// When scrolling to a non-zero offset, we need to determine whether that// position is within our scrollable range, so we need updated layout// information which requires a layout flush, otherwise all we need is to// flush frames to be able to access our scrollable frame here.FlushTypeflushType=(aScroll.x||aScroll.y)?FlushType::Layout:FlushType::Frames;FlushPendingNotifications(flushType);nsIScrollableFrame*sf=GetScrollFrame();if(sf){// Here we calculate what the max pixel value is that we can// scroll to, we do this by dividing maxint with the pixel to// twips conversion factor, and subtracting 4, the 4 comes from// experimenting with this value, anything less makes the view// code not scroll correctly, I have no idea why. -- jstconstint32_tmaxpx=nsPresContext::AppUnitsToIntCSSPixels(0x7fffffff)-4;CSSIntPointscroll(aScroll);if(scroll.x>maxpx){scroll.x=maxpx;}if(scroll.y>maxpx){scroll.y=maxpx;}boolsmoothScroll=sf->GetScrollbarStyles().IsSmoothScroll(aOptions.mBehavior);sf->ScrollToCSSPixels(scroll,smoothScroll?nsIScrollableFrame::SMOOTH_MSD:nsIScrollableFrame::INSTANT);}}voidnsGlobalWindowInner::ScrollBy(doubleaXScrollDif,doubleaYScrollDif){FlushPendingNotifications(FlushType::Layout);nsIScrollableFrame*sf=GetScrollFrame();if(sf){// Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.autoscrollDif=CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScrollDif),mozilla::ToZeroIfNonfinite(aYScrollDif));// It seems like it would make more sense for ScrollBy to use// SMOOTH mode, but tests seem to depend on the synchronous behaviour.// Perhaps Web content does too.ScrollTo(sf->GetScrollPositionCSSPixels()+scrollDif,ScrollOptions());}}voidnsGlobalWindowInner::ScrollBy(constScrollToOptions&aOptions){FlushPendingNotifications(FlushType::Layout);nsIScrollableFrame*sf=GetScrollFrame();if(sf){CSSIntPointscrollPos=sf->GetScrollPositionCSSPixels();if(aOptions.mLeft.WasPassed()){scrollPos.x+=mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value());}if(aOptions.mTop.WasPassed()){scrollPos.y+=mozilla::ToZeroIfNonfinite(aOptions.mTop.Value());}ScrollTo(scrollPos,aOptions);}}voidnsGlobalWindowInner::ScrollByLines(int32_tnumLines,constScrollOptions&aOptions){MOZ_ASSERT(IsInnerWindow());FlushPendingNotifications(FlushType::Layout);nsIScrollableFrame*sf=GetScrollFrame();if(sf){// It seems like it would make more sense for ScrollByLines to use// SMOOTH mode, but tests seem to depend on the synchronous behaviour.// Perhaps Web content does too.boolsmoothScroll=sf->GetScrollbarStyles().IsSmoothScroll(aOptions.mBehavior);sf->ScrollBy(nsIntPoint(0,numLines),nsIScrollableFrame::LINES,smoothScroll?nsIScrollableFrame::SMOOTH_MSD:nsIScrollableFrame::INSTANT);}}voidnsGlobalWindowInner::ScrollByPages(int32_tnumPages,constScrollOptions&aOptions){MOZ_ASSERT(IsInnerWindow());FlushPendingNotifications(FlushType::Layout);nsIScrollableFrame*sf=GetScrollFrame();if(sf){// It seems like it would make more sense for ScrollByPages to use// SMOOTH mode, but tests seem to depend on the synchronous behaviour.// Perhaps Web content does too.boolsmoothScroll=sf->GetScrollbarStyles().IsSmoothScroll(aOptions.mBehavior);sf->ScrollBy(nsIntPoint(0,numPages),nsIScrollableFrame::PAGES,smoothScroll?nsIScrollableFrame::SMOOTH_MSD:nsIScrollableFrame::INSTANT);}}voidnsGlobalWindowInner::MozScrollSnap(){MOZ_ASSERT(IsInnerWindow());FlushPendingNotifications(FlushType::Layout);nsIScrollableFrame*sf=GetScrollFrame();if(sf){sf->ScrollSnap();}}voidnsGlobalWindowInner::ClearTimeout(int32_taHandle){MOZ_RELEASE_ASSERT(IsInnerWindow());if(aHandle>0){mTimeoutManager->ClearTimeout(aHandle,Timeout::Reason::eTimeoutOrInterval);}}voidnsGlobalWindowInner::ClearInterval(int32_taHandle){MOZ_RELEASE_ASSERT(IsInnerWindow());if(aHandle>0){mTimeoutManager->ClearTimeout(aHandle,Timeout::Reason::eTimeoutOrInterval);}}voidnsGlobalWindowInner::SetResizable(boolaResizable)const{// nop}voidnsGlobalWindowInner::CaptureEvents(){if(mDoc){mDoc->WarnOnceAbout(nsIDocument::eUseOfCaptureEvents);}}voidnsGlobalWindowInner::ReleaseEvents(){if(mDoc){mDoc->WarnOnceAbout(nsIDocument::eUseOfReleaseEvents);}}voidnsGlobalWindowInner::FirePopupBlockedEvent(nsIDocument*aDoc,nsIURI*aPopupURI,constnsAString&aPopupWindowName,constnsAString&aPopupWindowFeatures){MOZ_ASSERT(IsOuterWindow(),"All callers seem to assume we're an outer window?");MOZ_ASSERT(aDoc);// Fire a "DOMPopupBlocked" event so that the UI can hear about// blocked popups.PopupBlockedEventInitinit;init.mBubbles=true;init.mCancelable=true;// XXX: This is a different object, but webidl requires an inner window here// now.init.mRequestingWindow=GetCurrentInnerWindowInternal();init.mPopupWindowURI=aPopupURI;init.mPopupWindowName=aPopupWindowName;init.mPopupWindowFeatures=aPopupWindowFeatures;RefPtr<PopupBlockedEvent>event=PopupBlockedEvent::Constructor(aDoc,NS_LITERAL_STRING("DOMPopupBlocked"),init);event->SetTrusted(true);booldefaultActionEnabled;aDoc->DispatchEvent(event,&defaultActionEnabled);}// staticboolnsGlobalWindowInner::CanSetProperty(constchar*aPrefName){// Chrome can set any property.if(nsContentUtils::LegacyIsCallerChromeOrNativeCode()){returntrue;}// If the pref is set to true, we can not set the property// and vice versa.return!Preferences::GetBool(aPrefName,true);}boolnsGlobalWindowInner::PopupWhitelisted(){MOZ_CRASH("Outer Window only");}/* * Examine the current document state to see if we're in a way that is * typically abused by web designers. The window.open code uses this * routine to determine whether to allow the new window. * Returns a value from the PopupControlState enum. */PopupControlStatensGlobalWindowInner::RevisePopupAbuseLevel(PopupControlStateaControl){MOZ_CRASH("Outer window only");}/* If a window open is blocked, fire the appropriate DOM events. */voidnsGlobalWindowInner::FireAbuseEvents(constnsAString&aPopupURL,constnsAString&aPopupWindowName,constnsAString&aPopupWindowFeatures){MOZ_ASSERT(IsOuterWindow());// fetch the URI of the window requesting the opened windownsCOMPtr<nsPIDOMWindowOuter>window=GetTop();if(!window){return;}nsCOMPtr<nsIDocument>topDoc=window->GetDoc();nsCOMPtr<nsIURI>popupURI;// build the URI of the would-have-been popup window// (see nsWindowWatcher::URIfromURL)// first, fetch the opener's base URInsIURI*baseURL=nullptr;nsCOMPtr<nsIDocument>doc=GetEntryDocument();if(doc)baseURL=doc->GetDocBaseURI();// use the base URI to build what would have been the popup's URInsCOMPtr<nsIIOService>ios(do_GetService(NS_IOSERVICE_CONTRACTID));if(ios)ios->NewURI(NS_ConvertUTF16toUTF8(aPopupURL),nullptr,baseURL,getter_AddRefs(popupURI));// fire an event chock full of informative URIsFirePopupBlockedEvent(topDoc,popupURI,aPopupWindowName,aPopupWindowFeatures);}already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::OpenOuter(constnsAString&aUrl,constnsAString&aName,constnsAString&aOptions,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());nsCOMPtr<nsPIDOMWindowOuter>window;aError=OpenJS(aUrl,aName,aOptions,getter_AddRefs(window));returnwindow.forget();}already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::Open(constnsAString&aUrl,constnsAString&aName,constnsAString&aOptions,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(OpenOuter,(aUrl,aName,aOptions,aError),aError,nullptr);}nsresultnsGlobalWindowInner::Open(constnsAString&aUrl,constnsAString&aName,constnsAString&aOptions,nsIDocShellLoadInfo*aLoadInfo,boolaForceNoOpener,nsPIDOMWindowOuter**_retval){FORWARD_TO_OUTER(Open,(aUrl,aName,aOptions,aLoadInfo,aForceNoOpener,_retval),NS_ERROR_NOT_INITIALIZED);returnOpenInternal(aUrl,aName,aOptions,false,// aDialogfalse,// aContentModaltrue,// aCalledNoScriptfalse,// aDoJSFixupstrue,// aNavigatenullptr,nullptr,// No argsaLoadInfo,aForceNoOpener,_retval);}nsresultnsGlobalWindowInner::OpenJS(constnsAString&aUrl,constnsAString&aName,constnsAString&aOptions,nsPIDOMWindowOuter**_retval){MOZ_ASSERT(IsOuterWindow());returnOpenInternal(aUrl,aName,aOptions,false,// aDialogfalse,// aContentModalfalse,// aCalledNoScripttrue,// aDoJSFixupstrue,// aNavigatenullptr,nullptr,// No argsnullptr,// aLoadInfofalse,// aForceNoOpener_retval);}// like Open, but attaches to the new window any extra parameters past// [features] as a JS property named "arguments"nsresultnsGlobalWindowInner::OpenDialog(constnsAString&aUrl,constnsAString&aName,constnsAString&aOptions,nsISupports*aExtraArgument,nsPIDOMWindowOuter**_retval){MOZ_ASSERT(IsOuterWindow());returnOpenInternal(aUrl,aName,aOptions,true,// aDialogfalse,// aContentModaltrue,// aCalledNoScriptfalse,// aDoJSFixupstrue,// aNavigatenullptr,aExtraArgument,// Argumentsnullptr,// aLoadInfofalse,// aForceNoOpener_retval);}// Like Open, but passes aNavigate=false./* virtual */nsresultnsGlobalWindowInner::OpenNoNavigate(constnsAString&aUrl,constnsAString&aName,constnsAString&aOptions,nsPIDOMWindowOuter**_retval){MOZ_ASSERT(IsOuterWindow());returnOpenInternal(aUrl,aName,aOptions,false,// aDialogfalse,// aContentModaltrue,// aCalledNoScriptfalse,// aDoJSFixupsfalse,// aNavigatenullptr,nullptr,// No argsnullptr,// aLoadInfofalse,// aForceNoOpener_retval);}already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::OpenDialogOuter(JSContext*aCx,constnsAString&aUrl,constnsAString&aName,constnsAString&aOptions,constSequence<JS::Value>&aExtraArgument,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());nsCOMPtr<nsIJSArgArray>argvArray;aError=NS_CreateJSArgv(aCx,aExtraArgument.Length(),aExtraArgument.Elements(),getter_AddRefs(argvArray));if(aError.Failed()){returnnullptr;}nsCOMPtr<nsPIDOMWindowOuter>dialog;aError=OpenInternal(aUrl,aName,aOptions,true,// aDialogfalse,// aContentModalfalse,// aCalledNoScriptfalse,// aDoJSFixupstrue,// aNavigateargvArray,nullptr,// Argumentsnullptr,// aLoadInfofalse,// aForceNoOpenergetter_AddRefs(dialog));returndialog.forget();}already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::OpenDialog(JSContext*aCx,constnsAString&aUrl,constnsAString&aName,constnsAString&aOptions,constSequence<JS::Value>&aExtraArgument,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(OpenDialogOuter,(aCx,aUrl,aName,aOptions,aExtraArgument,aError),aError,nullptr);}already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::GetFramesOuter(){RefPtr<nsPIDOMWindowOuter>frames(AsOuter());FlushPendingNotifications(FlushType::ContentAndNotify);returnframes.forget();}already_AddRefed<nsPIDOMWindowOuter>nsGlobalWindowInner::GetFrames(ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(GetFramesOuter,(),aError,nullptr);}nsGlobalWindowInner*nsGlobalWindowInner::CallerInnerWindow(){JSContext*cx=nsContentUtils::GetCurrentJSContext();NS_ENSURE_TRUE(cx,nullptr);nsIGlobalObject*global=GetIncumbentGlobal();NS_ENSURE_TRUE(global,nullptr);JS::Rooted<JSObject*>scope(cx,global->GetGlobalJSObject());NS_ENSURE_TRUE(scope,nullptr);// When Jetpack runs content scripts inside a sandbox, it uses// sandboxPrototype to make them appear as though they're running in the// scope of the page. So when a content script invokes postMessage, it expects// the |source| of the received message to be the window set as the// sandboxPrototype. This used to work incidentally for unrelated reasons, but// now we need to do some special handling to support it.if(xpc::IsSandbox(scope)){JSAutoCompartmentac(cx,scope);JS::Rooted<JSObject*>scopeProto(cx);boolok=JS_GetPrototype(cx,scope,&scopeProto);NS_ENSURE_TRUE(ok,nullptr);if(scopeProto&&xpc::IsSandboxPrototypeProxy(scopeProto)&&(scopeProto=js::CheckedUnwrap(scopeProto,/* stopAtWindowProxy = */false))){global=xpc::NativeGlobal(scopeProto);NS_ENSURE_TRUE(global,nullptr);}}// The calling window must be holding a reference, so we can return a weak// pointer.nsCOMPtr<nsPIDOMWindowInner>win=do_QueryInterface(global);returnnsGlobalWindowInner::Cast(win);}voidnsGlobalWindowInner::PostMessageMozOuter(JSContext*aCx,JS::Handle<JS::Value>aMessage,constnsAString&aTargetOrigin,JS::Handle<JS::Value>aTransfer,nsIPrincipal&aSubjectPrincipal,ErrorResult&aError){MOZ_RELEASE_ASSERT(IsOuterWindow());//// Window.postMessage is an intentional subversion of the same-origin policy.// As such, this code must be particularly careful in the information it// exposes to calling code.//// http://www.whatwg.org/specs/web-apps/current-work/multipage/section-crossDocumentMessages.html//// First, get the caller's windowRefPtr<nsGlobalWindowInner>callerInnerWin=CallerInnerWindow();nsIPrincipal*callerPrin;if(callerInnerWin){MOZ_ASSERT(callerInnerWin->IsInnerWindow(),"should have gotten an inner window here");// Compute the caller's origin either from its principal or, in the case the// principal doesn't carry a URI (e.g. the system principal), the caller's// document. We must get this now instead of when the event is created and// dispatched, because ultimately it is the identity of the calling window// *now* that determines who sent the message (and not an identity which might// have changed due to intervening navigations).callerPrin=callerInnerWin->GetPrincipal();}else{// In case the global is not a window, it can be a sandbox, and the sandbox's// principal can be used for the security check.nsIGlobalObject*global=GetIncumbentGlobal();NS_ASSERTION(global,"Why is there no global object?");callerPrin=global->PrincipalOrNull();}if(!callerPrin){return;}nsCOMPtr<nsIURI>callerOuterURI;if(NS_FAILED(callerPrin->GetURI(getter_AddRefs(callerOuterURI)))){return;}nsAutoStringorigin;if(callerOuterURI){// if the principal has a URI, use that to generate the originnsContentUtils::GetUTFOrigin(callerPrin,origin);}elseif(callerInnerWin){// otherwise use the URI of the document to generate originnsCOMPtr<nsIDocument>doc=callerInnerWin->GetExtantDoc();if(!doc){return;}callerOuterURI=doc->GetDocumentURI();// if the principal has a URI, use that to generate the originnsContentUtils::GetUTFOrigin(callerOuterURI,origin);}else{// in case of a sandbox with a system principal origin can be emptyif(!nsContentUtils::IsSystemPrincipal(callerPrin)){return;}}// Convert the provided origin string into a URI for comparison purposes.nsCOMPtr<nsIPrincipal>providedPrincipal;if(aTargetOrigin.EqualsASCII("/")){providedPrincipal=callerPrin;}// "*" indicates no specific origin is required.elseif(!aTargetOrigin.EqualsASCII("*")){nsCOMPtr<nsIURI>originURI;if(NS_FAILED(NS_NewURI(getter_AddRefs(originURI),aTargetOrigin))){aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);return;}if(NS_FAILED(originURI->SetUserPass(EmptyCString()))||NS_FAILED(originURI->SetPathQueryRef(EmptyCString()))){return;}OriginAttributesattrs=aSubjectPrincipal.OriginAttributesRef();if(aSubjectPrincipal.GetIsSystemPrincipal()){autoprincipal=BasePrincipal::Cast(GetPrincipal());if(attrs!=principal->OriginAttributesRef()){nsCOMPtr<nsIURI>targetURI;nsAutoCStringtargetURL;nsAutoCStringsourceOrigin;nsAutoCStringtargetOrigin;if(NS_FAILED(principal->GetURI(getter_AddRefs(targetURI)))||NS_FAILED(targetURI->GetAsciiSpec(targetURL))||NS_FAILED(principal->GetOrigin(targetOrigin))||NS_FAILED(aSubjectPrincipal.GetOrigin(sourceOrigin))){NS_WARNING("Failed to get source and target origins");return;}nsContentUtils::LogSimpleConsoleError(NS_ConvertUTF8toUTF16(nsPrintfCString(R"(Attempting to post a message to window with url "%s" and )"R"(origin "%s" from a system principal scope with mismatched )"R"(origin "%s".)",targetURL.get(),targetOrigin.get(),sourceOrigin.get())),"DOM");attrs=principal->OriginAttributesRef();}}// Create a nsIPrincipal inheriting the app/browser attributes from the// caller.providedPrincipal=BasePrincipal::CreateCodebasePrincipal(originURI,attrs);if(NS_WARN_IF(!providedPrincipal)){return;}}// Create and asynchronously dispatch a runnable which will handle actual DOM// event creation and dispatch.RefPtr<PostMessageEvent>event=newPostMessageEvent(nsContentUtils::IsCallerChrome()||!callerInnerWin?nullptr:callerInnerWin->GetOuterWindowInternal(),origin,AssertOuter(),providedPrincipal,callerInnerWin?callerInnerWin->GetDoc():nullptr,nsContentUtils::IsCallerChrome());JS::Rooted<JS::Value>message(aCx,aMessage);JS::Rooted<JS::Value>transfer(aCx,aTransfer);event->Write(aCx,message,transfer,JS::CloneDataPolicy(),aError);if(NS_WARN_IF(aError.Failed())){return;}aError=Dispatch(TaskCategory::Other,event.forget());}voidnsGlobalWindowInner::PostMessageMoz(JSContext*aCx,JS::Handle<JS::Value>aMessage,constnsAString&aTargetOrigin,JS::Handle<JS::Value>aTransfer,nsIPrincipal&aSubjectPrincipal,ErrorResult&aError){FORWARD_TO_OUTER_OR_THROW(PostMessageMozOuter,(aCx,aMessage,aTargetOrigin,aTransfer,aSubjectPrincipal,aError),aError,);}voidnsGlobalWindowInner::PostMessageMoz(JSContext*aCx,JS::Handle<JS::Value>aMessage,constnsAString&aTargetOrigin,constSequence<JSObject*>&aTransfer,nsIPrincipal&aSubjectPrincipal,ErrorResult&aRv){JS::Rooted<JS::Value>transferArray(aCx,JS::UndefinedValue());aRv=nsContentUtils::CreateJSValueFromSequenceOfObject(aCx,aTransfer,&transferArray);if(NS_WARN_IF(aRv.Failed())){return;}PostMessageMoz(aCx,aMessage,aTargetOrigin,transferArray,aSubjectPrincipal,aRv);}boolnsGlobalWindowInner::CanClose(){MOZ_ASSERT(IsOuterWindow());if(mIsChrome){nsCOMPtr<nsIBrowserDOMWindow>bwin;GetBrowserDOMWindow(getter_AddRefs(bwin));boolcanClose=true;if(bwin&&NS_SUCCEEDED(bwin->CanClose(&canClose))){returncanClose;}}if(!mDocShell){returntrue;}// Ask the content viewer whether the toplevel window can close.// If the content viewer returns false, it is responsible for calling// Close() as soon as it is possible for the window to close.// This allows us to not close the window while printing is happening.nsCOMPtr<nsIContentViewer>cv;mDocShell->GetContentViewer(getter_AddRefs(cv));if(cv){boolcanClose;nsresultrv=cv->PermitUnload(&canClose);if(NS_SUCCEEDED(rv)&&!canClose)returnfalse;rv=cv->RequestWindowClose(&canClose);if(NS_SUCCEEDED(rv)&&!canClose)returnfalse;}returntrue;}voidnsGlobalWindowInner::CloseOuter(boolaTrustedCaller){MOZ_RELEASE_ASSERT(IsOuterWindow());if(!mDocShell||IsInModalState()||(IsFrame()&&!mDocShell->GetIsMozBrowser())){// window.close() is called on a frame in a frameset, on a window// that's already closed, or on a window for which there's// currently a modal dialog open. Ignore such calls.return;}if(mHavePendingClose){// We're going to be closed anyway; do nothing since we don't want// to double-closereturn;}if(mBlockScriptedClosingFlag){// A script's popup has been blocked and we don't want// the window to be closed directly after this event,// so the user can see that there was a blocked popup.return;}// Don't allow scripts from content to close non-neterror windows that// were not opened by script.nsAutoStringurl;nsresultrv=mDoc->GetURL(url);NS_ENSURE_SUCCESS_VOID(rv);if(!StringBeginsWith(url,NS_LITERAL_STRING("about:neterror"))&&!mHadOriginalOpener&&!aTrustedCaller){boolallowClose=mAllowScriptsToClose||Preferences::GetBool("dom.allow_scripts_to_close_windows",true