2017-11-15 19:30:13 +03:00
|
|
|
/* -*- 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/. */
|
|
|
|
|
2017-11-22 00:00:04 +03:00
|
|
|
#include "nsGlobalWindow.h"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
#include "mozilla/MemoryReporting.h"
|
|
|
|
|
|
|
|
// Local Includes
|
|
|
|
#include "Navigator.h"
|
|
|
|
#include "nsContentSecurityManager.h"
|
|
|
|
#include "nsScreen.h"
|
|
|
|
#include "nsHistory.h"
|
|
|
|
#include "nsDOMNavigationTiming.h"
|
|
|
|
#include "nsIDOMStorageManager.h"
|
|
|
|
#include "mozilla/dom/LocalStorage.h"
|
|
|
|
#include "mozilla/dom/Storage.h"
|
|
|
|
#include "mozilla/dom/IdleRequest.h"
|
|
|
|
#include "mozilla/dom/Performance.h"
|
|
|
|
#include "mozilla/dom/StorageEvent.h"
|
|
|
|
#include "mozilla/dom/StorageEventBinding.h"
|
|
|
|
#include "mozilla/dom/StorageNotifierService.h"
|
|
|
|
#include "mozilla/dom/StorageUtils.h"
|
|
|
|
#include "mozilla/dom/Timeout.h"
|
|
|
|
#include "mozilla/dom/TimeoutHandler.h"
|
|
|
|
#include "mozilla/dom/TimeoutManager.h"
|
|
|
|
#include "mozilla/IntegerPrintfMacros.h"
|
|
|
|
#if defined(MOZ_WIDGET_ANDROID)
|
|
|
|
#include "mozilla/dom/WindowOrientationObserver.h"
|
|
|
|
#endif
|
|
|
|
#include "nsDOMOfflineResourceList.h"
|
|
|
|
#include "nsError.h"
|
|
|
|
#include "nsIIdleService.h"
|
|
|
|
#include "nsISizeOfEventTarget.h"
|
|
|
|
#include "nsDOMJSUtils.h"
|
|
|
|
#include "nsArrayUtils.h"
|
|
|
|
#include "nsIDOMWindowCollection.h"
|
|
|
|
#include "nsDOMWindowList.h"
|
|
|
|
#include "mozilla/dom/WakeLock.h"
|
|
|
|
#include "mozilla/dom/power/PowerManagerService.h"
|
|
|
|
#include "nsIDocShellTreeOwner.h"
|
|
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
|
|
#include "nsIPermissionManager.h"
|
|
|
|
#include "nsIScriptContext.h"
|
|
|
|
#include "nsIScriptTimeoutHandler.h"
|
|
|
|
#include "nsITimeoutHandler.h"
|
|
|
|
#include "nsIController.h"
|
|
|
|
#include "nsScriptNameSpaceManager.h"
|
|
|
|
#include "nsISlowScriptDebug.h"
|
|
|
|
#include "nsWindowMemoryReporter.h"
|
|
|
|
#include "nsWindowSizes.h"
|
|
|
|
#include "WindowNamedPropertiesHandler.h"
|
|
|
|
#include "nsFrameSelection.h"
|
|
|
|
#include "nsNetUtil.h"
|
|
|
|
#include "nsVariant.h"
|
|
|
|
#include "nsPrintfCString.h"
|
|
|
|
#include "mozilla/intl/LocaleService.h"
|
|
|
|
#include "WindowDestroyedEvent.h"
|
|
|
|
|
|
|
|
// Helper Classes
|
|
|
|
#include "nsJSUtils.h"
|
|
|
|
#include "jsapi.h" // for JSAutoRequest
|
|
|
|
#include "jswrapper.h"
|
|
|
|
#include "nsCharSeparatedTokenizer.h"
|
|
|
|
#include "nsReadableUtils.h"
|
|
|
|
#include "nsDOMClassInfo.h"
|
|
|
|
#include "nsJSEnvironment.h"
|
|
|
|
#include "mozilla/dom/ScriptSettings.h"
|
|
|
|
#include "mozilla/Preferences.h"
|
|
|
|
#include "mozilla/Likely.h"
|
|
|
|
#include "mozilla/Sprintf.h"
|
|
|
|
#include "mozilla/Unused.h"
|
|
|
|
|
|
|
|
// Other Classes
|
|
|
|
#include "mozilla/dom/BarProps.h"
|
|
|
|
#include "nsContentCID.h"
|
|
|
|
#include "nsLayoutStatics.h"
|
|
|
|
#include "nsCCUncollectableMarker.h"
|
|
|
|
#include "mozilla/dom/workers/Workers.h"
|
|
|
|
#include "mozilla/dom/ToJSValue.h"
|
|
|
|
#include "nsJSPrincipals.h"
|
|
|
|
#include "mozilla/Attributes.h"
|
|
|
|
#include "mozilla/Debug.h"
|
|
|
|
#include "mozilla/EventListenerManager.h"
|
|
|
|
#include "mozilla/EventStates.h"
|
|
|
|
#include "mozilla/MouseEvents.h"
|
|
|
|
#include "mozilla/ProcessHangMonitor.h"
|
|
|
|
#include "mozilla/ThrottledEventQueue.h"
|
|
|
|
#include "AudioChannelService.h"
|
|
|
|
#include "nsAboutProtocolUtils.h"
|
|
|
|
#include "nsCharTraits.h" // NS_IS_HIGH/LOW_SURROGATE
|
|
|
|
#include "PostMessageEvent.h"
|
|
|
|
#include "mozilla/dom/DocGroup.h"
|
|
|
|
#include "mozilla/dom/TabGroup.h"
|
|
|
|
|
|
|
|
// Interfaces Needed
|
|
|
|
#include "nsIFrame.h"
|
|
|
|
#include "nsCanvasFrame.h"
|
|
|
|
#include "nsIWidget.h"
|
|
|
|
#include "nsIWidgetListener.h"
|
|
|
|
#include "nsIBaseWindow.h"
|
|
|
|
#include "nsIDeviceSensors.h"
|
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsIDocShell.h"
|
|
|
|
#include "nsIDocCharset.h"
|
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "Crypto.h"
|
|
|
|
#include "nsIDOMDocument.h"
|
|
|
|
#include "nsIDOMElement.h"
|
|
|
|
#include "nsIDOMEvent.h"
|
|
|
|
#include "nsIDOMOfflineResourceList.h"
|
|
|
|
#include "nsDOMString.h"
|
|
|
|
#include "nsIEmbeddingSiteWindow.h"
|
|
|
|
#include "nsThreadUtils.h"
|
|
|
|
#include "nsILoadContext.h"
|
|
|
|
#include "nsIPresShell.h"
|
|
|
|
#include "nsIScrollableFrame.h"
|
|
|
|
#include "nsView.h"
|
|
|
|
#include "nsViewManager.h"
|
|
|
|
#include "nsISelectionController.h"
|
|
|
|
#include "nsISelection.h"
|
|
|
|
#include "nsIPrompt.h"
|
|
|
|
#include "nsIPromptService.h"
|
|
|
|
#include "nsIPromptFactory.h"
|
|
|
|
#include "nsIAddonPolicyService.h"
|
|
|
|
#include "nsIWritablePropertyBag2.h"
|
|
|
|
#include "nsIWebNavigation.h"
|
|
|
|
#include "nsIWebBrowserChrome.h"
|
|
|
|
#include "nsIWebBrowserFind.h" // For window.find()
|
|
|
|
#include "nsIWindowMediator.h" // For window.find()
|
|
|
|
#include "nsComputedDOMStyle.h"
|
|
|
|
#include "nsDOMCID.h"
|
|
|
|
#include "nsDOMWindowUtils.h"
|
|
|
|
#include "nsIWindowWatcher.h"
|
|
|
|
#include "nsPIWindowWatcher.h"
|
|
|
|
#include "nsIContentViewer.h"
|
|
|
|
#include "nsIScriptError.h"
|
|
|
|
#include "nsIControllers.h"
|
|
|
|
#include "nsIControllerContext.h"
|
|
|
|
#include "nsGlobalWindowCommands.h"
|
|
|
|
#include "nsQueryObject.h"
|
|
|
|
#include "nsContentUtils.h"
|
|
|
|
#include "nsCSSProps.h"
|
|
|
|
#include "nsIDOMFileList.h"
|
|
|
|
#include "nsIURIFixup.h"
|
|
|
|
#ifndef DEBUG
|
|
|
|
#include "nsIAppStartup.h"
|
|
|
|
#include "nsToolkitCompsCID.h"
|
|
|
|
#endif
|
|
|
|
#include "nsCDefaultURIFixup.h"
|
|
|
|
#include "mozilla/EventDispatcher.h"
|
|
|
|
#include "mozilla/EventStateManager.h"
|
|
|
|
#include "nsIObserverService.h"
|
|
|
|
#include "nsFocusManager.h"
|
|
|
|
#include "nsIXULWindow.h"
|
|
|
|
#include "nsITimedChannel.h"
|
|
|
|
#include "nsServiceManagerUtils.h"
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
#include "nsIDOMXULControlElement.h"
|
|
|
|
#include "nsMenuPopupFrame.h"
|
|
|
|
#endif
|
|
|
|
#include "mozilla/dom/CustomEvent.h"
|
|
|
|
#include "nsIJARChannel.h"
|
|
|
|
#include "nsIScreenManager.h"
|
|
|
|
#include "nsIEffectiveTLDService.h"
|
|
|
|
|
|
|
|
#include "xpcprivate.h"
|
|
|
|
|
|
|
|
#ifdef NS_PRINTING
|
|
|
|
#include "nsIPrintSettings.h"
|
|
|
|
#include "nsIPrintSettingsService.h"
|
|
|
|
#include "nsIWebBrowserPrint.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "nsWindowRoot.h"
|
|
|
|
#include "nsNetCID.h"
|
|
|
|
#include "nsIArray.h"
|
|
|
|
|
|
|
|
// XXX An unfortunate dependency exists here (two XUL files).
|
|
|
|
#include "nsIDOMXULDocument.h"
|
|
|
|
#include "nsIDOMXULCommandDispatcher.h"
|
|
|
|
|
|
|
|
#include "nsBindingManager.h"
|
|
|
|
#include "nsXBLService.h"
|
|
|
|
|
|
|
|
// used for popup blocking, needs to be converted to something
|
|
|
|
// belonging to the back-end like nsIContentPolicy
|
|
|
|
#include "nsIPopupWindowManager.h"
|
|
|
|
|
|
|
|
#include "nsIDragService.h"
|
|
|
|
#include "mozilla/dom/Element.h"
|
|
|
|
#include "mozilla/dom/Selection.h"
|
|
|
|
#include "nsFrameLoader.h"
|
|
|
|
#include "nsISupportsPrimitives.h"
|
|
|
|
#include "nsXPCOMCID.h"
|
|
|
|
#include "mozilla/Logging.h"
|
|
|
|
#include "prenv.h"
|
|
|
|
|
|
|
|
#include "mozilla/dom/IDBFactory.h"
|
|
|
|
#include "mozilla/dom/MessageChannel.h"
|
|
|
|
#include "mozilla/dom/Promise.h"
|
|
|
|
|
|
|
|
#include "mozilla/dom/Gamepad.h"
|
|
|
|
#include "mozilla/dom/GamepadManager.h"
|
|
|
|
|
|
|
|
#include "gfxVR.h"
|
|
|
|
#include "mozilla/dom/VRDisplay.h"
|
|
|
|
#include "mozilla/dom/VRDisplayEvent.h"
|
|
|
|
#include "mozilla/dom/VRDisplayEventBinding.h"
|
|
|
|
#include "mozilla/dom/VREventObserver.h"
|
|
|
|
|
|
|
|
#include "nsRefreshDriver.h"
|
|
|
|
#include "Layers.h"
|
|
|
|
|
|
|
|
#include "mozilla/AddonPathService.h"
|
|
|
|
#include "mozilla/BasePrincipal.h"
|
|
|
|
#include "mozilla/Services.h"
|
|
|
|
#include "mozilla/Telemetry.h"
|
|
|
|
#include "mozilla/dom/Location.h"
|
|
|
|
#include "nsHTMLDocument.h"
|
|
|
|
#include "nsWrapperCacheInlines.h"
|
|
|
|
#include "mozilla/DOMEventTargetHelper.h"
|
|
|
|
#include "prrng.h"
|
|
|
|
#include "nsSandboxFlags.h"
|
|
|
|
#include "TimeChangeObserver.h"
|
|
|
|
#include "mozilla/dom/AudioContext.h"
|
|
|
|
#include "mozilla/dom/BrowserElementDictionariesBinding.h"
|
|
|
|
#include "mozilla/dom/cache/CacheStorage.h"
|
|
|
|
#include "mozilla/dom/Console.h"
|
|
|
|
#include "mozilla/dom/Fetch.h"
|
|
|
|
#include "mozilla/dom/FunctionBinding.h"
|
|
|
|
#include "mozilla/dom/HashChangeEvent.h"
|
|
|
|
#include "mozilla/dom/IntlUtils.h"
|
|
|
|
#include "mozilla/dom/MozSelfSupportBinding.h"
|
|
|
|
#include "mozilla/dom/PopStateEvent.h"
|
|
|
|
#include "mozilla/dom/PopupBlockedEvent.h"
|
|
|
|
#include "mozilla/dom/PrimitiveConversions.h"
|
|
|
|
#include "mozilla/dom/WindowBinding.h"
|
|
|
|
#include "nsITabChild.h"
|
|
|
|
#include "mozilla/dom/MediaQueryList.h"
|
|
|
|
#include "mozilla/dom/ScriptSettings.h"
|
|
|
|
#include "mozilla/dom/NavigatorBinding.h"
|
|
|
|
#include "mozilla/dom/ImageBitmap.h"
|
|
|
|
#include "mozilla/dom/ImageBitmapBinding.h"
|
|
|
|
#include "mozilla/dom/ServiceWorkerRegistration.h"
|
|
|
|
#include "mozilla/dom/U2F.h"
|
|
|
|
#include "mozilla/dom/WebIDLGlobalNameHash.h"
|
|
|
|
#include "mozilla/dom/Worklet.h"
|
|
|
|
#ifdef HAVE_SIDEBAR
|
|
|
|
#include "mozilla/dom/ExternalBinding.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef MOZ_WEBSPEECH
|
|
|
|
#include "mozilla/dom/SpeechSynthesis.h"
|
|
|
|
#endif
|
|
|
|
|
2017-11-21 23:13:05 +03:00
|
|
|
#include "mozilla/dom/ClientManager.h"
|
|
|
|
#include "mozilla/dom/ClientSource.h"
|
|
|
|
|
2017-11-22 00:00:04 +03:00
|
|
|
// Apple system headers seem to have a check() macro. <sigh>
|
|
|
|
#ifdef check
|
|
|
|
class nsIScriptTimeoutHandler;
|
|
|
|
#undef check
|
|
|
|
#endif // check
|
|
|
|
#include "AccessCheck.h"
|
|
|
|
|
|
|
|
#ifdef ANDROID
|
|
|
|
#include <android/log.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef XP_WIN
|
|
|
|
#include <process.h>
|
|
|
|
#define getpid _getpid
|
|
|
|
#else
|
|
|
|
#include <unistd.h> // for getpid()
|
|
|
|
#endif
|
2017-11-23 21:43:41 +03:00
|
|
|
|
2017-11-18 01:49:56 +03:00
|
|
|
using namespace mozilla;
|
|
|
|
using namespace mozilla::dom;
|
|
|
|
using namespace mozilla::dom::ipc;
|
|
|
|
using mozilla::TimeStamp;
|
|
|
|
using mozilla::TimeDuration;
|
|
|
|
using mozilla::dom::cache::CacheStorage;
|
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
#define FORWARD_TO_OUTER(method, args, err_rval) \
|
|
|
|
PR_BEGIN_MACRO \
|
|
|
|
nsGlobalWindowOuter *outer = GetOuterWindowInternal(); \
|
|
|
|
if (!HasActiveDocument()) { \
|
|
|
|
NS_WARNING(outer ? \
|
|
|
|
"Inner window does not have active document." : \
|
|
|
|
"No outer window available!"); \
|
|
|
|
return err_rval; \
|
|
|
|
} \
|
|
|
|
return outer->method args; \
|
|
|
|
PR_END_MACRO
|
|
|
|
|
|
|
|
#define FORWARD_TO_OUTER_OR_THROW(method, args, errorresult, err_rval) \
|
|
|
|
PR_BEGIN_MACRO \
|
|
|
|
nsGlobalWindowOuter *outer = GetOuterWindowInternal(); \
|
|
|
|
if (MOZ_LIKELY(HasActiveDocument())) { \
|
|
|
|
return outer->method args; \
|
|
|
|
} \
|
|
|
|
if (!outer) { \
|
|
|
|
NS_WARNING("No outer window available!"); \
|
|
|
|
errorresult.Throw(NS_ERROR_NOT_INITIALIZED); \
|
|
|
|
} else { \
|
|
|
|
errorresult.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); \
|
|
|
|
} \
|
|
|
|
return err_rval; \
|
|
|
|
PR_END_MACRO
|
|
|
|
|
|
|
|
#define FORWARD_TO_OUTER_VOID(method, args) \
|
|
|
|
PR_BEGIN_MACRO \
|
|
|
|
nsGlobalWindowOuter *outer = GetOuterWindowInternal(); \
|
|
|
|
if (!HasActiveDocument()) { \
|
|
|
|
NS_WARNING(outer ? \
|
|
|
|
"Inner window does not have active document." : \
|
|
|
|
"No outer window available!"); \
|
|
|
|
return; \
|
|
|
|
} \
|
|
|
|
outer->method args; \
|
|
|
|
return; \
|
|
|
|
PR_END_MACRO
|
|
|
|
|
2017-11-18 00:53:08 +03:00
|
|
|
#define DOM_TOUCH_LISTENER_ADDED "dom-touch-listener-added"
|
|
|
|
#define MEMORY_PRESSURE_OBSERVER_TOPIC "memory-pressure"
|
|
|
|
|
2017-11-21 23:56:56 +03:00
|
|
|
// Amount of time allowed between alert/prompt/confirm before enabling
|
|
|
|
// the stop dialog checkbox.
|
|
|
|
#define DEFAULT_SUCCESSIVE_DIALOG_TIME_LIMIT 3 // 3 sec
|
|
|
|
|
|
|
|
// Maximum number of successive dialogs before we prompt users to disable
|
|
|
|
// dialogs for this window.
|
|
|
|
#define MAX_SUCCESSIVE_DIALOG_COUNT 5
|
|
|
|
|
|
|
|
// Idle fuzz time upper limit
|
|
|
|
#define MAX_IDLE_FUZZ_TIME_MS 90000
|
|
|
|
|
|
|
|
// Min idle notification time in seconds.
|
|
|
|
#define MIN_IDLE_NOTIFICATION_TIME_S 1
|
|
|
|
|
2017-11-18 01:49:56 +03:00
|
|
|
static LazyLogModule gDOMLeakPRLogInner("DOMLeakInner");
|
|
|
|
|
2017-11-18 00:23:49 +03:00
|
|
|
static bool gIdleObserversAPIFuzzTimeDisabled = false;
|
2017-11-18 01:16:16 +03:00
|
|
|
static FILE *gDumpFile = nullptr;
|
2017-11-15 19:34:13 +03:00
|
|
|
|
2017-11-15 19:30:13 +03:00
|
|
|
nsGlobalWindowInner::InnerWindowByIdTable *nsGlobalWindowInner::sInnerWindowsById = nullptr;
|
|
|
|
|
2017-11-22 00:36:13 +03:00
|
|
|
bool nsGlobalWindowInner::sDragServiceDisabled = false;
|
|
|
|
bool nsGlobalWindowInner::sMouseDown = false;
|
|
|
|
|
2017-11-15 19:30:13 +03:00
|
|
|
/**
|
|
|
|
* An indirect observer object that means we don't have to implement nsIObserver
|
|
|
|
* on nsGlobalWindow, where any script could see it.
|
|
|
|
*/
|
|
|
|
class nsGlobalWindowObserver final : public nsIObserver
|
|
|
|
, public nsIInterfaceRequestor
|
|
|
|
, public StorageNotificationObserver
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit nsGlobalWindowObserver(nsGlobalWindowInner* aWindow) : mWindow(aWindow) {}
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) override
|
|
|
|
{
|
|
|
|
if (!mWindow)
|
|
|
|
return NS_OK;
|
|
|
|
return mWindow->Observe(aSubject, aTopic, aData);
|
|
|
|
}
|
|
|
|
void Forget() { mWindow = nullptr; }
|
|
|
|
NS_IMETHOD GetInterface(const nsIID& aIID, void** aResult) override
|
|
|
|
{
|
|
|
|
if (mWindow && aIID.Equals(NS_GET_IID(nsIDOMWindow)) && mWindow) {
|
|
|
|
return mWindow->QueryInterface(aIID, aResult);
|
|
|
|
}
|
|
|
|
return NS_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ObserveStorageNotification(StorageEvent* aEvent,
|
|
|
|
const char16_t* aStorageType,
|
|
|
|
bool aPrivateBrowsing) override
|
|
|
|
{
|
|
|
|
if (mWindow) {
|
|
|
|
mWindow->ObserveStorageNotification(aEvent, aStorageType,
|
|
|
|
aPrivateBrowsing);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIPrincipal*
|
|
|
|
GetPrincipal() const override
|
|
|
|
{
|
|
|
|
return mWindow ? mWindow->GetPrincipal() : nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
IsPrivateBrowsing() const override
|
|
|
|
{
|
|
|
|
return mWindow ? mWindow->IsPrivateBrowsing() : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIEventTarget*
|
|
|
|
GetEventTarget() const override
|
|
|
|
{
|
|
|
|
return mWindow ? mWindow->EventTargetFor(TaskCategory::Other) : nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
~nsGlobalWindowObserver() = default;
|
|
|
|
|
|
|
|
// This reference is non-owning and safe because it's cleared by
|
2017-11-15 19:33:39 +03:00
|
|
|
// nsGlobalWindowInner::CleanUp().
|
2017-11-15 19:30:13 +03:00
|
|
|
nsGlobalWindowInner* MOZ_NON_OWNING_REF mWindow;
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS(nsGlobalWindowObserver, nsIObserver, nsIInterfaceRequestor)
|
|
|
|
|
|
|
|
class IdleRequestExecutor;
|
|
|
|
|
|
|
|
class IdleRequestExecutorTimeoutHandler final : public TimeoutHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit IdleRequestExecutorTimeoutHandler(IdleRequestExecutor* aExecutor)
|
|
|
|
: mExecutor(aExecutor)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
|
|
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IdleRequestExecutorTimeoutHandler,
|
|
|
|
TimeoutHandler)
|
|
|
|
|
|
|
|
nsresult Call() 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)
|
|
|
|
|
|
|
|
|
|
|
|
class IdleRequestExecutor final : public nsIRunnable
|
|
|
|
, public nsICancelableRunnable
|
|
|
|
, public nsINamed
|
|
|
|
, public nsIIdleRunnable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit IdleRequestExecutor(nsGlobalWindowInner* aWindow)
|
|
|
|
: mDispatched(false)
|
|
|
|
, mDeadline(TimeStamp::Now())
|
|
|
|
, mWindow(aWindow)
|
|
|
|
{
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(mWindow);
|
|
|
|
|
|
|
|
mIdlePeriodLimit = { mDeadline, mWindow->LastIdleRequestHandle() };
|
|
|
|
mDelayedExecutorDispatcher = new IdleRequestExecutorTimeoutHandler(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
|
|
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IdleRequestExecutor, nsIRunnable)
|
|
|
|
|
|
|
|
NS_DECL_NSIRUNNABLE
|
|
|
|
NS_DECL_NSINAMED
|
|
|
|
nsresult Cancel() override;
|
|
|
|
void SetDeadline(TimeStamp aDeadline) override;
|
|
|
|
|
2017-11-15 19:34:27 +03:00
|
|
|
bool IsCancelled() const { return !mWindow || mWindow->InnerObjectsFreed(); }
|
2017-11-15 19:30:13 +03:00
|
|
|
// 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.
|
|
|
|
bool IneligibleForCurrentIdlePeriod(IdleRequest* aRequest) const
|
|
|
|
{
|
|
|
|
return aRequest->Handle() >= mIdlePeriodLimit.mLastRequestIdInIdlePeriod &&
|
|
|
|
TimeStamp::Now() <= mIdlePeriodLimit.mEndOfIdlePeriod;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MaybeUpdateIdlePeriodLimit();
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
void MaybeDispatch(TimeStamp aDelayUntil = TimeStamp());
|
|
|
|
void ScheduleDispatch();
|
|
|
|
private:
|
|
|
|
struct IdlePeriodLimit
|
|
|
|
{
|
|
|
|
TimeStamp mEndOfIdlePeriod;
|
|
|
|
uint32_t mLastRequestIdInIdlePeriod;
|
|
|
|
};
|
|
|
|
|
|
|
|
void DelayedDispatch(uint32_t aDelay);
|
|
|
|
|
|
|
|
~IdleRequestExecutor() override {}
|
|
|
|
|
|
|
|
bool mDispatched;
|
|
|
|
TimeStamp mDeadline;
|
|
|
|
IdlePeriodLimit mIdlePeriodLimit;
|
|
|
|
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_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IdleRequestExecutor)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDelayedExecutorDispatcher)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
|
|
|
NS_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_END
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
IdleRequestExecutor::GetName(nsACString& aName)
|
|
|
|
{
|
|
|
|
aName.AssignASCII("IdleRequestExecutor");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
IdleRequestExecutor::Run()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
mDispatched = false;
|
|
|
|
if (mWindow) {
|
|
|
|
return mWindow->ExecuteIdleRequest(mDeadline);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
IdleRequestExecutor::Cancel()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
if (mDelayedExecutorHandle && mWindow) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mWindow->TimeoutManager().ClearTimeout(
|
2017-11-15 19:30:13 +03:00
|
|
|
mDelayedExecutorHandle.value(),
|
|
|
|
Timeout::Reason::eIdleCallbackTimeout);
|
|
|
|
}
|
|
|
|
|
|
|
|
mWindow = nullptr;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
IdleRequestExecutor::SetDeadline(TimeStamp aDeadline)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
if (!mWindow) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mDeadline = aDeadline;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
IdleRequestExecutor::MaybeUpdateIdlePeriodLimit()
|
|
|
|
{
|
|
|
|
if (TimeStamp::Now() > mIdlePeriodLimit.mEndOfIdlePeriod) {
|
|
|
|
mIdlePeriodLimit = { mDeadline, mWindow->LastIdleRequestHandle() };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
IdleRequestExecutor::MaybeDispatch(TimeStamp aDelayUntil)
|
|
|
|
{
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
TimeStamp now = TimeStamp::Now();
|
|
|
|
if (!aDelayUntil || aDelayUntil < now) {
|
|
|
|
ScheduleDispatch();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TimeDuration delay = aDelayUntil - now;
|
|
|
|
DelayedDispatch(static_cast<uint32_t>(delay.ToMilliseconds()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
IdleRequestExecutor::ScheduleDispatch()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mWindow);
|
|
|
|
mDelayedExecutorHandle = Nothing();
|
|
|
|
RefPtr<IdleRequestExecutor> request = this;
|
|
|
|
NS_IdleDispatchToCurrentThread(request.forget());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
IdleRequestExecutor::DelayedDispatch(uint32_t aDelay)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mWindow);
|
|
|
|
MOZ_ASSERT(mDelayedExecutorHandle.isNothing());
|
|
|
|
int32_t handle;
|
2017-11-15 19:34:27 +03:00
|
|
|
mWindow->TimeoutManager().SetTimeout(
|
2017-11-15 19:30:13 +03:00
|
|
|
mDelayedExecutorDispatcher, aDelay, false, Timeout::Reason::eIdleCallbackTimeout, &handle);
|
|
|
|
mDelayedExecutorHandle = Some(handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
IdleRequestExecutorTimeoutHandler::Call()
|
|
|
|
{
|
|
|
|
if (!mExecutor->IsCancelled()) {
|
|
|
|
mExecutor->ScheduleDispatch();
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ScheduleIdleRequestDispatch()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
|
|
|
|
if (!mIdleRequestExecutor) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mIdleRequestExecutor = new IdleRequestExecutor(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
mIdleRequestExecutor->MaybeDispatch();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SuspendIdleRequests()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mIdleRequestExecutor) {
|
|
|
|
mIdleRequestExecutor->Cancel();
|
|
|
|
mIdleRequestExecutor = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ResumeIdleRequests()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(!mIdleRequestExecutor);
|
|
|
|
|
|
|
|
ScheduleIdleRequestDispatch();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::RemoveIdleCallback(mozilla::dom::IdleRequest* aRequest)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
|
|
|
|
if (aRequest->HasTimeout()) {
|
|
|
|
mTimeoutManager->ClearTimeout(aRequest->GetTimeoutHandle(),
|
|
|
|
Timeout::Reason::eIdleCallbackTimeout);
|
|
|
|
}
|
|
|
|
|
|
|
|
aRequest->removeFrom(mIdleRequestCallbacks);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::RunIdleRequest(IdleRequest* aRequest,
|
2017-11-15 19:30:13 +03:00
|
|
|
DOMHighResTimeStamp aDeadline,
|
|
|
|
bool aDidTimeout)
|
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
RefPtr<IdleRequest> request(aRequest);
|
|
|
|
RemoveIdleCallback(request);
|
2017-11-15 19:34:27 +03:00
|
|
|
return request->IdleRun(this, aDeadline, aDidTimeout);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ExecuteIdleRequest(TimeStamp aDeadline)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst();
|
|
|
|
|
|
|
|
if (!request) {
|
|
|
|
// There are no more idle requests, so stop scheduling idle
|
|
|
|
// request callbacks.
|
|
|
|
return NS_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);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
DOMHighResTimeStamp deadline = 0.0;
|
|
|
|
|
|
|
|
if (Performance* perf = GetPerformance()) {
|
|
|
|
deadline = perf->GetDOMTiming()->TimeStampToDOMHighRes(aDeadline);
|
|
|
|
}
|
|
|
|
|
|
|
|
mIdleRequestExecutor->MaybeUpdateIdlePeriodLimit();
|
|
|
|
nsresult result = RunIdleRequest(request, deadline, false);
|
|
|
|
|
|
|
|
// Running the idle callback could've suspended the window, in which
|
|
|
|
// case mIdleRequestExecutor will be null.
|
|
|
|
if (mIdleRequestExecutor) {
|
|
|
|
mIdleRequestExecutor->MaybeDispatch();
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
class IdleRequestTimeoutHandler final : public TimeoutHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
IdleRequestTimeoutHandler(JSContext* aCx,
|
|
|
|
IdleRequest* aIdleRequest,
|
|
|
|
nsPIDOMWindowInner* aWindow)
|
|
|
|
: TimeoutHandler(aCx)
|
|
|
|
, mIdleRequest(aIdleRequest)
|
|
|
|
, mWindow(aWindow)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
|
|
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IdleRequestTimeoutHandler,
|
|
|
|
TimeoutHandler)
|
|
|
|
|
|
|
|
nsresult Call() override
|
|
|
|
{
|
|
|
|
return nsGlobalWindowInner::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_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::RequestIdleCallback(JSContext* aCx,
|
2017-11-15 19:34:41 +03:00
|
|
|
IdleRequestCallback& aCallback,
|
|
|
|
const IdleRequestOptions& aOptions,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
|
2017-11-30 13:14:00 +03:00
|
|
|
if (mInnerObjectsFreed) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:30:13 +03:00
|
|
|
uint32_t handle = mIdleRequestCallbackCounter++;
|
|
|
|
|
|
|
|
RefPtr<IdleRequest> request =
|
|
|
|
new IdleRequest(&aCallback, handle);
|
|
|
|
|
|
|
|
if (aOptions.mTimeout.WasPassed()) {
|
|
|
|
int32_t timeoutHandle;
|
2017-11-15 19:34:27 +03:00
|
|
|
nsCOMPtr<nsITimeoutHandler> handler(new IdleRequestTimeoutHandler(aCx, request, this));
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
nsresult rv = mTimeoutManager->SetTimeout(
|
|
|
|
handler, aOptions.mTimeout.Value(), false,
|
|
|
|
Timeout::Reason::eIdleCallbackTimeout, &timeoutHandle);
|
|
|
|
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
request->SetTimeoutHandle(timeoutHandle);
|
|
|
|
}
|
|
|
|
|
2017-11-28 22:23:46 +03:00
|
|
|
mIdleRequestCallbacks.insertBack(request);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
if (!IsSuspended()) {
|
|
|
|
ScheduleIdleRequestDispatch();
|
|
|
|
}
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::CancelIdleCallback(uint32_t aHandle)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
for (IdleRequest* r : mIdleRequestCallbacks) {
|
|
|
|
if (r->Handle() == aHandle) {
|
|
|
|
RemoveIdleCallback(r);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DisableIdleCallbackRequests()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mIdleRequestExecutor) {
|
|
|
|
mIdleRequestExecutor->Cancel();
|
|
|
|
mIdleRequestExecutor = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!mIdleRequestCallbacks.isEmpty()) {
|
|
|
|
RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst();
|
|
|
|
RemoveIdleCallback(request);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IsBackgroundInternal() const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return !mOuterWindow || mOuterWindow->IsBackground();
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
2017-11-15 19:33:39 +03:00
|
|
|
//*** nsGlobalWindowInner: Object Management
|
2017-11-15 19:30:13 +03:00
|
|
|
//*****************************************************************************
|
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter *aOuterWindow)
|
2017-11-15 19:34:04 +03:00
|
|
|
: nsPIDOMWindowInner(aOuterWindow->AsOuter()),
|
2017-11-15 19:30:13 +03:00
|
|
|
mIdleFuzzFactor(0),
|
|
|
|
mIdleCallbackIndex(-1),
|
|
|
|
mCurrentlyIdle(false),
|
|
|
|
mAddActiveEventFuzzTime(true),
|
|
|
|
mWasOffline(false),
|
|
|
|
mHasHadSlowScript(false),
|
|
|
|
mNotifyIdleObserversIdleOnThaw(false),
|
|
|
|
mNotifyIdleObserversActiveOnThaw(false),
|
|
|
|
mIsChrome(false),
|
|
|
|
mCleanMessageManager(false),
|
|
|
|
mNeedsFocus(true),
|
|
|
|
mHasFocus(false),
|
|
|
|
mShowFocusRingForContent(false),
|
|
|
|
mFocusByKeyOccurred(false),
|
|
|
|
mHasGamepad(false),
|
|
|
|
mHasVREvents(false),
|
|
|
|
mHasVRDisplayActivateEvents(false),
|
|
|
|
mHasSeenGamepadInput(false),
|
|
|
|
mSuspendDepth(0),
|
|
|
|
mFreezeDepth(0),
|
|
|
|
mFocusMethod(0),
|
|
|
|
mSerial(0),
|
|
|
|
mIdleRequestCallbackCounter(1),
|
|
|
|
mIdleRequestExecutor(nullptr),
|
|
|
|
mCleanedUp(false),
|
|
|
|
mDialogAbuseCount(0),
|
|
|
|
mAreDialogsEnabled(true),
|
|
|
|
mCanSkipCCGeneration(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);
|
|
|
|
|
2017-11-18 02:33:21 +03:00
|
|
|
mTimeoutManager =
|
|
|
|
MakeUnique<mozilla::dom::TimeoutManager>(*nsGlobalWindowInner::Cast(AsInner()));
|
|
|
|
|
2017-11-15 19:34:27 +03:00
|
|
|
mObserver = new nsGlobalWindowObserver(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
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.
|
|
|
|
|
2017-11-22 00:20:45 +03:00
|
|
|
mSerial = nsContentUtils::InnerOrOuterWindowCreated();
|
2017-11-15 19:30:13 +03:00
|
|
|
|
2017-11-18 00:23:49 +03:00
|
|
|
static bool sFirstTime = true;
|
|
|
|
if (sFirstTime) {
|
|
|
|
sFirstTime = false;
|
|
|
|
TimeoutManager::Initialize();
|
|
|
|
Preferences::AddBoolVarCache(&gIdleObserversAPIFuzzTimeDisabled,
|
|
|
|
"dom.idle-observers-api.fuzz_time.disabled",
|
|
|
|
false);
|
|
|
|
}
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
if (gDumpFile == nullptr) {
|
|
|
|
nsAutoCString fname;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (!PR_GetEnv("MOZ_QUIET")) {
|
|
|
|
printf_stderr("++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n",
|
2017-11-22 00:20:45 +03:00
|
|
|
nsContentUtils::GetCurrentInnerOrOuterWindowCount(),
|
2017-11-15 19:30:13 +03:00
|
|
|
static_cast<void*>(ToCanonicalSupports(this)),
|
|
|
|
getpid(),
|
2017-11-22 00:20:45 +03:00
|
|
|
mSerial,
|
2017-11-15 19:30:13 +03:00
|
|
|
static_cast<void*>(ToCanonicalSupports(aOuterWindow)));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-11-18 01:49:56 +03:00
|
|
|
MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
|
2017-11-15 19:30:13 +03:00
|
|
|
("DOMWINDOW %p created outer=%p", this, aOuterWindow));
|
2017-11-15 19:33:39 +03:00
|
|
|
|
|
|
|
// 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) {
|
2017-11-15 19:34:27 +03:00
|
|
|
sInnerWindowsById->Put(mWindowID, this);
|
2017-11-15 19:33:39 +03:00
|
|
|
}
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::AssertIsOnMainThread()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Init()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
|
2017-11-18 01:49:56 +03:00
|
|
|
NS_ASSERTION(gDOMLeakPRLogInner, "gDOMLeakPRLogInner should have been initialized!");
|
2017-11-15 19:30:13 +03:00
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
sInnerWindowsById = new InnerWindowByIdTable();
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::~nsGlobalWindowInner()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
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();
|
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
if (sInnerWindowsById) {
|
|
|
|
MOZ_ASSERT(sInnerWindowsById->Get(mWindowID),
|
|
|
|
"This window should be in the hash table");
|
|
|
|
sInnerWindowsById->Remove(mWindowID);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
2017-11-22 00:20:45 +03:00
|
|
|
nsContentUtils::InnerOrOuterWindowDestroyed();
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (!PR_GetEnv("MOZ_QUIET")) {
|
|
|
|
nsAutoCString url;
|
|
|
|
if (mLastOpenedURI) {
|
|
|
|
url = mLastOpenedURI->GetSpecOrDefault();
|
|
|
|
|
|
|
|
// Data URLs can be very long, so truncate to avoid flooding the log.
|
|
|
|
const uint32_t maxURLLength = 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",
|
2017-11-22 00:20:45 +03:00
|
|
|
nsContentUtils::GetCurrentInnerOrOuterWindowCount(),
|
2017-11-15 19:30:13 +03:00
|
|
|
static_cast<void*>(ToCanonicalSupports(this)),
|
|
|
|
getpid(),
|
|
|
|
mSerial,
|
|
|
|
static_cast<void*>(ToCanonicalSupports(outer)),
|
|
|
|
url.get());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-11-18 01:49:56 +03:00
|
|
|
MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug, ("DOMWINDOW %p destroyed", this));
|
2017-11-15 19:30:13 +03:00
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,
|
|
|
|
mMutationBits ? 1 : 0);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
if (mListenerManager) {
|
|
|
|
mListenerManager->Disconnect();
|
|
|
|
mListenerManager = nullptr;
|
|
|
|
}
|
2017-11-15 19:30:13 +03:00
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
// An inner window is destroyed, pull it out of the outer window's
|
|
|
|
// list if inner windows.
|
2017-11-15 19:30:13 +03:00
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
PR_REMOVE_LINK(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
// 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) {
|
2017-11-15 19:34:27 +03:00
|
|
|
outer->MaybeClearInnerWindow(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// We don't have to leave the tab group if we are an inner window.
|
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
// 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
|
2017-11-15 19:30:13 +03:00
|
|
|
// separating the handling into CleanUp() and FreeInnerObjects.
|
2017-11-15 19:34:13 +03:00
|
|
|
CleanUp();
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
|
|
|
|
if (ac)
|
|
|
|
ac->RemoveWindowAsListener(this);
|
|
|
|
|
|
|
|
nsLayoutStatics::Release();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::AddEventTargetObject(DOMEventTargetHelper* aObject)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
mEventTargetObjects.PutEntry(aObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::RemoveEventTargetObject(DOMEventTargetHelper* aObject)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
mEventTargetObjects.RemoveEntry(aObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DisconnectEventTargetObjects()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
for (auto iter = mEventTargetObjects.ConstIter(); !iter.Done();
|
|
|
|
iter.Next()) {
|
|
|
|
RefPtr<DOMEventTargetHelper> target = iter.Get()->GetKey();
|
|
|
|
target->DisconnectFromOwner();
|
|
|
|
}
|
|
|
|
mEventTargetObjects.Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ShutDown()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
AssertIsOnMainThread();
|
|
|
|
|
2017-11-18 01:16:16 +03:00
|
|
|
if (gDumpFile && gDumpFile != stdout) {
|
|
|
|
fclose(gDumpFile);
|
|
|
|
}
|
|
|
|
gDumpFile = nullptr;
|
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
delete sInnerWindowsById;
|
|
|
|
sInnerWindowsById = nullptr;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::CleanupCachedXBLHandlers()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mCachedXBLPrototypeHandlers &&
|
|
|
|
mCachedXBLPrototypeHandlers->Count() > 0) {
|
|
|
|
mCachedXBLPrototypeHandlers->Clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::CleanUp()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// 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;
|
|
|
|
mApplicationCache = nullptr;
|
|
|
|
mIndexedDB = nullptr;
|
|
|
|
|
|
|
|
mConsole = nullptr;
|
|
|
|
|
|
|
|
mAudioWorklet = nullptr;
|
|
|
|
mPaintWorklet = nullptr;
|
|
|
|
|
|
|
|
mExternal = nullptr;
|
|
|
|
|
|
|
|
mMozSelfSupport = nullptr;
|
|
|
|
|
|
|
|
mPerformance = nullptr;
|
|
|
|
|
|
|
|
#ifdef MOZ_WEBSPEECH
|
|
|
|
mSpeechSynthesis = nullptr;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(MOZ_WIDGET_ANDROID)
|
|
|
|
mOrientationChangeObserver = nullptr;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
mChromeEventHandler = nullptr; // Forces Release
|
|
|
|
mParentTarget = nullptr;
|
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
DisableGamepadUpdates();
|
|
|
|
mHasGamepad = false;
|
|
|
|
DisableVRUpdates();
|
|
|
|
mHasVREvents = false;
|
|
|
|
mHasVRDisplayActivateEvents = false;
|
|
|
|
DisableIdleCallbackRequests();
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
if (mCleanMessageManager) {
|
|
|
|
MOZ_ASSERT(mIsChrome, "only chrome should have msg manager cleaned");
|
|
|
|
if (mChromeFields.mMessageManager) {
|
|
|
|
static_cast<nsFrameMessageManager*>(
|
|
|
|
mChromeFields.mMessageManager.get())->Disconnect();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CleanupCachedXBLHandlers();
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
|
|
|
|
mAudioContexts[i]->Shutdown();
|
|
|
|
}
|
|
|
|
mAudioContexts.Clear();
|
|
|
|
|
|
|
|
if (mIdleTimer) {
|
|
|
|
mIdleTimer->Cancel();
|
|
|
|
mIdleTimer = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
mServiceWorkerRegistrationTable.Clear();
|
|
|
|
|
|
|
|
mIntlUtils = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::FreeInnerObjects()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Make sure that this is called before we null out the document and
|
|
|
|
// other members that the window destroyed observers could
|
|
|
|
// re-create.
|
2017-11-15 19:34:27 +03:00
|
|
|
NotifyDOMWindowDestroyed(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
if (auto* reporter = nsWindowMemoryReporter::Get()) {
|
2017-11-15 19:34:27 +03:00
|
|
|
reporter->ObserveDOMWindowDetached(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
mInnerObjectsFreed = true;
|
|
|
|
|
|
|
|
// Kill all of the workers for this window.
|
2017-11-15 19:34:27 +03:00
|
|
|
mozilla::dom::workers::CancelWorkersForWindow(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
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;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (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_t i = 0; i < mAudioContexts.Length(); ++i) {
|
|
|
|
mAudioContexts[i]->Shutdown();
|
|
|
|
}
|
|
|
|
mAudioContexts.Clear();
|
|
|
|
|
|
|
|
DisableGamepadUpdates();
|
|
|
|
mHasGamepad = false;
|
|
|
|
mGamepads.Clear();
|
|
|
|
DisableVRUpdates();
|
|
|
|
mHasVREvents = false;
|
|
|
|
mHasVRDisplayActivateEvents = false;
|
|
|
|
mVRDisplays.Clear();
|
|
|
|
|
2017-11-21 23:13:05 +03:00
|
|
|
// This breaks a cycle between the window and the ClientSource object.
|
|
|
|
mClientSource.reset();
|
|
|
|
|
2017-11-15 19:30:13 +03:00
|
|
|
if (mTabChild) {
|
2017-11-27 23:50:00 +03:00
|
|
|
// Remove any remaining listeners, and reset mBeforeUnloadListenerCount.
|
|
|
|
for (int i = 0; i < mBeforeUnloadListenerCount; ++i) {
|
2017-11-15 19:30:13 +03:00
|
|
|
mTabChild->BeforeUnloadRemoved();
|
|
|
|
}
|
2017-11-27 23:50:00 +03:00
|
|
|
mBeforeUnloadListenerCount = 0;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
2017-11-15 19:33:39 +03:00
|
|
|
// nsGlobalWindowInner::nsISupports
|
2017-11-15 19:30:13 +03:00
|
|
|
//*****************************************************************************
|
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
// QueryInterface implementation for nsGlobalWindowInner
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindowInner)
|
2017-11-15 19:30:13 +03:00
|
|
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
2017-11-15 19:33:39 +03:00
|
|
|
// Make sure this matches the cast in nsGlobalWindowInner::FromWrapper()
|
2017-11-15 19:30:13 +03:00
|
|
|
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))) {
|
2017-11-15 19:34:27 +03:00
|
|
|
foundInterface = static_cast<nsPIDOMWindowInner*>(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
} else
|
2017-11-22 02:07:45 +03:00
|
|
|
if (aIID.Equals(NS_GET_IID(mozIDOMWindow))) {
|
2017-11-15 19:34:27 +03:00
|
|
|
foundInterface = static_cast<mozIDOMWindow*>(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
} else
|
|
|
|
if (aIID.Equals(NS_GET_IID(nsIDOMChromeWindow)) && IsChromeWindow()) {
|
|
|
|
foundInterface = static_cast<nsIDOMChromeWindow*>(this);
|
|
|
|
} else
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
|
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGlobalWindowInner)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGlobalWindowInner)
|
2017-11-15 19:30:13 +03:00
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindowInner)
|
2017-11-15 19:30:13 +03:00
|
|
|
if (tmp->IsBlackForCC(false)) {
|
|
|
|
if (nsCCUncollectableMarker::InGeneration(tmp->mCanSkipCCGeneration)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
tmp->mCanSkipCCGeneration = nsCCUncollectableMarker::sGeneration;
|
|
|
|
if (tmp->mCachedXBLPrototypeHandlers) {
|
|
|
|
for (auto iter = tmp->mCachedXBLPrototypeHandlers->Iter();
|
|
|
|
!iter.Done();
|
|
|
|
iter.Next()) {
|
|
|
|
iter.Data().exposeToActiveJS();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (EventListenerManager* elm = tmp->GetExistingListenerManager()) {
|
|
|
|
elm->MarkForCC();
|
|
|
|
}
|
|
|
|
if (tmp->mTimeoutManager) {
|
|
|
|
tmp->mTimeoutManager->UnmarkGrayTimers();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
|
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGlobalWindowInner)
|
2017-11-15 19:30:13 +03:00
|
|
|
return tmp->IsBlackForCC(true);
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
|
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsGlobalWindowInner)
|
2017-11-15 19:30:13 +03:00
|
|
|
return tmp->IsBlackForCC(false);
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
|
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindowInner)
|
2017-11-15 19:30:13 +03:00
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowInner)
|
2017-11-15 19:30:13 +03:00
|
|
|
if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
|
|
|
|
char name[512];
|
|
|
|
nsAutoCString uri;
|
|
|
|
if (tmp->mDoc && tmp->mDoc->GetDocumentURI()) {
|
|
|
|
uri = tmp->mDoc->GetDocumentURI()->GetSpecOrDefault();
|
|
|
|
}
|
2017-11-22 02:07:45 +03:00
|
|
|
SprintfLiteral(name, "nsGlobalWindowInner # %" PRIu64 " inner %s", tmp->mWindowID,
|
|
|
|
uri.get());
|
2017-11-15 19:30:13 +03:00
|
|
|
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
|
|
|
|
} else {
|
2017-11-15 19:33:39 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindowInner, tmp->mRefCnt.get())
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerRegistrationTable)
|
|
|
|
|
|
|
|
#ifdef MOZ_WEBSPEECH
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSpeechSynthesis)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
NS_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(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(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 nsPIDOMWindow
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)
|
|
|
|
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)
|
|
|
|
|
|
|
|
tmp->TraverseHostObjectURIs(cb);
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mMessageManager)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mGroupMessageManagers)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)
|
2017-11-15 19:30:13 +03:00
|
|
|
tmp->CleanupCachedXBLHandlers();
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mServiceWorkerRegistrationTable)
|
|
|
|
|
|
|
|
#ifdef MOZ_WEBSPEECH
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSpeechSynthesis)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (tmp->mOuterWindow) {
|
|
|
|
nsGlobalWindowOuter::Cast(tmp->mOuterWindow)->
|
2017-11-15 19:34:27 +03:00
|
|
|
MaybeClearInnerWindow(tmp);
|
2017-11-15 19:30:13 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOuterWindow)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tmp->mListenerManager) {
|
|
|
|
tmp->mListenerManager->Disconnect();
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mListenerManager)
|
|
|
|
}
|
|
|
|
|
2017-11-28 22:23:46 +03:00
|
|
|
// Here the Timeouts list would've been unlinked, but we rely on
|
|
|
|
// that Timeout objects have been traced and will remove themselves
|
|
|
|
// while unlinking.
|
|
|
|
|
2017-11-15 19:30:13 +03:00
|
|
|
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(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(mIdleObservers)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGamepads)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDisplays)
|
|
|
|
|
|
|
|
// Unlink stuff from nsPIDOMWindow
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)
|
|
|
|
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)
|
|
|
|
|
|
|
|
tmp->UnlinkHostObjectURIs();
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor)
|
2017-11-28 22:23:46 +03:00
|
|
|
|
|
|
|
// Here the IdleRequest list would've been unlinked, but we rely on
|
|
|
|
// that IdleRequest objects have been traced and will remove
|
|
|
|
// themselves while unlinking.
|
2017-11-15 19:30:13 +03:00
|
|
|
|
2017-11-21 23:13:05 +03:00
|
|
|
tmp->mClientSource.reset();
|
|
|
|
|
2017-11-15 19:30:13 +03:00
|
|
|
if (tmp->IsChromeWindow()) {
|
|
|
|
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_PRESERVED_WRAPPER
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::RiskyUnlink()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
NS_CYCLE_COLLECTION_INNERNAME.Unlink(this);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindowInner)
|
2017-11-15 19:30:13 +03:00
|
|
|
if (tmp->mCachedXBLPrototypeHandlers) {
|
|
|
|
for (auto iter = tmp->mCachedXBLPrototypeHandlers->Iter();
|
|
|
|
!iter.Done();
|
|
|
|
iter.Next()) {
|
|
|
|
aCallbacks.Trace(&iter.Data(), "Cached XBL prototype handler", aClosure);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IsBlackForCC(bool aTracingNeeded)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!nsCCUncollectableMarker::sGeneration) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (nsCCUncollectableMarker::InGeneration(GetMarkedCCGeneration()) ||
|
|
|
|
HasKnownLiveWrapper()) &&
|
|
|
|
(!aTracingNeeded ||
|
|
|
|
HasNothingToTrace(static_cast<nsIDOMEventTarget*>(this)));
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
2017-11-15 19:33:39 +03:00
|
|
|
// nsGlobalWindowInner::nsIScriptGlobalObject
|
2017-11-15 19:30:13 +03:00
|
|
|
//*****************************************************************************
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::EnsureScriptEnvironment()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:47 +03:00
|
|
|
// NOTE: We can't use FORWARD_TO_OUTER here because we don't want to fail if
|
|
|
|
// we're called on an inactive inner window.
|
2017-11-15 19:30:13 +03:00
|
|
|
nsGlobalWindowOuter* outer = GetOuterWindowInternal();
|
|
|
|
if (!outer) {
|
|
|
|
NS_WARNING("No outer window available!");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2017-11-15 19:34:47 +03:00
|
|
|
return outer->EnsureScriptEnvironment();
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsIScriptContext *
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScriptContext()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsGlobalWindowOuter* outer = GetOuterWindowInternal();
|
|
|
|
if (!outer) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-11-15 19:34:47 +03:00
|
|
|
return outer->GetScriptContext();
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
JSObject *
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetGlobalJSObject()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return FastGetGlobalJSObject();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::TraceGlobalJSObject(JSTracer* aTrc)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
TraceWrapper(aTrc, "active window global");
|
|
|
|
}
|
|
|
|
|
|
|
|
PopupControlState
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetPopupControlState() const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-18 01:09:20 +03:00
|
|
|
return nsContentUtils::GetPopupControlState();
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetNewDocument(nsIDocument* aDocument,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsISupports* aState,
|
|
|
|
bool aForceReuseInnerWindow)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(mDocumentPrincipal == nullptr,
|
|
|
|
"mDocumentPrincipal prematurely set!");
|
|
|
|
MOZ_ASSERT(aDocument);
|
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
if (!mOuterWindow) {
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
// Refuse to set a new document if the call came from an inner
|
|
|
|
// window that's not the current inner window.
|
2017-11-15 19:34:27 +03:00
|
|
|
if (mOuterWindow->GetCurrentInnerWindow() != this) {
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
return GetOuterWindowInternal()->SetNewDocument(aDocument, aState,
|
|
|
|
aForceReuseInnerWindow);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::InnerSetNewDocument(JSContext* aCx, nsIDocument* aDocument)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(aDocument);
|
|
|
|
|
2017-11-18 01:49:56 +03:00
|
|
|
if (MOZ_LOG_TEST(gDOMLeakPRLogInner, LogLevel::Debug)) {
|
2017-11-15 19:30:13 +03:00
|
|
|
nsIURI *uri = aDocument->GetDocumentURI();
|
2017-11-18 01:49:56 +03:00
|
|
|
MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
|
2017-11-15 19:30:13 +03:00
|
|
|
("DOMWINDOW %p SetNewDocument %s",
|
|
|
|
this, uri ? uri->GetSpecOrDefault().get() : ""));
|
|
|
|
}
|
|
|
|
|
|
|
|
mDoc = aDocument;
|
|
|
|
ClearDocumentDependentSlots(aCx);
|
|
|
|
mFocusedNode = nullptr;
|
|
|
|
mLocalStorage = nullptr;
|
|
|
|
mSessionStorage = nullptr;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
mLastOpenedURI = aDocument->GetDocumentURI();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,
|
|
|
|
mMutationBits ? 1 : 0);
|
|
|
|
|
|
|
|
// Clear our mutation bitfield.
|
|
|
|
mMutationBits = 0;
|
|
|
|
}
|
|
|
|
|
2017-11-21 23:13:05 +03:00
|
|
|
nsresult
|
|
|
|
nsGlobalWindowInner::EnsureClientSource()
|
|
|
|
{
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(mDoc);
|
|
|
|
|
2017-11-21 23:13:05 +03:00
|
|
|
bool newClientSource = false;
|
|
|
|
|
2017-11-21 23:13:05 +03:00
|
|
|
nsCOMPtr<nsIChannel> channel = mDoc->GetChannel();
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = channel ? channel->GetLoadInfo() : nullptr;
|
|
|
|
|
2017-11-28 20:10:40 +03:00
|
|
|
// Take the initial client source from the docshell immediately. Even if we
|
|
|
|
// don't end up using it here we should consume it.
|
|
|
|
UniquePtr<ClientSource> initialClientSource;
|
|
|
|
nsIDocShell* docshell = GetDocShell();
|
|
|
|
if (docshell) {
|
|
|
|
initialClientSource = docshell->TakeInitialClientSource();
|
|
|
|
}
|
|
|
|
|
2017-11-21 23:13:05 +03:00
|
|
|
// Try to get the reserved client from the LoadInfo. A Client is
|
|
|
|
// reserved at the start of the channel load if there is not an
|
|
|
|
// initial about:blank document that will be reused. It is also
|
|
|
|
// created if the channel load encounters a cross-origin redirect.
|
|
|
|
if (loadInfo) {
|
|
|
|
UniquePtr<ClientSource> reservedClient = loadInfo->TakeReservedClientSource();
|
|
|
|
if (reservedClient) {
|
|
|
|
mClientSource.reset();
|
|
|
|
mClientSource = Move(reservedClient);
|
2017-11-21 23:13:05 +03:00
|
|
|
newClientSource = true;
|
2017-11-21 23:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We don't have a LoadInfo reserved client, but maybe we should
|
|
|
|
// be inheriting an initial one from the docshell. This means
|
|
|
|
// that the docshell started the channel load before creating the
|
|
|
|
// initial about:blank document. This is an optimization, though,
|
|
|
|
// and it created an initial Client as a placeholder for the document.
|
|
|
|
// In this case we want to inherit this placeholder Client here.
|
|
|
|
if (!mClientSource) {
|
2017-11-28 20:10:40 +03:00
|
|
|
mClientSource = Move(initialClientSource);
|
|
|
|
if (mClientSource) {
|
|
|
|
newClientSource = true;
|
2017-11-21 23:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we don't have a reserved client or an initial client, then create
|
|
|
|
// one now. This can happen in certain cases where we avoid preallocating
|
|
|
|
// the client in the docshell. This mainly occurs in situations where
|
|
|
|
// the principal is not clearly inherited from the parent; e.g. sandboxed
|
|
|
|
// iframes, window.open(), etc.
|
|
|
|
if (!mClientSource) {
|
|
|
|
mClientSource = ClientManager::CreateSource(ClientType::Window,
|
|
|
|
EventTargetFor(TaskCategory::Other),
|
|
|
|
mDoc->NodePrincipal());
|
|
|
|
if (NS_WARN_IF(!mClientSource)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2017-11-21 23:13:05 +03:00
|
|
|
newClientSource = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Its possible that we got a client just after being frozen in
|
|
|
|
// the bfcache. In that case freeze the client immediately.
|
|
|
|
if (newClientSource && IsFrozen()) {
|
|
|
|
mClientSource->Freeze();
|
2017-11-21 23:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsGlobalWindowInner::ExecutionReady()
|
|
|
|
{
|
|
|
|
nsresult rv = EnsureClientSource();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
rv = mClientSource->WindowExecutionReady(AsInner());
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:30:13 +03:00
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
|
2017-11-15 19:34:41 +03:00
|
|
|
bool aOriginalOpener)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_VOID(SetOpenerWindow, (aOpener, aOriginalOpener));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::UpdateParentTarget()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:47 +03:00
|
|
|
// NOTE: This method is identical to
|
|
|
|
// nsGlobalWindowOuter::UpdateParentTarget(). IF YOU UPDATE THIS METHOD,
|
|
|
|
// UPDATE THE OTHER ONE TOO!
|
|
|
|
|
2017-11-15 19:30:13 +03:00
|
|
|
// 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 =
|
2017-11-18 00:42:50 +03:00
|
|
|
nsContentUtils::TryGetTabChildGlobalAsEventTarget(frameElement);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
if (!eventTarget) {
|
|
|
|
nsGlobalWindowOuter* topWin = GetScriptableTopInternal();
|
|
|
|
if (topWin) {
|
|
|
|
frameElement = topWin->AsOuter()->GetFrameElementInternal();
|
2017-11-18 00:42:50 +03:00
|
|
|
eventTarget =
|
|
|
|
nsContentUtils::TryGetTabChildGlobalAsEventTarget(frameElement);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eventTarget) {
|
2017-11-18 00:42:50 +03:00
|
|
|
eventTarget =
|
|
|
|
nsContentUtils::TryGetTabChildGlobalAsEventTarget(mChromeEventHandler);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!eventTarget) {
|
|
|
|
eventTarget = mChromeEventHandler;
|
|
|
|
}
|
|
|
|
|
|
|
|
mParentTarget = eventTarget;
|
|
|
|
}
|
|
|
|
|
|
|
|
EventTarget*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetTargetForDOMEvent()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return GetOuterWindowInternal();
|
|
|
|
}
|
|
|
|
|
|
|
|
EventTarget*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetTargetForEventTargetChain()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:13 +03:00
|
|
|
return this;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::WillHandleEvent(EventChainPostVisitor& aVisitor)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
EventMessage msg = aVisitor.mEvent->mMessage;
|
|
|
|
|
|
|
|
aVisitor.mCanHandle = true;
|
|
|
|
aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119
|
|
|
|
if (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;
|
|
|
|
}
|
|
|
|
} else if (msg == eMouseDown && aVisitor.mEvent->IsTrusted()) {
|
2017-11-22 00:36:13 +03:00
|
|
|
sMouseDown = true;
|
2017-11-15 19:30:13 +03:00
|
|
|
} else if ((msg == eMouseUp || msg == eDragEnd) &&
|
|
|
|
aVisitor.mEvent->IsTrusted()) {
|
2017-11-22 00:36:13 +03:00
|
|
|
sMouseDown = false;
|
|
|
|
if (sDragServiceDisabled) {
|
2017-11-15 19:30:13 +03:00
|
|
|
nsCOMPtr<nsIDragService> ds =
|
|
|
|
do_GetService("@mozilla.org/widget/dragservice;1");
|
|
|
|
if (ds) {
|
2017-11-22 00:36:13 +03:00
|
|
|
sDragServiceDisabled = false;
|
2017-11-15 19:30:13 +03:00
|
|
|
ds->Unsuppress();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
aVisitor.mParentTarget = GetParentTarget();
|
|
|
|
|
|
|
|
// Handle 'active' event.
|
|
|
|
if (!mIdleObservers.IsEmpty() &&
|
|
|
|
aVisitor.mEvent->IsTrusted() &&
|
|
|
|
(aVisitor.mEvent->HasMouseEventMessage() ||
|
|
|
|
aVisitor.mEvent->HasDragEventMessage())) {
|
|
|
|
mAddActiveEventFuzzTime = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DialogsAreBeingAbused()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
NS_ASSERTION(GetScriptableTopInternal() &&
|
|
|
|
GetScriptableTopInternal()->GetCurrentInnerWindowInternal() == this,
|
|
|
|
"DialogsAreBeingAbused called with invalid window");
|
|
|
|
|
|
|
|
if (mLastDialogQuitTime.IsNull() ||
|
|
|
|
nsContentUtils::IsCallerChrome()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
TimeDuration dialogInterval(TimeStamp::Now() - mLastDialogQuitTime);
|
|
|
|
if (dialogInterval.ToSeconds() <
|
|
|
|
Preferences::GetInt("dom.successive_dialog_time_limit",
|
|
|
|
DEFAULT_SUCCESSIVE_DIALOG_TIME_LIMIT)) {
|
|
|
|
mDialogAbuseCount++;
|
|
|
|
|
|
|
|
return GetPopupControlState() > openAllowed ||
|
|
|
|
mDialogAbuseCount > MAX_SUCCESSIVE_DIALOG_COUNT;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset the abuse counter
|
|
|
|
mDialogAbuseCount = 0;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DisableDialogs()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:47 +03:00
|
|
|
FORWARD_TO_OUTER_VOID(DisableDialogs, ());
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::EnableDialogs()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:47 +03:00
|
|
|
FORWARD_TO_OUTER_VOID(EnableDialogs, ());
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Return early if there is nothing to do.
|
|
|
|
switch (aVisitor.mEvent->mMessage) {
|
|
|
|
case eResize:
|
|
|
|
case eUnload:
|
|
|
|
case eLoad:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NS_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 function
|
|
|
|
nsCOMPtr<nsIScriptContext> kungFuDeathGrip2(GetContextInternal());
|
|
|
|
mozilla::Unused << kungFuDeathGrip2; // These aren't referred to through the function
|
|
|
|
|
|
|
|
|
|
|
|
if (aVisitor.mEvent->mMessage == eResize) {
|
|
|
|
mIsHandlingResizeEvent = false;
|
|
|
|
} else if (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 (const auto& 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;
|
|
|
|
} else if (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.
|
|
|
|
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
|
|
|
WidgetEvent event(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_t autoActivateVRDisplayID = 0;
|
|
|
|
nsGlobalWindowOuter* outer = GetOuterWindowInternal();
|
|
|
|
if (outer) {
|
|
|
|
autoActivateVRDisplayID = outer->GetAutoActivateVRDisplayID();
|
|
|
|
}
|
|
|
|
if (autoActivateVRDisplayID) {
|
|
|
|
DispatchVRDisplayActivate(autoActivateVRDisplayID,
|
|
|
|
VRDisplayEventReason::Navigation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DefineArgumentsProperty(nsIArray *aArguments)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsIScriptContext *ctx = GetOuterWindowInternal()->mContext;
|
|
|
|
NS_ENSURE_TRUE(aArguments && ctx, NS_ERROR_NOT_INITIALIZED);
|
|
|
|
|
|
|
|
JS::Rooted<JSObject*> obj(RootingCx(), GetWrapperPreserveColor());
|
|
|
|
return ctx->SetProperty(obj, "arguments", aArguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
2017-11-15 19:33:39 +03:00
|
|
|
// nsGlobalWindowInner::nsIScriptObjectPrincipal
|
2017-11-15 19:30:13 +03:00
|
|
|
//*****************************************************************************
|
|
|
|
|
|
|
|
nsIPrincipal*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetPrincipal()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mDoc) {
|
|
|
|
// If we have a document, get the principal from the document
|
|
|
|
return mDoc->NodePrincipal();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mDocumentPrincipal) {
|
|
|
|
return mDocumentPrincipal;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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) {
|
|
|
|
return objPrincipal->GetPrincipal();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
2017-11-15 19:33:39 +03:00
|
|
|
// nsGlobalWindowInner::nsIDOMWindow
|
2017-11-15 19:30:13 +03:00
|
|
|
//*****************************************************************************
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsPIDOMWindowInner::AddAudioContext(AudioContext* aAudioContext)
|
|
|
|
{
|
|
|
|
mAudioContexts.AppendElement(aAudioContext);
|
|
|
|
|
|
|
|
// Return true if the context should be muted and false if not.
|
|
|
|
nsIDocShell* docShell = GetDocShell();
|
|
|
|
return docShell && !docShell->GetAllowMedia() && !aAudioContext->IsOffline();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPIDOMWindowInner::RemoveAudioContext(AudioContext* aAudioContext)
|
|
|
|
{
|
|
|
|
mAudioContexts.RemoveElement(aAudioContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPIDOMWindowInner::MuteAudioContexts()
|
|
|
|
{
|
|
|
|
for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
|
|
|
|
if (!mAudioContexts[i]->IsOffline()) {
|
|
|
|
mAudioContexts[i]->Mute();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPIDOMWindowInner::UnmuteAudioContexts()
|
|
|
|
{
|
|
|
|
for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
|
|
|
|
if (!mAudioContexts[i]->IsOffline()) {
|
|
|
|
mAudioContexts[i]->Unmute();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsGlobalWindowInner*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Window()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:13 +03:00
|
|
|
return this;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsGlobalWindowInner*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Self()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:13 +03:00
|
|
|
return this;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
Navigator*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Navigator()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mNavigator) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mNavigator = new mozilla::dom::Navigator(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return mNavigator;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIDOMNavigator*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetNavigator()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return Navigator();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsScreen*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScreen(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mScreen) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mScreen = nsScreen::Create(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
if (!mScreen) {
|
|
|
|
aError.Throw(NS_ERROR_UNEXPECTED);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return mScreen;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIDOMScreen*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScreen()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
ErrorResult dummy;
|
|
|
|
nsIDOMScreen* screen = GetScreen(dummy);
|
|
|
|
dummy.SuppressException();
|
|
|
|
return screen;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsHistory*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetHistory(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mHistory) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mHistory = new nsHistory(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return mHistory;
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomElementRegistry*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::CustomElements()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mCustomElements) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mCustomElements = new CustomElementRegistry(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return mCustomElements;
|
|
|
|
}
|
|
|
|
|
|
|
|
Performance*
|
|
|
|
nsPIDOMWindowInner::GetPerformance()
|
|
|
|
{
|
|
|
|
CreatePerformanceObjectIfNeeded();
|
|
|
|
return mPerformance;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded()
|
|
|
|
{
|
|
|
|
if (mPerformance || !mDoc) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
RefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming();
|
|
|
|
nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
|
|
|
|
bool timingEnabled = false;
|
|
|
|
if (!timedChannel ||
|
|
|
|
!NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled)) ||
|
|
|
|
!timingEnabled) {
|
|
|
|
timedChannel = nullptr;
|
|
|
|
}
|
|
|
|
if (timing) {
|
|
|
|
mPerformance = Performance::CreateForMainThread(this, timing, timedChannel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsPIDOMWindowInner::IsSecureContext() const
|
|
|
|
{
|
|
|
|
return nsGlobalWindowInner::Cast(this)->IsSecureContext();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPIDOMWindowInner::Suspend()
|
|
|
|
{
|
|
|
|
nsGlobalWindowInner::Cast(this)->Suspend();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPIDOMWindowInner::Resume()
|
|
|
|
{
|
|
|
|
nsGlobalWindowInner::Cast(this)->Resume();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPIDOMWindowInner::Freeze()
|
|
|
|
{
|
|
|
|
nsGlobalWindowInner::Cast(this)->Freeze();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPIDOMWindowInner::Thaw()
|
|
|
|
{
|
|
|
|
nsGlobalWindowInner::Cast(this)->Thaw();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPIDOMWindowInner::SyncStateFromParentWindow()
|
|
|
|
{
|
|
|
|
nsGlobalWindowInner::Cast(this)->SyncStateFromParentWindow();
|
|
|
|
}
|
|
|
|
|
2017-11-21 23:13:05 +03:00
|
|
|
Maybe<ClientInfo>
|
|
|
|
nsPIDOMWindowInner::GetClientInfo() const
|
|
|
|
{
|
|
|
|
return Move(nsGlobalWindowInner::Cast(this)->GetClientInfo());
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:30:13 +03:00
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::UpdateTopInnerWindow()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-22 02:07:45 +03:00
|
|
|
if (IsTopInnerWindow() || !mTopInnerWindow) {
|
2017-11-15 19:30:13 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mTopInnerWindow->UpdateWebSocketCount(-(int32_t)mNumOfOpenWebSockets);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPIDOMWindowInner::AddPeerConnection()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections++
|
|
|
|
: mActivePeerConnections++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPIDOMWindowInner::RemovePeerConnection()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections
|
|
|
|
: mActivePeerConnections);
|
|
|
|
|
|
|
|
mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections--
|
|
|
|
: mActivePeerConnections--;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsPIDOMWindowInner::HasActivePeerConnections()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
return mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections
|
|
|
|
: mActivePeerConnections;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsPIDOMWindowInner::IsPlayingAudio()
|
|
|
|
{
|
|
|
|
for (uint32_t i = 0; i < mAudioContexts.Length(); i++) {
|
|
|
|
if (mAudioContexts[i]->IsRunning()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RefPtr<AudioChannelService> acs = AudioChannelService::Get();
|
|
|
|
if (!acs) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto outer = GetOuterWindow();
|
|
|
|
if (!outer) {
|
|
|
|
// We've been unlinked and are about to die. Not a good time to pretend to
|
|
|
|
// be playing audio.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return acs->IsWindowActive(outer);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsPIDOMWindowInner::IsDocumentLoaded() const
|
|
|
|
{
|
|
|
|
return mIsDocumentLoaded;
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::dom::TimeoutManager&
|
|
|
|
nsPIDOMWindowInner::TimeoutManager()
|
|
|
|
{
|
|
|
|
return *mTimeoutManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsPIDOMWindowInner::IsRunningTimeout()
|
|
|
|
{
|
|
|
|
return TimeoutManager().IsRunningTimeout();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPIDOMWindowInner::TryToCacheTopInnerWindow()
|
|
|
|
{
|
|
|
|
if (mHasTriedToCacheTopInnerWindow) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(!mInnerObjectsFreed);
|
|
|
|
|
|
|
|
mHasTriedToCacheTopInnerWindow = true;
|
|
|
|
|
2017-11-15 19:34:27 +03:00
|
|
|
nsGlobalWindowInner* window = nsGlobalWindowInner::Cast(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
MOZ_ASSERT(window);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
if (nsCOMPtr<nsPIDOMWindowOuter> topOutter = window->GetScriptableTop()) {
|
|
|
|
mTopInnerWindow = topOutter->GetCurrentInnerWindow();
|
|
|
|
}
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
nsPIDOMWindowInner::UpdateActiveIndexedDBTransactionCount(int32_t aDelta)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2017-11-15 19:30:13 +03:00
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
if (aDelta == 0) {
|
|
|
|
return;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
TabGroup()->IndexedDBTransactionCounter() += aDelta;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
nsPIDOMWindowInner::UpdateActiveIndexedDBDatabaseCount(int32_t aDelta)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2017-11-15 19:30:13 +03:00
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
if (aDelta == 0) {
|
2017-11-15 19:30:13 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
// We count databases but not transactions because only active databases
|
|
|
|
// could block throttling.
|
|
|
|
uint32_t& counter = mTopInnerWindow ?
|
|
|
|
mTopInnerWindow->mNumOfIndexedDBDatabases : mNumOfIndexedDBDatabases;
|
2017-11-15 19:30:13 +03:00
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
counter+= aDelta;
|
2017-11-15 19:30:13 +03:00
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
TabGroup()->IndexedDBDatabaseCounter() += aDelta;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
bool
|
|
|
|
nsPIDOMWindowInner::HasActiveIndexedDBDatabases()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2017-11-15 19:30:13 +03:00
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
return mTopInnerWindow ?
|
|
|
|
mTopInnerWindow->mNumOfIndexedDBDatabases > 0 :
|
|
|
|
mNumOfIndexedDBDatabases > 0;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
nsPIDOMWindowInner::UpdateWebSocketCount(int32_t aDelta)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
if (aDelta == 0) {
|
|
|
|
return;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
if (mTopInnerWindow && !IsTopInnerWindow()) {
|
|
|
|
mTopInnerWindow->UpdateWebSocketCount(aDelta);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(
|
|
|
|
aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets));
|
2017-11-15 19:30:13 +03:00
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
mNumOfOpenWebSockets += aDelta;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
nsPIDOMWindowInner::HasOpenWebSockets() const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
return mNumOfOpenWebSockets ||
|
|
|
|
(mTopInnerWindow && mTopInnerWindow->mNumOfOpenWebSockets);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsPIDOMWindowInner::GetAudioCaptured() const
|
|
|
|
{
|
|
|
|
return mAudioCaptured;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPIDOMWindowInner::SetAudioCapture(bool aCapture)
|
|
|
|
{
|
|
|
|
mAudioCaptured = aCapture;
|
|
|
|
|
|
|
|
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
|
|
|
|
if (service) {
|
|
|
|
service->SetWindowAudioCaptured(GetOuterWindow(), mWindowID, aCapture);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// nsISpeechSynthesisGetter
|
|
|
|
|
|
|
|
#ifdef MOZ_WEBSPEECH
|
|
|
|
SpeechSynthesis*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetSpeechSynthesis(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mSpeechSynthesis) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mSpeechSynthesis = new SpeechSynthesis(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return mSpeechSynthesis;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::HasActiveSpeechSynthesis()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mSpeechSynthesis) {
|
|
|
|
return !mSpeechSynthesis->HasEmptyQueue();
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
already_AddRefed<nsPIDOMWindowOuter>
|
2017-11-15 19:34:13 +03:00
|
|
|
nsGlobalWindowInner::GetParent(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
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*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScriptableParent()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER(GetScriptableParent, (), nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Behavies identically to GetScriptableParent extept that it returns null
|
|
|
|
* if GetScriptableParent would return this window.
|
|
|
|
*/
|
|
|
|
nsPIDOMWindowOuter*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScriptableParentOrNull()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER(GetScriptableParentOrNull, (), nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScriptableTop()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER(GetScriptableTop, (), nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetContent(JSContext* aCx,
|
2017-11-15 19:34:41 +03:00
|
|
|
JS::MutableHandle<JSObject*> aRetval,
|
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetContentOuter,
|
|
|
|
(aCx, aRetval, aCallerType, aError), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
MozSelfSupport*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetMozSelfSupport(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mMozSelfSupport) {
|
|
|
|
return mMozSelfSupport;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We're called from JS and want to use out existing JSContext (and,
|
|
|
|
// importantly, its compartment!) here.
|
|
|
|
AutoJSContext cx;
|
|
|
|
GlobalObject global(cx, FastGetGlobalJSObject());
|
|
|
|
mMozSelfSupport = MozSelfSupport::Constructor(global, cx, aError);
|
|
|
|
return mMozSelfSupport;
|
|
|
|
}
|
|
|
|
|
|
|
|
BarProp*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetMenubar(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mMenubar) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mMenubar = new MenubarProp(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return mMenubar;
|
|
|
|
}
|
|
|
|
|
|
|
|
BarProp*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetToolbar(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mToolbar) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mToolbar = new ToolbarProp(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return mToolbar;
|
|
|
|
}
|
|
|
|
|
|
|
|
BarProp*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetLocationbar(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mLocationbar) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mLocationbar = new LocationbarProp(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
return mLocationbar;
|
|
|
|
}
|
|
|
|
|
|
|
|
BarProp*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetPersonalbar(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mPersonalbar) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mPersonalbar = new PersonalbarProp(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
return mPersonalbar;
|
|
|
|
}
|
|
|
|
|
|
|
|
BarProp*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetStatusbar(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mStatusbar) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mStatusbar = new StatusbarProp(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
return mStatusbar;
|
|
|
|
}
|
|
|
|
|
|
|
|
BarProp*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScrollbars(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mScrollbars) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mScrollbars = new ScrollbarsProp(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return mScrollbars;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetClosed(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetClosedOuter, (), aError, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsIDOMWindowCollection>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetFrames()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER(GetFrames, (), nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsPIDOMWindowOuter>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IndexedGetter(uint32_t aIndex)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER(IndexedGetterOuter, (aIndex), nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
|
2017-11-15 19:34:41 +03:00
|
|
|
JS::Handle<jsid> aId,
|
|
|
|
JS::MutableHandle<JS::PropertyDescriptor> aDesc)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Note: Keep this in sync with MayResolve.
|
|
|
|
|
|
|
|
// Note: The infallibleInit call in GlobalResolve depends on this check.
|
|
|
|
if (!JSID_IS_STRING(aId)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool found;
|
|
|
|
if (!WebIDLGlobalNameHash::DefineIfEnabled(aCx, aObj, aId, aDesc, &found)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:34:27 +03:00
|
|
|
nsresult rv = nsWindowSH::GlobalResolve(this, aCx, aObj, aId, aDesc);
|
2017-11-15 19:30:13 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return Throw(aCx, rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::MayResolve(jsid aId)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// 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)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_COMPONENTS)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
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.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WebIDLGlobalNameHash::MayResolve(aId)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsScriptNameSpaceManager *nameSpaceManager = PeekNameSpaceManager();
|
|
|
|
if (!nameSpaceManager) {
|
|
|
|
// Really shouldn't happen. Fail safe.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString name;
|
|
|
|
AssignJSFlatString(name, JSID_TO_FLAT_STRING(aId));
|
|
|
|
|
|
|
|
return nameSpaceManager->LookupName(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetOwnPropertyNames(JSContext* aCx, JS::AutoIdVector& aNames,
|
2017-11-15 19:34:41 +03:00
|
|
|
bool aEnumerableOnly, ErrorResult& aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// "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::NameType nameType =
|
|
|
|
js::IsObjectInContextCompartment(wrapper, aCx) ?
|
|
|
|
WebIDLGlobalNameHash::UnresolvedNamesOnly :
|
|
|
|
WebIDLGlobalNameHash::AllNames;
|
|
|
|
if (!WebIDLGlobalNameHash::GetNames(aCx, wrapper, nameType, aNames)) {
|
|
|
|
aRv.NoteJSContextException(aCx);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto i = nameSpaceManager->GlobalNameIter(); !i.Done(); i.Next()) {
|
|
|
|
const GlobalNameMapEntry* entry = i.Get();
|
2017-11-15 19:34:27 +03:00
|
|
|
if (nsWindowSH::NameStructEnabled(aCx, this, entry->mKey,
|
2017-11-15 19:30:13 +03:00
|
|
|
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 */ bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IsPrivilegedChromeWindow(JSContext* aCx, JSObject* aObj)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// For now, have to deal with XPConnect objects here.
|
|
|
|
return xpc::WindowOrNull(aObj)->IsChromeWindow() &&
|
|
|
|
nsContentUtils::ObjectPrincipal(aObj) == nsContentUtils::GetSystemPrincipal();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IsRequestIdleCallbackEnabled(JSContext* aCx, JSObject* aObj)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// The requestIdleCallback should always be enabled for system code.
|
|
|
|
return nsContentUtils::RequestIdleCallbackEnabled() ||
|
|
|
|
nsContentUtils::IsSystemCaller(aCx);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIDOMOfflineResourceList*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetApplicationCache(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mApplicationCache) {
|
|
|
|
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(GetDocShell()));
|
|
|
|
if (!webNav || !mDoc) {
|
|
|
|
aError.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
aError = webNav->GetCurrentURI(getter_AddRefs(uri));
|
|
|
|
if (aError.Failed()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> manifestURI;
|
|
|
|
nsContentUtils::GetOfflineAppManifest(mDoc, getter_AddRefs(manifestURI));
|
|
|
|
|
|
|
|
RefPtr<nsDOMOfflineResourceList> applicationCache =
|
|
|
|
new nsDOMOfflineResourceList(manifestURI, uri, mDoc->NodePrincipal(),
|
2017-11-15 19:34:27 +03:00
|
|
|
this);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
applicationCache->Init();
|
|
|
|
|
|
|
|
mApplicationCache = applicationCache;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mApplicationCache;
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsIDOMOfflineResourceList>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetApplicationCache()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
ErrorResult dummy;
|
|
|
|
nsCOMPtr<nsIDOMOfflineResourceList> applicationCache =
|
|
|
|
GetApplicationCache(dummy);
|
|
|
|
dummy.SuppressException();
|
|
|
|
return applicationCache.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
Crypto*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetCrypto(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mCrypto) {
|
|
|
|
mCrypto = new Crypto();
|
|
|
|
mCrypto->Init(this);
|
|
|
|
}
|
|
|
|
return mCrypto;
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::dom::U2F*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetU2f(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mU2F) {
|
2017-11-15 19:34:27 +03:00
|
|
|
RefPtr<U2F> u2f = new U2F(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
u2f->Init(aError);
|
|
|
|
if (NS_WARN_IF(aError.Failed())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
mU2F = u2f;
|
|
|
|
}
|
|
|
|
return mU2F;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIControllers*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetControllers(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetControllersOuter, (aError), aError, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetControllers(nsIControllers** aResult)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
ErrorResult rv;
|
|
|
|
nsCOMPtr<nsIControllers> controllers = GetControllers(rv);
|
|
|
|
controllers.forget(aResult);
|
|
|
|
|
|
|
|
return rv.StealNSResult();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPIDOMWindowOuter*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetOpenerWindow(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetOpenerWindowOuter, (), aError, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
|
2017-11-15 19:34:41 +03:00
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> opener = GetOpenerWindow(aError);
|
|
|
|
if (aError.Failed() || !opener) {
|
|
|
|
aRetval.setNull();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
aError = nsContentUtils::WrapNative(aCx, opener, aRetval);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
2017-11-15 19:34:41 +03:00
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// 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 opener
|
|
|
|
aError.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 window
|
|
|
|
aError.Throw(NS_ERROR_INVALID_ARG);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:34:27 +03:00
|
|
|
win = globalWindow;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsPIDOMWindowOuter* outer = nullptr;
|
|
|
|
if (win) {
|
|
|
|
if (!win->IsCurrentInnerWindow()) {
|
|
|
|
aError.Throw(NS_ERROR_FAILURE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
outer = win->GetOuterWindow();
|
|
|
|
}
|
|
|
|
|
|
|
|
SetOpenerWindow(outer, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetStatus(nsAString& aStatus, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetStatusOuter, (aStatus), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetStatus(const nsAString& aStatus, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(SetStatusOuter, (aStatus), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetName(nsAString& aName, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetNameOuter, (aName), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetName(const nsAString& aName, mozilla::ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(SetNameOuter, (aName, aError), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetInnerWidth(CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// We ignore aCallerType; we only have that argument because some other things
|
|
|
|
// called by GetReplaceableWindowCoord need it. If this ever changes, fix
|
2017-11-15 19:33:39 +03:00
|
|
|
// nsresult nsGlobalWindowInner::GetInnerWidth(int32_t* aInnerWidth)
|
2017-11-15 19:30:13 +03:00
|
|
|
// to actually take a useful CallerType and pass it in here.
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetInnerWidthOuter, (aError), aError, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetInnerWidth(JSContext* aCx,
|
2017-11-15 19:34:41 +03:00
|
|
|
JS::MutableHandle<JS::Value> aValue,
|
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:33:39 +03:00
|
|
|
GetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::GetInnerWidth, aValue,
|
2017-11-15 19:30:13 +03:00
|
|
|
aCallerType, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetInnerWidth(int32_t* aInnerWidth)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
ErrorResult rv;
|
|
|
|
// Callee doesn't care about the caller type, but play it safe.
|
|
|
|
*aInnerWidth = GetInnerWidth(CallerType::NonSystem, rv);
|
|
|
|
|
|
|
|
return rv.StealNSResult();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetInnerWidth(int32_t aInnerWidth, CallerType aCallerType,
|
2017-11-15 19:34:41 +03:00
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(SetInnerWidthOuter,
|
|
|
|
(aInnerWidth, aCallerType, aError), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetInnerWidth(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:33:39 +03:00
|
|
|
SetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::SetInnerWidth,
|
2017-11-15 19:30:13 +03:00
|
|
|
aValue, "innerWidth", aCallerType, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:34:13 +03:00
|
|
|
nsGlobalWindowInner::GetInnerHeight(CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// We ignore aCallerType; we only have that argument because some other things
|
|
|
|
// called by GetReplaceableWindowCoord need it. If this ever changes, fix
|
2017-11-15 19:33:39 +03:00
|
|
|
// nsresult nsGlobalWindowInner::GetInnerHeight(int32_t* aInnerWidth)
|
2017-11-15 19:30:13 +03:00
|
|
|
// to actually take a useful CallerType and pass it in here.
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetInnerHeightOuter, (aError), aError, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetInnerHeight(JSContext* aCx,
|
2017-11-15 19:34:41 +03:00
|
|
|
JS::MutableHandle<JS::Value> aValue,
|
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:33:39 +03:00
|
|
|
GetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::GetInnerHeight, aValue,
|
2017-11-15 19:30:13 +03:00
|
|
|
aCallerType, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetInnerHeight(int32_t* aInnerHeight)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
ErrorResult rv;
|
|
|
|
// Callee doesn't care about the caller type, but play it safe.
|
|
|
|
*aInnerHeight = GetInnerHeight(CallerType::NonSystem, rv);
|
|
|
|
|
|
|
|
return rv.StealNSResult();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetInnerHeight(int32_t aInnerHeight,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(SetInnerHeightOuter,
|
|
|
|
(aInnerHeight, aCallerType, aError), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetInnerHeight(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:33:39 +03:00
|
|
|
SetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::SetInnerHeight,
|
2017-11-15 19:30:13 +03:00
|
|
|
aValue, "innerHeight", aCallerType, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetOuterWidth(CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetOuterWidthOuter, (aCallerType, aError),
|
|
|
|
aError, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetOuterWidth(JSContext* aCx,
|
2017-11-15 19:34:41 +03:00
|
|
|
JS::MutableHandle<JS::Value> aValue,
|
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:33:39 +03:00
|
|
|
GetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::GetOuterWidth, aValue,
|
2017-11-15 19:30:13 +03:00
|
|
|
aCallerType, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetOuterHeight(CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetOuterHeightOuter, (aCallerType, aError),
|
|
|
|
aError, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetOuterHeight(JSContext* aCx,
|
2017-11-15 19:34:41 +03:00
|
|
|
JS::MutableHandle<JS::Value> aValue,
|
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:33:39 +03:00
|
|
|
GetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::GetOuterHeight, aValue,
|
2017-11-15 19:30:13 +03:00
|
|
|
aCallerType, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetOuterWidth(int32_t aOuterWidth,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(SetOuterWidthOuter,
|
|
|
|
(aOuterWidth, aCallerType, aError), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetOuterWidth(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:33:39 +03:00
|
|
|
SetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::SetOuterWidth,
|
2017-11-15 19:30:13 +03:00
|
|
|
aValue, "outerWidth", aCallerType, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetOuterHeight(int32_t aOuterHeight,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(SetOuterHeightOuter,
|
|
|
|
(aOuterHeight, aCallerType, aError), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetOuterHeight(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:33:39 +03:00
|
|
|
SetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::SetOuterHeight,
|
2017-11-15 19:30:13 +03:00
|
|
|
aValue, "outerHeight", aCallerType, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScreenX(CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetScreenXOuter, (aCallerType, aError), aError, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScreenX(JSContext* aCx,
|
2017-11-15 19:34:41 +03:00
|
|
|
JS::MutableHandle<JS::Value> aValue,
|
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:33:39 +03:00
|
|
|
GetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::GetScreenX, aValue,
|
2017-11-15 19:30:13 +03:00
|
|
|
aCallerType, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
float
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetMozInnerScreenX(CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenXOuter, (aCallerType), aError, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
float
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetMozInnerScreenY(CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenYOuter, (aCallerType), aError, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
double
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetDevicePixelRatio(CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetDevicePixelRatioOuter, (aCallerType), aError, 0.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetMozPaintCount(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetMozPaintCountOuter, (), aError, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::RequestAnimationFrame(FrameRequestCallback& aCallback,
|
2017-11-15 19:34:41 +03:00
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mDoc) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetWrapperPreserveColor()) {
|
|
|
|
js::NotifyAnimationActivity(GetWrapperPreserveColor());
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t handle;
|
|
|
|
aError = mDoc->ScheduleFrameRequestCallback(aCallback, &handle);
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::CancelAnimationFrame(int32_t aHandle, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mDoc) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mDoc->CancelFrameRequestCallback(aHandle);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<MediaQueryList>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::MatchMedia(const nsAString& aMediaQueryList,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetScreenX(int32_t aScreenX,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(SetScreenXOuter,
|
|
|
|
(aScreenX, aCallerType, aError), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetScreenX(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:33:39 +03:00
|
|
|
SetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::SetScreenX,
|
2017-11-15 19:30:13 +03:00
|
|
|
aValue, "screenX", aCallerType, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScreenY(CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetScreenYOuter, (aCallerType, aError), aError, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScreenY(JSContext* aCx,
|
2017-11-15 19:34:41 +03:00
|
|
|
JS::MutableHandle<JS::Value> aValue,
|
|
|
|
CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:33:39 +03:00
|
|
|
GetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::GetScreenY, aValue,
|
2017-11-15 19:30:13 +03:00
|
|
|
aCallerType, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetScreenY(int32_t aScreenY,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(SetScreenYOuter,
|
|
|
|
(aScreenY, aCallerType, aError), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetScreenY(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:33:39 +03:00
|
|
|
SetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::SetScreenY,
|
2017-11-15 19:30:13 +03:00
|
|
|
aValue, "screenY", aCallerType, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScrollMinX(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideLeft), aError, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScrollMinY(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideTop), aError, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScrollMaxX(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideRight), aError, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScrollMaxY(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideBottom), aError, 0);
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
double
|
|
|
|
nsGlobalWindowInner::GetScrollX(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:13 +03:00
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetScrollXOuter, (), aError, 0);
|
|
|
|
}
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
double
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScrollY(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetScrollYOuter, (), aError, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Length()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER(Length, (), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsPIDOMWindowOuter>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetTop(mozilla::ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetTopOuter, (), aError, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPIDOMWindowOuter*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetChildWindow(const nsAString& aName)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:47 +03:00
|
|
|
if (GetOuterWindowInternal()) {
|
|
|
|
return GetOuterWindowInternal()->GetChildWindow(aName);
|
|
|
|
}
|
|
|
|
return nullptr;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::RefreshCompartmentPrincipal()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
JS_SetCompartmentPrincipals(js::GetObjectCompartment(GetWrapperPreserveColor()),
|
|
|
|
nsJSPrincipals::get(mDoc->NodePrincipal()));
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsIWidget>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetMainWidget()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER(GetMainWidget, (), nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIWidget*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetNearestWidget() const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:47 +03:00
|
|
|
if (GetOuterWindowInternal()) {
|
|
|
|
return GetOuterWindowInternal()->GetNearestWidget();
|
|
|
|
}
|
|
|
|
return nullptr;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetFullScreen(bool aFullScreen, mozilla::ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(SetFullScreenOuter, (aFullScreen, aError), aError, /* void */);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetFullScreen(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetFullScreenOuter, (), aError, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetFullScreen()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
ErrorResult dummy;
|
|
|
|
bool fullscreen = GetFullScreen(dummy);
|
|
|
|
dummy.SuppressException();
|
|
|
|
return fullscreen;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Dump(const nsAString& aStr)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-30 23:35:32 +03:00
|
|
|
if (!nsContentUtils::DOMWindowDumpEnabled()) {
|
2017-11-15 19:30:13 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *cstr = ToNewUTF8String(aStr);
|
|
|
|
|
|
|
|
#if defined(XP_MACOSX)
|
|
|
|
// have to convert \r to \n so that printing to the console works
|
|
|
|
char *c = cstr, *cEnd = cstr + strlen(cstr);
|
|
|
|
while (c < cEnd) {
|
|
|
|
if (*c == '\r')
|
|
|
|
*c = '\n';
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (cstr) {
|
|
|
|
MOZ_LOG(nsContentUtils::DOMDumpLog(), LogLevel::Debug, ("[Window.Dump] %s", cstr));
|
|
|
|
#ifdef XP_WIN
|
|
|
|
PrintToDebugger(cstr);
|
|
|
|
#endif
|
|
|
|
#ifdef ANDROID
|
|
|
|
__android_log_write(ANDROID_LOG_INFO, "GeckoDump", cstr);
|
|
|
|
#endif
|
|
|
|
FILE *fp = gDumpFile ? gDumpFile : stdout;
|
|
|
|
fputs(cstr, fp);
|
|
|
|
fflush(fp);
|
|
|
|
free(cstr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Alert(nsIPrincipal& aSubjectPrincipal,
|
2017-11-15 19:34:41 +03:00
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
Alert(EmptyString(), aSubjectPrincipal, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Alert(const nsAString& aMessage,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsIPrincipal& aSubjectPrincipal,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(AlertOuter, (aMessage, aSubjectPrincipal, aError),
|
|
|
|
aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Confirm(const nsAString& aMessage,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsIPrincipal& aSubjectPrincipal,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(ConfirmOuter, (aMessage, aSubjectPrincipal, aError),
|
|
|
|
aError, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<Promise>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Fetch(const RequestOrUSVString& aInput,
|
2017-11-15 19:34:41 +03:00
|
|
|
const RequestInit& aInit,
|
|
|
|
CallerType aCallerType, ErrorResult& aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return FetchRequest(this, aInput, aInit, aCallerType, aRv);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Prompt(const nsAString& aMessage, const nsAString& aInitial,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsAString& aReturn,
|
|
|
|
nsIPrincipal& aSubjectPrincipal,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(PromptOuter,
|
2017-11-15 19:34:13 +03:00
|
|
|
(aMessage, aInitial, aReturn, aSubjectPrincipal,
|
|
|
|
aError),
|
|
|
|
aError, );
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:34:13 +03:00
|
|
|
nsGlobalWindowInner::Focus(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:13 +03:00
|
|
|
FORWARD_TO_OUTER_OR_THROW(FocusOuter, (aError), aError, );
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
nsresult
|
|
|
|
nsGlobalWindowInner::Focus()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:13 +03:00
|
|
|
ErrorResult rv;
|
|
|
|
Focus(rv);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
return rv.StealNSResult();
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:34:13 +03:00
|
|
|
nsGlobalWindowInner::Blur(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:13 +03:00
|
|
|
FORWARD_TO_OUTER_OR_THROW(BlurOuter, (), aError, );
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:34:13 +03:00
|
|
|
nsGlobalWindowInner::Back(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:13 +03:00
|
|
|
FORWARD_TO_OUTER_OR_THROW(BackOuter, (aError), aError, );
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:34:13 +03:00
|
|
|
nsGlobalWindowInner::Forward(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:13 +03:00
|
|
|
FORWARD_TO_OUTER_OR_THROW(ForwardOuter, (aError), aError, );
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:34:13 +03:00
|
|
|
nsGlobalWindowInner::Home(nsIPrincipal& aSubjectPrincipal, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:13 +03:00
|
|
|
FORWARD_TO_OUTER_OR_THROW(HomeOuter, (aSubjectPrincipal, aError), aError, );
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Stop(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(StopOuter, (aError), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IsWindowPrintEnabled(JSContext*, JSObject*)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
static bool called = false;
|
|
|
|
static bool printDisabled = false;
|
|
|
|
if (!called) {
|
|
|
|
called = true;
|
|
|
|
Preferences::AddBoolVarCache(&printDisabled, "dom.disable_window_print");
|
|
|
|
}
|
|
|
|
return !printDisabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Print(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(PrintOuter, (aError), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::MoveTo(int32_t aXPos, int32_t aYPos,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(MoveToOuter,
|
|
|
|
(aXPos, aYPos, aCallerType, aError), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::MoveBy(int32_t aXDif, int32_t aYDif,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(MoveByOuter,
|
|
|
|
(aXDif, aYDif, aCallerType, aError), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ResizeTo(int32_t aWidth, int32_t aHeight,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(ResizeToOuter,
|
|
|
|
(aWidth, aHeight, aCallerType, aError), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
|
2017-11-15 19:34:41 +03:00
|
|
|
CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(ResizeByOuter,
|
|
|
|
(aWidthDif, aHeightDif, aCallerType, aError),
|
|
|
|
aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SizeToContent(CallerType aCallerType, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(SizeToContentOuter, (aCallerType, aError),
|
|
|
|
aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsPIWindowRoot>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetTopWindowRoot()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-21 21:25:27 +03:00
|
|
|
nsGlobalWindowOuter* outer = GetOuterWindowInternal();
|
|
|
|
if (!outer) {
|
2017-11-15 19:30:13 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
2017-11-21 21:25:27 +03:00
|
|
|
return outer->GetTopWindowRoot();
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Scroll(double aXScroll, double aYScroll)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
|
|
|
|
auto scrollPos = CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScroll),
|
|
|
|
mozilla::ToZeroIfNonfinite(aYScroll));
|
|
|
|
ScrollTo(scrollPos, ScrollOptions());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ScrollTo(double aXScroll, double aYScroll)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
|
|
|
|
auto scrollPos = CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScroll),
|
|
|
|
mozilla::ToZeroIfNonfinite(aYScroll));
|
|
|
|
ScrollTo(scrollPos, ScrollOptions());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ScrollTo(const ScrollToOptions& aOptions)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// 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.
|
|
|
|
FlushType flushType = ((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) {
|
|
|
|
CSSIntPoint scrollPos = 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Scroll(const ScrollToOptions& aOptions)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
ScrollTo(aOptions);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ScrollTo(const CSSIntPoint& aScroll,
|
2017-11-15 19:34:41 +03:00
|
|
|
const ScrollOptions& aOptions)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// 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.
|
|
|
|
FlushType flushType = (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. -- jst
|
|
|
|
const int32_t maxpx = nsPresContext::AppUnitsToIntCSSPixels(0x7fffffff) - 4;
|
|
|
|
|
|
|
|
CSSIntPoint scroll(aScroll);
|
|
|
|
if (scroll.x > maxpx) {
|
|
|
|
scroll.x = maxpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (scroll.y > maxpx) {
|
|
|
|
scroll.y = maxpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool smoothScroll = sf->GetScrollbarStyles().IsSmoothScroll(aOptions.mBehavior);
|
|
|
|
|
|
|
|
sf->ScrollToCSSPixels(scroll, smoothScroll
|
|
|
|
? nsIScrollableFrame::SMOOTH_MSD
|
|
|
|
: nsIScrollableFrame::INSTANT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ScrollBy(double aXScrollDif, double aYScrollDif)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FlushPendingNotifications(FlushType::Layout);
|
|
|
|
nsIScrollableFrame *sf = GetScrollFrame();
|
|
|
|
|
|
|
|
if (sf) {
|
|
|
|
// Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
|
|
|
|
auto scrollDif = 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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ScrollBy(const ScrollToOptions& aOptions)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FlushPendingNotifications(FlushType::Layout);
|
|
|
|
nsIScrollableFrame *sf = GetScrollFrame();
|
|
|
|
|
|
|
|
if (sf) {
|
|
|
|
CSSIntPoint scrollPos = 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ScrollByLines(int32_t numLines,
|
2017-11-15 19:34:41 +03:00
|
|
|
const ScrollOptions& aOptions)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
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.
|
|
|
|
bool smoothScroll = sf->GetScrollbarStyles().IsSmoothScroll(aOptions.mBehavior);
|
|
|
|
|
|
|
|
sf->ScrollBy(nsIntPoint(0, numLines), nsIScrollableFrame::LINES,
|
|
|
|
smoothScroll
|
|
|
|
? nsIScrollableFrame::SMOOTH_MSD
|
|
|
|
: nsIScrollableFrame::INSTANT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ScrollByPages(int32_t numPages,
|
2017-11-15 19:34:41 +03:00
|
|
|
const ScrollOptions& aOptions)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
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.
|
|
|
|
bool smoothScroll = sf->GetScrollbarStyles().IsSmoothScroll(aOptions.mBehavior);
|
|
|
|
|
|
|
|
sf->ScrollBy(nsIntPoint(0, numPages), nsIScrollableFrame::PAGES,
|
|
|
|
smoothScroll
|
|
|
|
? nsIScrollableFrame::SMOOTH_MSD
|
|
|
|
: nsIScrollableFrame::INSTANT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::MozScrollSnap()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FlushPendingNotifications(FlushType::Layout);
|
|
|
|
nsIScrollableFrame *sf = GetScrollFrame();
|
|
|
|
if (sf) {
|
|
|
|
sf->ScrollSnap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ClearTimeout(int32_t aHandle)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (aHandle > 0) {
|
|
|
|
mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ClearInterval(int32_t aHandle)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (aHandle > 0) {
|
|
|
|
mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetResizable(bool aResizable) const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// nop
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::CaptureEvents()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mDoc) {
|
|
|
|
mDoc->WarnOnceAbout(nsIDocument::eUseOfCaptureEvents);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
void
|
|
|
|
nsGlobalWindowInner::ReleaseEvents()
|
|
|
|
{
|
|
|
|
if (mDoc) {
|
|
|
|
mDoc->WarnOnceAbout(nsIDocument::eUseOfReleaseEvents);
|
|
|
|
}
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsPIDOMWindowOuter>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Open(const nsAString& aUrl, const nsAString& aName,
|
2017-11-15 19:34:41 +03:00
|
|
|
const nsAString& aOptions, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(OpenOuter, (aUrl, aName, aOptions, aError), aError,
|
|
|
|
nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsPIDOMWindowOuter>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::OpenDialog(JSContext* aCx, const nsAString& aUrl,
|
2017-11-15 19:34:41 +03:00
|
|
|
const nsAString& aName, const nsAString& aOptions,
|
|
|
|
const Sequence<JS::Value>& aExtraArgument,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(OpenDialogOuter,
|
|
|
|
(aCx, aUrl, aName, aOptions, aExtraArgument, aError),
|
|
|
|
aError, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsPIDOMWindowOuter>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetFrames(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetFramesOuter, (), aError, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsGlobalWindowInner*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::CallerInnerWindow()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
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)) {
|
|
|
|
JSAutoCompartment ac(cx, scope);
|
|
|
|
JS::Rooted<JSObject*> scopeProto(cx);
|
|
|
|
bool ok = 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);
|
|
|
|
return nsGlobalWindowInner::Cast(win);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
2017-11-15 19:34:41 +03:00
|
|
|
const nsAString& aTargetOrigin,
|
|
|
|
JS::Handle<JS::Value> aTransfer,
|
|
|
|
nsIPrincipal& aSubjectPrincipal,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(PostMessageMozOuter,
|
|
|
|
(aCx, aMessage, aTargetOrigin, aTransfer,
|
|
|
|
aSubjectPrincipal, aError),
|
|
|
|
aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
2017-11-15 19:34:41 +03:00
|
|
|
const nsAString& aTargetOrigin,
|
|
|
|
const Sequence<JSObject*>& aTransfer,
|
|
|
|
nsIPrincipal& aSubjectPrincipal,
|
|
|
|
ErrorResult& aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Close(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(CloseOuter, (nsContentUtils::IsCallerChrome()), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Close()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER(Close, (), NS_ERROR_UNEXPECTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ReallyCloseWindow()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_VOID(ReallyCloseWindow, ());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IsInModalState()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:47 +03:00
|
|
|
FORWARD_TO_OUTER(IsInModalState, (), false);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void
|
2017-11-15 19:34:41 +03:00
|
|
|
nsGlobalWindowInner::NotifyDOMWindowDestroyed(nsGlobalWindowInner* aWindow)
|
|
|
|
{
|
2017-11-15 19:30:13 +03:00
|
|
|
nsCOMPtr<nsIObserverService> observerService =
|
|
|
|
services::GetObserverService();
|
|
|
|
if (observerService) {
|
|
|
|
observerService->
|
|
|
|
NotifyObservers(ToSupports(aWindow),
|
|
|
|
DOM_WINDOW_DESTROYED_TOPIC, nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::NotifyWindowIDDestroyed(const char* aTopic)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:13 +03:00
|
|
|
nsCOMPtr<nsIRunnable> runnable =
|
2017-11-15 19:34:27 +03:00
|
|
|
new WindowDestroyedEvent(this, mWindowID, aTopic);
|
2017-11-21 23:06:21 +03:00
|
|
|
Dispatch(TaskCategory::Other, runnable.forget());
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void
|
2017-11-15 19:34:41 +03:00
|
|
|
nsGlobalWindowInner::NotifyDOMWindowFrozen(nsGlobalWindowInner* aWindow)
|
|
|
|
{
|
2017-11-15 19:30:13 +03:00
|
|
|
if (aWindow) {
|
|
|
|
nsCOMPtr<nsIObserverService> observerService =
|
|
|
|
services::GetObserverService();
|
|
|
|
if (observerService) {
|
|
|
|
observerService->
|
|
|
|
NotifyObservers(ToSupports(aWindow),
|
|
|
|
DOM_WINDOW_FROZEN_TOPIC, nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void
|
2017-11-15 19:34:41 +03:00
|
|
|
nsGlobalWindowInner::NotifyDOMWindowThawed(nsGlobalWindowInner* aWindow)
|
|
|
|
{
|
2017-11-15 19:30:13 +03:00
|
|
|
if (aWindow) {
|
|
|
|
nsCOMPtr<nsIObserverService> observerService =
|
|
|
|
services::GetObserverService();
|
|
|
|
if (observerService) {
|
|
|
|
observerService->
|
|
|
|
NotifyObservers(ToSupports(aWindow),
|
|
|
|
DOM_WINDOW_THAWED_TOPIC, nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
JSObject*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
JS::Rooted<JSObject*> handler(RootingCx());
|
|
|
|
if (mCachedXBLPrototypeHandlers) {
|
|
|
|
mCachedXBLPrototypeHandlers->Get(aKey, handler.address());
|
|
|
|
}
|
|
|
|
return handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
|
2017-11-15 19:34:41 +03:00
|
|
|
JS::Handle<JSObject*> aHandler)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mCachedXBLPrototypeHandlers) {
|
|
|
|
mCachedXBLPrototypeHandlers = MakeUnique<XBLPrototypeHandlerTable>();
|
|
|
|
PreserveWrapper(ToSupports(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
mCachedXBLPrototypeHandlers->Put(aKey, aHandler);
|
|
|
|
}
|
|
|
|
|
|
|
|
Element*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetFrameElement(nsIPrincipal& aSubjectPrincipal,
|
2017-11-15 19:34:41 +03:00
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetFrameElementOuter, (aSubjectPrincipal), aError,
|
|
|
|
nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
Element*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetRealFrameElement(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetRealFrameElementOuter, (), aError, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* nsIGlobalWindow::GetFrameElement (when called from C++) is just a wrapper
|
|
|
|
* around GetRealFrameElement.
|
|
|
|
*/
|
|
|
|
already_AddRefed<nsIDOMElement>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetFrameElement()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
ErrorResult dummy;
|
|
|
|
nsCOMPtr<nsIDOMElement> frameElement =
|
|
|
|
do_QueryInterface(GetRealFrameElement(dummy));
|
|
|
|
dummy.SuppressException();
|
|
|
|
return frameElement.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::TokenizeDialogOptions(nsAString& aToken,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsAString::const_iterator& aIter,
|
|
|
|
nsAString::const_iterator aEnd)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
while (aIter != aEnd && nsCRT::IsAsciiSpace(*aIter)) {
|
|
|
|
++aIter;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aIter == aEnd) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*aIter == ';' || *aIter == ':' || *aIter == '=') {
|
|
|
|
aToken.Assign(*aIter);
|
|
|
|
++aIter;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAString::const_iterator start = aIter;
|
|
|
|
|
|
|
|
// Skip characters until we find whitespace, ';', ':', or '='
|
|
|
|
while (aIter != aEnd && !nsCRT::IsAsciiSpace(*aIter) &&
|
|
|
|
*aIter != ';' &&
|
|
|
|
*aIter != ':' &&
|
|
|
|
*aIter != '=') {
|
|
|
|
++aIter;
|
|
|
|
}
|
|
|
|
|
|
|
|
aToken.Assign(Substring(start, aIter));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Helper for converting window.showModalDialog() options (list of ';'
|
|
|
|
// separated name (:|=) value pairs) to a format that's parsable by
|
|
|
|
// our normal window opening code.
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ConvertDialogOptions(const nsAString& aOptions,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsAString& aResult)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsAString::const_iterator end;
|
|
|
|
aOptions.EndReading(end);
|
|
|
|
|
|
|
|
nsAString::const_iterator iter;
|
|
|
|
aOptions.BeginReading(iter);
|
|
|
|
|
|
|
|
nsAutoString token;
|
|
|
|
nsAutoString name;
|
|
|
|
nsAutoString value;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
if (!TokenizeDialogOptions(name, iter, end)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Invalid name.
|
|
|
|
if (name.EqualsLiteral("=") ||
|
|
|
|
name.EqualsLiteral(":") ||
|
|
|
|
name.EqualsLiteral(";")) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!TokenizeDialogOptions(token, iter, end)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!token.EqualsLiteral(":") && !token.EqualsLiteral("=")) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We found name followed by ':' or '='. Look for a value.
|
|
|
|
if (!TokenizeDialogOptions(value, iter, end)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name.LowerCaseEqualsLiteral("center")) {
|
|
|
|
if (value.LowerCaseEqualsLiteral("on") ||
|
|
|
|
value.LowerCaseEqualsLiteral("yes") ||
|
|
|
|
value.LowerCaseEqualsLiteral("1")) {
|
|
|
|
aResult.AppendLiteral(",centerscreen=1");
|
|
|
|
}
|
|
|
|
} else if (name.LowerCaseEqualsLiteral("dialogwidth")) {
|
|
|
|
if (!value.IsEmpty()) {
|
|
|
|
aResult.AppendLiteral(",width=");
|
|
|
|
aResult.Append(value);
|
|
|
|
}
|
|
|
|
} else if (name.LowerCaseEqualsLiteral("dialogheight")) {
|
|
|
|
if (!value.IsEmpty()) {
|
|
|
|
aResult.AppendLiteral(",height=");
|
|
|
|
aResult.Append(value);
|
|
|
|
}
|
|
|
|
} else if (name.LowerCaseEqualsLiteral("dialogtop")) {
|
|
|
|
if (!value.IsEmpty()) {
|
|
|
|
aResult.AppendLiteral(",top=");
|
|
|
|
aResult.Append(value);
|
|
|
|
}
|
|
|
|
} else if (name.LowerCaseEqualsLiteral("dialogleft")) {
|
|
|
|
if (!value.IsEmpty()) {
|
|
|
|
aResult.AppendLiteral(",left=");
|
|
|
|
aResult.Append(value);
|
|
|
|
}
|
|
|
|
} else if (name.LowerCaseEqualsLiteral("resizable")) {
|
|
|
|
if (value.LowerCaseEqualsLiteral("on") ||
|
|
|
|
value.LowerCaseEqualsLiteral("yes") ||
|
|
|
|
value.LowerCaseEqualsLiteral("1")) {
|
|
|
|
aResult.AppendLiteral(",resizable=1");
|
|
|
|
}
|
|
|
|
} else if (name.LowerCaseEqualsLiteral("scroll")) {
|
|
|
|
if (value.LowerCaseEqualsLiteral("off") ||
|
|
|
|
value.LowerCaseEqualsLiteral("no") ||
|
|
|
|
value.LowerCaseEqualsLiteral("0")) {
|
|
|
|
aResult.AppendLiteral(",scrollbars=0");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iter == end ||
|
|
|
|
!TokenizeDialogOptions(token, iter, end) ||
|
|
|
|
!token.EqualsLiteral(";")) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:34:41 +03:00
|
|
|
nsGlobalWindowInner::UpdateCommands(const nsAString& anAction,
|
|
|
|
nsISelection* aSel,
|
|
|
|
int16_t aReason)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:47 +03:00
|
|
|
if (GetOuterWindowInternal()) {
|
|
|
|
return GetOuterWindowInternal()->UpdateCommands(anAction, aSel, aReason);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
Selection*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetSelection(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetSelectionOuter, (), aError, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Find(const nsAString& aString, bool aCaseSensitive,
|
2017-11-15 19:34:41 +03:00
|
|
|
bool aBackwards, bool aWrapAround, bool aWholeWord,
|
|
|
|
bool aSearchInFrames, bool aShowDialog,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(FindOuter,
|
|
|
|
(aString, aCaseSensitive, aBackwards, aWrapAround,
|
|
|
|
aWholeWord, aSearchInFrames, aShowDialog, aError),
|
|
|
|
aError, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetOrigin(nsAString& aOrigin)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsContentUtils::GetUTFOrigin(GetPrincipal(), aOrigin);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Atob(const nsAString& aAsciiBase64String,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsAString& aBinaryData, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
aError = nsContentUtils::Atob(aAsciiBase64String, aBinaryData);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Btoa(const nsAString& aBinaryData,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsAString& aAsciiBase64String, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
aError = nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
2017-11-15 19:33:39 +03:00
|
|
|
// nsGlobalWindowInner::nsIDOMEventTarget
|
2017-11-15 19:30:13 +03:00
|
|
|
//*****************************************************************************
|
|
|
|
|
|
|
|
nsPIDOMWindowOuter*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetOwnerGlobalForBindings()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:27 +03:00
|
|
|
return nsPIDOMWindowOuter::GetFromCurrentInner(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::RemoveEventListener(const nsAString& aType,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsIDOMEventListener* aListener,
|
|
|
|
bool aUseCapture)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (RefPtr<EventListenerManager> elm = GetExistingListenerManager()) {
|
|
|
|
elm->RemoveEventListener(aType, aListener, aUseCapture);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsGlobalWindowInner)
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DispatchEvent(nsIDOMEvent* aEvent, bool* aRetVal)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:27 +03:00
|
|
|
if (!IsCurrentInnerWindow()) {
|
2017-11-15 19:30:13 +03:00
|
|
|
NS_WARNING("DispatchEvent called on non-current inner window, dropping. "
|
|
|
|
"Please check the window in the caller instead.");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mDoc) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Obtain a presentation shell
|
|
|
|
nsIPresShell *shell = mDoc->GetShell();
|
|
|
|
RefPtr<nsPresContext> presContext;
|
|
|
|
if (shell) {
|
|
|
|
// Retrieve the context
|
|
|
|
presContext = shell->GetPresContext();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
2017-11-15 19:34:27 +03:00
|
|
|
nsresult rv = EventDispatcher::DispatchDOMEvent(ToSupports(this), nullptr,
|
|
|
|
aEvent, presContext, &status);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
*aRetVal = (status != nsEventStatus_eConsumeNoDefault);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::AddEventListener(const nsAString& aType,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsIDOMEventListener *aListener,
|
|
|
|
bool aUseCapture, bool aWantsUntrusted,
|
|
|
|
uint8_t aOptionalArgc)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
|
|
|
|
"Won't check if this is chrome, you want to set "
|
|
|
|
"aWantsUntrusted to false or make the aWantsUntrusted "
|
|
|
|
"explicit by making optional_argc non-zero.");
|
|
|
|
|
|
|
|
if (!aWantsUntrusted &&
|
|
|
|
(aOptionalArgc < 2 && !nsContentUtils::IsChromeDoc(mDoc))) {
|
|
|
|
aWantsUntrusted = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
EventListenerManager* manager = GetOrCreateListenerManager();
|
|
|
|
NS_ENSURE_STATE(manager);
|
|
|
|
manager->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::AddEventListener(const nsAString& aType,
|
2017-11-15 19:34:41 +03:00
|
|
|
EventListener* aListener,
|
|
|
|
const AddEventListenerOptionsOrBoolean& aOptions,
|
|
|
|
const Nullable<bool>& aWantsUntrusted,
|
|
|
|
ErrorResult& aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
bool wantsUntrusted;
|
|
|
|
if (aWantsUntrusted.IsNull()) {
|
|
|
|
wantsUntrusted = !nsContentUtils::IsChromeDoc(mDoc);
|
|
|
|
} else {
|
|
|
|
wantsUntrusted = aWantsUntrusted.Value();
|
|
|
|
}
|
|
|
|
|
|
|
|
EventListenerManager* manager = GetOrCreateListenerManager();
|
|
|
|
if (!manager) {
|
|
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
manager->AddEventListener(aType, aListener, aOptions, wantsUntrusted);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::AddSystemEventListener(const nsAString& aType,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsIDOMEventListener *aListener,
|
|
|
|
bool aUseCapture,
|
|
|
|
bool aWantsUntrusted,
|
|
|
|
uint8_t aOptionalArgc)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
|
|
|
|
"Won't check if this is chrome, you want to set "
|
|
|
|
"aWantsUntrusted to false or make the aWantsUntrusted "
|
|
|
|
"explicit by making optional_argc non-zero.");
|
|
|
|
|
|
|
|
if (!aWantsUntrusted &&
|
|
|
|
(aOptionalArgc < 2 && !nsContentUtils::IsChromeDoc(mDoc))) {
|
|
|
|
aWantsUntrusted = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_AddSystemEventListener(this, aType, aListener, aUseCapture,
|
|
|
|
aWantsUntrusted);
|
|
|
|
}
|
|
|
|
|
|
|
|
EventListenerManager*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetOrCreateListenerManager()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mListenerManager) {
|
|
|
|
mListenerManager =
|
|
|
|
new EventListenerManager(static_cast<EventTarget*>(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
return mListenerManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
EventListenerManager*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetExistingListenerManager() const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return mListenerManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIScriptContext*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetContextForEventHandlers(nsresult* aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
*aRv = NS_ERROR_UNEXPECTED;
|
2017-11-15 19:34:47 +03:00
|
|
|
FORWARD_TO_OUTER(GetContextForEventHandlers, (aRv), nullptr);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
//*****************************************************************************
|
|
|
|
// nsGlobalWindowInner::nsPIDOMWindow
|
|
|
|
//*****************************************************************************
|
2017-11-15 19:30:13 +03:00
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
nsPIDOMWindowOuter*
|
|
|
|
nsGlobalWindowInner::GetPrivateRoot()
|
|
|
|
{
|
|
|
|
nsGlobalWindowOuter* outer = GetOuterWindowInternal();
|
|
|
|
if (!outer) {
|
|
|
|
NS_WARNING("No outer window available!");
|
|
|
|
return nullptr;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
2017-11-15 19:34:13 +03:00
|
|
|
return outer->GetPrivateRoot();
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
Location*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetLocation()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mLocation) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mLocation = new dom::Location(this, GetDocShell());
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return mLocation;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IsTopLevelWindowActive()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:47 +03:00
|
|
|
if (GetOuterWindowInternal()) {
|
|
|
|
return GetOuterWindowInternal()->IsTopLevelWindowActive();
|
|
|
|
}
|
|
|
|
return false;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
Bug 1416384 - Part 2e: Eliminate duplicate declarations, and get gecko building again, r=smaug
There are many helper methods and structs in nsGlobalWindow.cpp. Many of these
are used by only the inner or only the outer window, while some are used by
both. In the case of the items used by both, I extracted them into
nsGlobalWindow.cpp, which includes nsGlobalWindowInner.cpp and
nsGlobalWindowOuter.cpp as the compilation unit entry point.
In the case of items used by just one or the other, I removed them from the
other file, and deleted the bodies of functions which used them, replacing them,
with a MOZ_CRASH.
This gets gecko building again, so that we can make further incremental
improvements.
MozReview-Commit-ID: 8QnJ1PX6TAO
--HG--
extra : rebase_source : 0eac00ad757f825a22a1af95d0a01d6fa92d824d
2017-11-15 19:33:58 +03:00
|
|
|
void
|
|
|
|
nsGlobalWindowInner::MaybeUpdateTouchState()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mMayHaveTouchEventListener) {
|
|
|
|
nsCOMPtr<nsIObserverService> observerService =
|
|
|
|
services::GetObserverService();
|
|
|
|
|
|
|
|
if (observerService) {
|
|
|
|
observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),
|
|
|
|
DOM_TOUCH_LISTENER_ADDED,
|
|
|
|
nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::EnableGamepadUpdates()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mHasGamepad) {
|
|
|
|
RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
|
|
|
|
if (gamepadManager) {
|
2017-11-15 19:34:27 +03:00
|
|
|
gamepadManager->AddListener(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DisableGamepadUpdates()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mHasGamepad) {
|
|
|
|
RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
|
|
|
|
if (gamepadManager) {
|
2017-11-15 19:34:27 +03:00
|
|
|
gamepadManager->RemoveListener(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::EnableVRUpdates()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mHasVREvents && !mVREventObserver) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mVREventObserver = new VREventObserver(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DisableVRUpdates()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mVREventObserver) {
|
|
|
|
mVREventObserver->DisconnectFromOwner();
|
|
|
|
mVREventObserver = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ResetVRTelemetry(bool aUpdate)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mVREventObserver) {
|
|
|
|
mVREventObserver->UpdateSpentTimeIn2DTelemetry(aUpdate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-18 00:20:16 +03:00
|
|
|
static bool ShouldShowFocusRingIfFocusedByMouse(nsIContent* aNode)
|
|
|
|
{
|
|
|
|
if (!aNode) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return !nsContentUtils::ContentIsLink(aNode) &&
|
|
|
|
!aNode->IsAnyOfHTMLElements(nsGkAtoms::video, nsGkAtoms::audio);
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:30:13 +03:00
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetFocusedNode(nsIContent* aNode,
|
2017-11-15 19:34:41 +03:00
|
|
|
uint32_t aFocusMethod,
|
|
|
|
bool aNeedsFocus)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (aNode && aNode->GetComposedDoc() != mDoc) {
|
|
|
|
NS_WARNING("Trying to set focus to a node from a wrong document");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mCleanedUp) {
|
|
|
|
NS_ASSERTION(!aNode, "Trying to focus cleaned up window!");
|
|
|
|
aNode = nullptr;
|
|
|
|
aNeedsFocus = false;
|
|
|
|
}
|
|
|
|
if (mFocusedNode != aNode) {
|
|
|
|
UpdateCanvasFocus(false, aNode);
|
|
|
|
mFocusedNode = aNode;
|
|
|
|
mFocusMethod = aFocusMethod & FOCUSMETHOD_MASK;
|
|
|
|
mShowFocusRingForContent = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mFocusedNode) {
|
|
|
|
// if a node was focused by a keypress, turn on focus rings for the
|
|
|
|
// window.
|
|
|
|
if (mFocusMethod & nsIFocusManager::FLAG_BYKEY) {
|
|
|
|
mFocusByKeyOccurred = true;
|
|
|
|
} else if (
|
|
|
|
// otherwise, we set mShowFocusRingForContent, as we don't want this to
|
|
|
|
// be permanent for the window. On Windows, focus rings are only shown
|
|
|
|
// when the FLAG_SHOWRING flag is used. On other platforms, focus rings
|
|
|
|
// are only visible on some elements.
|
|
|
|
#ifndef XP_WIN
|
|
|
|
!(mFocusMethod & nsIFocusManager::FLAG_BYMOUSE) ||
|
|
|
|
ShouldShowFocusRingIfFocusedByMouse(aNode) ||
|
|
|
|
#endif
|
|
|
|
aFocusMethod & nsIFocusManager::FLAG_SHOWRING) {
|
|
|
|
mShowFocusRingForContent = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aNeedsFocus)
|
|
|
|
mNeedsFocus = aNeedsFocus;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetFocusMethod()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return mFocusMethod;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ShouldShowFocusRing()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mShowFocusRingForContent || mFocusByKeyOccurred) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsPIWindowRoot> root = GetTopWindowRoot();
|
|
|
|
return root ? root->ShowFocusRings() : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::TakeFocus(bool aFocus, uint32_t aFocusMethod)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mCleanedUp) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aFocus)
|
|
|
|
mFocusMethod = aFocusMethod & FOCUSMETHOD_MASK;
|
|
|
|
|
|
|
|
if (mHasFocus != aFocus) {
|
|
|
|
mHasFocus = aFocus;
|
|
|
|
UpdateCanvasFocus(true, mFocusedNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
// if mNeedsFocus is true, then the document has not yet received a
|
|
|
|
// document-level focus event. If there is a root content node, then return
|
|
|
|
// true to tell the calling focus manager that a focus event is expected. If
|
|
|
|
// there is no root content node, the document hasn't loaded enough yet, or
|
|
|
|
// there isn't one and there is no point in firing a focus event.
|
|
|
|
if (aFocus && mNeedsFocus && mDoc && mDoc->GetRootElement() != nullptr) {
|
|
|
|
mNeedsFocus = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
mNeedsFocus = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetReadyForFocus()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
bool oldNeedsFocus = mNeedsFocus;
|
|
|
|
mNeedsFocus = false;
|
|
|
|
|
|
|
|
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
|
|
|
if (fm) {
|
|
|
|
fm->WindowShown(GetOuterWindow(), oldNeedsFocus);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::PageHidden()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// the window is being hidden, so tell the focus manager that the frame is
|
|
|
|
// no longer valid. Use the persisted field to determine if the document
|
|
|
|
// is being destroyed.
|
|
|
|
|
|
|
|
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
|
|
|
if (fm) {
|
|
|
|
fm->WindowHidden(GetOuterWindow());
|
|
|
|
}
|
|
|
|
|
|
|
|
mNeedsFocus = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
class HashchangeCallback : public Runnable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
HashchangeCallback(const nsAString& aOldURL,
|
|
|
|
const nsAString& aNewURL,
|
|
|
|
nsGlobalWindowInner* aWindow)
|
|
|
|
: mozilla::Runnable("HashchangeCallback")
|
|
|
|
, mWindow(aWindow)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mWindow);
|
|
|
|
mOldURL.Assign(aOldURL);
|
|
|
|
mNewURL.Assign(aNewURL);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD Run() override
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(NS_IsMainThread(), "Should be called on the main thread.");
|
|
|
|
return mWindow->FireHashchange(mOldURL, mNewURL);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsString mOldURL;
|
|
|
|
nsString mNewURL;
|
|
|
|
RefPtr<nsGlobalWindowInner> mWindow;
|
|
|
|
};
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DispatchAsyncHashchange(nsIURI *aOldURI, nsIURI *aNewURI)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Make sure that aOldURI and aNewURI are identical up to the '#', and that
|
|
|
|
// their hashes are different.
|
|
|
|
bool equal = false;
|
|
|
|
NS_ENSURE_STATE(NS_SUCCEEDED(aOldURI->EqualsExceptRef(aNewURI, &equal)) && equal);
|
|
|
|
nsAutoCString oldHash, newHash;
|
|
|
|
bool oldHasHash, newHasHash;
|
|
|
|
NS_ENSURE_STATE(NS_SUCCEEDED(aOldURI->GetRef(oldHash)) &&
|
|
|
|
NS_SUCCEEDED(aNewURI->GetRef(newHash)) &&
|
|
|
|
NS_SUCCEEDED(aOldURI->GetHasRef(&oldHasHash)) &&
|
|
|
|
NS_SUCCEEDED(aNewURI->GetHasRef(&newHasHash)) &&
|
|
|
|
(oldHasHash != newHasHash || !oldHash.Equals(newHash)));
|
|
|
|
|
|
|
|
nsAutoCString oldSpec, newSpec;
|
|
|
|
nsresult rv = aOldURI->GetSpec(oldSpec);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = aNewURI->GetSpec(newSpec);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
NS_ConvertUTF8toUTF16 oldWideSpec(oldSpec);
|
|
|
|
NS_ConvertUTF8toUTF16 newWideSpec(newSpec);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIRunnable> callback =
|
2017-11-15 19:34:27 +03:00
|
|
|
new HashchangeCallback(oldWideSpec, newWideSpec, this);
|
2017-11-15 19:30:13 +03:00
|
|
|
return Dispatch(TaskCategory::Other, callback.forget());
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::FireHashchange(const nsAString &aOldURL,
|
2017-11-15 19:34:41 +03:00
|
|
|
const nsAString &aNewURL)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Don't do anything if the window is frozen.
|
|
|
|
if (IsFrozen()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a presentation shell for use in creating the hashchange event.
|
2017-11-15 19:34:27 +03:00
|
|
|
NS_ENSURE_STATE(IsCurrentInnerWindow());
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
nsIPresShell *shell = mDoc->GetShell();
|
|
|
|
RefPtr<nsPresContext> presContext;
|
|
|
|
if (shell) {
|
|
|
|
presContext = shell->GetPresContext();
|
|
|
|
}
|
|
|
|
|
|
|
|
HashChangeEventInit init;
|
|
|
|
init.mBubbles = true;
|
|
|
|
init.mCancelable = false;
|
|
|
|
init.mNewURL = aNewURL;
|
|
|
|
init.mOldURL = aOldURL;
|
|
|
|
|
|
|
|
RefPtr<HashChangeEvent> event =
|
|
|
|
HashChangeEvent::Constructor(this, NS_LITERAL_STRING("hashchange"),
|
|
|
|
init);
|
|
|
|
|
|
|
|
event->SetTrusted(true);
|
|
|
|
|
|
|
|
bool dummy;
|
|
|
|
return DispatchEvent(event, &dummy);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DispatchSyncPopState()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
|
|
|
|
"Must be safe to run script here.");
|
|
|
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
// Bail if the window is frozen.
|
|
|
|
if (IsFrozen()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the document's pending state object -- it contains the data we're
|
|
|
|
// going to send along with the popstate event. The object is serialized
|
|
|
|
// using structured clone.
|
|
|
|
nsCOMPtr<nsIVariant> stateObj;
|
|
|
|
rv = mDoc->GetStateObject(getter_AddRefs(stateObj));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// Obtain a presentation shell for use in creating a popstate event.
|
|
|
|
nsIPresShell *shell = mDoc->GetShell();
|
|
|
|
RefPtr<nsPresContext> presContext;
|
|
|
|
if (shell) {
|
|
|
|
presContext = shell->GetPresContext();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool result = true;
|
|
|
|
AutoJSAPI jsapi;
|
2017-11-15 19:34:27 +03:00
|
|
|
result = jsapi.Init(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
JSContext* cx = jsapi.cx();
|
|
|
|
JS::Rooted<JS::Value> stateJSValue(cx, JS::NullValue());
|
|
|
|
result = stateObj ? VariantToJsval(cx, stateObj, &stateJSValue) : true;
|
|
|
|
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
RootedDictionary<PopStateEventInit> init(cx);
|
|
|
|
init.mBubbles = true;
|
|
|
|
init.mCancelable = false;
|
|
|
|
init.mState = stateJSValue;
|
|
|
|
|
|
|
|
RefPtr<PopStateEvent> event =
|
|
|
|
PopStateEvent::Constructor(this, NS_LITERAL_STRING("popstate"),
|
|
|
|
init);
|
|
|
|
event->SetTrusted(true);
|
|
|
|
event->SetTarget(this);
|
|
|
|
|
|
|
|
bool dummy; // default action
|
|
|
|
return DispatchEvent(event, &dummy);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find an nsICanvasFrame under aFrame. Only search the principal
|
|
|
|
// child lists. aFrame must be non-null.
|
2017-11-15 19:34:41 +03:00
|
|
|
static nsCanvasFrame*
|
|
|
|
FindCanvasFrame(nsIFrame* aFrame)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsCanvasFrame* canvasFrame = do_QueryFrame(aFrame);
|
|
|
|
if (canvasFrame) {
|
|
|
|
return canvasFrame;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (nsIFrame* kid : aFrame->PrincipalChildList()) {
|
|
|
|
canvasFrame = FindCanvasFrame(kid);
|
|
|
|
if (canvasFrame) {
|
|
|
|
return canvasFrame;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------
|
|
|
|
// Tells the HTMLFrame/CanvasFrame that is now has focus
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::UpdateCanvasFocus(bool aFocusChanged, nsIContent* aNewContent)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// this is called from the inner window so use GetDocShell
|
|
|
|
nsIDocShell* docShell = GetDocShell();
|
|
|
|
if (!docShell)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool editable;
|
|
|
|
docShell->GetEditable(&editable);
|
|
|
|
if (editable)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
|
|
|
|
if (!presShell || !mDoc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Element *rootElement = mDoc->GetRootElement();
|
|
|
|
if (rootElement) {
|
|
|
|
if ((mHasFocus || aFocusChanged) &&
|
|
|
|
(mFocusedNode == rootElement || aNewContent == rootElement)) {
|
|
|
|
nsIFrame* frame = rootElement->GetPrimaryFrame();
|
|
|
|
if (frame) {
|
|
|
|
frame = frame->GetParent();
|
|
|
|
nsCanvasFrame* canvasFrame = do_QueryFrame(frame);
|
|
|
|
if (canvasFrame) {
|
|
|
|
canvasFrame->SetHasFocus(mHasFocus && rootElement == aNewContent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Look for the frame the hard way
|
|
|
|
nsIFrame* frame = presShell->GetRootFrame();
|
|
|
|
if (frame) {
|
|
|
|
nsCanvasFrame* canvasFrame = FindCanvasFrame(frame);
|
|
|
|
if (canvasFrame) {
|
|
|
|
canvasFrame->SetHasFocus(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsICSSDeclaration>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetComputedStyle(Element& aElt, const nsAString& aPseudoElt,
|
2017-11-15 19:34:41 +03:00
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return GetComputedStyleHelper(aElt, aPseudoElt, false, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsICSSDeclaration>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetDefaultComputedStyle(Element& aElt,
|
2017-11-15 19:34:41 +03:00
|
|
|
const nsAString& aPseudoElt,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return GetComputedStyleHelper(aElt, aPseudoElt, true, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetComputedStyleHelper(nsIDOMElement* aElt,
|
2017-11-15 19:34:41 +03:00
|
|
|
const nsAString& aPseudoElt,
|
|
|
|
bool aDefaultStylesOnly,
|
|
|
|
nsIDOMCSSStyleDeclaration** aReturn)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aReturn);
|
|
|
|
*aReturn = nullptr;
|
|
|
|
|
|
|
|
nsCOMPtr<dom::Element> element = do_QueryInterface(aElt);
|
|
|
|
if (!element) {
|
|
|
|
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
ErrorResult rv;
|
|
|
|
nsCOMPtr<nsIDOMCSSStyleDeclaration> declaration =
|
|
|
|
GetComputedStyleHelper(*element, aPseudoElt, aDefaultStylesOnly, rv);
|
|
|
|
declaration.forget(aReturn);
|
|
|
|
|
|
|
|
return rv.StealNSResult();
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsICSSDeclaration>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetComputedStyleHelper(Element& aElt,
|
2017-11-15 19:34:41 +03:00
|
|
|
const nsAString& aPseudoElt,
|
|
|
|
bool aDefaultStylesOnly,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetComputedStyleHelperOuter,
|
|
|
|
(aElt, aPseudoElt, aDefaultStylesOnly),
|
|
|
|
aError, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
Storage*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetSessionStorage(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsIPrincipal *principal = GetPrincipal();
|
|
|
|
nsIDocShell* docShell = GetDocShell();
|
|
|
|
|
2017-11-22 00:25:33 +03:00
|
|
|
if (!principal || !docShell || !Storage::StoragePrefIsEnabled()) {
|
2017-11-15 19:30:13 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mSessionStorage) {
|
2017-11-18 01:49:56 +03:00
|
|
|
MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
|
2017-11-15 19:33:39 +03:00
|
|
|
("nsGlobalWindowInner %p has %p sessionStorage", this, mSessionStorage.get()));
|
2017-11-15 19:30:13 +03:00
|
|
|
bool canAccess = principal->Subsumes(mSessionStorage->Principal());
|
|
|
|
NS_ASSERTION(canAccess,
|
|
|
|
"This window owned sessionStorage "
|
|
|
|
"that could not be accessed!");
|
|
|
|
if (!canAccess) {
|
|
|
|
mSessionStorage = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mSessionStorage) {
|
|
|
|
nsString documentURI;
|
|
|
|
if (mDoc) {
|
|
|
|
aError = mDoc->GetDocumentURI(documentURI);
|
|
|
|
if (NS_WARN_IF(aError.Failed())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the document has the sandboxed origin flag set
|
|
|
|
// don't allow access to sessionStorage.
|
|
|
|
if (!mDoc) {
|
|
|
|
aError.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN) {
|
|
|
|
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMStorageManager> storageManager = do_QueryInterface(docShell, &rv);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aError.Throw(rv);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMStorage> storage;
|
2017-11-15 19:34:27 +03:00
|
|
|
aError = storageManager->CreateStorage(this, principal, documentURI,
|
2017-11-15 19:30:13 +03:00
|
|
|
IsPrivateBrowsing(),
|
|
|
|
getter_AddRefs(storage));
|
|
|
|
if (aError.Failed()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
mSessionStorage = static_cast<Storage*>(storage.get());
|
|
|
|
MOZ_ASSERT(mSessionStorage);
|
|
|
|
|
2017-11-18 01:49:56 +03:00
|
|
|
MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
|
2017-11-15 19:33:39 +03:00
|
|
|
("nsGlobalWindowInner %p tried to get a new sessionStorage %p", this, mSessionStorage.get()));
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
if (!mSessionStorage) {
|
|
|
|
aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-18 01:49:56 +03:00
|
|
|
MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
|
2017-11-15 19:33:39 +03:00
|
|
|
("nsGlobalWindowInner %p returns %p sessionStorage", this, mSessionStorage.get()));
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
return mSessionStorage;
|
|
|
|
}
|
|
|
|
|
|
|
|
Storage*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetLocalStorage(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-22 00:25:33 +03:00
|
|
|
if (!Storage::StoragePrefIsEnabled()) {
|
2017-11-15 19:30:13 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mLocalStorage) {
|
2017-11-15 19:34:27 +03:00
|
|
|
if (nsContentUtils::StorageAllowedForWindow(this) ==
|
2017-11-15 19:30:13 +03:00
|
|
|
nsContentUtils::StorageAccess::eDeny) {
|
|
|
|
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIPrincipal *principal = GetPrincipal();
|
|
|
|
if (!principal) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIDOMStorageManager> storageManager =
|
|
|
|
do_GetService("@mozilla.org/dom/localStorage-manager;1", &rv);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aError.Throw(rv);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsString documentURI;
|
|
|
|
if (mDoc) {
|
|
|
|
aError = mDoc->GetDocumentURI(documentURI);
|
|
|
|
if (NS_WARN_IF(aError.Failed())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMStorage> storage;
|
2017-11-15 19:34:27 +03:00
|
|
|
aError = storageManager->CreateStorage(this, principal, documentURI,
|
2017-11-15 19:30:13 +03:00
|
|
|
IsPrivateBrowsing(),
|
|
|
|
getter_AddRefs(storage));
|
|
|
|
if (aError.Failed()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
mLocalStorage = static_cast<Storage*>(storage.get());
|
|
|
|
MOZ_ASSERT(mLocalStorage);
|
|
|
|
}
|
|
|
|
|
|
|
|
return mLocalStorage;
|
|
|
|
}
|
|
|
|
|
|
|
|
IDBFactory*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetIndexedDB(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mIndexedDB) {
|
|
|
|
// This may keep mIndexedDB null without setting an error.
|
2017-11-15 19:34:27 +03:00
|
|
|
aError = IDBFactory::CreateForWindow(this,
|
2017-11-15 19:30:13 +03:00
|
|
|
getter_AddRefs(mIndexedDB));
|
|
|
|
}
|
|
|
|
|
|
|
|
return mIndexedDB;
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
2017-11-15 19:33:39 +03:00
|
|
|
// nsGlobalWindowInner::nsIInterfaceRequestor
|
2017-11-15 19:30:13 +03:00
|
|
|
//*****************************************************************************
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetInterface(const nsIID & aIID, void **aSink)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:47 +03:00
|
|
|
nsGlobalWindowOuter* outer = GetOuterWindowInternal();
|
|
|
|
NS_ENSURE_TRUE(outer, NS_ERROR_NOT_INITIALIZED);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
2017-11-15 19:34:47 +03:00
|
|
|
nsresult rv = outer->GetInterfaceInternal(aIID, aSink);
|
|
|
|
if (rv == NS_ERROR_NO_INTERFACE) {
|
2017-11-15 19:30:13 +03:00
|
|
|
return QueryInterface(aIID, aSink);
|
|
|
|
}
|
2017-11-15 19:34:47 +03:00
|
|
|
return rv;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetInterface(JSContext* aCx, nsIJSID* aIID,
|
2017-11-15 19:34:41 +03:00
|
|
|
JS::MutableHandle<JS::Value> aRetval,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
dom::GetInterface(aCx, this, aIID, aRetval, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<CacheStorage>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetCaches(ErrorResult& aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mCacheStorage) {
|
|
|
|
bool forceTrustedOrigin =
|
|
|
|
GetOuterWindow()->GetServiceWorkersTestingEnabled();
|
|
|
|
|
|
|
|
nsContentUtils::StorageAccess access =
|
2017-11-15 19:34:27 +03:00
|
|
|
nsContentUtils::StorageAllowedForWindow(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
// We don't block the cache API when being told to only allow storage for the
|
|
|
|
// current session.
|
|
|
|
bool storageBlocked = access <= nsContentUtils::StorageAccess::ePrivateBrowsing;
|
|
|
|
|
|
|
|
mCacheStorage = CacheStorage::CreateOnMainThread(cache::DEFAULT_NAMESPACE,
|
|
|
|
this, GetPrincipal(),
|
|
|
|
storageBlocked,
|
|
|
|
forceTrustedOrigin, aRv);
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<CacheStorage> ref = mCacheStorage;
|
|
|
|
return ref.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<ServiceWorkerRegistration>
|
|
|
|
nsPIDOMWindowInner::GetServiceWorkerRegistration(const nsAString& aScope)
|
|
|
|
{
|
|
|
|
RefPtr<ServiceWorkerRegistration> registration;
|
|
|
|
if (!mServiceWorkerRegistrationTable.Get(aScope,
|
|
|
|
getter_AddRefs(registration))) {
|
|
|
|
registration =
|
|
|
|
ServiceWorkerRegistration::CreateForMainThread(this, aScope);
|
|
|
|
mServiceWorkerRegistrationTable.Put(aScope, registration);
|
|
|
|
}
|
|
|
|
return registration.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPIDOMWindowInner::InvalidateServiceWorkerRegistration(const nsAString& aScope)
|
|
|
|
{
|
|
|
|
mServiceWorkerRegistrationTable.Remove(aScope);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::FireOfflineStatusEventIfChanged()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:27 +03:00
|
|
|
if (!IsCurrentInnerWindow())
|
2017-11-15 19:30:13 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Don't fire an event if the status hasn't changed
|
|
|
|
if (mWasOffline == NS_IsOffline()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mWasOffline = !mWasOffline;
|
|
|
|
|
|
|
|
nsAutoString name;
|
|
|
|
if (mWasOffline) {
|
|
|
|
name.AssignLiteral("offline");
|
|
|
|
} else {
|
|
|
|
name.AssignLiteral("online");
|
|
|
|
}
|
|
|
|
// The event is fired at the body element, or if there is no body element,
|
|
|
|
// at the document.
|
|
|
|
nsCOMPtr<EventTarget> eventTarget = mDoc.get();
|
|
|
|
nsHTMLDocument* htmlDoc = mDoc->AsHTMLDocument();
|
|
|
|
if (htmlDoc) {
|
|
|
|
Element* body = htmlDoc->GetBody();
|
|
|
|
if (body) {
|
|
|
|
eventTarget = body;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Element* documentElement = mDoc->GetDocumentElement();
|
|
|
|
if (documentElement) {
|
|
|
|
eventTarget = documentElement;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nsContentUtils::DispatchTrustedEvent(mDoc, eventTarget, name, true, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
class NotifyIdleObserverRunnable : public Runnable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
NotifyIdleObserverRunnable(nsIIdleObserver* aIdleObserver,
|
|
|
|
uint32_t aTimeInS,
|
|
|
|
bool aCallOnidle,
|
|
|
|
nsGlobalWindowInner* aIdleWindow)
|
|
|
|
: mozilla::Runnable("NotifyIdleObserverRunnable")
|
|
|
|
, mIdleObserver(aIdleObserver)
|
|
|
|
, mTimeInS(aTimeInS)
|
|
|
|
, mIdleWindow(aIdleWindow)
|
|
|
|
, mCallOnidle(aCallOnidle)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
NS_IMETHOD Run() override
|
|
|
|
{
|
|
|
|
if (mIdleWindow->ContainsIdleObserver(mIdleObserver, mTimeInS)) {
|
|
|
|
return mCallOnidle ? mIdleObserver->Onidle() : mIdleObserver->Onactive();
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsCOMPtr<nsIIdleObserver> mIdleObserver;
|
|
|
|
uint32_t mTimeInS;
|
|
|
|
RefPtr<nsGlobalWindowInner> mIdleWindow;
|
|
|
|
|
|
|
|
// If false then call on active
|
|
|
|
bool mCallOnidle;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::NotifyIdleObserver(IdleObserverHolder* aIdleObserverHolder,
|
2017-11-15 19:34:41 +03:00
|
|
|
bool aCallOnidle)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(aIdleObserverHolder);
|
|
|
|
aIdleObserverHolder->mPrevNotificationIdle = aCallOnidle;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIRunnable> caller =
|
|
|
|
new NotifyIdleObserverRunnable(aIdleObserverHolder->mIdleObserver,
|
|
|
|
aIdleObserverHolder->mTimeInS,
|
2017-11-15 19:34:27 +03:00
|
|
|
aCallOnidle, this);
|
2017-11-15 19:30:13 +03:00
|
|
|
if (NS_FAILED(Dispatch(TaskCategory::Other, caller.forget()))) {
|
|
|
|
NS_WARNING("Failed to dispatch thread for idle observer notification.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ContainsIdleObserver(nsIIdleObserver* aIdleObserver, uint32_t aTimeInS)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(aIdleObserver, "Idle observer not instantiated.");
|
|
|
|
bool found = false;
|
|
|
|
nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
|
|
|
|
while (iter.HasMore()) {
|
|
|
|
IdleObserverHolder& idleObserver = iter.GetNext();
|
|
|
|
if (idleObserver.mIdleObserver == aIdleObserver &&
|
|
|
|
idleObserver.mTimeInS == aTimeInS) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
IdleActiveTimerCallback(nsITimer* aTimer, void* aClosure)
|
|
|
|
{
|
|
|
|
RefPtr<nsGlobalWindowInner> idleWindow =
|
|
|
|
static_cast<nsGlobalWindowInner*>(aClosure);
|
|
|
|
MOZ_ASSERT(idleWindow, "Idle window has not been instantiated.");
|
|
|
|
idleWindow->HandleIdleActiveEvent();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
IdleObserverTimerCallback(nsITimer* aTimer, void* aClosure)
|
|
|
|
{
|
|
|
|
RefPtr<nsGlobalWindowInner> idleWindow =
|
|
|
|
static_cast<nsGlobalWindowInner*>(aClosure);
|
|
|
|
MOZ_ASSERT(idleWindow, "Idle window has not been instantiated.");
|
|
|
|
idleWindow->HandleIdleObserverCallback();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::HandleIdleObserverCallback()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(static_cast<uint32_t>(mIdleCallbackIndex) < mIdleObservers.Length(),
|
|
|
|
"Idle callback index exceeds array bounds!");
|
|
|
|
IdleObserverHolder& idleObserver = mIdleObservers.ElementAt(mIdleCallbackIndex);
|
|
|
|
NotifyIdleObserver(&idleObserver, true);
|
|
|
|
mIdleCallbackIndex++;
|
|
|
|
if (NS_FAILED(ScheduleNextIdleObserverCallback())) {
|
|
|
|
NS_WARNING("Failed to set next idle observer callback.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ScheduleNextIdleObserverCallback()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mIdleService, "No idle service!");
|
|
|
|
|
|
|
|
if (mIdleCallbackIndex < 0 ||
|
|
|
|
static_cast<uint32_t>(mIdleCallbackIndex) >= mIdleObservers.Length()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
IdleObserverHolder& idleObserver =
|
|
|
|
mIdleObservers.ElementAt(mIdleCallbackIndex);
|
|
|
|
|
|
|
|
uint32_t userIdleTimeMS = 0;
|
|
|
|
nsresult rv = mIdleService->GetIdleTime(&userIdleTimeMS);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
uint32_t callbackTimeMS = 0;
|
|
|
|
if (idleObserver.mTimeInS * 1000 + mIdleFuzzFactor > userIdleTimeMS) {
|
|
|
|
callbackTimeMS = idleObserver.mTimeInS * 1000 - userIdleTimeMS + mIdleFuzzFactor;
|
|
|
|
}
|
|
|
|
|
|
|
|
mIdleTimer->Cancel();
|
|
|
|
rv = mIdleTimer->InitWithNamedFuncCallback(
|
|
|
|
IdleObserverTimerCallback,
|
2017-11-15 19:34:27 +03:00
|
|
|
this,
|
2017-11-15 19:30:13 +03:00
|
|
|
callbackTimeMS,
|
|
|
|
nsITimer::TYPE_ONE_SHOT,
|
2017-11-15 19:33:39 +03:00
|
|
|
"nsGlobalWindowInner::ScheduleNextIdleObserverCallback");
|
2017-11-15 19:30:13 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetFuzzTimeMS()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (gIdleObserversAPIFuzzTimeDisabled) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t randNum = MAX_IDLE_FUZZ_TIME_MS;
|
|
|
|
size_t nbytes = PR_GetRandomNoise(&randNum, sizeof(randNum));
|
|
|
|
if (nbytes != sizeof(randNum)) {
|
|
|
|
NS_WARNING("PR_GetRandomNoise(...) Not implemented or no available noise!");
|
|
|
|
return MAX_IDLE_FUZZ_TIME_MS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (randNum > MAX_IDLE_FUZZ_TIME_MS) {
|
|
|
|
randNum %= MAX_IDLE_FUZZ_TIME_MS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return randNum;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ScheduleActiveTimerCallback()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mAddActiveEventFuzzTime) {
|
|
|
|
return HandleIdleActiveEvent();
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(mIdleTimer);
|
|
|
|
mIdleTimer->Cancel();
|
|
|
|
|
|
|
|
uint32_t fuzzFactorInMS = GetFuzzTimeMS();
|
|
|
|
nsresult rv = mIdleTimer->InitWithNamedFuncCallback(
|
|
|
|
IdleActiveTimerCallback,
|
2017-11-15 19:34:27 +03:00
|
|
|
this,
|
2017-11-15 19:30:13 +03:00
|
|
|
fuzzFactorInMS,
|
|
|
|
nsITimer::TYPE_ONE_SHOT,
|
2017-11-15 19:33:39 +03:00
|
|
|
"nsGlobalWindowInner::ScheduleActiveTimerCallback");
|
2017-11-15 19:30:13 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::HandleIdleActiveEvent()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mCurrentlyIdle) {
|
|
|
|
mIdleCallbackIndex = 0;
|
|
|
|
mIdleFuzzFactor = GetFuzzTimeMS();
|
|
|
|
nsresult rv = ScheduleNextIdleObserverCallback();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
mIdleCallbackIndex = -1;
|
|
|
|
MOZ_ASSERT(mIdleTimer);
|
|
|
|
mIdleTimer->Cancel();
|
|
|
|
nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
|
|
|
|
while (iter.HasMore()) {
|
|
|
|
IdleObserverHolder& idleObserver = iter.GetNext();
|
|
|
|
if (idleObserver.mPrevNotificationIdle) {
|
|
|
|
NotifyIdleObserver(&idleObserver, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SlowScriptResponse
|
|
|
|
nsGlobalWindowInner::ShowSlowScriptDialog(const nsString& aAddonId)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
AutoJSContext cx;
|
|
|
|
|
|
|
|
if (Preferences::GetBool("dom.always_stop_slow_scripts")) {
|
|
|
|
return KillSlowScript;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If it isn't safe to run script, then it isn't safe to bring up the prompt
|
|
|
|
// (since that spins the event loop). In that (rare) case, we just kill the
|
|
|
|
// script and report a warning.
|
|
|
|
if (!nsContentUtils::IsSafeToRunScript()) {
|
|
|
|
JS_ReportWarningASCII(cx, "A long running script was terminated");
|
|
|
|
return KillSlowScript;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If our document is not active, just kill the script: we've been unloaded
|
2017-11-15 19:34:27 +03:00
|
|
|
if (!HasActiveDocument()) {
|
2017-11-15 19:30:13 +03:00
|
|
|
return KillSlowScript;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if we should offer the option to debug
|
|
|
|
JS::AutoFilename filename;
|
|
|
|
unsigned lineno;
|
|
|
|
// Computing the line number can be very expensive (see bug 1330231 for
|
|
|
|
// example), and we don't use the line number anywhere except than in the
|
|
|
|
// parent process, so we avoid computing it elsewhere. This gives us most of
|
|
|
|
// the wins we are interested in, since the source of the slowness here is
|
|
|
|
// minified scripts which is more common in Web content that is loaded in the
|
|
|
|
// content process.
|
|
|
|
unsigned* linenop = XRE_IsParentProcess() ? &lineno : nullptr;
|
|
|
|
bool hasFrame = JS::DescribeScriptedCaller(cx, &filename, linenop);
|
|
|
|
|
|
|
|
// Record the slow script event if we haven't done so already for this inner window
|
|
|
|
// (which represents a particular page to the user).
|
|
|
|
if (!mHasHadSlowScript) {
|
|
|
|
Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_PAGE_COUNT, 1);
|
|
|
|
}
|
|
|
|
mHasHadSlowScript = true;
|
|
|
|
|
|
|
|
if (XRE_IsContentProcess() &&
|
|
|
|
ProcessHangMonitor::Get()) {
|
|
|
|
ProcessHangMonitor::SlowScriptAction action;
|
|
|
|
RefPtr<ProcessHangMonitor> monitor = ProcessHangMonitor::Get();
|
|
|
|
nsIDocShell* docShell = GetDocShell();
|
|
|
|
nsCOMPtr<nsITabChild> child = docShell ? docShell->GetTabChild() : nullptr;
|
|
|
|
action = monitor->NotifySlowScript(child,
|
|
|
|
filename.get(),
|
|
|
|
aAddonId);
|
|
|
|
if (action == ProcessHangMonitor::Terminate) {
|
|
|
|
return KillSlowScript;
|
|
|
|
}
|
|
|
|
if (action == ProcessHangMonitor::TerminateGlobal) {
|
|
|
|
return KillScriptGlobal;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action == ProcessHangMonitor::StartDebugger) {
|
|
|
|
// Spin a nested event loop so that the debugger in the parent can fetch
|
|
|
|
// any information it needs. Once the debugger has started, return to the
|
|
|
|
// script.
|
|
|
|
RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowInternal();
|
|
|
|
outer->EnterModalState();
|
|
|
|
SpinEventLoopUntil([&]() { return monitor->IsDebuggerStartupComplete(); });
|
|
|
|
outer->LeaveModalState();
|
|
|
|
return ContinueSlowScript;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ContinueSlowScriptAndKeepNotifying;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reached only on non-e10s - once per slow script dialog.
|
|
|
|
// On e10s - we probe once at ProcessHangsMonitor.jsm
|
|
|
|
Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_NOTICE_COUNT, 1);
|
|
|
|
|
|
|
|
// Get the nsIPrompt interface from the docshell
|
|
|
|
nsCOMPtr<nsIDocShell> ds = GetDocShell();
|
|
|
|
NS_ENSURE_TRUE(ds, KillSlowScript);
|
|
|
|
nsCOMPtr<nsIPrompt> prompt = do_GetInterface(ds);
|
|
|
|
NS_ENSURE_TRUE(prompt, KillSlowScript);
|
|
|
|
|
|
|
|
// Prioritize the SlowScriptDebug interface over JSD1.
|
|
|
|
nsCOMPtr<nsISlowScriptDebugCallback> debugCallback;
|
|
|
|
|
|
|
|
if (hasFrame) {
|
|
|
|
const char *debugCID = "@mozilla.org/dom/slow-script-debug;1";
|
|
|
|
nsCOMPtr<nsISlowScriptDebug> debugService = do_GetService(debugCID, &rv);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
debugService->GetActivationHandler(getter_AddRefs(debugCallback));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool failed = false;
|
|
|
|
auto getString = [&] (const char* name,
|
|
|
|
nsContentUtils::PropertiesFile propFile = nsContentUtils::eDOM_PROPERTIES) {
|
|
|
|
nsAutoString result;
|
|
|
|
nsresult rv = nsContentUtils::GetLocalizedString(
|
|
|
|
propFile, name, result);
|
|
|
|
|
|
|
|
// GetStringFromName can return NS_OK and still give nullptr string
|
|
|
|
failed = failed || NS_FAILED(rv) || result.IsEmpty();
|
|
|
|
return Move(result);
|
|
|
|
};
|
|
|
|
|
|
|
|
bool isAddonScript = !aAddonId.IsEmpty();
|
|
|
|
bool showDebugButton = debugCallback && !isAddonScript;
|
|
|
|
|
|
|
|
// Get localizable strings
|
|
|
|
|
|
|
|
nsAutoString title, checkboxMsg, debugButton, msg;
|
|
|
|
if (isAddonScript) {
|
|
|
|
title = getString("KillAddonScriptTitle");
|
|
|
|
checkboxMsg = getString("KillAddonScriptGlobalMessage");
|
|
|
|
|
|
|
|
auto appName = getString("brandShortName", nsContentUtils::eBRAND_PROPERTIES);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAddonPolicyService> aps = do_GetService("@mozilla.org/addons/policy-service;1");
|
|
|
|
nsString addonName;
|
|
|
|
if (!aps || NS_FAILED(aps->GetExtensionName(aAddonId, addonName))) {
|
|
|
|
addonName = aAddonId;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char16_t* params[] = {addonName.get(), appName.get()};
|
|
|
|
rv = nsContentUtils::FormatLocalizedString(
|
|
|
|
nsContentUtils::eDOM_PROPERTIES, "KillAddonScriptMessage",
|
|
|
|
params, msg);
|
|
|
|
|
|
|
|
failed = failed || NS_FAILED(rv);
|
|
|
|
} else {
|
|
|
|
title = getString("KillScriptTitle");
|
|
|
|
checkboxMsg = getString("DontAskAgain");
|
|
|
|
|
|
|
|
if (showDebugButton) {
|
|
|
|
debugButton = getString("DebugScriptButton");
|
|
|
|
msg = getString("KillScriptWithDebugMessage");
|
|
|
|
} else {
|
|
|
|
msg = getString("KillScriptMessage");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
auto stopButton = getString("StopScriptButton");
|
|
|
|
auto waitButton = getString("WaitForScriptButton");
|
|
|
|
|
|
|
|
if (failed) {
|
|
|
|
NS_ERROR("Failed to get localized strings.");
|
|
|
|
return ContinueSlowScript;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Append file and line number information, if available
|
|
|
|
if (filename.get()) {
|
|
|
|
nsAutoString scriptLocation;
|
|
|
|
// We want to drop the middle part of too-long locations. We'll
|
|
|
|
// define "too-long" as longer than 60 UTF-16 code units. Just
|
|
|
|
// have to be a bit careful about unpaired surrogates.
|
|
|
|
NS_ConvertUTF8toUTF16 filenameUTF16(filename.get());
|
|
|
|
if (filenameUTF16.Length() > 60) {
|
|
|
|
// XXXbz Do we need to insert any bidi overrides here?
|
|
|
|
size_t cutStart = 30;
|
|
|
|
size_t cutLength = filenameUTF16.Length() - 60;
|
|
|
|
MOZ_ASSERT(cutLength > 0);
|
|
|
|
if (NS_IS_LOW_SURROGATE(filenameUTF16[cutStart])) {
|
|
|
|
// Don't truncate before the low surrogate, in case it's preceded by a
|
|
|
|
// high surrogate and forms a single Unicode character. Instead, just
|
|
|
|
// include the low surrogate.
|
|
|
|
++cutStart;
|
|
|
|
--cutLength;
|
|
|
|
}
|
|
|
|
if (NS_IS_LOW_SURROGATE(filenameUTF16[cutStart + cutLength])) {
|
|
|
|
// Likewise, don't drop a trailing low surrogate here. We want to
|
|
|
|
// increase cutLength, since it might be 0 already so we can't very well
|
|
|
|
// decrease it.
|
|
|
|
++cutLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert U+2026 HORIZONTAL ELLIPSIS
|
|
|
|
filenameUTF16.ReplaceLiteral(cutStart, cutLength, u"\x2026");
|
|
|
|
}
|
|
|
|
const char16_t *formatParams[] = { filenameUTF16.get() };
|
|
|
|
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
|
|
|
"KillScriptLocation",
|
|
|
|
formatParams,
|
|
|
|
scriptLocation);
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
msg.AppendLiteral("\n\n");
|
|
|
|
msg.Append(scriptLocation);
|
|
|
|
msg.Append(':');
|
|
|
|
msg.AppendInt(lineno);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t buttonFlags = nsIPrompt::BUTTON_POS_1_DEFAULT +
|
|
|
|
(nsIPrompt::BUTTON_TITLE_IS_STRING *
|
|
|
|
(nsIPrompt::BUTTON_POS_0 + nsIPrompt::BUTTON_POS_1));
|
|
|
|
|
|
|
|
// Add a third button if necessary.
|
|
|
|
if (showDebugButton)
|
|
|
|
buttonFlags += nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_2;
|
|
|
|
|
|
|
|
bool checkboxValue = false;
|
|
|
|
int32_t buttonPressed = 0; // In case the user exits dialog by clicking X.
|
|
|
|
{
|
|
|
|
// Null out the operation callback while we're re-entering JS here.
|
|
|
|
AutoDisableJSInterruptCallback disabler(cx);
|
|
|
|
|
|
|
|
// Open the dialog.
|
|
|
|
rv = prompt->ConfirmEx(title.get(), msg.get(), buttonFlags,
|
|
|
|
waitButton.get(), stopButton.get(),
|
|
|
|
debugButton.get(), checkboxMsg.get(),
|
|
|
|
&checkboxValue, &buttonPressed);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buttonPressed == 0) {
|
|
|
|
if (checkboxValue && !isAddonScript && NS_SUCCEEDED(rv))
|
|
|
|
return AlwaysContinueSlowScript;
|
|
|
|
return ContinueSlowScript;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buttonPressed == 2) {
|
|
|
|
MOZ_RELEASE_ASSERT(debugCallback);
|
|
|
|
|
|
|
|
rv = debugCallback->HandleSlowScriptDebug(this);
|
|
|
|
return NS_SUCCEEDED(rv) ? ContinueSlowScript : KillSlowScript;
|
|
|
|
}
|
|
|
|
|
|
|
|
JS_ClearPendingException(cx);
|
|
|
|
|
|
|
|
if (checkboxValue && isAddonScript)
|
|
|
|
return KillScriptGlobal;
|
|
|
|
return KillSlowScript;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::FindInsertionIndex(IdleObserverHolder* aIdleObserver)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(aIdleObserver, "Idle observer not instantiated.");
|
|
|
|
|
|
|
|
uint32_t i = 0;
|
|
|
|
nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
|
|
|
|
while (iter.HasMore()) {
|
|
|
|
IdleObserverHolder& idleObserver = iter.GetNext();
|
|
|
|
if (idleObserver.mTimeInS > aIdleObserver->mTimeInS) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
MOZ_ASSERT(i <= mIdleObservers.Length(), "Array index out of bounds error.");
|
|
|
|
}
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::RegisterIdleObserver(nsIIdleObserver* aIdleObserver)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
if (mIdleObservers.IsEmpty()) {
|
|
|
|
mIdleService = do_GetService("@mozilla.org/widget/idleservice;1", &rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
rv = mIdleService->AddIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (!mIdleTimer) {
|
|
|
|
mIdleTimer = NS_NewTimer();
|
|
|
|
NS_ENSURE_TRUE(mIdleTimer, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
} else {
|
|
|
|
mIdleTimer->Cancel();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(mIdleService);
|
|
|
|
MOZ_ASSERT(mIdleTimer);
|
|
|
|
|
|
|
|
IdleObserverHolder tmpIdleObserver;
|
|
|
|
tmpIdleObserver.mIdleObserver = aIdleObserver;
|
|
|
|
rv = aIdleObserver->GetTime(&tmpIdleObserver.mTimeInS);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
NS_ENSURE_ARG_MAX(tmpIdleObserver.mTimeInS, UINT32_MAX / 1000);
|
|
|
|
NS_ENSURE_ARG_MIN(tmpIdleObserver.mTimeInS, MIN_IDLE_NOTIFICATION_TIME_S);
|
|
|
|
|
|
|
|
uint32_t insertAtIndex = FindInsertionIndex(&tmpIdleObserver);
|
|
|
|
if (insertAtIndex == mIdleObservers.Length()) {
|
|
|
|
mIdleObservers.AppendElement(tmpIdleObserver);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mIdleObservers.InsertElementAt(insertAtIndex, tmpIdleObserver);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool userIsIdle = false;
|
|
|
|
rv = nsContentUtils::IsUserIdle(MIN_IDLE_NOTIFICATION_TIME_S, &userIsIdle);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// Special case. First idle observer added to empty list while the user is idle.
|
|
|
|
// Haven't received 'idle' topic notification from slow idle service yet.
|
|
|
|
// Need to wait for the idle notification and then notify idle observers in the list.
|
|
|
|
if (userIsIdle && mIdleCallbackIndex == -1) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mCurrentlyIdle) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(mIdleCallbackIndex >= 0);
|
|
|
|
|
|
|
|
if (static_cast<int32_t>(insertAtIndex) < mIdleCallbackIndex) {
|
|
|
|
IdleObserverHolder& idleObserver = mIdleObservers.ElementAt(insertAtIndex);
|
|
|
|
NotifyIdleObserver(&idleObserver, true);
|
|
|
|
mIdleCallbackIndex++;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (static_cast<int32_t>(insertAtIndex) == mIdleCallbackIndex) {
|
|
|
|
mIdleTimer->Cancel();
|
|
|
|
rv = ScheduleNextIdleObserverCallback();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::FindIndexOfElementToRemove(nsIIdleObserver* aIdleObserver,
|
2017-11-15 19:34:41 +03:00
|
|
|
int32_t* aRemoveElementIndex)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(aIdleObserver, "Idle observer not instantiated.");
|
|
|
|
|
|
|
|
*aRemoveElementIndex = 0;
|
|
|
|
if (mIdleObservers.IsEmpty()) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t aIdleObserverTimeInS;
|
|
|
|
nsresult rv = aIdleObserver->GetTime(&aIdleObserverTimeInS);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
NS_ENSURE_ARG_MIN(aIdleObserverTimeInS, MIN_IDLE_NOTIFICATION_TIME_S);
|
|
|
|
|
|
|
|
nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
|
|
|
|
while (iter.HasMore()) {
|
|
|
|
IdleObserverHolder& idleObserver = iter.GetNext();
|
|
|
|
if (idleObserver.mTimeInS == aIdleObserverTimeInS &&
|
|
|
|
idleObserver.mIdleObserver == aIdleObserver ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
(*aRemoveElementIndex)++;
|
|
|
|
}
|
|
|
|
return static_cast<uint32_t>(*aRemoveElementIndex) >= mIdleObservers.Length() ?
|
|
|
|
NS_ERROR_FAILURE : NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::UnregisterIdleObserver(nsIIdleObserver* aIdleObserver)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
int32_t removeElementIndex;
|
|
|
|
nsresult rv = FindIndexOfElementToRemove(aIdleObserver, &removeElementIndex);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_WARNING("Idle observer not found in list of idle observers. No idle observer removed.");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
mIdleObservers.RemoveElementAt(removeElementIndex);
|
|
|
|
|
|
|
|
MOZ_ASSERT(mIdleTimer);
|
|
|
|
if (mIdleObservers.IsEmpty() && mIdleService) {
|
|
|
|
rv = mIdleService->RemoveIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
mIdleService = nullptr;
|
|
|
|
|
|
|
|
mIdleTimer->Cancel();
|
|
|
|
mIdleCallbackIndex = -1;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mCurrentlyIdle) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (removeElementIndex < mIdleCallbackIndex) {
|
|
|
|
mIdleCallbackIndex--;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (removeElementIndex != mIdleCallbackIndex) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
mIdleTimer->Cancel();
|
|
|
|
|
|
|
|
// If the last element in the array had been notified then decrement
|
|
|
|
// mIdleCallbackIndex because an idle was removed from the list of
|
|
|
|
// idle observers.
|
|
|
|
// Example: add idle observer with time 1, 2, 3,
|
|
|
|
// Idle notifications for idle observers with time 1, 2, 3 are complete
|
|
|
|
// Remove idle observer with time 3 while the user is still idle.
|
|
|
|
// The user never transitioned to active state.
|
|
|
|
// Add an idle observer with idle time 4
|
|
|
|
if (static_cast<uint32_t>(mIdleCallbackIndex) == mIdleObservers.Length()) {
|
|
|
|
mIdleCallbackIndex--;
|
|
|
|
}
|
|
|
|
rv = ScheduleNextIdleObserverCallback();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Observe(nsISupports* aSubject, const char* aTopic,
|
2017-11-15 19:34:41 +03:00
|
|
|
const char16_t* aData)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!nsCRT::strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC)) {
|
|
|
|
if (!IsFrozen()) {
|
|
|
|
// Fires an offline status event if the offline status has changed
|
|
|
|
FireOfflineStatusEventIfChanged();
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!nsCRT::strcmp(aTopic, MEMORY_PRESSURE_OBSERVER_TOPIC)) {
|
|
|
|
if (mPerformance) {
|
|
|
|
mPerformance->MemoryPressure();
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_IDLE)) {
|
|
|
|
mCurrentlyIdle = true;
|
|
|
|
if (IsFrozen()) {
|
|
|
|
// need to fire only one idle event while the window is frozen.
|
|
|
|
mNotifyIdleObserversIdleOnThaw = true;
|
|
|
|
mNotifyIdleObserversActiveOnThaw = false;
|
2017-11-15 19:34:27 +03:00
|
|
|
} else if (IsCurrentInnerWindow()) {
|
2017-11-15 19:30:13 +03:00
|
|
|
HandleIdleActiveEvent();
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_ACTIVE)) {
|
|
|
|
mCurrentlyIdle = false;
|
|
|
|
if (IsFrozen()) {
|
|
|
|
mNotifyIdleObserversActiveOnThaw = true;
|
|
|
|
mNotifyIdleObserversIdleOnThaw = false;
|
2017-11-15 19:34:27 +03:00
|
|
|
} else if (IsCurrentInnerWindow()) {
|
2017-11-15 19:30:13 +03:00
|
|
|
ScheduleActiveTimerCallback();
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!nsCRT::strcmp(aTopic, "offline-cache-update-added")) {
|
|
|
|
if (mApplicationCache)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// Instantiate the application object now. It observes update belonging to
|
|
|
|
// this window's document and correctly updates the applicationCache object
|
|
|
|
// state.
|
|
|
|
nsCOMPtr<nsIDOMOfflineResourceList> applicationCache = GetApplicationCache();
|
|
|
|
nsCOMPtr<nsIObserver> observer = do_QueryInterface(applicationCache);
|
|
|
|
if (observer)
|
|
|
|
observer->Observe(aSubject, aTopic, aData);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
|
|
|
|
MOZ_ASSERT(!NS_strcmp(aData, u"intl.accept_languages"));
|
|
|
|
|
|
|
|
// The user preferred languages have changed, we need to fire an event on
|
|
|
|
// Window object and invalidate the cache for navigator.languages. It is
|
|
|
|
// done for every change which can be a waste of cycles but those should be
|
|
|
|
// fairly rare.
|
|
|
|
// We MUST invalidate navigator.languages before sending the event in the
|
|
|
|
// very likely situation where an event handler will try to read its value.
|
|
|
|
|
|
|
|
if (mNavigator) {
|
|
|
|
NavigatorBinding::ClearCachedLanguageValue(mNavigator);
|
|
|
|
NavigatorBinding::ClearCachedLanguagesValue(mNavigator);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The event has to be dispatched only to the current inner window.
|
2017-11-15 19:34:27 +03:00
|
|
|
if (!IsCurrentInnerWindow()) {
|
2017-11-15 19:30:13 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
|
|
|
|
event->InitEvent(NS_LITERAL_STRING("languagechange"), false, false);
|
|
|
|
event->SetTrusted(true);
|
|
|
|
|
|
|
|
bool dummy;
|
|
|
|
return DispatchEvent(event, &dummy);
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
NS_WARNING("unrecognized topic in nsGlobalWindowInner::Observe");
|
2017-11-15 19:30:13 +03:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ObserveStorageNotification(StorageEvent* aEvent,
|
2017-11-15 19:34:41 +03:00
|
|
|
const char16_t* aStorageType,
|
|
|
|
bool aPrivateBrowsing)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(aEvent);
|
|
|
|
|
|
|
|
// The private browsing check must be done here again because this window
|
|
|
|
// could have changed its state before the notification check and now. This
|
|
|
|
// happens in case this window did have a docShell at that time.
|
|
|
|
if (aPrivateBrowsing != IsPrivateBrowsing()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// LocalStorage can only exist on an inner window, and we don't want to
|
|
|
|
// generate events on frozen or otherwise-navigated-away from windows.
|
|
|
|
// (Actually, this code used to try and buffer events for frozen windows,
|
|
|
|
// but it never worked, so we've removed it. See bug 1285898.)
|
2017-11-22 02:07:45 +03:00
|
|
|
if (!IsCurrentInnerWindow() || IsFrozen()) {
|
2017-11-15 19:30:13 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIPrincipal *principal = GetPrincipal();
|
|
|
|
if (!principal) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool fireMozStorageChanged = false;
|
|
|
|
nsAutoString eventType;
|
|
|
|
eventType.AssignLiteral("storage");
|
|
|
|
|
|
|
|
if (!NS_strcmp(aStorageType, u"sessionStorage")) {
|
|
|
|
nsCOMPtr<nsIDOMStorage> changingStorage = aEvent->GetStorageArea();
|
|
|
|
MOZ_ASSERT(changingStorage);
|
|
|
|
|
|
|
|
bool check = false;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMStorageManager> storageManager = do_QueryInterface(GetDocShell());
|
|
|
|
if (storageManager) {
|
|
|
|
nsresult rv = storageManager->CheckStorage(principal, changingStorage,
|
|
|
|
&check);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!check) {
|
|
|
|
// This storage event is not coming from our storage or is coming
|
|
|
|
// from a different docshell, i.e. it is a clone, ignore this event.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-11-18 01:49:56 +03:00
|
|
|
MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
|
2017-11-15 19:33:39 +03:00
|
|
|
("nsGlobalWindowInner %p with sessionStorage %p passing event from %p",
|
2017-11-15 19:30:13 +03:00
|
|
|
this, mSessionStorage.get(), changingStorage.get()));
|
|
|
|
|
|
|
|
fireMozStorageChanged = mSessionStorage == changingStorage;
|
|
|
|
if (fireMozStorageChanged) {
|
|
|
|
eventType.AssignLiteral("MozSessionStorageChanged");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
MOZ_ASSERT(!NS_strcmp(aStorageType, u"localStorage"));
|
|
|
|
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(StorageUtils::PrincipalsEqual(aEvent->GetPrincipal(),
|
|
|
|
principal));
|
|
|
|
|
|
|
|
fireMozStorageChanged = mLocalStorage == aEvent->GetStorageArea();
|
|
|
|
|
|
|
|
if (fireMozStorageChanged) {
|
|
|
|
eventType.AssignLiteral("MozLocalStorageChanged");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clone the storage event included in the observer notification. We want
|
|
|
|
// to dispatch clones rather than the original event.
|
|
|
|
IgnoredErrorResult error;
|
|
|
|
RefPtr<StorageEvent> clonedEvent =
|
|
|
|
CloneStorageEvent(eventType, aEvent, error);
|
|
|
|
if (error.Failed()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
clonedEvent->SetTrusted(true);
|
|
|
|
|
|
|
|
if (fireMozStorageChanged) {
|
|
|
|
WidgetEvent* internalEvent = clonedEvent->WidgetEventPtr();
|
|
|
|
internalEvent->mFlags.mOnlyChromeDispatch = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool defaultActionEnabled;
|
|
|
|
DispatchEvent(clonedEvent, &defaultActionEnabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<StorageEvent>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::CloneStorageEvent(const nsAString& aType,
|
2017-11-15 19:34:41 +03:00
|
|
|
const RefPtr<StorageEvent>& aEvent,
|
|
|
|
ErrorResult& aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
StorageEventInit dict;
|
|
|
|
|
|
|
|
dict.mBubbles = aEvent->Bubbles();
|
|
|
|
dict.mCancelable = aEvent->Cancelable();
|
|
|
|
aEvent->GetKey(dict.mKey);
|
|
|
|
aEvent->GetOldValue(dict.mOldValue);
|
|
|
|
aEvent->GetNewValue(dict.mNewValue);
|
|
|
|
aEvent->GetUrl(dict.mUrl);
|
|
|
|
|
|
|
|
RefPtr<Storage> storageArea = aEvent->GetStorageArea();
|
|
|
|
|
|
|
|
RefPtr<Storage> storage;
|
|
|
|
|
|
|
|
// If null, this is a localStorage event received by IPC.
|
|
|
|
if (!storageArea) {
|
|
|
|
storage = GetLocalStorage(aRv);
|
|
|
|
if (aRv.Failed() || !storage) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(storage->Type() == Storage::eLocalStorage);
|
|
|
|
RefPtr<LocalStorage> localStorage =
|
|
|
|
static_cast<LocalStorage*>(storage.get());
|
|
|
|
|
|
|
|
// We must apply the current change to the 'local' localStorage.
|
|
|
|
localStorage->ApplyEvent(aEvent);
|
|
|
|
} else if (storageArea->Type() == Storage::eSessionStorage) {
|
|
|
|
storage = GetSessionStorage(aRv);
|
|
|
|
} else {
|
|
|
|
MOZ_ASSERT(storageArea->Type() == Storage::eLocalStorage);
|
|
|
|
storage = GetLocalStorage(aRv);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aRv.Failed() || !storage) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(storage);
|
|
|
|
MOZ_ASSERT_IF(storageArea, storage->IsForkOf(storageArea));
|
|
|
|
|
|
|
|
dict.mStorageArea = storage;
|
|
|
|
|
|
|
|
RefPtr<StorageEvent> event = StorageEvent::Constructor(this, aType, dict);
|
|
|
|
return event.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Suspend()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
// We can only safely suspend windows that are the current inner window. If
|
|
|
|
// its not the current inner, then we are in one of two different cases.
|
|
|
|
// Either we are in the bfcache or we are doomed window that is going away.
|
|
|
|
// When a window becomes inactive we purposely avoid placing already suspended
|
|
|
|
// windows into the bfcache. It only expects windows suspended due to the
|
|
|
|
// Freeze() method which occurs while the window is still the current inner.
|
|
|
|
// So we must not call Suspend() on bfcache windows at this point or this
|
|
|
|
// invariant will be broken. If the window is doomed there is no point in
|
|
|
|
// suspending it since it will soon be gone.
|
2017-11-15 19:34:27 +03:00
|
|
|
if (!IsCurrentInnerWindow()) {
|
2017-11-15 19:30:13 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// All children are also suspended. This ensure mSuspendDepth is
|
|
|
|
// set properly and the timers are properly canceled for each child.
|
2017-11-15 19:33:39 +03:00
|
|
|
CallOnChildren(&nsGlobalWindowInner::Suspend);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
mSuspendDepth += 1;
|
|
|
|
if (mSuspendDepth != 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
|
|
|
|
if (ac) {
|
|
|
|
for (uint32_t i = 0; i < mEnabledSensors.Length(); i++)
|
|
|
|
ac->RemoveWindowListener(mEnabledSensors[i], this);
|
|
|
|
}
|
|
|
|
DisableGamepadUpdates();
|
|
|
|
DisableVRUpdates();
|
|
|
|
|
2017-11-15 19:34:27 +03:00
|
|
|
mozilla::dom::workers::SuspendWorkersForWindow(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
SuspendIdleRequests();
|
|
|
|
|
|
|
|
mTimeoutManager->Suspend();
|
|
|
|
|
|
|
|
// Suspend all of the AudioContexts for this window
|
|
|
|
for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
|
|
|
|
ErrorResult dummy;
|
|
|
|
RefPtr<Promise> d = mAudioContexts[i]->Suspend(dummy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Resume()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
// We can only safely resume a window if its the current inner window. If
|
|
|
|
// its not the current inner, then we are in one of two different cases.
|
|
|
|
// Either we are in the bfcache or we are doomed window that is going away.
|
|
|
|
// If a window is suspended when it becomes inactive we purposely do not
|
|
|
|
// put it in the bfcache, so Resume should never be needed in that case.
|
|
|
|
// If the window is doomed then there is no point in resuming it.
|
2017-11-15 19:34:27 +03:00
|
|
|
if (!IsCurrentInnerWindow()) {
|
2017-11-15 19:30:13 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resume all children. This restores timers recursively canceled
|
|
|
|
// in Suspend() and ensures all children have the correct mSuspendDepth.
|
2017-11-15 19:33:39 +03:00
|
|
|
CallOnChildren(&nsGlobalWindowInner::Resume);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
MOZ_ASSERT(mSuspendDepth != 0);
|
|
|
|
mSuspendDepth -= 1;
|
|
|
|
if (mSuspendDepth != 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We should not be able to resume a frozen window. It must be Thaw()'d first.
|
|
|
|
MOZ_ASSERT(mFreezeDepth == 0);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
|
|
|
|
if (ac) {
|
|
|
|
for (uint32_t i = 0; i < mEnabledSensors.Length(); i++)
|
|
|
|
ac->AddWindowListener(mEnabledSensors[i], this);
|
|
|
|
}
|
|
|
|
EnableGamepadUpdates();
|
|
|
|
EnableVRUpdates();
|
|
|
|
|
|
|
|
// Resume all of the AudioContexts for this window
|
|
|
|
for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
|
|
|
|
ErrorResult dummy;
|
|
|
|
RefPtr<Promise> d = mAudioContexts[i]->Resume(dummy);
|
|
|
|
}
|
|
|
|
|
|
|
|
mTimeoutManager->Resume();
|
|
|
|
|
|
|
|
ResumeIdleRequests();
|
|
|
|
|
|
|
|
// Resume all of the workers for this window. We must do this
|
|
|
|
// after timeouts since workers may have queued events that can trigger
|
|
|
|
// a setTimeout().
|
2017-11-15 19:34:27 +03:00
|
|
|
mozilla::dom::workers::ResumeWorkersForWindow(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IsSuspended() const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
return mSuspendDepth != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Freeze()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
Suspend();
|
|
|
|
FreezeInternal();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::FreezeInternal()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2017-11-15 19:34:27 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(IsCurrentInnerWindow());
|
2017-11-15 19:30:13 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(IsSuspended());
|
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
CallOnChildren(&nsGlobalWindowInner::FreezeInternal);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
mFreezeDepth += 1;
|
|
|
|
MOZ_ASSERT(mSuspendDepth >= mFreezeDepth);
|
|
|
|
if (mFreezeDepth != 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:34:27 +03:00
|
|
|
mozilla::dom::workers::FreezeWorkersForWindow(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
mTimeoutManager->Freeze();
|
2017-11-21 23:13:05 +03:00
|
|
|
if (mClientSource) {
|
|
|
|
mClientSource->Freeze();
|
|
|
|
}
|
2017-11-15 19:30:13 +03:00
|
|
|
|
2017-11-22 02:07:45 +03:00
|
|
|
NotifyDOMWindowFrozen(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Thaw()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
ThawInternal();
|
|
|
|
Resume();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ThawInternal()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2017-11-15 19:34:27 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(IsCurrentInnerWindow());
|
2017-11-15 19:30:13 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(IsSuspended());
|
|
|
|
|
2017-11-15 19:33:39 +03:00
|
|
|
CallOnChildren(&nsGlobalWindowInner::ThawInternal);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
MOZ_ASSERT(mFreezeDepth != 0);
|
|
|
|
mFreezeDepth -= 1;
|
|
|
|
MOZ_ASSERT(mSuspendDepth >= mFreezeDepth);
|
|
|
|
if (mFreezeDepth != 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-11-21 23:13:05 +03:00
|
|
|
if (mClientSource) {
|
|
|
|
mClientSource->Thaw();
|
|
|
|
}
|
2017-11-15 19:30:13 +03:00
|
|
|
mTimeoutManager->Thaw();
|
|
|
|
|
2017-11-15 19:34:27 +03:00
|
|
|
mozilla::dom::workers::ThawWorkersForWindow(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
|
2017-11-22 02:07:45 +03:00
|
|
|
NotifyDOMWindowThawed(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IsFrozen() const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
bool frozen = mFreezeDepth != 0;
|
|
|
|
MOZ_ASSERT_IF(frozen, IsSuspended());
|
|
|
|
return frozen;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SyncStateFromParentWindow()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// This method should only be called on an inner window that has been
|
|
|
|
// assigned to an outer window already.
|
2017-11-15 19:34:27 +03:00
|
|
|
MOZ_ASSERT(IsCurrentInnerWindow());
|
2017-11-15 19:30:13 +03:00
|
|
|
nsPIDOMWindowOuter* outer = GetOuterWindow();
|
|
|
|
MOZ_ASSERT(outer);
|
|
|
|
|
|
|
|
// Attempt to find our parent windows.
|
|
|
|
nsCOMPtr<Element> frame = outer->GetFrameElementInternal();
|
|
|
|
nsPIDOMWindowOuter* parentOuter = frame ? frame->OwnerDoc()->GetWindow()
|
|
|
|
: nullptr;
|
|
|
|
nsGlobalWindowInner* parentInner =
|
|
|
|
parentOuter ? nsGlobalWindowInner::Cast(parentOuter->GetCurrentInnerWindow())
|
|
|
|
: nullptr;
|
|
|
|
|
|
|
|
// If our outer is in a modal state, but our parent is not in a modal
|
|
|
|
// state, then we must apply the suspend directly. If our parent is
|
|
|
|
// in a modal state then we should get the suspend automatically
|
|
|
|
// via the parentSuspendDepth application below.
|
|
|
|
if ((!parentInner || !parentInner->IsInModalState()) && IsInModalState()) {
|
|
|
|
Suspend();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t parentFreezeDepth = parentInner ? parentInner->mFreezeDepth : 0;
|
|
|
|
uint32_t parentSuspendDepth = parentInner ? parentInner->mSuspendDepth : 0;
|
|
|
|
|
|
|
|
// Since every Freeze() calls Suspend(), the suspend count must
|
|
|
|
// be equal or greater to the freeze count.
|
|
|
|
MOZ_ASSERT(parentFreezeDepth <= parentSuspendDepth);
|
|
|
|
|
|
|
|
// First apply the Freeze() calls.
|
|
|
|
for (uint32_t i = 0; i < parentFreezeDepth; ++i) {
|
|
|
|
Freeze();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now apply only the number of Suspend() calls to reach the target
|
|
|
|
// suspend count after applying the Freeze() calls.
|
|
|
|
for (uint32_t i = 0; i < (parentSuspendDepth - parentFreezeDepth); ++i) {
|
|
|
|
Suspend();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Method>
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::CallOnChildren(Method aMethod)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2017-11-15 19:34:27 +03:00
|
|
|
MOZ_ASSERT(IsCurrentInnerWindow());
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = GetDocShell();
|
|
|
|
if (!docShell) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t childCount = 0;
|
|
|
|
docShell->GetChildCount(&childCount);
|
|
|
|
|
|
|
|
for (int32_t i = 0; i < childCount; ++i) {
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> childShell;
|
|
|
|
docShell->GetChildAt(i, getter_AddRefs(childShell));
|
|
|
|
NS_ASSERTION(childShell, "null child shell");
|
|
|
|
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> pWin = childShell->GetWindow();
|
|
|
|
if (!pWin) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto* win = nsGlobalWindowOuter::Cast(pWin);
|
|
|
|
nsGlobalWindowInner* inner = win->GetCurrentInnerWindowInternal();
|
|
|
|
|
|
|
|
// This is a bit hackish. Only freeze/suspend windows which are truly our
|
|
|
|
// subwindows.
|
|
|
|
nsCOMPtr<Element> frame = pWin->GetFrameElementInternal();
|
|
|
|
if (!mDoc || !frame || mDoc != frame->OwnerDoc() || !inner) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
(inner->*aMethod)();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-21 23:13:05 +03:00
|
|
|
Maybe<ClientInfo>
|
|
|
|
nsGlobalWindowInner::GetClientInfo() const
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
Maybe<ClientInfo> clientInfo;
|
|
|
|
if (mClientSource) {
|
|
|
|
clientInfo.emplace(mClientSource->Info());
|
|
|
|
}
|
|
|
|
return Move(clientInfo);
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:30:13 +03:00
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::FireDelayedDOMEvents()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mApplicationCache) {
|
|
|
|
static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())->FirePendingEvents();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fires an offline status event if the offline status has changed
|
|
|
|
FireOfflineStatusEventIfChanged();
|
|
|
|
|
|
|
|
if (mNotifyIdleObserversIdleOnThaw) {
|
|
|
|
mNotifyIdleObserversIdleOnThaw = false;
|
|
|
|
HandleIdleActiveEvent();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mNotifyIdleObserversActiveOnThaw) {
|
|
|
|
mNotifyIdleObserversActiveOnThaw = false;
|
|
|
|
ScheduleActiveTimerCallback();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = GetDocShell();
|
|
|
|
if (docShell) {
|
|
|
|
int32_t childCount = 0;
|
|
|
|
docShell->GetChildCount(&childCount);
|
|
|
|
|
|
|
|
for (int32_t i = 0; i < childCount; ++i) {
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> childShell;
|
|
|
|
docShell->GetChildAt(i, getter_AddRefs(childShell));
|
|
|
|
NS_ASSERTION(childShell, "null child shell");
|
|
|
|
|
|
|
|
if (nsCOMPtr<nsPIDOMWindowOuter> pWin = childShell->GetWindow()) {
|
|
|
|
auto* win = nsGlobalWindowOuter::Cast(pWin);
|
|
|
|
win->FireDelayedDOMEvents();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
2017-11-15 19:33:39 +03:00
|
|
|
// nsGlobalWindowInner: Window Control Functions
|
2017-11-15 19:30:13 +03:00
|
|
|
//*****************************************************************************
|
|
|
|
|
|
|
|
nsPIDOMWindowOuter*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetParentInternal()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:13 +03:00
|
|
|
nsGlobalWindowOuter* outer = GetOuterWindowInternal();
|
|
|
|
if (!outer) {
|
|
|
|
// No outer window available!
|
|
|
|
return nullptr;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
2017-11-15 19:34:13 +03:00
|
|
|
return outer->GetParentInternal();
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
2017-11-15 19:33:39 +03:00
|
|
|
// nsGlobalWindowInner: Timeout Functions
|
2017-11-15 19:30:13 +03:00
|
|
|
//*****************************************************************************
|
|
|
|
|
|
|
|
nsGlobalWindowInner*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::InnerForSetTimeoutOrInterval(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:13 +03:00
|
|
|
nsGlobalWindowOuter* outer = GetOuterWindowInternal();
|
|
|
|
nsGlobalWindowInner* currentInner = outer ? outer->GetCurrentInnerWindowInternal() : this;
|
2017-11-15 19:30:13 +03:00
|
|
|
|
|
|
|
// If forwardTo is not the window with an active document then we want the
|
|
|
|
// call to setTimeout/Interval to be a noop, so return null but don't set an
|
|
|
|
// error.
|
2017-11-15 19:34:13 +03:00
|
|
|
return HasActiveDocument() ? currentInner : nullptr;
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetTimeout(JSContext* aCx, Function& aFunction,
|
2017-11-15 19:34:41 +03:00
|
|
|
int32_t aTimeout,
|
|
|
|
const Sequence<JS::Value>& aArguments,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments, false,
|
|
|
|
aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetTimeout(JSContext* aCx, const nsAString& aHandler,
|
2017-11-15 19:34:41 +03:00
|
|
|
int32_t aTimeout,
|
|
|
|
const Sequence<JS::Value>& /* unused */,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return SetTimeoutOrInterval(aCx, aHandler, aTimeout, false, aError);
|
|
|
|
}
|
|
|
|
|
2017-11-18 00:26:19 +03:00
|
|
|
static bool
|
|
|
|
IsInterval(const Optional<int32_t>& aTimeout, int32_t& aResultTimeout)
|
|
|
|
{
|
|
|
|
if (aTimeout.WasPassed()) {
|
|
|
|
aResultTimeout = aTimeout.Value();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If no interval was specified, treat this like a timeout, to avoid setting
|
|
|
|
// an interval of 0 milliseconds.
|
|
|
|
aResultTimeout = 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:30:13 +03:00
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetInterval(JSContext* aCx, Function& aFunction,
|
2017-11-15 19:34:41 +03:00
|
|
|
const Optional<int32_t>& aTimeout,
|
|
|
|
const Sequence<JS::Value>& aArguments,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
int32_t timeout;
|
|
|
|
bool isInterval = IsInterval(aTimeout, timeout);
|
|
|
|
return SetTimeoutOrInterval(aCx, aFunction, timeout, aArguments, isInterval,
|
|
|
|
aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetInterval(JSContext* aCx, const nsAString& aHandler,
|
2017-11-15 19:34:41 +03:00
|
|
|
const Optional<int32_t>& aTimeout,
|
|
|
|
const Sequence<JS::Value>& /* unused */,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
int32_t timeout;
|
|
|
|
bool isInterval = IsInterval(aTimeout, timeout);
|
|
|
|
return SetTimeoutOrInterval(aCx, aHandler, timeout, isInterval, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetTimeoutOrInterval(JSContext *aCx, Function& aFunction,
|
2017-11-15 19:34:41 +03:00
|
|
|
int32_t aTimeout,
|
|
|
|
const Sequence<JS::Value>& aArguments,
|
|
|
|
bool aIsInterval, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsGlobalWindowInner* inner = InnerForSetTimeoutOrInterval(aError);
|
|
|
|
if (!inner) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inner != this) {
|
|
|
|
return inner->SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments,
|
|
|
|
aIsInterval, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIScriptTimeoutHandler> handler =
|
2017-11-15 19:34:27 +03:00
|
|
|
NS_CreateJSTimeoutHandler(aCx, this, aFunction, aArguments, aError);
|
2017-11-15 19:30:13 +03:00
|
|
|
if (!handler) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t result;
|
|
|
|
aError = mTimeoutManager->SetTimeout(handler, aTimeout, aIsInterval,
|
|
|
|
Timeout::Reason::eTimeoutOrInterval,
|
|
|
|
&result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetTimeoutOrInterval(JSContext* aCx, const nsAString& aHandler,
|
2017-11-15 19:34:41 +03:00
|
|
|
int32_t aTimeout, bool aIsInterval,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsGlobalWindowInner* inner = InnerForSetTimeoutOrInterval(aError);
|
|
|
|
if (!inner) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inner != this) {
|
|
|
|
return inner->SetTimeoutOrInterval(aCx, aHandler, aTimeout, aIsInterval,
|
|
|
|
aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIScriptTimeoutHandler> handler =
|
2017-11-15 19:34:27 +03:00
|
|
|
NS_CreateJSTimeoutHandler(aCx, this, aHandler, aError);
|
2017-11-15 19:30:13 +03:00
|
|
|
if (!handler) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t result;
|
|
|
|
aError = mTimeoutManager->SetTimeout(handler, aTimeout, aIsInterval,
|
|
|
|
Timeout::Reason::eTimeoutOrInterval,
|
|
|
|
&result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::RunTimeoutHandler(Timeout* aTimeout,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsIScriptContext* aScx)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Hold on to the timeout in case mExpr or mFunObj releases its
|
|
|
|
// doc.
|
|
|
|
RefPtr<Timeout> timeout = aTimeout;
|
|
|
|
Timeout* last_running_timeout = mTimeoutManager->BeginRunningTimeout(timeout);
|
|
|
|
timeout->mRunning = true;
|
|
|
|
|
|
|
|
// Push this timeout's popup control state, which should only be
|
|
|
|
// eabled the first time a timeout fires that was created while
|
|
|
|
// popups were enabled and with a delay less than
|
|
|
|
// "dom.disable_open_click_delay".
|
|
|
|
nsAutoPopupStatePusher popupStatePusher(timeout->mPopupState);
|
|
|
|
|
|
|
|
// Clear the timeout's popup state, if any, to prevent interval
|
|
|
|
// timeouts from repeatedly opening poups.
|
|
|
|
timeout->mPopupState = openAbused;
|
|
|
|
|
|
|
|
bool trackNestingLevel = !timeout->mIsInterval;
|
|
|
|
uint32_t nestingLevel;
|
|
|
|
if (trackNestingLevel) {
|
|
|
|
nestingLevel = TimeoutManager::GetNestingLevel();
|
|
|
|
TimeoutManager::SetNestingLevel(timeout->mNestingLevel);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *reason;
|
|
|
|
if (timeout->mIsInterval) {
|
|
|
|
reason = "setInterval handler";
|
|
|
|
} else {
|
|
|
|
reason = "setTimeout handler";
|
|
|
|
}
|
|
|
|
|
|
|
|
bool abortIntervalHandler = false;
|
|
|
|
nsCOMPtr<nsIScriptTimeoutHandler> handler(do_QueryInterface(timeout->mScriptHandler));
|
|
|
|
if (handler) {
|
|
|
|
RefPtr<Function> callback = handler->GetCallback();
|
|
|
|
|
|
|
|
if (!callback) {
|
|
|
|
// Evaluate the timeout expression.
|
|
|
|
const nsAString& script = handler->GetHandlerText();
|
|
|
|
|
|
|
|
const char* filename = nullptr;
|
|
|
|
uint32_t lineNo = 0, dummyColumn = 0;
|
|
|
|
handler->GetLocation(&filename, &lineNo, &dummyColumn);
|
|
|
|
|
|
|
|
// New script entry point required, due to the "Create a script" sub-step of
|
|
|
|
// http://www.whatwg.org/specs/web-apps/current-work/#timer-initialisation-steps
|
|
|
|
nsAutoMicroTask mt;
|
|
|
|
AutoEntryScript aes(this, reason, true);
|
|
|
|
JS::CompileOptions options(aes.cx());
|
2017-11-17 14:12:39 +03:00
|
|
|
options.setFileAndLine(filename, lineNo);
|
2017-11-15 19:30:13 +03:00
|
|
|
options.setNoScriptRval(true);
|
|
|
|
JS::Rooted<JSObject*> global(aes.cx(), FastGetGlobalJSObject());
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
{
|
|
|
|
nsJSUtils::ExecutionContext exec(aes.cx(), global);
|
|
|
|
rv = exec.CompileAndExec(options, script);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rv == NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE) {
|
|
|
|
abortIntervalHandler = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Hold strong ref to ourselves while we call the callback.
|
|
|
|
nsCOMPtr<nsISupports> me(static_cast<nsIDOMWindow*>(this));
|
|
|
|
ErrorResult rv;
|
|
|
|
JS::Rooted<JS::Value> ignoredVal(RootingCx());
|
|
|
|
callback->Call(me, handler->GetArgs(), &ignoredVal, rv, reason);
|
|
|
|
if (rv.IsUncatchableException()) {
|
|
|
|
abortIntervalHandler = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv.SuppressException();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
nsCOMPtr<nsITimeoutHandler> basicHandler(timeout->mScriptHandler);
|
|
|
|
nsCOMPtr<nsISupports> kungFuDeathGrip(static_cast<nsIDOMWindow*>(this));
|
|
|
|
mozilla::Unused << kungFuDeathGrip;
|
|
|
|
basicHandler->Call();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we received an uncatchable exception, do not schedule the timeout again.
|
|
|
|
// This allows the slow script dialog to break easy DoS attacks like
|
|
|
|
// setInterval(function() { while(1); }, 100);
|
|
|
|
if (abortIntervalHandler) {
|
|
|
|
// If it wasn't an interval timer to begin with, this does nothing. If it
|
|
|
|
// was, we'll treat it as a timeout that we just ran and discard it when
|
|
|
|
// we return.
|
|
|
|
timeout->mIsInterval = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We ignore any failures from calling EvaluateString() on the context or
|
|
|
|
// Call() on a Function here since we're in a loop
|
|
|
|
// where we're likely to be running timeouts whose OS timers
|
|
|
|
// didn't fire in time and we don't want to not fire those timers
|
|
|
|
// now just because execution of one timer failed. We can't
|
|
|
|
// propagate the error to anyone who cares about it from this
|
|
|
|
// point anyway, and the script context should have already reported
|
|
|
|
// the script error in the usual way - so we just drop it.
|
|
|
|
|
|
|
|
// Since we might be processing more timeouts, go ahead and flush the promise
|
|
|
|
// queue now before we do that. We need to do that while we're still in our
|
|
|
|
// "running JS is safe" state (e.g. mRunningTimeout is set, timeout->mRunning
|
|
|
|
// is false).
|
|
|
|
Promise::PerformMicroTaskCheckpoint();
|
|
|
|
|
|
|
|
if (trackNestingLevel) {
|
|
|
|
TimeoutManager::SetNestingLevel(nestingLevel);
|
|
|
|
}
|
|
|
|
|
|
|
|
mTimeoutManager->EndRunningTimeout(last_running_timeout);
|
|
|
|
timeout->mRunning = false;
|
|
|
|
|
|
|
|
return timeout->mCleared;
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
2017-11-15 19:33:39 +03:00
|
|
|
// nsGlobalWindowInner: Helper Functions
|
2017-11-15 19:30:13 +03:00
|
|
|
//*****************************************************************************
|
|
|
|
|
|
|
|
already_AddRefed<nsIDocShellTreeOwner>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetTreeOwner()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER(GetTreeOwner, (), nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsIWebBrowserChrome>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetWebBrowserChrome()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
|
|
|
|
|
|
|
|
nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(treeOwner);
|
|
|
|
return browserChrome.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIScrollableFrame *
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetScrollFrame()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER(GetScrollFrame, (), nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IsPrivateBrowsing()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(GetDocShell());
|
|
|
|
return loadContext && loadContext->UsePrivateBrowsing();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::FlushPendingNotifications(FlushType aType)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mDoc) {
|
|
|
|
mDoc->FlushPendingNotifications(aType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::EnableDeviceSensor(uint32_t aType)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
bool alreadyEnabled = false;
|
|
|
|
for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) {
|
|
|
|
if (mEnabledSensors[i] == aType) {
|
|
|
|
alreadyEnabled = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mEnabledSensors.AppendElement(aType);
|
|
|
|
|
|
|
|
if (alreadyEnabled) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
|
|
|
|
if (ac) {
|
|
|
|
ac->AddWindowListener(aType, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DisableDeviceSensor(uint32_t aType)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
int32_t doomedElement = -1;
|
|
|
|
int32_t listenerCount = 0;
|
|
|
|
for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) {
|
|
|
|
if (mEnabledSensors[i] == aType) {
|
|
|
|
doomedElement = i;
|
|
|
|
listenerCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (doomedElement == -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mEnabledSensors.RemoveElementAt(doomedElement);
|
|
|
|
|
|
|
|
if (listenerCount > 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
|
|
|
|
if (ac) {
|
|
|
|
ac->RemoveWindowListener(aType, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(MOZ_WIDGET_ANDROID)
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::EnableOrientationChangeListener()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-21 22:06:28 +03:00
|
|
|
// XXX: mDocShell is never set on the inner window?
|
2017-11-21 23:06:21 +03:00
|
|
|
nsIDocShell* docShell = nullptr;
|
|
|
|
if (!nsContentUtils::ShouldResistFingerprinting(docShell) &&
|
2017-11-15 19:30:13 +03:00
|
|
|
!mOrientationChangeObserver) {
|
|
|
|
mOrientationChangeObserver =
|
2017-11-15 19:34:27 +03:00
|
|
|
MakeUnique<WindowOrientationObserver>(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DisableOrientationChangeListener()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
mOrientationChangeObserver = nullptr;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetHasGamepadEventListener(bool aHasGamepad/* = true*/)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
mHasGamepad = aHasGamepad;
|
|
|
|
if (aHasGamepad) {
|
|
|
|
EnableGamepadUpdates();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::EventListenerAdded(nsAtom* aType)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (aType == nsGkAtoms::onvrdisplayactivate ||
|
|
|
|
aType == nsGkAtoms::onvrdisplayconnect ||
|
|
|
|
aType == nsGkAtoms::onvrdisplaydeactivate ||
|
|
|
|
aType == nsGkAtoms::onvrdisplaydisconnect ||
|
|
|
|
aType == nsGkAtoms::onvrdisplaypresentchange) {
|
|
|
|
NotifyVREventListenerAdded();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aType == nsGkAtoms::onvrdisplayactivate) {
|
|
|
|
mHasVRDisplayActivateEvents = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aType == nsGkAtoms::onbeforeunload &&
|
|
|
|
mTabChild &&
|
|
|
|
(!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS))) {
|
|
|
|
mBeforeUnloadListenerCount++;
|
|
|
|
MOZ_ASSERT(mBeforeUnloadListenerCount > 0);
|
|
|
|
mTabChild->BeforeUnloadAdded();
|
|
|
|
}
|
|
|
|
|
|
|
|
// We need to initialize localStorage in order to receive notifications.
|
|
|
|
if (aType == nsGkAtoms::onstorage) {
|
|
|
|
ErrorResult rv;
|
|
|
|
GetLocalStorage(rv);
|
|
|
|
rv.SuppressException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::EventListenerRemoved(nsAtom* aType)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (aType == nsGkAtoms::onbeforeunload &&
|
|
|
|
mTabChild &&
|
|
|
|
(!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS))) {
|
|
|
|
mBeforeUnloadListenerCount--;
|
|
|
|
MOZ_ASSERT(mBeforeUnloadListenerCount >= 0);
|
|
|
|
mTabChild->BeforeUnloadRemoved();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::NotifyVREventListenerAdded()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
mHasVREvents = true;
|
|
|
|
EnableVRUpdates();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::HasUsedVR() const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Returns true only if any WebVR API call or related event
|
|
|
|
// has been used
|
|
|
|
return mHasVREvents;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IsVRContentDetected() const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Returns true only if the content will respond to
|
|
|
|
// the VRDisplayActivate event.
|
|
|
|
return mHasVRDisplayActivateEvents;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IsVRContentPresenting() const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
for (const auto& display : mVRDisplays) {
|
|
|
|
if (display->IsAnyPresenting(gfx::kVRGroupAll)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::EnableTimeChangeNotifications()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:27 +03:00
|
|
|
mozilla::time::AddWindowListener(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DisableTimeChangeNotifications()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:27 +03:00
|
|
|
mozilla::time::RemoveWindowListener(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::AddSizeOfIncludingThis(nsWindowSizes& aWindowSizes) const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
aWindowSizes.mDOMOtherSize += aWindowSizes.mState.mMallocSizeOf(this);
|
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
EventListenerManager* elm = GetExistingListenerManager();
|
|
|
|
if (elm) {
|
|
|
|
aWindowSizes.mDOMOtherSize +=
|
|
|
|
elm->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
|
|
|
|
aWindowSizes.mDOMEventListenersCount += elm->ListenerCount();
|
|
|
|
}
|
|
|
|
if (mDoc) {
|
|
|
|
// Multiple global windows can share a document. So only measure the
|
|
|
|
// document if it (a) doesn't have a global window, or (b) it's the
|
|
|
|
// primary document for the window.
|
|
|
|
if (!mDoc->GetInnerWindow() ||
|
2017-11-15 19:34:27 +03:00
|
|
|
mDoc->GetInnerWindow() == this) {
|
2017-11-15 19:34:13 +03:00
|
|
|
mDoc->DocAddSizeOfIncludingThis(aWindowSizes);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mNavigator) {
|
|
|
|
aWindowSizes.mDOMOtherSize +=
|
|
|
|
mNavigator->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
|
|
|
|
}
|
|
|
|
|
|
|
|
aWindowSizes.mDOMEventTargetsSize +=
|
|
|
|
mEventTargetObjects.ShallowSizeOfExcludingThis(
|
|
|
|
aWindowSizes.mState.mMallocSizeOf);
|
|
|
|
|
|
|
|
for (auto iter = mEventTargetObjects.ConstIter(); !iter.Done(); iter.Next()) {
|
|
|
|
DOMEventTargetHelper* et = iter.Get()->GetKey();
|
|
|
|
if (nsCOMPtr<nsISizeOfEventTarget> iSizeOf = do_QueryObject(et)) {
|
|
|
|
aWindowSizes.mDOMEventTargetsSize +=
|
|
|
|
iSizeOf->SizeOfEventTargetIncludingThis(
|
|
|
|
aWindowSizes.mState.mMallocSizeOf);
|
|
|
|
}
|
|
|
|
if (EventListenerManager* elm = et->GetExistingListenerManager()) {
|
|
|
|
aWindowSizes.mDOMEventListenersCount += elm->ListenerCount();
|
|
|
|
}
|
|
|
|
++aWindowSizes.mDOMEventTargetsCount;
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
if (mPerformance) {
|
2017-11-15 19:30:13 +03:00
|
|
|
aWindowSizes.mDOMPerformanceUserEntries =
|
|
|
|
mPerformance->SizeOfUserEntries(aWindowSizes.mState.mMallocSizeOf);
|
|
|
|
aWindowSizes.mDOMPerformanceResourceEntries =
|
|
|
|
mPerformance->SizeOfResourceEntries(aWindowSizes.mState.mMallocSizeOf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::AddGamepad(uint32_t aIndex, Gamepad* aGamepad)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Create the index we will present to content based on which indices are
|
|
|
|
// already taken, as required by the spec.
|
|
|
|
// https://w3c.github.io/gamepad/gamepad.html#widl-Gamepad-index
|
|
|
|
int index = 0;
|
|
|
|
while(mGamepadIndexSet.Contains(index)) {
|
|
|
|
++index;
|
|
|
|
}
|
|
|
|
mGamepadIndexSet.Put(index);
|
|
|
|
aGamepad->SetIndex(index);
|
|
|
|
mGamepads.Put(aIndex, aGamepad);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::RemoveGamepad(uint32_t aIndex)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
RefPtr<Gamepad> gamepad;
|
|
|
|
if (!mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Free up the index we were using so it can be reused
|
|
|
|
mGamepadIndexSet.Remove(gamepad->Index());
|
|
|
|
mGamepads.Remove(aIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetGamepads(nsTArray<RefPtr<Gamepad> >& aGamepads)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
aGamepads.Clear();
|
|
|
|
|
|
|
|
// navigator.getGamepads() always returns an empty array when
|
|
|
|
// privacy.resistFingerprinting is true.
|
|
|
|
if (nsContentUtils::ShouldResistFingerprinting()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// mGamepads.Count() may not be sufficient, but it's not harmful.
|
|
|
|
aGamepads.SetCapacity(mGamepads.Count());
|
|
|
|
for (auto iter = mGamepads.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
Gamepad* gamepad = iter.UserData();
|
|
|
|
aGamepads.EnsureLengthAtLeast(gamepad->Index() + 1);
|
|
|
|
aGamepads[gamepad->Index()] = gamepad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<Gamepad>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetGamepad(uint32_t aIndex)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
RefPtr<Gamepad> gamepad;
|
|
|
|
|
|
|
|
if (mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
|
|
|
|
return gamepad.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetHasSeenGamepadInput(bool aHasSeen)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
mHasSeenGamepadInput = aHasSeen;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::HasSeenGamepadInput()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return mHasSeenGamepadInput;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SyncGamepadState()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mHasSeenGamepadInput) {
|
|
|
|
RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
|
|
|
|
for (auto iter = mGamepads.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
gamepadManager->SyncGamepadState(iter.Key(), iter.UserData());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::StopGamepadHaptics()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mHasSeenGamepadInput) {
|
|
|
|
RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
|
|
|
|
gamepadManager->StopHaptics();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDevices)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-15 19:34:27 +03:00
|
|
|
VRDisplay::UpdateVRDisplays(mVRDisplays, this);
|
2017-11-15 19:30:13 +03:00
|
|
|
aDevices = mVRDisplays;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::NotifyActiveVRDisplaysChanged()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (mNavigator) {
|
|
|
|
mNavigator->NotifyActiveVRDisplaysChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DispatchVRDisplayActivate(uint32_t aDisplayID,
|
2017-11-15 19:34:41 +03:00
|
|
|
mozilla::dom::VRDisplayEventReason aReason)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Search for the display identified with aDisplayID and fire the
|
|
|
|
// event if found.
|
|
|
|
for (const auto& display : mVRDisplays) {
|
|
|
|
if (display->DisplayId() == aDisplayID) {
|
|
|
|
if (aReason != VRDisplayEventReason::Navigation &&
|
|
|
|
display->IsAnyPresenting(gfx::kVRGroupContent)) {
|
|
|
|
// We only want to trigger this event if nobody is presenting to the
|
|
|
|
// display already or when a page is loaded by navigating away
|
|
|
|
// from a page with an active VR Presentation.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
VRDisplayEventInit init;
|
|
|
|
init.mBubbles = false;
|
|
|
|
init.mCancelable = false;
|
|
|
|
init.mDisplay = display;
|
|
|
|
init.mReason.Construct(aReason);
|
|
|
|
|
|
|
|
RefPtr<VRDisplayEvent> event =
|
|
|
|
VRDisplayEvent::Constructor(this,
|
|
|
|
NS_LITERAL_STRING("vrdisplayactivate"),
|
|
|
|
init);
|
|
|
|
// vrdisplayactivate is a trusted event, allowing VRDisplay.requestPresent
|
|
|
|
// to be used in response to link traversal, user request (chrome UX), and
|
|
|
|
// HMD mounting detection sensors.
|
|
|
|
event->SetTrusted(true);
|
|
|
|
bool defaultActionEnabled;
|
|
|
|
// VRDisplay.requestPresent normally requires a user gesture; however, an
|
|
|
|
// exception is made to allow it to be called in response to vrdisplayactivate
|
|
|
|
// during VR link traversal.
|
|
|
|
display->StartHandlingVRNavigationEvent();
|
|
|
|
Unused << DispatchEvent(event, &defaultActionEnabled);
|
|
|
|
display->StopHandlingVRNavigationEvent();
|
|
|
|
// Once we dispatch the event, we must not access any members as an event
|
|
|
|
// listener can do anything, including closing windows.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DispatchVRDisplayDeactivate(uint32_t aDisplayID,
|
2017-11-15 19:34:41 +03:00
|
|
|
mozilla::dom::VRDisplayEventReason aReason)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Search for the display identified with aDisplayID and fire the
|
|
|
|
// event if found.
|
|
|
|
for (const auto& display : mVRDisplays) {
|
|
|
|
if (display->DisplayId() == aDisplayID && display->IsPresenting()) {
|
|
|
|
// We only want to trigger this event to content that is presenting to
|
|
|
|
// the display already.
|
|
|
|
|
|
|
|
VRDisplayEventInit init;
|
|
|
|
init.mBubbles = false;
|
|
|
|
init.mCancelable = false;
|
|
|
|
init.mDisplay = display;
|
|
|
|
init.mReason.Construct(aReason);
|
|
|
|
|
|
|
|
RefPtr<VRDisplayEvent> event =
|
|
|
|
VRDisplayEvent::Constructor(this,
|
|
|
|
NS_LITERAL_STRING("vrdisplaydeactivate"),
|
|
|
|
init);
|
|
|
|
event->SetTrusted(true);
|
|
|
|
bool defaultActionEnabled;
|
|
|
|
Unused << DispatchEvent(event, &defaultActionEnabled);
|
|
|
|
// Once we dispatch the event, we must not access any members as an event
|
|
|
|
// listener can do anything, including closing windows.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DispatchVRDisplayConnect(uint32_t aDisplayID)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Search for the display identified with aDisplayID and fire the
|
|
|
|
// event if found.
|
|
|
|
for (const auto& display : mVRDisplays) {
|
|
|
|
if (display->DisplayId() == aDisplayID) {
|
|
|
|
// Fire event even if not presenting to the display.
|
|
|
|
VRDisplayEventInit init;
|
|
|
|
init.mBubbles = false;
|
|
|
|
init.mCancelable = false;
|
|
|
|
init.mDisplay = display;
|
|
|
|
// VRDisplayEvent.reason is not set for vrdisplayconnect
|
|
|
|
|
|
|
|
RefPtr<VRDisplayEvent> event =
|
|
|
|
VRDisplayEvent::Constructor(this,
|
|
|
|
NS_LITERAL_STRING("vrdisplayconnect"),
|
|
|
|
init);
|
|
|
|
event->SetTrusted(true);
|
|
|
|
bool defaultActionEnabled;
|
|
|
|
Unused << DispatchEvent(event, &defaultActionEnabled);
|
|
|
|
// Once we dispatch the event, we must not access any members as an event
|
|
|
|
// listener can do anything, including closing windows.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DispatchVRDisplayDisconnect(uint32_t aDisplayID)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Search for the display identified with aDisplayID and fire the
|
|
|
|
// event if found.
|
|
|
|
for (const auto& display : mVRDisplays) {
|
|
|
|
if (display->DisplayId() == aDisplayID) {
|
|
|
|
// Fire event even if not presenting to the display.
|
|
|
|
VRDisplayEventInit init;
|
|
|
|
init.mBubbles = false;
|
|
|
|
init.mCancelable = false;
|
|
|
|
init.mDisplay = display;
|
|
|
|
// VRDisplayEvent.reason is not set for vrdisplaydisconnect
|
|
|
|
|
|
|
|
RefPtr<VRDisplayEvent> event =
|
|
|
|
VRDisplayEvent::Constructor(this,
|
|
|
|
NS_LITERAL_STRING("vrdisplaydisconnect"),
|
|
|
|
init);
|
|
|
|
event->SetTrusted(true);
|
|
|
|
bool defaultActionEnabled;
|
|
|
|
Unused << DispatchEvent(event, &defaultActionEnabled);
|
|
|
|
// Once we dispatch the event, we must not access any members as an event
|
|
|
|
// listener can do anything, including closing windows.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::DispatchVRDisplayPresentChange(uint32_t aDisplayID)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// Search for the display identified with aDisplayID and fire the
|
|
|
|
// event if found.
|
|
|
|
for (const auto& display : mVRDisplays) {
|
|
|
|
if (display->DisplayId() == aDisplayID) {
|
|
|
|
// Fire event even if not presenting to the display.
|
|
|
|
VRDisplayEventInit init;
|
|
|
|
init.mBubbles = false;
|
|
|
|
init.mCancelable = false;
|
|
|
|
init.mDisplay = display;
|
|
|
|
// VRDisplayEvent.reason is not set for vrdisplaypresentchange
|
|
|
|
RefPtr<VRDisplayEvent> event =
|
|
|
|
VRDisplayEvent::Constructor(this,
|
|
|
|
NS_LITERAL_STRING("vrdisplaypresentchange"),
|
|
|
|
init);
|
|
|
|
event->SetTrusted(true);
|
|
|
|
bool defaultActionEnabled;
|
|
|
|
Unused << DispatchEvent(event, &defaultActionEnabled);
|
|
|
|
// Once we dispatch the event, we must not access any members as an event
|
|
|
|
// listener can do anything, including closing windows.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
enum WindowState {
|
|
|
|
// These constants need to match the constants in Window.webidl
|
|
|
|
STATE_MAXIMIZED = 1,
|
|
|
|
STATE_MINIMIZED = 2,
|
|
|
|
STATE_NORMAL = 3,
|
|
|
|
STATE_FULLSCREEN = 4
|
|
|
|
};
|
|
|
|
|
|
|
|
uint16_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::WindowState()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIWidget> widget = GetMainWidget();
|
|
|
|
|
|
|
|
int32_t mode = widget ? widget->SizeMode() : 0;
|
|
|
|
|
|
|
|
switch (mode) {
|
|
|
|
case nsSizeMode_Minimized:
|
|
|
|
return STATE_MINIMIZED;
|
|
|
|
case nsSizeMode_Maximized:
|
|
|
|
return STATE_MAXIMIZED;
|
|
|
|
case nsSizeMode_Fullscreen:
|
|
|
|
return STATE_FULLSCREEN;
|
|
|
|
case nsSizeMode_Normal:
|
|
|
|
return STATE_NORMAL;
|
|
|
|
default:
|
|
|
|
NS_WARNING("Illegal window state for this chrome window");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATE_NORMAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IsFullyOccluded()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIWidget> widget = GetMainWidget();
|
|
|
|
return widget && widget->IsFullyOccluded();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Maximize()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIWidget> widget = GetMainWidget();
|
|
|
|
|
|
|
|
if (widget) {
|
|
|
|
widget->SetSizeMode(nsSizeMode_Maximized);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Minimize()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIWidget> widget = GetMainWidget();
|
|
|
|
|
|
|
|
if (widget) {
|
|
|
|
widget->SetSizeMode(nsSizeMode_Minimized);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Restore()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIWidget> widget = GetMainWidget();
|
|
|
|
|
|
|
|
if (widget) {
|
|
|
|
widget->SetSizeMode(nsSizeMode_Normal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetAttention(ErrorResult& aResult)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return GetAttentionWithCycleCount(-1, aResult);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetAttentionWithCycleCount(int32_t aCycleCount,
|
2017-11-15 19:34:41 +03:00
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIWidget> widget = GetMainWidget();
|
|
|
|
|
|
|
|
if (widget) {
|
|
|
|
aError = widget->GetAttention(aCycleCount);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::BeginWindowMove(Event& aMouseDownEvent, Element* aPanel,
|
2017-11-15 19:34:41 +03:00
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIWidget> widget;
|
|
|
|
|
|
|
|
// if a panel was supplied, use its widget instead.
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
if (aPanel) {
|
|
|
|
nsIFrame* frame = aPanel->GetPrimaryFrame();
|
|
|
|
if (!frame || !frame->IsMenuPopupFrame()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
widget = (static_cast<nsMenuPopupFrame*>(frame))->GetWidget();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
#endif
|
|
|
|
widget = GetMainWidget();
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!widget) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
WidgetMouseEvent* mouseEvent =
|
|
|
|
aMouseDownEvent.WidgetEventPtr()->AsMouseEvent();
|
|
|
|
if (!mouseEvent || mouseEvent->mClass != eMouseEventClass) {
|
|
|
|
aError.Throw(NS_ERROR_FAILURE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
aError = widget->BeginMoveDrag(mouseEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsWindowRoot>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetWindowRoot(mozilla::ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetWindowRootOuter, (), aError, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetCursor(const nsAString& aCursor, ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(SetCursorOuter, (aCursor, aError), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetBrowserDOMWindow(nsIBrowserDOMWindow **aBrowserWindow)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_RELEASE_ASSERT(IsChromeWindow());
|
|
|
|
|
|
|
|
ErrorResult rv;
|
|
|
|
NS_IF_ADDREF(*aBrowserWindow = GetBrowserDOMWindow(rv));
|
|
|
|
return rv.StealNSResult();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIBrowserDOMWindow*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetBrowserDOMWindow(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(GetBrowserDOMWindowOuter, (), aError, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserWindow,
|
2017-11-15 19:30:13 +03:00
|
|
|
ErrorResult& aError)
|
|
|
|
{
|
|
|
|
FORWARD_TO_OUTER_OR_THROW(SetBrowserDOMWindowOuter, (aBrowserWindow), aError, );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::NotifyDefaultButtonLoaded(Element& aDefaultButton,
|
2017-11-15 19:34:41 +03:00
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
// Don't snap to a disabled button.
|
|
|
|
nsCOMPtr<nsIDOMXULControlElement> xulControl =
|
|
|
|
do_QueryInterface(&aDefaultButton);
|
|
|
|
if (!xulControl) {
|
|
|
|
aError.Throw(NS_ERROR_FAILURE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
bool disabled;
|
|
|
|
aError = xulControl->GetDisabled(&disabled);
|
|
|
|
if (aError.Failed() || disabled) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the button rect in screen coordinates.
|
|
|
|
nsIFrame *frame = aDefaultButton.GetPrimaryFrame();
|
|
|
|
if (!frame) {
|
|
|
|
aError.Throw(NS_ERROR_FAILURE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
LayoutDeviceIntRect buttonRect =
|
|
|
|
LayoutDeviceIntRect::FromAppUnitsToNearest(
|
|
|
|
frame->GetScreenRectInAppUnits(),
|
|
|
|
frame->PresContext()->AppUnitsPerDevPixel());
|
|
|
|
|
|
|
|
// Get the widget rect in screen coordinates.
|
|
|
|
nsIWidget *widget = GetNearestWidget();
|
|
|
|
if (!widget) {
|
|
|
|
aError.Throw(NS_ERROR_FAILURE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
LayoutDeviceIntRect widgetRect = widget->GetScreenBounds();
|
|
|
|
|
|
|
|
// Convert the buttonRect coordinates from screen to the widget.
|
|
|
|
buttonRect -= widgetRect.TopLeft();
|
|
|
|
nsresult rv = widget->OnDefaultButtonLoaded(buttonRect);
|
|
|
|
if (NS_FAILED(rv) && rv != NS_ERROR_NOT_IMPLEMENTED) {
|
|
|
|
aError.Throw(rv);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
aError.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetMessageManager(nsIMessageBroadcaster** aManager)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
ErrorResult rv;
|
|
|
|
NS_IF_ADDREF(*aManager = GetMessageManager(rv));
|
|
|
|
return rv.StealNSResult();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIMessageBroadcaster*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetMessageManager(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(IsChromeWindow());
|
|
|
|
if (!mChromeFields.mMessageManager) {
|
|
|
|
nsCOMPtr<nsIMessageBroadcaster> globalMM =
|
|
|
|
do_GetService("@mozilla.org/globalmessagemanager;1");
|
|
|
|
mChromeFields.mMessageManager =
|
|
|
|
new nsFrameMessageManager(nullptr,
|
|
|
|
static_cast<nsFrameMessageManager*>(globalMM.get()),
|
|
|
|
MM_CHROME | MM_BROADCASTER);
|
|
|
|
}
|
|
|
|
return mChromeFields.mMessageManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetGroupMessageManager(const nsAString& aGroup,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsIMessageBroadcaster** aManager)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_RELEASE_ASSERT(IsChromeWindow());
|
|
|
|
ErrorResult rv;
|
|
|
|
NS_IF_ADDREF(*aManager = GetGroupMessageManager(aGroup, rv));
|
|
|
|
return rv.StealNSResult();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIMessageBroadcaster*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetGroupMessageManager(const nsAString& aGroup,
|
2017-11-15 19:34:41 +03:00
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(IsChromeWindow());
|
|
|
|
|
|
|
|
nsCOMPtr<nsIMessageBroadcaster> messageManager =
|
|
|
|
mChromeFields.mGroupMessageManagers.LookupForAdd(aGroup).OrInsert(
|
|
|
|
[this, &aError] () {
|
|
|
|
nsFrameMessageManager* parent =
|
|
|
|
static_cast<nsFrameMessageManager*>(GetMessageManager(aError));
|
|
|
|
|
|
|
|
return new nsFrameMessageManager(nullptr,
|
|
|
|
parent,
|
|
|
|
MM_CHROME | MM_BROADCASTER);
|
|
|
|
});
|
|
|
|
return messageManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::InitWasOffline()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
mWasOffline = NS_IsOffline();
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(MOZ_WIDGET_ANDROID)
|
|
|
|
int16_t
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Orientation(CallerType aCallerType) const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return nsContentUtils::ResistFingerprinting(aCallerType) ?
|
|
|
|
0 : WindowOrientationObserver::OrientationAngle();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Console*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetConsole(ErrorResult& aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mConsole) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mConsole = Console::Create(this, aRv);
|
2017-11-15 19:30:13 +03:00
|
|
|
if (NS_WARN_IF(aRv.Failed())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return mConsole;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::IsSecureContext() const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return JS_GetIsSecureContext(js::GetObjectCompartment(GetWrapperPreserveColor()));
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<External>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetExternal(ErrorResult& aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
#ifdef HAVE_SIDEBAR
|
|
|
|
if (!mExternal) {
|
|
|
|
AutoJSContext cx;
|
|
|
|
JS::Rooted<JSObject*> jsImplObj(cx);
|
|
|
|
ConstructJSImplementation("@mozilla.org/sidebar;1", this, &jsImplObj, aRv);
|
|
|
|
if (aRv.Failed()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
mExternal = new External(jsImplObj, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<External> external = static_cast<External*>(mExternal.get());
|
|
|
|
return external.forget();
|
|
|
|
#else
|
|
|
|
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
|
|
|
return nullptr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetSidebar(OwningExternalOrWindowProxy& aResult,
|
2017-11-15 19:34:41 +03:00
|
|
|
ErrorResult& aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
#ifdef HAVE_SIDEBAR
|
|
|
|
// First check for a named frame named "sidebar"
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetChildWindow(NS_LITERAL_STRING("sidebar"));
|
|
|
|
if (domWindow) {
|
|
|
|
aResult.SetAsWindowProxy() = domWindow.forget();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<External> external = GetExternal(aRv);
|
|
|
|
if (external) {
|
|
|
|
aResult.SetAsExternal() = external;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::ClearDocumentDependentSlots(JSContext* aCx)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// If JSAPI OOMs here, there is basically nothing we can do to recover safely.
|
2017-11-15 19:34:27 +03:00
|
|
|
if (!WindowBinding::ClearCachedDocumentValue(aCx, this) ||
|
|
|
|
!WindowBinding::ClearCachedPerformanceValue(aCx, this)) {
|
2017-11-15 19:30:13 +03:00
|
|
|
MOZ_CRASH("Unhandlable OOM while clearing document dependent slots.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
JSObject*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::CreateNamedPropertiesObject(JSContext *aCx,
|
2017-11-15 19:34:41 +03:00
|
|
|
JS::Handle<JSObject*> aProto)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
return WindowNamedPropertiesHandler::Create(aCx, aProto);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetIsPrerendered()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
nsIDocShell* docShell = GetDocShell();
|
|
|
|
return docShell && docShell->GetIsPrerendered();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::RedefineProperty(JSContext* aCx, const char* aPropName,
|
2017-11-15 19:34:41 +03:00
|
|
|
JS::Handle<JS::Value> aValue,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
JS::Rooted<JSObject*> thisObj(aCx, GetWrapperPreserveColor());
|
|
|
|
if (!thisObj) {
|
|
|
|
aError.Throw(NS_ERROR_UNEXPECTED);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!JS_WrapObject(aCx, &thisObj) ||
|
|
|
|
!JS_DefineProperty(aCx, thisObj, aPropName, aValue, JSPROP_ENUMERATE)) {
|
|
|
|
aError.Throw(NS_ERROR_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetReplaceableWindowCoord(JSContext* aCx,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsGlobalWindowInner::WindowCoordGetter aGetter,
|
|
|
|
JS::MutableHandle<JS::Value> aRetval,
|
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
int32_t coord = (this->*aGetter)(aCallerType, aError);
|
|
|
|
if (!aError.Failed() &&
|
|
|
|
!ToJSValue(aCx, coord, aRetval)) {
|
|
|
|
aError.Throw(NS_ERROR_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::SetReplaceableWindowCoord(JSContext* aCx,
|
2017-11-15 19:34:41 +03:00
|
|
|
nsGlobalWindowInner::WindowCoordSetter aSetter,
|
|
|
|
JS::Handle<JS::Value> aValue,
|
|
|
|
const char* aPropName,
|
|
|
|
CallerType aCallerType,
|
|
|
|
ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If caller is not chrome and the user has not explicitly exempted the site,
|
|
|
|
* just treat this the way we would an IDL replaceable property.
|
|
|
|
*/
|
|
|
|
nsGlobalWindowOuter* outer = GetOuterWindowInternal();
|
|
|
|
if (!outer ||
|
|
|
|
!outer->CanMoveResizeWindows(aCallerType) ||
|
|
|
|
outer->IsFrame()) {
|
|
|
|
RedefineProperty(aCx, aPropName, aValue, aError);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t value;
|
|
|
|
if (!ValueToPrimitive<int32_t, eDefault>(aCx, aValue, &value)) {
|
|
|
|
aError.Throw(NS_ERROR_UNEXPECTED);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nsContentUtils::ShouldResistFingerprinting(GetDocShell())) {
|
|
|
|
bool innerWidthSpecified = false;
|
|
|
|
bool innerHeightSpecified = false;
|
|
|
|
bool outerWidthSpecified = false;
|
|
|
|
bool outerHeightSpecified = false;
|
|
|
|
|
|
|
|
if (strcmp(aPropName, "innerWidth") == 0) {
|
|
|
|
innerWidthSpecified = true;
|
|
|
|
} else if (strcmp(aPropName, "innerHeight") == 0) {
|
|
|
|
innerHeightSpecified = true;
|
|
|
|
} else if (strcmp(aPropName, "outerWidth") == 0) {
|
|
|
|
outerWidthSpecified = true;
|
|
|
|
} else if (strcmp(aPropName, "outerHeight") == 0) {
|
|
|
|
outerHeightSpecified = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (innerWidthSpecified || innerHeightSpecified ||
|
|
|
|
outerWidthSpecified || outerHeightSpecified)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = outer->GetTreeOwnerWindow();
|
|
|
|
nsCOMPtr<nsIScreen> screen;
|
|
|
|
nsCOMPtr<nsIScreenManager> screenMgr(
|
|
|
|
do_GetService("@mozilla.org/gfx/screenmanager;1"));
|
|
|
|
int32_t winLeft = 0;
|
|
|
|
int32_t winTop = 0;
|
|
|
|
int32_t winWidth = 0;
|
|
|
|
int32_t winHeight = 0;
|
|
|
|
double scale = 1.0;
|
|
|
|
|
|
|
|
|
|
|
|
if (treeOwnerAsWin && screenMgr) {
|
|
|
|
// Acquire current window size.
|
|
|
|
treeOwnerAsWin->GetUnscaledDevicePixelsPerCSSPixel(&scale);
|
|
|
|
treeOwnerAsWin->GetPositionAndSize(&winLeft, &winTop, &winWidth, &winHeight);
|
|
|
|
winLeft = NSToIntRound(winHeight / scale);
|
|
|
|
winTop = NSToIntRound(winWidth / scale);
|
|
|
|
winWidth = NSToIntRound(winWidth / scale);
|
|
|
|
winHeight = NSToIntRound(winHeight / scale);
|
|
|
|
|
|
|
|
// Acquire content window size.
|
|
|
|
CSSIntSize contentSize;
|
|
|
|
outer->GetInnerSize(contentSize);
|
|
|
|
|
|
|
|
screenMgr->ScreenForRect(winLeft, winTop, winWidth, winHeight,
|
|
|
|
getter_AddRefs(screen));
|
|
|
|
|
|
|
|
if (screen) {
|
|
|
|
int32_t* targetContentWidth = nullptr;
|
|
|
|
int32_t* targetContentHeight = nullptr;
|
|
|
|
int32_t screenWidth = 0;
|
|
|
|
int32_t screenHeight = 0;
|
|
|
|
int32_t chromeWidth = 0;
|
|
|
|
int32_t chromeHeight = 0;
|
|
|
|
int32_t inputWidth = 0;
|
|
|
|
int32_t inputHeight = 0;
|
|
|
|
int32_t unused = 0;
|
|
|
|
|
|
|
|
// Get screen dimensions (in device pixels)
|
|
|
|
screen->GetAvailRect(&unused, &unused, &screenWidth,
|
|
|
|
&screenHeight);
|
|
|
|
// Convert them to CSS pixels
|
|
|
|
screenWidth = NSToIntRound(screenWidth / scale);
|
|
|
|
screenHeight = NSToIntRound(screenHeight / scale);
|
|
|
|
|
|
|
|
// Calculate the chrome UI size.
|
|
|
|
chromeWidth = winWidth - contentSize.width;
|
|
|
|
chromeHeight = winHeight - contentSize.height;
|
|
|
|
|
|
|
|
if (innerWidthSpecified || outerWidthSpecified) {
|
|
|
|
inputWidth = value;
|
|
|
|
targetContentWidth = &value;
|
|
|
|
targetContentHeight = &unused;
|
|
|
|
} else if (innerHeightSpecified || outerHeightSpecified) {
|
|
|
|
inputHeight = value;
|
|
|
|
targetContentWidth = &unused;
|
|
|
|
targetContentHeight = &value;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting(
|
|
|
|
chromeWidth,
|
|
|
|
chromeHeight,
|
|
|
|
screenWidth,
|
|
|
|
screenHeight,
|
|
|
|
inputWidth,
|
|
|
|
inputHeight,
|
|
|
|
outerWidthSpecified,
|
|
|
|
outerHeightSpecified,
|
|
|
|
targetContentWidth,
|
|
|
|
targetContentHeight
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
(this->*aSetter)(value, aCallerType, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::FireOnNewGlobalObject()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// AutoEntryScript required to invoke debugger hook, which is a
|
|
|
|
// Gecko-specific concept at present.
|
2017-11-15 19:33:39 +03:00
|
|
|
AutoEntryScript aes(this, "nsGlobalWindowInner report new global");
|
2017-11-15 19:30:13 +03:00
|
|
|
JS::Rooted<JSObject*> global(aes.cx(), GetWrapper());
|
|
|
|
JS_FireOnNewGlobalObject(aes.cx(), global);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef _WINDOWS_
|
|
|
|
#error "Never include windows.h in this file!"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
already_AddRefed<Promise>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::CreateImageBitmap(JSContext* aCx,
|
2017-11-15 19:34:41 +03:00
|
|
|
const ImageBitmapSource& aImage,
|
|
|
|
ErrorResult& aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
|
|
|
|
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ImageBitmap::Create(this, aImage, Nothing(), aRv);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<Promise>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::CreateImageBitmap(JSContext* aCx,
|
2017-11-15 19:34:41 +03:00
|
|
|
const ImageBitmapSource& aImage,
|
|
|
|
int32_t aSx, int32_t aSy, int32_t aSw, int32_t aSh,
|
|
|
|
ErrorResult& aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
|
|
|
|
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ImageBitmap::Create(this, aImage, Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aRv);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<mozilla::dom::Promise>
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::CreateImageBitmap(JSContext* aCx,
|
2017-11-15 19:34:41 +03:00
|
|
|
const ImageBitmapSource& aImage,
|
|
|
|
int32_t aOffset, int32_t aLength,
|
|
|
|
ImageBitmapFormat aFormat,
|
|
|
|
const Sequence<ChannelPixelLayout>& aLayout,
|
|
|
|
ErrorResult& aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
2017-11-30 23:35:32 +03:00
|
|
|
if (!ImageBitmap::ExtensionsEnabled(aCx)) {
|
2017-11-15 19:30:13 +03:00
|
|
|
aRv.Throw(NS_ERROR_TYPE_ERR);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
|
|
|
|
return ImageBitmap::Create(this, aImage, aOffset, aLength, aFormat, aLayout,
|
|
|
|
aRv);
|
|
|
|
}
|
|
|
|
aRv.Throw(NS_ERROR_TYPE_ERR);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::dom::TabGroup*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::TabGroupInner()
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
// If we don't have a TabGroup yet, try to get it from the outer window and
|
|
|
|
// cache it.
|
|
|
|
if (!mTabGroup) {
|
|
|
|
nsGlobalWindowOuter* outer = GetOuterWindowInternal();
|
|
|
|
// This will never be called without either an outer window, or a cached tab group.
|
|
|
|
// This is because of the following:
|
|
|
|
// * This method is only called on inner windows
|
|
|
|
// * This method is called as a document is attached to it's script global
|
|
|
|
// by the document
|
2017-11-15 19:33:39 +03:00
|
|
|
// * Inner windows are created in nsGlobalWindowInner::SetNewDocument, which
|
2017-11-15 19:30:13 +03:00
|
|
|
// immediately sets a document, which will call this method, causing
|
|
|
|
// the TabGroup to be cached.
|
|
|
|
MOZ_RELEASE_ASSERT(outer, "Inner window without outer window has no cached tab group!");
|
|
|
|
mTabGroup = outer->TabGroup();
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(mTabGroup);
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
nsGlobalWindowOuter* outer = GetOuterWindowInternal();
|
|
|
|
MOZ_ASSERT_IF(outer, outer->TabGroup() == mTabGroup);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return mTabGroup;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::Dispatch(TaskCategory aCategory,
|
2017-11-15 19:34:41 +03:00
|
|
|
already_AddRefed<nsIRunnable>&& aRunnable)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
|
|
|
if (GetDocGroup()) {
|
|
|
|
return GetDocGroup()->Dispatch(aCategory, Move(aRunnable));
|
|
|
|
}
|
|
|
|
return DispatcherTrait::Dispatch(aCategory, Move(aRunnable));
|
|
|
|
}
|
|
|
|
|
|
|
|
nsISerialEventTarget*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::EventTargetFor(TaskCategory aCategory) const
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
|
|
|
if (GetDocGroup()) {
|
|
|
|
return GetDocGroup()->EventTargetFor(aCategory);
|
|
|
|
}
|
|
|
|
return DispatcherTrait::EventTargetFor(aCategory);
|
|
|
|
}
|
|
|
|
|
|
|
|
AbstractThread*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::AbstractMainThreadFor(TaskCategory aCategory)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
|
|
|
if (GetDocGroup()) {
|
|
|
|
return GetDocGroup()->AbstractMainThreadFor(aCategory);
|
|
|
|
}
|
|
|
|
return DispatcherTrait::AbstractMainThreadFor(aCategory);
|
|
|
|
}
|
|
|
|
|
|
|
|
Worklet*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetAudioWorklet(ErrorResult& aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mAudioWorklet) {
|
|
|
|
nsIPrincipal* principal = GetPrincipal();
|
|
|
|
if (!principal) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:34:27 +03:00
|
|
|
mAudioWorklet = new Worklet(this, principal, Worklet::eAudioWorklet);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return mAudioWorklet;
|
|
|
|
}
|
|
|
|
|
|
|
|
Worklet*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetPaintWorklet(ErrorResult& aRv)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mPaintWorklet) {
|
|
|
|
nsIPrincipal* principal = GetPrincipal();
|
|
|
|
if (!principal) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:34:27 +03:00
|
|
|
mPaintWorklet = new Worklet(this, principal, Worklet::ePaintWorklet);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return mPaintWorklet;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetRegionalPrefsLocales(nsTArray<nsString>& aLocales)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
AutoTArray<nsCString, 10> rpLocales;
|
|
|
|
mozilla::intl::LocaleService::GetInstance()->GetRegionalPrefsLocales(rpLocales);
|
|
|
|
|
|
|
|
for (const auto& loc : rpLocales) {
|
|
|
|
aLocales.AppendElement(NS_ConvertUTF8toUTF16(loc));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IntlUtils*
|
2017-11-15 19:33:39 +03:00
|
|
|
nsGlobalWindowInner::GetIntlUtils(ErrorResult& aError)
|
2017-11-15 19:30:13 +03:00
|
|
|
{
|
|
|
|
if (!mIntlUtils) {
|
2017-11-15 19:34:27 +03:00
|
|
|
mIntlUtils = new IntlUtils(this);
|
2017-11-15 19:30:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return mIntlUtils;
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:34:33 +03:00
|
|
|
mozilla::dom::TabGroup*
|
|
|
|
nsPIDOMWindowInner::TabGroup()
|
|
|
|
{
|
|
|
|
return nsGlobalWindowInner::Cast(this)->TabGroupInner();
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:30:13 +03:00
|
|
|
/* static */ already_AddRefed<nsGlobalWindowInner>
|
|
|
|
nsGlobalWindowInner::Create(nsGlobalWindowOuter *aOuterWindow, bool aIsChrome)
|
|
|
|
{
|
|
|
|
RefPtr<nsGlobalWindowInner> window = new nsGlobalWindowInner(aOuterWindow);
|
|
|
|
if (aIsChrome) {
|
|
|
|
window->mIsChrome = true;
|
|
|
|
window->mCleanMessageManager = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
window->InitWasOffline();
|
|
|
|
return window.forget();
|
|
|
|
}
|
2017-11-15 19:34:13 +03:00
|
|
|
|
2017-11-21 21:25:27 +03:00
|
|
|
nsIURI*
|
|
|
|
nsPIDOMWindowInner::GetDocumentURI() const
|
|
|
|
{
|
|
|
|
return mDoc ? mDoc->GetDocumentURI() : mDocumentURI.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIURI*
|
|
|
|
nsPIDOMWindowInner::GetDocBaseURI() const
|
|
|
|
{
|
|
|
|
return mDoc ? mDoc->GetDocBaseURI() : mDocBaseURI.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPIDOMWindowInner::MaybeCreateDoc()
|
|
|
|
{
|
|
|
|
// XXX: Forward to outer?
|
|
|
|
MOZ_ASSERT(!mDoc);
|
|
|
|
if (nsIDocShell* docShell = GetDocShell()) {
|
|
|
|
// Note that |document| here is the same thing as our mDoc, but we
|
|
|
|
// don't have to explicitly set the member variable because the docshell
|
|
|
|
// has already called SetNewDocument().
|
|
|
|
nsCOMPtr<nsIDocument> document = docShell->GetDocument();
|
|
|
|
Unused << document;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::dom::DocGroup*
|
|
|
|
nsPIDOMWindowInner::GetDocGroup() const
|
|
|
|
{
|
|
|
|
nsIDocument* doc = GetExtantDoc();
|
|
|
|
if (doc) {
|
|
|
|
return doc->GetDocGroup();
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-11-21 21:47:36 +03:00
|
|
|
// XXX: Can we define this in a header instead of here?
|
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
|
|
extern uint64_t
|
|
|
|
NextWindowID();
|
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter *aOuterWindow)
|
2017-11-21 22:06:28 +03:00
|
|
|
: mMutationBits(0), mActivePeerConnections(0), mIsDocumentLoaded(false),
|
|
|
|
mIsHandlingResizeEvent(false),
|
2017-11-21 21:47:36 +03:00
|
|
|
mMayHavePaintEventListener(false), mMayHaveTouchEventListener(false),
|
|
|
|
mMayHaveSelectionChangeEventListener(false),
|
|
|
|
mMayHaveMouseEnterLeaveEventListener(false),
|
|
|
|
mMayHavePointerEnterLeaveEventListener(false),
|
|
|
|
mInnerObjectsFreed(false),
|
2017-11-21 22:06:28 +03:00
|
|
|
mAudioCaptured(false),
|
2017-11-21 21:47:36 +03:00
|
|
|
mOuterWindow(aOuterWindow),
|
|
|
|
// Make sure no actual window ends up with mWindowID == 0
|
|
|
|
mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
|
2017-11-21 22:06:28 +03:00
|
|
|
mMarkedCCGeneration(0),
|
2017-11-21 21:47:36 +03:00
|
|
|
mHasTriedToCacheTopInnerWindow(false),
|
|
|
|
mNumOfIndexedDBDatabases(0),
|
|
|
|
mNumOfOpenWebSockets(0)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aOuterWindow);
|
|
|
|
}
|
|
|
|
|
2017-11-21 21:25:27 +03:00
|
|
|
nsPIDOMWindowInner::~nsPIDOMWindowInner() {}
|
|
|
|
|
2017-11-15 19:34:13 +03:00
|
|
|
#undef FORWARD_TO_OUTER
|
|
|
|
#undef FORWARD_TO_OUTER_OR_THROW
|
|
|
|
#undef FORWARD_TO_OUTER_VOID
|