mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-15 08:53:07 +09:00
Merge remote-tracking branch 'origin/tracking' into custom
This commit is contained in:
commit
b0345ff809
35 changed files with 789 additions and 133 deletions
|
|
@ -136,7 +136,7 @@ nsDSURIContentListener::DoContent(const nsACString& aContentType,
|
|||
mExistingJPEGRequest = baseChannel;
|
||||
}
|
||||
|
||||
if (rv == NS_ERROR_REMOTE_XUL) {
|
||||
if (rv == NS_ERROR_REMOTE_XUL || rv == NS_ERROR_DOCSHELL_DYING) {
|
||||
aRequest->Cancel(rv);
|
||||
*aAbortProcess = true;
|
||||
return NS_OK;
|
||||
|
|
|
|||
|
|
@ -893,6 +893,8 @@ nsDocShell::~nsDocShell()
|
|||
nsresult
|
||||
nsDocShell::Init()
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
nsresult rv = nsDocLoader::Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
|
@ -1921,6 +1923,8 @@ bool
|
|||
nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest,
|
||||
bool aFireOnLocationChange, uint32_t aLocationFlags)
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
if (gDocShellLeakLog && MOZ_LOG_TEST(gDocShellLeakLog, LogLevel::Debug)) {
|
||||
PR_LogPrint("DOCSHELL %p SetCurrentURI %s\n",
|
||||
this, aURI ? aURI->GetSpecOrDefault().get() : "");
|
||||
|
|
@ -2181,6 +2185,8 @@ nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing)
|
|||
NS_IMETHODIMP
|
||||
nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing)
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
bool changed = aUsePrivateBrowsing != (mPrivateBrowsingId > 0);
|
||||
if (changed) {
|
||||
mPrivateBrowsingId = aUsePrivateBrowsing ? 1 : 0;
|
||||
|
|
@ -2251,6 +2257,8 @@ nsDocShell::SetRemoteTabs(bool aUseRemoteTabs)
|
|||
NS_IMETHODIMP
|
||||
nsDocShell::SetAffectPrivateSessionLifetime(bool aAffectLifetime)
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
bool change = aAffectLifetime != mAffectPrivateSessionLifetime;
|
||||
if (change && UsePrivateBrowsing()) {
|
||||
AssertOriginAttributesMatchPrivateBrowsing();
|
||||
|
|
@ -2753,6 +2761,8 @@ nsDocShell::GetSecurityUI(nsISecureBrowserUI** aSecurityUI)
|
|||
NS_IMETHODIMP
|
||||
nsDocShell::SetSecurityUI(nsISecureBrowserUI* aSecurityUI)
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
mSecurityUI = aSecurityUI;
|
||||
mSecurityUI->SetDocShell(this);
|
||||
return NS_OK;
|
||||
|
|
@ -3935,6 +3945,10 @@ PrintDocTree(nsIDocShellTreeItem* aParentNode)
|
|||
NS_IMETHODIMP
|
||||
nsDocShell::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner)
|
||||
{
|
||||
if (mIsBeingDestroyed && aTreeOwner) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DOCSHELL_FOCUS
|
||||
nsCOMPtr<nsIDocShellTreeItem> item(do_QueryInterface(aTreeOwner));
|
||||
if (item) {
|
||||
|
|
@ -5216,6 +5230,8 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
|
|||
const char* aCSSClass,
|
||||
nsIChannel* aFailedChannel)
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
#if defined(DEBUG)
|
||||
if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)) {
|
||||
nsAutoCString chanName;
|
||||
|
|
@ -5571,6 +5587,8 @@ nsDocShell::SetSessionHistory(nsISHistory* aSessionHistory)
|
|||
// make sure that we are the root docshell and
|
||||
// set a handle to root docshell in SH.
|
||||
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> root;
|
||||
/* Get the root docshell. If *this* is the root docshell
|
||||
* then save a handle to *this* in SH. SH needs it to do
|
||||
|
|
@ -5751,16 +5769,22 @@ nsDocShell::Create()
|
|||
NS_IMETHODIMP
|
||||
nsDocShell::Destroy()
|
||||
{
|
||||
// XXX: We allow this function to be called just once. If you are going to
|
||||
// reset new variables in this function, please make sure the variables will
|
||||
// never be re-initialized. Adding assertions to check |mIsBeingDestroyed|
|
||||
// in the setter functions for the variables would be enough.
|
||||
if (mIsBeingDestroyed) {
|
||||
return NS_ERROR_DOCSHELL_DYING;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,
|
||||
"Unexpected item type in docshell");
|
||||
|
||||
if (!mIsBeingDestroyed) {
|
||||
nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
|
||||
if (serv) {
|
||||
const char* msg = mItemType == typeContent ?
|
||||
NS_WEBNAVIGATION_DESTROY : NS_CHROME_WEBNAVIGATION_DESTROY;
|
||||
serv->NotifyObservers(GetAsSupports(this), msg, nullptr);
|
||||
}
|
||||
nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
|
||||
if (serv) {
|
||||
const char* msg = mItemType == typeContent ?
|
||||
NS_WEBNAVIGATION_DESTROY : NS_CHROME_WEBNAVIGATION_DESTROY;
|
||||
serv->NotifyObservers(GetAsSupports(this), msg, nullptr);
|
||||
}
|
||||
|
||||
mIsBeingDestroyed = true;
|
||||
|
|
@ -6043,6 +6067,7 @@ nsDocShell::GetParentWidget(nsIWidget** aParentWidget)
|
|||
NS_IMETHODIMP
|
||||
nsDocShell::SetParentWidget(nsIWidget* aParentWidget)
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
mParentWidget = aParentWidget;
|
||||
|
||||
return NS_OK;
|
||||
|
|
@ -6313,6 +6338,8 @@ nsDocShell::SetOnePermittedSandboxedNavigator(nsIDocShell* aSandboxedNavigator)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
mOnePermittedSandboxedNavigator = do_GetWeakReference(aSandboxedNavigator);
|
||||
NS_ASSERTION(mOnePermittedSandboxedNavigator,
|
||||
"One Permitted Sandboxed Navigator must support weak references.");
|
||||
|
|
@ -6673,6 +6700,8 @@ nsDocShell::RefreshURI(nsIURI* aURI,
|
|||
bool aMetaRefresh,
|
||||
nsIPrincipal* aPrincipal)
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
NS_ENSURE_ARG(aURI);
|
||||
|
||||
/* Check if Meta refresh/redirects are permitted. Some
|
||||
|
|
@ -8056,6 +8085,10 @@ nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
|
|||
// wrong information :-(
|
||||
//
|
||||
(void)FirePageHideNotification(!mSavingOldViewer);
|
||||
// pagehide notification might destroy this docshell.
|
||||
if (mIsBeingDestroyed) {
|
||||
return NS_ERROR_DOCSHELL_DYING;
|
||||
}
|
||||
}
|
||||
|
||||
// Now make sure we don't think we're in the middle of firing unload after
|
||||
|
|
@ -8199,6 +8232,8 @@ nsDocShell::CanSavePresentation(uint32_t aLoadType,
|
|||
void
|
||||
nsDocShell::ReattachEditorToWindow(nsISHEntry* aSHEntry)
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
NS_ASSERTION(!mEditorData,
|
||||
"Why reattach an editor when we already have one?");
|
||||
NS_ASSERTION(aSHEntry && aSHEntry->HasDetachedEditor(),
|
||||
|
|
@ -8236,6 +8271,9 @@ nsDocShell::DetachEditorFromWindow()
|
|||
if (NS_SUCCEEDED(res)) {
|
||||
// Make mOSHE hold the owning ref to the editor data.
|
||||
if (mOSHE) {
|
||||
MOZ_ASSERT(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor(),
|
||||
"We should not set the editor data again once after we "
|
||||
"detached the editor data during destroying this docshell");
|
||||
mOSHE->SetEditorData(mEditorData.forget());
|
||||
} else {
|
||||
mEditorData = nullptr;
|
||||
|
|
@ -8422,6 +8460,8 @@ nsDocShell::GetRestoringDocument(bool* aRestoring)
|
|||
nsresult
|
||||
nsDocShell::RestorePresentation(nsISHEntry* aSHEntry, bool* aRestoring)
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
NS_ASSERTION(mLoadType & LOAD_CMD_HISTORY,
|
||||
"RestorePresentation should only be called for history loads");
|
||||
|
||||
|
|
@ -8583,6 +8623,10 @@ nsDocShell::RestoreFromHistory()
|
|||
|
||||
// Notify the old content viewer that it's being hidden.
|
||||
FirePageHideNotification(!mSavingOldViewer);
|
||||
// pagehide notification might destroy this docshell.
|
||||
if (mIsBeingDestroyed) {
|
||||
return NS_ERROR_DOCSHELL_DYING;
|
||||
}
|
||||
|
||||
// If mLSHE was changed as a result of the pagehide event, then
|
||||
// something else was loaded. Don't finish restoring.
|
||||
|
|
@ -9040,6 +9084,12 @@ nsDocShell::CreateContentViewer(const nsACString& aContentType,
|
|||
{
|
||||
*aContentHandler = nullptr;
|
||||
|
||||
if (!mTreeOwner || mIsBeingDestroyed) {
|
||||
// If we don't have a tree owner, then we're in the process of being
|
||||
// destroyed. Rather than continue trying to load something, just give up.
|
||||
return NS_ERROR_DOCSHELL_DYING;
|
||||
}
|
||||
|
||||
// Can we check the content type of the current content viewer
|
||||
// and reuse it without destroying it and re-creating it?
|
||||
|
||||
|
|
@ -9079,6 +9129,11 @@ nsDocShell::CreateContentViewer(const nsACString& aContentType,
|
|||
aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI));
|
||||
}
|
||||
FirePageHideNotification(!mSavingOldViewer);
|
||||
if (mIsBeingDestroyed) {
|
||||
// Force to stop the newly created orphaned viewer.
|
||||
viewer->Stop();
|
||||
return NS_ERROR_DOCSHELL_DYING;
|
||||
}
|
||||
mLoadingURI = nullptr;
|
||||
|
||||
// Set mFiredUnloadEvent = false so that the unload handler for the
|
||||
|
|
@ -9268,6 +9323,8 @@ nsDocShell::NewContentViewerObj(const nsACString& aContentType,
|
|||
nsresult
|
||||
nsDocShell::SetupNewViewer(nsIContentViewer* aNewViewer)
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
//
|
||||
// Copy content viewer state from previous or parent content viewer.
|
||||
//
|
||||
|
|
@ -13460,6 +13517,8 @@ nsDocShell::EnsureScriptEnvironment()
|
|||
NS_IMETHODIMP
|
||||
nsDocShell::EnsureEditorData()
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
bool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor();
|
||||
if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) {
|
||||
// We shouldn't recreate the editor data if it already exists, or
|
||||
|
|
@ -13475,6 +13534,8 @@ nsDocShell::EnsureEditorData()
|
|||
nsresult
|
||||
nsDocShell::EnsureTransferableHookData()
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
if (!mTransferableHookData) {
|
||||
mTransferableHookData = new nsTransferableHookData();
|
||||
}
|
||||
|
|
@ -14562,6 +14623,8 @@ nsDocShell::CanSetOriginAttributes()
|
|||
nsresult
|
||||
nsDocShell::SetOriginAttributes(const DocShellOriginAttributes& aAttrs)
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
|
||||
if (!CanSetOriginAttributes()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,14 @@ DOMIntersectionObserver::Constructor(const mozilla::dom::GlobalObject& aGlobal,
|
|||
RefPtr<DOMIntersectionObserver> observer =
|
||||
new DOMIntersectionObserver(window.forget(), aCb);
|
||||
|
||||
observer->mRoot = aOptions.mRoot;
|
||||
if (!aOptions.mRoot.IsNull()) {
|
||||
if (aOptions.mRoot.Value().IsElement()) {
|
||||
observer->mRoot = aOptions.mRoot.Value().GetAsElement();
|
||||
} else {
|
||||
MOZ_ASSERT(aOptions.mRoot.Value().IsDocument());
|
||||
observer->mRoot = aOptions.mRoot.Value().GetAsDocument();
|
||||
}
|
||||
}
|
||||
|
||||
if (!observer->SetRootMargin(aOptions.mRootMargin)) {
|
||||
aRv.ThrowDOMException(NS_ERROR_DOM_SYNTAX_ERR,
|
||||
|
|
@ -258,6 +265,30 @@ EdgeInclusiveIntersection(const nsRect& aRect, const nsRect& aOtherRect)
|
|||
return Some(nsRect(left, top, right - left, bottom - top));
|
||||
}
|
||||
|
||||
// NOTE: This returns nullptr if |aDocument| is in a cross process.
|
||||
static nsIDocument* GetTopLevelDocument(const nsIDocument& aDocument) {
|
||||
nsCOMPtr<nsIPresShell> presShell = aDocument.GetShell();
|
||||
|
||||
if (presShell) {
|
||||
nsIFrame* rootFrame = presShell->GetRootScrollFrame();
|
||||
if (rootFrame) {
|
||||
nsPresContext* presContext = rootFrame->PresContext();
|
||||
while (!presContext->IsRootContentDocument()) {
|
||||
// Walk up the tree
|
||||
presContext = presContext->GetParentPresContext();
|
||||
if (!presContext) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(presContext && presContext->IsRootContentDocument()) {
|
||||
return presContext->Document();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
enum class BrowsingContextInfo {
|
||||
SimilarOriginBrowsingContext,
|
||||
DifferentOriginBrowsingContext,
|
||||
|
|
@ -267,14 +298,12 @@ enum class BrowsingContextInfo {
|
|||
void
|
||||
DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time)
|
||||
{
|
||||
Element* root = nullptr;
|
||||
nsINode* root = mRoot;
|
||||
nsIFrame* rootFrame = nullptr;
|
||||
nsRect rootRect;
|
||||
|
||||
if (mRoot) {
|
||||
root = mRoot;
|
||||
rootFrame = root->GetPrimaryFrame();
|
||||
if (rootFrame) {
|
||||
if (mRoot && mRoot->IsElement()) {
|
||||
if ((rootFrame = mRoot->AsElement()->GetPrimaryFrame())) {
|
||||
nsRect rootRectRelativeToRootFrame;
|
||||
if (rootFrame->GetType() == nsGkAtoms::scrollFrame) {
|
||||
// rootRectRelativeToRootFrame should be the content rect of rootFrame, not including the scrollbars.
|
||||
|
|
@ -292,30 +321,18 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time
|
|||
containingBlock);
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsIPresShell> presShell = aDocument->GetShell();
|
||||
if (presShell) {
|
||||
rootFrame = presShell->GetRootScrollFrame();
|
||||
if (rootFrame) {
|
||||
nsPresContext* presContext = rootFrame->PresContext();
|
||||
while (!presContext->IsRootContentDocument()) {
|
||||
// Walk up the tree
|
||||
presContext = presContext->GetParentPresContext();
|
||||
if (!presContext) {
|
||||
break;
|
||||
MOZ_ASSERT(!mRoot || mRoot->IsInUncomposedDoc());
|
||||
nsIDocument* rootDocument =
|
||||
mRoot ? mRoot->GetUncomposedDoc() : GetTopLevelDocument(*aDocument);
|
||||
if (rootDocument) {
|
||||
if (nsIPresShell* presShell = rootDocument->GetShell()) {
|
||||
rootFrame = presShell->GetRootScrollFrame();
|
||||
if (rootFrame) {
|
||||
root = rootFrame->GetContent()->AsElement();
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
|
||||
if (scrollFrame) {
|
||||
rootRect = scrollFrame->GetScrollPortRect();
|
||||
}
|
||||
nsIFrame* rootScrollFrame = presContext->PresShell()->GetRootScrollFrame();
|
||||
if (rootScrollFrame) {
|
||||
rootFrame = rootScrollFrame;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
root = rootFrame->GetContent()->AsElement();
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
|
||||
// If we end up with a null root frame for some reason, we'll proceed
|
||||
// with an empty root intersection rect.
|
||||
if (scrollFrame) {
|
||||
rootRect = scrollFrame->GetScrollPortRect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ public:
|
|||
return mOwner;
|
||||
}
|
||||
|
||||
Element* GetRoot() const {
|
||||
nsINode* GetRoot() const {
|
||||
return mRoot;
|
||||
}
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ protected:
|
|||
nsCOMPtr<nsPIDOMWindowInner> mOwner;
|
||||
RefPtr<nsIDocument> mDocument;
|
||||
RefPtr<mozilla::dom::IntersectionCallback> mCallback;
|
||||
RefPtr<Element> mRoot;
|
||||
RefPtr<nsINode> mRoot;
|
||||
nsCSSRect mRootMargin;
|
||||
nsTArray<double> mThresholds;
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ nsContentSink::nsContentSink()
|
|||
, mDeferredFlushTags(0)
|
||||
, mIsDocumentObserver(0)
|
||||
, mRunsToCompletion(0)
|
||||
, mIsBlockingOnload(false)
|
||||
, mDeflectedCount(0)
|
||||
, mHasPendingEvent(false)
|
||||
, mCurrentParseEndTime(0)
|
||||
|
|
@ -1539,8 +1540,14 @@ nsContentSink::DropParserAndPerfHint(void)
|
|||
FavorPerformanceHint(true, 0);
|
||||
}
|
||||
|
||||
if (!mRunsToCompletion) {
|
||||
// Call UnblockOnload only if mRunsToComletion is false and if
|
||||
// we have already started loading because it's possible that this function
|
||||
// is called (i.e. the parser is terminated) before we start loading due to
|
||||
// destroying the window inside unload event callbacks for the previous
|
||||
// document.
|
||||
if (!mRunsToCompletion && mIsBlockingOnload) {
|
||||
mDocument->UnblockOnload(true);
|
||||
mIsBlockingOnload = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1595,6 +1602,7 @@ nsContentSink::WillBuildModelImpl()
|
|||
{
|
||||
if (!mRunsToCompletion) {
|
||||
mDocument->BlockOnload();
|
||||
mIsBlockingOnload = true;
|
||||
|
||||
mBeginLoadTime = PR_IntervalToMicroseconds(PR_IntervalNow());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -304,6 +304,8 @@ protected:
|
|||
// True if this is parser is a fragment parser or an HTML DOMParser.
|
||||
// XML DOMParser leaves this to false for now!
|
||||
uint8_t mRunsToCompletion : 1;
|
||||
// True if we are blocking load event.
|
||||
bool mIsBlockingOnload : 1;
|
||||
|
||||
//
|
||||
// -- Can interrupt parsing members --
|
||||
|
|
|
|||
|
|
@ -5444,6 +5444,14 @@ nsContentUtils::AddPendingIDBTransaction(already_AddRefed<nsIRunnable> aTransact
|
|||
CycleCollectedJSContext::Get()->AddPendingIDBTransaction(Move(aTransaction));
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
nsContentUtils::IsInStableOrMetaStableState()
|
||||
{
|
||||
MOZ_ASSERT(CycleCollectedJSContext::Get(), "Must be on a script thread!");
|
||||
return CycleCollectedJSContext::Get()->IsInStableOrMetaStableState();
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for nsContentUtils::ProcessViewportInfo.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1779,6 +1779,11 @@ public:
|
|||
*/
|
||||
static void AddPendingIDBTransaction(already_AddRefed<nsIRunnable> aTransaction);
|
||||
|
||||
/**
|
||||
* Returns true if we are doing StableState/MetastableState.
|
||||
*/
|
||||
static bool IsInStableOrMetaStableState();
|
||||
|
||||
/* Process viewport META data. This gives us information for the scale
|
||||
* and zoom of a page on mobile devices. We stick the information in
|
||||
* the document header and use it later on after rendering.
|
||||
|
|
|
|||
|
|
@ -269,6 +269,7 @@ nsRange::nsRange(nsINode* aNode)
|
|||
, mStartOffsetWasIncremented(false)
|
||||
, mEndOffsetWasIncremented(false)
|
||||
, mEnableGravitationOnElementRemoval(true)
|
||||
, mCalledByJS(false)
|
||||
#ifdef DEBUG
|
||||
, mAssertNextInsertOrAppendIndex(-1)
|
||||
, mAssertNextInsertOrAppendNode(nullptr)
|
||||
|
|
@ -997,7 +998,16 @@ nsRange::DoSetRange(nsINode* aStartN, uint32_t aStartOffset,
|
|||
// Notify any selection listeners. This has to occur last because otherwise the world
|
||||
// could be observed by a selection listener while the range was in an invalid state.
|
||||
if (mSelection) {
|
||||
mSelection->NotifySelectionListeners();
|
||||
// Our internal code should not move focus with using this instance while
|
||||
// it's calling Selection::NotifySelectionListeners() which may move focus
|
||||
// or calls selection listeners. So, let's set mCalledByJS to false here
|
||||
// since non-*JS() methods don't set it to false.
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = false;
|
||||
// Be aware, this range may be modified or stop being a range for selection
|
||||
// after this call. Additionally, the selection instance may have gone.
|
||||
RefPtr<Selection> selection = mSelection;
|
||||
selection->NotifySelectionListeners(calledByJSRestorer.SavedValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1224,6 +1234,14 @@ nsRange::IsValidBoundary(nsINode* aNode)
|
|||
return root;
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetStartJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SetStart(aNode, aOffset, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetStart(nsINode& aNode, uint32_t aOffset, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -1279,6 +1297,14 @@ nsRange::SetStart(nsINode* aParent, uint32_t aOffset)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetStartBeforeJS(nsINode& aNode, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SetStartBefore(aNode, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetStartBefore(nsINode& aNode, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -1310,6 +1336,14 @@ nsRange::SetStartBefore(nsIDOMNode* aSibling)
|
|||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetStartAfterJS(nsINode& aNode, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SetStartAfter(aNode, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetStartAfter(nsINode& aNode, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -1341,6 +1375,14 @@ nsRange::SetStartAfter(nsIDOMNode* aSibling)
|
|||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetEndJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SetEnd(aNode, aOffset, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetEnd(nsINode& aNode, uint32_t aOffset, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -1455,6 +1497,14 @@ nsRange::SetStartAndEnd(nsINode* aStartParent, uint32_t aStartOffset,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetEndBeforeJS(nsINode& aNode, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SetEndBefore(aNode, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetEndBefore(nsINode& aNode, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -1486,6 +1536,14 @@ nsRange::SetEndBefore(nsIDOMNode* aSibling)
|
|||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetEndAfterJS(nsINode& aNode, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SetEndAfter(aNode, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetEndAfter(nsINode& aNode, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -1532,6 +1590,14 @@ nsRange::Collapse(bool aToStart)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::CollapseJS(bool aToStart)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
Unused << Collapse(aToStart);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsRange::SelectNode(nsIDOMNode* aN)
|
||||
{
|
||||
|
|
@ -1543,6 +1609,14 @@ nsRange::SelectNode(nsIDOMNode* aN)
|
|||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SelectNodeJS(nsINode& aNode, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SelectNode(aNode, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SelectNode(nsINode& aNode, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -1582,6 +1656,14 @@ nsRange::SelectNodeContents(nsIDOMNode* aN)
|
|||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SelectNodeContentsJS(nsINode& aNode, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SelectNodeContents(aNode, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SelectNodeContents(nsINode& aNode, ErrorResult& aRv)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "nsStubMutationObserver.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/GuardObjects.h"
|
||||
|
||||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
|
|
@ -256,14 +257,20 @@ public:
|
|||
void InsertNode(nsINode& aNode, ErrorResult& aErr);
|
||||
bool IntersectsNode(nsINode& aNode, ErrorResult& aRv);
|
||||
bool IsPointInRange(nsINode& aParent, uint32_t aOffset, ErrorResult& aErr);
|
||||
void SelectNode(nsINode& aNode, ErrorResult& aErr);
|
||||
void SelectNodeContents(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetEnd(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
|
||||
void SetEndAfter(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetEndBefore(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetStart(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
|
||||
void SetStartAfter(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetStartBefore(nsINode& aNode, ErrorResult& aErr);
|
||||
|
||||
// *JS() methods are mapped to Range.*() of DOM.
|
||||
// They may move focus only when the range represents normal selection.
|
||||
// These methods shouldn't be used from internal.
|
||||
void CollapseJS(bool aToStart);
|
||||
void SelectNodeJS(nsINode& aNode, ErrorResult& aErr);
|
||||
void SelectNodeContentsJS(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetEndJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
|
||||
void SetEndAfterJS(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetEndBeforeJS(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetStartJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
|
||||
void SetStartAfterJS(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetStartBeforeJS(nsINode& aNode, ErrorResult& aErr);
|
||||
|
||||
void SurroundContents(nsINode& aNode, ErrorResult& aErr);
|
||||
already_AddRefed<DOMRect> GetBoundingClientRect(bool aClampToEdge = true,
|
||||
bool aFlushLayout = true);
|
||||
|
|
@ -272,6 +279,17 @@ public:
|
|||
void GetClientRectsAndTexts(
|
||||
mozilla::dom::ClientRectsAndTexts& aResult,
|
||||
ErrorResult& aErr);
|
||||
|
||||
// Following methods should be used for internal use instead of *JS().
|
||||
void SelectNode(nsINode& aNode, ErrorResult& aErr);
|
||||
void SelectNodeContents(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetEnd(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
|
||||
void SetEndAfter(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetEndBefore(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetStart(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
|
||||
void SetStartAfter(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetStartBefore(nsINode& aNode, ErrorResult& aErr);
|
||||
|
||||
static void GetInnerTextNoFlush(mozilla::dom::DOMString& aValue,
|
||||
mozilla::ErrorResult& aError,
|
||||
nsIContent* aStartParent,
|
||||
|
|
@ -392,6 +410,31 @@ protected:
|
|||
size_t aRangeStart,
|
||||
size_t aRangeEnd);
|
||||
|
||||
// Assume that this is guaranteed that this is held by the caller when
|
||||
// this is used. (Note that we cannot use AutoRestore for mCalledByJS
|
||||
// due to a bit field.)
|
||||
class MOZ_RAII AutoCalledByJSRestore final
|
||||
{
|
||||
private:
|
||||
nsRange& mRange;
|
||||
bool mOldValue;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
public:
|
||||
explicit AutoCalledByJSRestore(nsRange& aRange
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mRange(aRange)
|
||||
, mOldValue(aRange.mCalledByJS)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
~AutoCalledByJSRestore()
|
||||
{
|
||||
mRange.mCalledByJS = mOldValue;
|
||||
}
|
||||
bool SavedValue() const { return mOldValue; }
|
||||
};
|
||||
|
||||
struct MOZ_STACK_CLASS AutoInvalidateSelection
|
||||
{
|
||||
explicit AutoInvalidateSelection(nsRange* aRange) : mRange(aRange)
|
||||
|
|
@ -428,6 +471,7 @@ protected:
|
|||
bool mStartOffsetWasIncremented : 1;
|
||||
bool mEndOffsetWasIncremented : 1;
|
||||
bool mEnableGravitationOnElementRemoval : 1;
|
||||
bool mCalledByJS : 1;
|
||||
#ifdef DEBUG
|
||||
int32_t mAssertNextInsertOrAppendIndex;
|
||||
nsINode* mAssertNextInsertOrAppendNode;
|
||||
|
|
|
|||
|
|
@ -693,6 +693,13 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
|
|||
NS_ENSURE_TRUE(aEvent->mMessage || !aDOMEvent || aTargets,
|
||||
NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
|
||||
// Events shall not be fired while we are in stable state to prevent anything
|
||||
// visible from the scripts.
|
||||
// See comment in CycleCollectedJSContext::AfterProcessMicrotasks for why we allow it anyway.
|
||||
// MOZ_ASSERT(!nsContentUtils::IsInStableOrMetaStableState());
|
||||
// NS_ENSURE_TRUE(!nsContentUtils::IsInStableOrMetaStableState(),
|
||||
// NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
|
||||
#ifdef MOZ_TASK_TRACER
|
||||
{
|
||||
if (aDOMEvent) {
|
||||
|
|
|
|||
|
|
@ -3105,6 +3105,26 @@ HTMLInputElement::GetFiles()
|
|||
return mFileList;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::SetFiles(FileList* aFiles)
|
||||
{
|
||||
if (mType != NS_FORM_INPUT_FILE || !aFiles) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear |mFileList| to omit |UpdateFileList|
|
||||
if (mFileList) {
|
||||
mFileList->Clear();
|
||||
mFileList = nullptr;
|
||||
}
|
||||
|
||||
// Update |mFilesOrDirectories|
|
||||
SetFiles(aFiles, true);
|
||||
|
||||
// Update |mFileList| without copy
|
||||
mFileList = aFiles;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
HTMLInputElement::HandleNumberControlSpin(void* aData)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -474,6 +474,7 @@ public:
|
|||
// XPCOM GetForm() is OK
|
||||
|
||||
FileList* GetFiles();
|
||||
void SetFiles(FileList* aFiles);
|
||||
|
||||
// XPCOM GetFormAction() is OK
|
||||
void SetFormAction(const nsAString& aValue, ErrorResult& aRv)
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
#include "MediaDecoder.h"
|
||||
#include "MediaPrefs.h"
|
||||
#include "MediaResource.h"
|
||||
#include "MediaShutdownManager.h"
|
||||
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
|
|
@ -3203,6 +3204,13 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
|
|||
NotifyOwnerDocumentActivityChanged();
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// We initialize the MediaShutdownManager as the HTMLMediaElement is always
|
||||
// constructed on the main thread, and not during stable state.
|
||||
// (MediaShutdownManager make use of nsIAsyncShutdownClient which is written
|
||||
// in JS)
|
||||
MediaShutdownManager::InitStatics();
|
||||
|
||||
mWatchManager.Watch(mDownloadSuspendedByCache, &HTMLMediaElement::UpdateReadyStateInternal);
|
||||
// Paradoxically, there is a self-edge whereby UpdateReadyStateInternal refuses
|
||||
// to run until mReadyState reaches at least HAVE_METADATA by some other means.
|
||||
|
|
|
|||
|
|
@ -264,14 +264,16 @@ void
|
|||
HTMLTrackElement::DispatchLoadResource()
|
||||
{
|
||||
if (!mLoadResourceDispatched) {
|
||||
RefPtr<Runnable> r = NewRunnableMethod(this, &HTMLTrackElement::LoadResource);
|
||||
RefPtr<WebVTTListener> listener = new WebVTTListener(this);
|
||||
RefPtr<Runnable> r = NewRunnableMethod<RefPtr<WebVTTListener>>(this,
|
||||
&HTMLTrackElement::LoadResource, std::move(listener));
|
||||
nsContentUtils::RunInStableState(r.forget());
|
||||
mLoadResourceDispatched = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HTMLTrackElement::LoadResource()
|
||||
HTMLTrackElement::LoadResource(RefPtr<WebVTTListener>&& aWebVTTListener)
|
||||
{
|
||||
mLoadResourceDispatched = false;
|
||||
|
||||
|
|
@ -317,33 +319,46 @@ HTMLTrackElement::LoadResource()
|
|||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = OwnerDoc()->GetDocumentLoadGroup();
|
||||
rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
uri,
|
||||
static_cast<Element*>(this),
|
||||
secFlags,
|
||||
nsIContentPolicy::TYPE_INTERNAL_TRACK,
|
||||
loadGroup,
|
||||
nullptr, // aCallbacks
|
||||
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI);
|
||||
|
||||
NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv));
|
||||
|
||||
mListener = new WebVTTListener(this);
|
||||
mListener = std::move(aWebVTTListener);
|
||||
// This will do 6. Set the text track readiness state to loading.
|
||||
rv = mListener->LoadResource();
|
||||
NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv));
|
||||
channel->SetNotificationCallbacks(mListener);
|
||||
|
||||
LOG(LogLevel::Debug, ("opening webvtt channel"));
|
||||
rv = channel->AsyncOpen2(mListener);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
SetReadyState(TextTrackReadyState::FailedToLoad);
|
||||
nsIDocument* doc = OwnerDoc();
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
mChannel = channel;
|
||||
// 9. End the synchronous section, continuing the remaining steps in parallel.
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
[ self = RefPtr<HTMLTrackElement>(this), uri, secFlags ]() {
|
||||
if (!self->mListener) {
|
||||
// Shutdown got called, abort.
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = self->OwnerDoc()->GetDocumentLoadGroup();
|
||||
nsresult rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
uri,
|
||||
static_cast<Element*>(self),
|
||||
secFlags,
|
||||
nsIContentPolicy::TYPE_INTERNAL_TRACK,
|
||||
loadGroup,
|
||||
nullptr, // aCallbacks
|
||||
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI);
|
||||
NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv));
|
||||
|
||||
channel->SetNotificationCallbacks(self->mListener);
|
||||
|
||||
LOG(LogLevel::Debug, ("opening webvtt channel"));
|
||||
rv = channel->AsyncOpen2(self->mListener);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
self->SetReadyState(TextTrackReadyState::FailedToLoad);
|
||||
return;
|
||||
}
|
||||
self->mChannel = channel;
|
||||
}));
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
|||
|
|
@ -118,9 +118,6 @@ protected:
|
|||
virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
void OnChannelRedirect(nsIChannel* aChannel, nsIChannel* aNewChannel,
|
||||
uint32_t aFlags);
|
||||
// Open a new channel to the HTMLTrackElement's src attribute and call
|
||||
// mListener's LoadResource().
|
||||
void LoadResource();
|
||||
|
||||
friend class TextTrackCue;
|
||||
friend class WebVTTListener;
|
||||
|
|
@ -134,6 +131,9 @@ protected:
|
|||
|
||||
private:
|
||||
void DispatchLoadResource();
|
||||
// Open a new channel to the HTMLTrackElement's src attribute and call
|
||||
// mListener's LoadResource().
|
||||
void LoadResource(RefPtr<WebVTTListener>&& aWebVTTListener);
|
||||
bool mLoadResourceDispatched;
|
||||
|
||||
RefPtr<WindowDestroyObserver> mWindowDestroyObserver;
|
||||
|
|
|
|||
|
|
@ -602,6 +602,17 @@ void
|
|||
TextTrackManager::TimeMarchesOn()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
CycleCollectedJSContext* context = CycleCollectedJSContext::Get();
|
||||
if (context && context->IsInStableOrMetaStableState()) {
|
||||
// FireTimeUpdate can be called while at stable state following a
|
||||
// current position change which triggered a state watcher in MediaDecoder
|
||||
// (see bug 1443429).
|
||||
// TimeMarchesOn() will modify JS attributes which is forbidden while in
|
||||
// stable state. So we dispatch a task to perform such operation later
|
||||
// instead.
|
||||
DispatchTimeMarchesOn();
|
||||
return;
|
||||
}
|
||||
WEBVTT_LOG("TimeMarchesOn");
|
||||
mTimeMarchesOnDispatched = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -453,8 +453,6 @@ MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
|
|||
mWatchManager.Watch(mLogicallySeeking, &MediaDecoder::SeekingChanged);
|
||||
|
||||
mWatchManager.Watch(mIsAudioDataAudible, &MediaDecoder::NotifyAudibleStateChanged);
|
||||
|
||||
MediaShutdownManager::InitStatics();
|
||||
}
|
||||
|
||||
#undef INIT_MIRROR
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebVTTListener.h"
|
||||
#include "mozilla/CycleCollectedJSContext.h"
|
||||
#include "mozilla/dom/TextTrackCue.h"
|
||||
#include "mozilla/dom/TextTrackRegion.h"
|
||||
#include "mozilla/dom/VTTRegionBinding.h"
|
||||
|
|
@ -34,9 +35,22 @@ LazyLogModule gTextTrackLog("TextTrack");
|
|||
|
||||
WebVTTListener::WebVTTListener(HTMLTrackElement* aElement)
|
||||
: mElement(aElement)
|
||||
, mParserWrapperError(NS_OK)
|
||||
{
|
||||
MOZ_ASSERT(mElement, "Must pass an element to the callback");
|
||||
VTT_LOG("WebVTTListener created.");
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
CycleCollectedJSContext::Get() &&
|
||||
!CycleCollectedJSContext::Get()->IsInStableOrMetaStableState());
|
||||
mParserWrapper = do_CreateInstance(NS_WEBVTTPARSERWRAPPER_CONTRACTID,
|
||||
&mParserWrapperError);
|
||||
if (NS_SUCCEEDED(mParserWrapperError)) {
|
||||
nsPIDOMWindowInner* window = mElement->OwnerDoc()->GetInnerWindow();
|
||||
mParserWrapperError = mParserWrapper->LoadParser(window);
|
||||
}
|
||||
if (NS_SUCCEEDED(mParserWrapperError)) {
|
||||
mParserWrapperError = mParserWrapper->Watch(this);
|
||||
}
|
||||
}
|
||||
|
||||
WebVTTListener::~WebVTTListener()
|
||||
|
|
@ -54,16 +68,8 @@ WebVTTListener::GetInterface(const nsIID &aIID,
|
|||
nsresult
|
||||
WebVTTListener::LoadResource()
|
||||
{
|
||||
nsresult rv;
|
||||
mParserWrapper = do_CreateInstance(NS_WEBVTTPARSERWRAPPER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsPIDOMWindowInner* window = mElement->OwnerDoc()->GetInnerWindow();
|
||||
rv = mParserWrapper->LoadParser(window);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mParserWrapper->Watch(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Exit if we failed to create the WebVTTParserWrapper (vtt.jsm)
|
||||
NS_ENSURE_SUCCESS(mParserWrapperError, mParserWrapperError);
|
||||
|
||||
mElement->SetReadyState(TextTrackReadyState::Loading);
|
||||
return NS_OK;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ private:
|
|||
|
||||
RefPtr<HTMLTrackElement> mElement;
|
||||
nsCOMPtr<nsIWebVTTParserWrapper> mParserWrapper;
|
||||
nsresult mParserWrapperError;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
|||
|
|
@ -59,15 +59,30 @@ public:
|
|||
switch (event) {
|
||||
case MediaStreamGraphEvent::EVENT_FINISHED:
|
||||
{
|
||||
RefPtr<SynthStreamListener> self = this;
|
||||
if (!mStarted) {
|
||||
mStarted = true;
|
||||
nsCOMPtr<nsIRunnable> startRunnable =
|
||||
NewRunnableMethod(this, &SynthStreamListener::DoNotifyStarted);
|
||||
nsCOMPtr<nsIRunnable> startRunnable = NS_NewRunnableFunction(
|
||||
[self] {
|
||||
// "start" event will be fired in DoNotifyStarted() which is
|
||||
// not allowed in stable state, so we do it asynchronously in
|
||||
// next run.
|
||||
NS_DispatchToMainThread(NewRunnableMethod(
|
||||
self,
|
||||
&SynthStreamListener::DoNotifyStarted));
|
||||
});
|
||||
aGraph->DispatchToMainThreadAfterStreamStateUpdate(startRunnable.forget());
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> endRunnable =
|
||||
NewRunnableMethod(this, &SynthStreamListener::DoNotifyFinished);
|
||||
nsCOMPtr<nsIRunnable> endRunnable = NS_NewRunnableFunction(
|
||||
[self] {
|
||||
// "end" event will be fired in DoNotifyFinished() which is
|
||||
// not allowed in stable state, so we do it asynchronously in
|
||||
// next run.
|
||||
NS_DispatchToMainThread(NewRunnableMethod(
|
||||
self,
|
||||
&SynthStreamListener::DoNotifyFinished));
|
||||
});
|
||||
aGraph->DispatchToMainThreadAfterStreamStateUpdate(endRunnable.forget());
|
||||
}
|
||||
break;
|
||||
|
|
@ -85,8 +100,16 @@ public:
|
|||
{
|
||||
if (aBlocked == MediaStreamListener::UNBLOCKED && !mStarted) {
|
||||
mStarted = true;
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NewRunnableMethod(this, &SynthStreamListener::DoNotifyStarted);
|
||||
RefPtr<SynthStreamListener> self = this;
|
||||
nsCOMPtr<nsIRunnable> event = NS_NewRunnableFunction(
|
||||
[self] {
|
||||
// "start" event will be fired in DoNotifyStarted() which is
|
||||
// not allowed in stable state, so we do it asynchronously in
|
||||
// next run.
|
||||
NS_DispatchToMainThread(NewRunnableMethod(
|
||||
self,
|
||||
&SynthStreamListener::DoNotifyStarted));
|
||||
});
|
||||
aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ interface HTMLInputElement : HTMLElement {
|
|||
attribute boolean disabled;
|
||||
readonly attribute HTMLFormElement? form;
|
||||
[Pure]
|
||||
readonly attribute FileList? files;
|
||||
attribute FileList? files;
|
||||
[CEReactions, Pure, SetterThrows]
|
||||
attribute DOMString formAction;
|
||||
[CEReactions, Pure, SetterThrows]
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ interface IntersectionObserverEntry {
|
|||
Pref="dom.intersectionObserver.enabled"]
|
||||
interface IntersectionObserver {
|
||||
[Constant]
|
||||
readonly attribute Element? root;
|
||||
readonly attribute Node? root;
|
||||
[Constant]
|
||||
readonly attribute DOMString rootMargin;
|
||||
[Constant,Cached]
|
||||
|
|
@ -56,7 +56,7 @@ dictionary IntersectionObserverEntryInit {
|
|||
};
|
||||
|
||||
dictionary IntersectionObserverInit {
|
||||
Element? root = null;
|
||||
(Element or Document)? root = null;
|
||||
DOMString rootMargin = "0px";
|
||||
(double or sequence<double>) threshold = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -26,22 +26,23 @@ interface Range {
|
|||
[Throws]
|
||||
readonly attribute Node commonAncestorContainer;
|
||||
|
||||
[Throws]
|
||||
[Throws, BinaryName="setStartJS"]
|
||||
void setStart(Node refNode, unsigned long offset);
|
||||
[Throws]
|
||||
[Throws, BinaryName="setEndJS"]
|
||||
void setEnd(Node refNode, unsigned long offset);
|
||||
[Throws]
|
||||
[Throws, BinaryName="setStartBeforeJS"]
|
||||
void setStartBefore(Node refNode);
|
||||
[Throws]
|
||||
[Throws, BinaryName="setStartAfterJS"]
|
||||
void setStartAfter(Node refNode);
|
||||
[Throws]
|
||||
[Throws, BinaryName="setEndBeforeJS"]
|
||||
void setEndBefore(Node refNode);
|
||||
[Throws]
|
||||
[Throws, BinaryName="setEndAfterJS"]
|
||||
void setEndAfter(Node refNode);
|
||||
[BinaryName="collapseJS"]
|
||||
void collapse(optional boolean toStart = false);
|
||||
[Throws]
|
||||
[Throws, BinaryName="selectNodeJS"]
|
||||
void selectNode(Node refNode);
|
||||
[Throws]
|
||||
[Throws, BinaryName="selectNodeContentsJS"]
|
||||
void selectNodeContents(Node refNode);
|
||||
|
||||
const unsigned short START_TO_START = 0;
|
||||
|
|
|
|||
|
|
@ -17,17 +17,17 @@ interface Selection {
|
|||
readonly attribute unsigned long focusOffset;
|
||||
|
||||
readonly attribute boolean isCollapsed;
|
||||
[Throws]
|
||||
[Throws, BinaryName="collapseJS"]
|
||||
void collapse(Node node, unsigned long offset);
|
||||
[Throws]
|
||||
[Throws, BinaryName="collapseToStartJS"]
|
||||
void collapseToStart();
|
||||
[Throws]
|
||||
[Throws, BinaryName="collapseToEndJS"]
|
||||
void collapseToEnd();
|
||||
|
||||
[Throws]
|
||||
[Throws, BinaryName="extendJS"]
|
||||
void extend(Node node, unsigned long offset);
|
||||
|
||||
[Throws]
|
||||
[Throws, BinaryName="selectAllChildrenJS"]
|
||||
void selectAllChildren(Node node);
|
||||
[Throws]
|
||||
void deleteFromDocument();
|
||||
|
|
@ -36,7 +36,7 @@ interface Selection {
|
|||
readonly attribute DOMString type;
|
||||
[Throws]
|
||||
Range getRangeAt(unsigned long index);
|
||||
[Throws]
|
||||
[Throws, BinaryName="addRangeJS"]
|
||||
void addRange(Range range);
|
||||
[Throws]
|
||||
void removeRange(Range range);
|
||||
|
|
@ -46,7 +46,7 @@ interface Selection {
|
|||
[Throws]
|
||||
boolean containsNode(Node node, boolean allowPartialContainment);
|
||||
|
||||
[Throws]
|
||||
[Throws, BinaryName="setBaseAndExtentJS"]
|
||||
void setBaseAndExtent(Node anchorNode,
|
||||
unsigned long anchorOffset,
|
||||
Node focusNode,
|
||||
|
|
|
|||
|
|
@ -3082,6 +3082,8 @@ void
|
|||
ServiceWorkerManager::FireControllerChange(ServiceWorkerRegistrationInfo* aRegistration)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
AutoTArray<nsCOMPtr<nsIDocument>, 16> documents;
|
||||
for (auto iter = mControlledDocuments.Iter(); !iter.Done(); iter.Next()) {
|
||||
if (iter.UserData() != aRegistration) {
|
||||
continue;
|
||||
|
|
@ -3092,6 +3094,12 @@ ServiceWorkerManager::FireControllerChange(ServiceWorkerRegistrationInfo* aRegis
|
|||
continue;
|
||||
}
|
||||
|
||||
documents.AppendElement(doc);
|
||||
}
|
||||
|
||||
// Fire event after iterating mControlledDocuments is done to prevent
|
||||
// modification by reentering from the event handlers during iteration.
|
||||
for (auto& doc : documents) {
|
||||
FireControllerChangeOnDocument(doc);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ WORKER_SIMPLE_PREF("browser.dom.window.dump.enabled", DumpEnabled, DUMP)
|
|||
WORKER_SIMPLE_PREF("canvas.imagebitmap_extensions.enabled", ImageBitmapExtensionsEnabled, IMAGEBITMAP_EXTENSIONS_ENABLED)
|
||||
WORKER_SIMPLE_PREF("dom.caches.enabled", DOMCachesEnabled, DOM_CACHES)
|
||||
WORKER_SIMPLE_PREF("dom.caches.testing.enabled", DOMCachesTestingEnabled, DOM_CACHES_TESTING)
|
||||
WORKER_SIMPLE_PREF("dom.min_timeout_value", DOMMinTimeoutValue, DOM_MIN_TIMEOUT_VALUE)
|
||||
WORKER_SIMPLE_PREF("dom.performance.enable_user_timing_logging", PerformanceLoggingEnabled, PERFORMANCE_LOGGING_ENABLED)
|
||||
WORKER_SIMPLE_PREF("dom.webnotifications.enabled", DOMWorkerNotificationEnabled, DOM_WORKERNOTIFICATION)
|
||||
WORKER_SIMPLE_PREF("dom.webnotifications.serviceworker.enabled", DOMServiceWorkerNotificationEnabled, DOM_SERVICEWORKERNOTIFICATION)
|
||||
|
|
|
|||
|
|
@ -1995,13 +1995,22 @@ struct WorkerPrivate::TimeoutInfo
|
|||
mNestingLevel = kClampTimeoutNestingLevel;
|
||||
}
|
||||
|
||||
void CalculateTargetTime() {
|
||||
void CalculateTargetTime(JSContext* aCx) {
|
||||
auto target = mInterval;
|
||||
int32_t minTimeoutValue;
|
||||
|
||||
// We're on a worker thread; go through WorkerPrivate for the pref.
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
if (workerPrivate) {
|
||||
minTimeoutValue = workerPrivate->DOMMinTimeoutValue();
|
||||
} else {
|
||||
// fall back to default 4 ms
|
||||
minTimeoutValue = 4;
|
||||
}
|
||||
|
||||
// Clamp timeout for workers, except chrome workers
|
||||
if (mNestingLevel >= kClampTimeoutNestingLevel && !mOnChromeWorker) {
|
||||
target = TimeDuration::Max(
|
||||
mInterval,
|
||||
TimeDuration::FromMilliseconds(Preferences::GetInt("dom.min_timeout_value")));
|
||||
target = TimeDuration::Max(mInterval,TimeDuration::FromMilliseconds(minTimeoutValue));
|
||||
}
|
||||
mTargetTime = TimeStamp::Now() + target;
|
||||
}
|
||||
|
|
@ -6387,7 +6396,7 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx)
|
|||
// Reschedule intervals.
|
||||
// Reschedule a timeout and, if needed, increase the nesting level.
|
||||
info->AccumulateNestingLevel(info->mNestingLevel);
|
||||
info->CalculateTargetTime();
|
||||
info->CalculateTargetTime(aCx);
|
||||
// Don't re-sort the list here, we'll do that at the end.
|
||||
++index;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1771,6 +1771,9 @@ PresShell::Initialize(nscoord aWidth, nscoord aHeight)
|
|||
// (Do this in a script runner, since our caller might have a script
|
||||
// blocker on the stack.)
|
||||
nsContentUtils::AddScriptRunner(new XBLConstructorRunner(mDocument));
|
||||
|
||||
// XBLConstructorRunner might destroy us.
|
||||
NS_ENSURE_STATE(!mHaveShutDown);
|
||||
}
|
||||
|
||||
NS_ASSERTION(rootFrame, "How did that happen?");
|
||||
|
|
|
|||
|
|
@ -21,8 +21,12 @@
|
|||
struct CachedOffsetForFrame;
|
||||
class nsAutoScrollTimer;
|
||||
class nsIContentIterator;
|
||||
class nsIDocument;
|
||||
class nsIEditor;
|
||||
class nsIFrame;
|
||||
class nsIHTMLEditor;
|
||||
class nsFrameSelection;
|
||||
class nsPIDOMWindowOuter;
|
||||
struct SelectionDetails;
|
||||
class nsCopySupport;
|
||||
class nsHTMLCopyEncoder;
|
||||
|
|
@ -170,13 +174,19 @@ public:
|
|||
uint32_t FocusOffset();
|
||||
|
||||
bool IsCollapsed() const;
|
||||
void Collapse(nsINode& aNode, uint32_t aOffset, mozilla::ErrorResult& aRv);
|
||||
void CollapseToStart(mozilla::ErrorResult& aRv);
|
||||
void CollapseToEnd(mozilla::ErrorResult& aRv);
|
||||
// *JS() methods are mapped to Selection.*().
|
||||
// They may move focus only when the range represents normal selection.
|
||||
// These methods shouldn't be used by non-JS callers.
|
||||
void CollapseJS(nsINode& aNode, uint32_t aOffset,
|
||||
mozilla::ErrorResult& aRv);
|
||||
void CollapseToStartJS(mozilla::ErrorResult& aRv);
|
||||
void CollapseToEndJS(mozilla::ErrorResult& aRv);
|
||||
|
||||
void Extend(nsINode& aNode, uint32_t aOffset, mozilla::ErrorResult& aRv);
|
||||
void ExtendJS(nsINode& aNode, uint32_t aOffset,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
void SelectAllChildrenJS(nsINode& aNode, mozilla::ErrorResult& aRv);
|
||||
|
||||
void SelectAllChildren(nsINode& aNode, mozilla::ErrorResult& aRv);
|
||||
void DeleteFromDocument(mozilla::ErrorResult& aRv);
|
||||
|
||||
uint32_t RangeCount() const
|
||||
|
|
@ -187,7 +197,7 @@ public:
|
|||
void GetType(nsAString& aOutType) const;
|
||||
|
||||
nsRange* GetRangeAt(uint32_t aIndex, mozilla::ErrorResult& aRv);
|
||||
void AddRange(nsRange& aRange, mozilla::ErrorResult& aRv);
|
||||
void AddRangeJS(nsRange& aRange, mozilla::ErrorResult& aRv);
|
||||
void RemoveRange(nsRange& aRange, mozilla::ErrorResult& aRv);
|
||||
void RemoveAllRanges(mozilla::ErrorResult& aRv);
|
||||
|
||||
|
|
@ -207,9 +217,9 @@ public:
|
|||
void Modify(const nsAString& aAlter, const nsAString& aDirection,
|
||||
const nsAString& aGranularity, mozilla::ErrorResult& aRv);
|
||||
|
||||
void SetBaseAndExtent(nsINode& aAnchorNode, uint32_t aAnchorOffset,
|
||||
nsINode& aFocusNode, uint32_t aFocusOffset,
|
||||
mozilla::ErrorResult& aRv);
|
||||
void SetBaseAndExtentJS(nsINode& aAnchorNode, uint32_t aAnchorOffset,
|
||||
nsINode& aFocusNode, uint32_t aFocusOffset,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
bool GetInterlinePosition(mozilla::ErrorResult& aRv);
|
||||
void SetInterlinePosition(bool aValue, mozilla::ErrorResult& aRv);
|
||||
|
|
@ -243,6 +253,17 @@ public:
|
|||
int16_t aVPercent, int16_t aHPercent,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
// Non-JS callers should use the following methods.
|
||||
void Collapse(nsINode& aNode, uint32_t aOffset, mozilla::ErrorResult& aRv);
|
||||
void CollapseToStart(mozilla::ErrorResult& aRv);
|
||||
void CollapseToEnd(mozilla::ErrorResult& aRv);
|
||||
void Extend(nsINode& aNode, uint32_t aOffset, mozilla::ErrorResult& aRv);
|
||||
void AddRange(nsRange& aRange, mozilla::ErrorResult& aRv);
|
||||
void SelectAllChildren(nsINode& aNode, mozilla::ErrorResult& aRv);
|
||||
void SetBaseAndExtent(nsINode& aAnchorNode, uint32_t aAnchorOffset,
|
||||
nsINode& aFocusNode, uint32_t aFocusOffset,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
void AddSelectionChangeBlocker();
|
||||
void RemoveSelectionChangeBlocker();
|
||||
bool IsBlockingSelectionChangeEvents() const;
|
||||
|
|
@ -265,7 +286,8 @@ public:
|
|||
mSelectionType = aSelectionType;
|
||||
}
|
||||
|
||||
nsresult NotifySelectionListeners();
|
||||
nsresult NotifySelectionListeners(bool aCalledByJS);
|
||||
nsresult NotifySelectionListeners();
|
||||
|
||||
friend struct AutoUserInitiated;
|
||||
struct MOZ_RAII AutoUserInitiated
|
||||
|
|
@ -341,6 +363,43 @@ private:
|
|||
*/
|
||||
nsresult AddItemInternal(nsRange* aRange, int32_t* aOutIndex);
|
||||
|
||||
nsIDocument* GetDocument() const;
|
||||
nsPIDOMWindowOuter* GetWindow() const;
|
||||
nsIEditor* GetEditor() const;
|
||||
|
||||
/**
|
||||
* GetCommonEditingHostForAllRanges() returns common editing host of all
|
||||
* ranges if there is. If at least one of the ranges is in non-editable
|
||||
* element, returns nullptr. See following examples for the detail:
|
||||
*
|
||||
* <div id="a" contenteditable>
|
||||
* an[cestor
|
||||
* <div id="b" contenteditable="false">
|
||||
* non-editable
|
||||
* <div id="c" contenteditable>
|
||||
* desc]endant
|
||||
* in this case, this returns div#a because div#c is also in div#a.
|
||||
*
|
||||
* <div id="a" contenteditable>
|
||||
* an[ce]stor
|
||||
* <div id="b" contenteditable="false">
|
||||
* non-editable
|
||||
* <div id="c" contenteditable>
|
||||
* de[sc]endant
|
||||
* in this case, this returns div#a because second range is also in div#a
|
||||
* and common ancestor of the range (i.e., div#c) is editable.
|
||||
*
|
||||
* <div id="a" contenteditable>
|
||||
* an[ce]stor
|
||||
* <div id="b" contenteditable="false">
|
||||
* [non]-editable
|
||||
* <div id="c" contenteditable>
|
||||
* de[sc]endant
|
||||
* in this case, this returns nullptr because the second range is in
|
||||
* non-editable area.
|
||||
*/
|
||||
Element* GetCommonEditingHostForAllRanges();
|
||||
|
||||
// These are the ranges inside this selection. They are kept sorted in order
|
||||
// of DOM start position.
|
||||
//
|
||||
|
|
@ -371,6 +430,12 @@ private:
|
|||
*/
|
||||
bool mUserInitiated;
|
||||
|
||||
/**
|
||||
* When the selection change is caused by a call of Selection API,
|
||||
* mCalledByJS is true. Otherwise, false.
|
||||
*/
|
||||
bool mCalledByJS;
|
||||
|
||||
// Non-zero if we don't want any changes we make to the selection to be
|
||||
// visible to content. If non-zero, content won't be notified about changes.
|
||||
uint32_t mSelectionChangeBlockerCount;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/dom/Selection.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
#include "mozilla/EventStates.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
|
|
@ -84,6 +85,7 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
|
|||
#include "nsIEditor.h"
|
||||
#include "nsIHTMLEditor.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
|
@ -1199,7 +1201,7 @@ Selection::ToString(nsAString& aReturn)
|
|||
aReturn.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
shell->FlushPendingNotifications(Flush_Style);
|
||||
shell->FlushPendingNotifications(Flush_Frames);
|
||||
|
||||
return ToStringWithFormat("text/plain",
|
||||
nsIDocumentEncoder::SkipInvisibleContent,
|
||||
|
|
@ -1876,6 +1878,7 @@ printf(" * TakeFocus - moving into new cell\n");
|
|||
// Don't notify selection listeners if batching is on:
|
||||
if (GetBatching())
|
||||
return NS_OK;
|
||||
// Be aware, the Selection instance may be destroyed after this call.
|
||||
return NotifySelectionListeners(SelectionType::eNormal);
|
||||
}
|
||||
|
||||
|
|
@ -1916,6 +1919,7 @@ nsFrameSelection::SetDragState(bool aState)
|
|||
mDragSelectingCells = false;
|
||||
// Notify that reason is mouse up.
|
||||
PostReason(nsISelectionListener::MOUSEUP_REASON);
|
||||
// Be aware, the Selection instance may be destroyed after this call.
|
||||
NotifySelectionListeners(SelectionType::eNormal);
|
||||
}
|
||||
}
|
||||
|
|
@ -2410,6 +2414,7 @@ nsFrameSelection::EndBatchChanges(int16_t aReason)
|
|||
int16_t postReason = PopReason() | aReason;
|
||||
PostReason(postReason);
|
||||
mChangesDuringBatching = false;
|
||||
// Be aware, the Selection instance may be destroyed after this call.
|
||||
NotifySelectionListeners(SelectionType::eNormal);
|
||||
}
|
||||
}
|
||||
|
|
@ -2421,7 +2426,8 @@ nsFrameSelection::NotifySelectionListeners(SelectionType aSelectionType)
|
|||
int8_t index = GetIndexFromSelectionType(aSelectionType);
|
||||
if (index >=0 && mDomSelections[index])
|
||||
{
|
||||
return mDomSelections[index]->NotifySelectionListeners();
|
||||
RefPtr<Selection> selection = mDomSelections[index];
|
||||
return selection->NotifySelectionListeners();
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
@ -3473,6 +3479,7 @@ Selection::Selection()
|
|||
, mDirection(eDirNext)
|
||||
, mSelectionType(SelectionType::eNormal)
|
||||
, mUserInitiated(false)
|
||||
, mCalledByJS(false)
|
||||
, mSelectionChangeBlockerCount(0)
|
||||
{
|
||||
}
|
||||
|
|
@ -3483,6 +3490,7 @@ Selection::Selection(nsFrameSelection* aList)
|
|||
, mDirection(eDirNext)
|
||||
, mSelectionType(SelectionType::eNormal)
|
||||
, mUserInitiated(false)
|
||||
, mCalledByJS(false)
|
||||
, mSelectionChangeBlockerCount(0)
|
||||
{
|
||||
}
|
||||
|
|
@ -4943,7 +4951,10 @@ Selection::RemoveAllRanges(ErrorResult& aRv)
|
|||
RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
|
||||
frameSelection->ClearTableCellSelection();
|
||||
|
||||
// Be aware, this instance may be destroyed after this call.
|
||||
// XXX Why doesn't this call Selection::NotifySelectionListener() directly?
|
||||
result = frameSelection->NotifySelectionListeners(GetType());
|
||||
|
||||
// Also need to notify the frames!
|
||||
// PresShell::CharacterDataChanged should do that on DocumentChanged
|
||||
if (NS_FAILED(result)) {
|
||||
|
|
@ -4966,6 +4977,14 @@ Selection::AddRange(nsIDOMRange* aDOMRange)
|
|||
return result.StealNSResult();
|
||||
}
|
||||
|
||||
void
|
||||
Selection::AddRangeJS(nsRange& aRange, ErrorResult& aRv)
|
||||
{
|
||||
AutoRestore<bool> calledFromJSRestorer(mCalledByJS);
|
||||
mCalledByJS = true;
|
||||
AddRange(aRange, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
Selection::AddRange(nsRange& aRange, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -5020,6 +5039,8 @@ Selection::AddRangeInternal(nsRange& aRange, nsIDocument* aDocument,
|
|||
if (!mFrameSelection)
|
||||
return;//nothing to do
|
||||
|
||||
// Be aware, this instance may be destroyed after this call.
|
||||
// XXX Why doesn't this call Selection::NotifySelectionListener() directly?
|
||||
RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
|
||||
result = frameSelection->NotifySelectionListeners(GetType());
|
||||
if (NS_FAILED(result)) {
|
||||
|
|
@ -5115,6 +5136,9 @@ Selection::RemoveRange(nsRange& aRange, ErrorResult& aRv)
|
|||
|
||||
if (!mFrameSelection)
|
||||
return;//nothing to do
|
||||
|
||||
// Be aware, this instance may be destroyed after this call.
|
||||
// XXX Why doesn't this call Selection::NotifySelectionListener() directly?
|
||||
RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
|
||||
rv = frameSelection->NotifySelectionListeners(GetType());
|
||||
if (NS_FAILED(rv)) {
|
||||
|
|
@ -5140,6 +5164,14 @@ Selection::CollapseNative(nsINode* aParentNode, int32_t aOffset)
|
|||
return Collapse(aParentNode, aOffset);
|
||||
}
|
||||
|
||||
void
|
||||
Selection::CollapseJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aRv)
|
||||
{
|
||||
AutoRestore<bool> calledFromJSRestorer(mCalledByJS);
|
||||
mCalledByJS = true;
|
||||
Collapse(aNode, aOffset, aRv);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Selection::Collapse(nsINode* aParentNode, int32_t aOffset)
|
||||
{
|
||||
|
|
@ -5222,6 +5254,9 @@ Selection::Collapse(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv)
|
|||
}
|
||||
setAnchorFocusRange(0);
|
||||
selectFrames(presContext, range, true);
|
||||
|
||||
// Be aware, this instance may be destroyed after this call.
|
||||
// XXX Why doesn't this call Selection::NotifySelectionListener() directly?
|
||||
result = frameSelection->NotifySelectionListeners(GetType());
|
||||
if (NS_FAILED(result)) {
|
||||
aRv.Throw(result);
|
||||
|
|
@ -5240,6 +5275,14 @@ Selection::CollapseToStart()
|
|||
return result.StealNSResult();
|
||||
}
|
||||
|
||||
void
|
||||
Selection::CollapseToStartJS(ErrorResult& aRv)
|
||||
{
|
||||
AutoRestore<bool> calledFromJSRestorer(mCalledByJS);
|
||||
mCalledByJS = true;
|
||||
CollapseToStart(aRv);
|
||||
}
|
||||
|
||||
void
|
||||
Selection::CollapseToStart(ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -5281,6 +5324,14 @@ Selection::CollapseToEnd()
|
|||
return result.StealNSResult();
|
||||
}
|
||||
|
||||
void
|
||||
Selection::CollapseToEndJS(ErrorResult& aRv)
|
||||
{
|
||||
AutoRestore<bool> calledFromJSRestorer(mCalledByJS);
|
||||
mCalledByJS = true;
|
||||
CollapseToEnd(aRv);
|
||||
}
|
||||
|
||||
void
|
||||
Selection::CollapseToEnd(ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -5495,6 +5546,14 @@ Selection::ExtendNative(nsINode* aParentNode, int32_t aOffset)
|
|||
return Extend(aParentNode, aOffset);
|
||||
}
|
||||
|
||||
void
|
||||
Selection::ExtendJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aRv)
|
||||
{
|
||||
AutoRestore<bool> calledFromJSRestorer(mCalledByJS);
|
||||
mCalledByJS = true;
|
||||
Extend(aNode, aOffset, aRv);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Selection::Extend(nsINode* aParentNode, int32_t aOffset)
|
||||
{
|
||||
|
|
@ -5773,6 +5832,9 @@ Selection::Extend(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv)
|
|||
printf ("Sel. Extend to %p %s %d\n", content.get(),
|
||||
nsAtomCString(content->NodeInfo()->NameAtom()).get(), aOffset);
|
||||
#endif
|
||||
|
||||
// Be aware, this instance may be destroyed after this call.
|
||||
// XXX Why doesn't this call Selection::NotifySelectionListener() directly?
|
||||
RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
|
||||
res = frameSelection->NotifySelectionListeners(GetType());
|
||||
if (NS_FAILED(res)) {
|
||||
|
|
@ -5790,6 +5852,14 @@ Selection::SelectAllChildren(nsIDOMNode* aParentNode)
|
|||
return result.StealNSResult();
|
||||
}
|
||||
|
||||
void
|
||||
Selection::SelectAllChildrenJS(nsINode& aNode, ErrorResult& aRv)
|
||||
{
|
||||
AutoRestore<bool> calledFromJSRestorer(mCalledByJS);
|
||||
mCalledByJS = true;
|
||||
SelectAllChildren(aNode, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
Selection::SelectAllChildren(nsINode& aNode, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -5938,6 +6008,30 @@ Selection::GetPresShell() const
|
|||
return mFrameSelection->GetShell();
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
Selection::GetDocument() const
|
||||
{
|
||||
nsIPresShell* presShell = GetPresShell();
|
||||
return presShell ? presShell->GetDocument() : nullptr;
|
||||
}
|
||||
|
||||
nsPIDOMWindowOuter*
|
||||
Selection::GetWindow() const
|
||||
{
|
||||
nsIDocument* document = GetDocument();
|
||||
return document ? document->GetWindow() : nullptr;
|
||||
}
|
||||
|
||||
nsIEditor*
|
||||
Selection::GetEditor() const
|
||||
{
|
||||
nsPresContext* presContext = GetPresContext();
|
||||
if (!presContext) {
|
||||
return nullptr;
|
||||
}
|
||||
return nsContentUtils::GetHTMLEditor(presContext);
|
||||
}
|
||||
|
||||
nsIFrame *
|
||||
Selection::GetSelectionAnchorGeometry(SelectionRegion aRegion, nsRect* aRect)
|
||||
{
|
||||
|
|
@ -6239,12 +6333,101 @@ Selection::RemoveSelectionListener(nsISelectionListener* aListenerToRemove,
|
|||
}
|
||||
}
|
||||
|
||||
Element*
|
||||
Selection::GetCommonEditingHostForAllRanges()
|
||||
{
|
||||
Element* editingHost = nullptr;
|
||||
for (RangeData& rangeData : mRanges) {
|
||||
nsRange* range = rangeData.mRange;
|
||||
MOZ_ASSERT(range);
|
||||
nsINode* commonAncestorNode = range->GetCommonAncestor();
|
||||
if (!commonAncestorNode || !commonAncestorNode->IsContent()) {
|
||||
return nullptr;
|
||||
}
|
||||
nsIContent* commonAncestor = commonAncestorNode->AsContent();
|
||||
Element* foundEditingHost = commonAncestor->GetEditingHost();
|
||||
// Even when common ancestor is a non-editable element in a contenteditable
|
||||
// element, we don't need to move focus to the contenteditable element
|
||||
// because Chromium doesn't set focus to it.
|
||||
if (!foundEditingHost) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!editingHost) {
|
||||
editingHost = foundEditingHost;
|
||||
continue;
|
||||
}
|
||||
if (editingHost == foundEditingHost) {
|
||||
continue;
|
||||
}
|
||||
if (nsContentUtils::ContentIsDescendantOf(foundEditingHost, editingHost)) {
|
||||
continue;
|
||||
}
|
||||
if (nsContentUtils::ContentIsDescendantOf(editingHost, foundEditingHost)) {
|
||||
editingHost = foundEditingHost;
|
||||
continue;
|
||||
}
|
||||
// editingHost and foundEditingHost are not a descendant of the other.
|
||||
// So, there is no common editing host.
|
||||
return nullptr;
|
||||
}
|
||||
return editingHost;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Selection::NotifySelectionListeners(bool aCalledByJS)
|
||||
{
|
||||
AutoRestore<bool> calledFromJSRestorer(mCalledByJS);
|
||||
mCalledByJS = aCalledByJS;
|
||||
return NotifySelectionListeners();
|
||||
}
|
||||
|
||||
nsresult
|
||||
Selection::NotifySelectionListeners()
|
||||
{
|
||||
if (!mFrameSelection)
|
||||
return NS_OK;//nothing to do
|
||||
|
||||
// Our internal code should not move focus with using this class while
|
||||
// this moves focus nor from selection listeners.
|
||||
AutoRestore<bool> calledByJSRestorer(mCalledByJS);
|
||||
mCalledByJS = false;
|
||||
|
||||
// When normal selection is changed by Selection API, we need to move focus
|
||||
// if common ancestor of all ranges are in an editing host. Note that we
|
||||
// don't need to move focus *to* the other focusable node, because other
|
||||
// browsers don't do this, either.
|
||||
if (mSelectionType == SelectionType::eNormal &&
|
||||
calledByJSRestorer.SavedValue()) {
|
||||
nsPIDOMWindowOuter* window = GetWindow();
|
||||
nsIDocument* document = GetDocument();
|
||||
// If the document is in design mode or doesn't have contenteditable
|
||||
// element, we don't need to move focus.
|
||||
if (window && document && !document->HasFlag(NODE_IS_EDITABLE) &&
|
||||
GetEditor()) {
|
||||
RefPtr<Element> newEditingHost = GetCommonEditingHostForAllRanges();
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
|
||||
nsIContent* focusedContent =
|
||||
fm->GetFocusedDescendant(window, false, getter_AddRefs(focusedWindow));
|
||||
nsCOMPtr<Element> focusedElement = do_QueryInterface(focusedContent);
|
||||
// When all selected ranges are in an editing host, it should take focus.
|
||||
if (newEditingHost && newEditingHost != focusedElement) {
|
||||
MOZ_ASSERT(!newEditingHost->IsInNativeAnonymousSubtree());
|
||||
nsCOMPtr<nsIDOMElement> domElementToFocus =
|
||||
do_QueryInterface(newEditingHost->AsDOMNode());
|
||||
// Note that don't steal focus from focused window if the window
|
||||
// doesn't have focus. Additionally, when an element gets focus,
|
||||
// we usually scroll to the element, but in this case we shouldn't
|
||||
// do that because Blink&Gecko don't do this.
|
||||
fm->SetFocus(domElementToFocus, nsIFocusManager::FLAG_NOSWITCHFRAME |
|
||||
nsIFocusManager::FLAG_NOSCROLL);
|
||||
}
|
||||
// Otherwise, we shouldn't move focus since Blink&Gecko don't move
|
||||
// focus; only the selection range is updated. This is a bit weird but
|
||||
// it is what it is and we should act the same for parity.
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
|
||||
if (frameSelection->GetBatching()) {
|
||||
frameSelection->SetDirty();
|
||||
|
|
@ -6454,6 +6637,19 @@ Selection::Modify(const nsAString& aAlter, const nsAString& aDirection,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Selection::SetBaseAndExtentJS(nsINode& aAnchorNode,
|
||||
uint32_t aAnchorOffset,
|
||||
nsINode& aFocusNode,
|
||||
uint32_t aFocusOffset,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AutoRestore<bool> calledFromJSRestorer(mCalledByJS);
|
||||
mCalledByJS = true;
|
||||
SetBaseAndExtent(aAnchorNode, aAnchorOffset,
|
||||
aFocusNode, aFocusOffset, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
Selection::SetBaseAndExtent(nsINode& aAnchorNode, uint32_t aAnchorOffset,
|
||||
nsINode& aFocusNode, uint32_t aFocusOffset,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
#include "mozilla/LinkedList.h"
|
||||
|
||||
#include "nsCORSListenerProxy.h"
|
||||
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "HttpChannelChild.h"
|
||||
|
|
@ -1507,6 +1509,9 @@ nsCORSListenerProxy::StartCORSPreflight(nsIChannel* aRequestChannel,
|
|||
method, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
RefPtr<nsIHttpChannel> reqCh = do_QueryObject(aRequestChannel);
|
||||
RefPtr<nsIHttpChannel> preCh = do_QueryObject(preHttp);
|
||||
|
||||
nsTArray<nsCString> preflightHeaders;
|
||||
if (!aUnsafeHeaders.IsEmpty()) {
|
||||
for (uint32_t i = 0; i < aUnsafeHeaders.Length(); ++i) {
|
||||
|
|
@ -1535,6 +1540,23 @@ nsCORSListenerProxy::StartCORSPreflight(nsIChannel* aRequestChannel,
|
|||
rv = preflightChannel->SetNotificationCallbacks(preflightListener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (reqCh && preCh) {
|
||||
// Per https://fetch.spec.whatwg.org/#cors-preflight-fetch step 1, the
|
||||
// request's referrer and referrer policy should match the original request.
|
||||
// Note that RFC 9110 says we SHOULD NOT send referrers on insecure requests
|
||||
// which CORS preflights by definition are, so there's a conflict here, but
|
||||
// since this is expected behaviour in mainstream implementations, we get and
|
||||
// send the referrer on CORS preflights here. See issue #2451
|
||||
uint32_t referrerPolicy = nsIHttpChannel::REFERRER_POLICY_UNSET;
|
||||
rv = reqCh->GetReferrerPolicy(&referrerPolicy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIURI> requestReferrerURI;
|
||||
rv = reqCh->GetReferrer(getter_AddRefs(requestReferrerURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = preCh->SetReferrerWithPolicy(requestReferrerURI, referrerPolicy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Start preflight
|
||||
rv = preflightChannel->AsyncOpen2(preflightListener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
|||
|
|
@ -1394,6 +1394,8 @@ CycleCollectedJSContext::ProcessStableStateQueue()
|
|||
MOZ_RELEASE_ASSERT(!mDoingStableStates);
|
||||
mDoingStableStates = true;
|
||||
|
||||
// When run, one event can add another event to the mStableStateEvents, as
|
||||
// such you can't use iterators here.
|
||||
for (uint32_t i = 0; i < mStableStateEvents.Length(); ++i) {
|
||||
nsCOMPtr<nsIRunnable> event = mStableStateEvents[i].forget();
|
||||
event->Run();
|
||||
|
|
@ -1477,11 +1479,33 @@ CycleCollectedJSContext::AfterProcessMicrotasks()
|
|||
}
|
||||
// Cleanup Indexed Database transactions:
|
||||
// https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint
|
||||
CleanupIDBTransactions(RecursionDepth());
|
||||
|
||||
// We should only ever get here from PerformMicroTaskCheckPoint after a task or other
|
||||
// checkpoint-able state, never from within ProcessStableStateQueue (mDoingStableStates==false).
|
||||
// However, some buggy XUL addons may dispatch JS Events from runnables in the StableState queue,
|
||||
// which then perform a checkpoint at their end, ending up here while ProcessStableStateQueue is
|
||||
// on the stack.
|
||||
// Specifically catch that here and add the call to CleanupIDBTransactions to the outer queue, to
|
||||
// be performed when we know we're in a "regular" stable state again.
|
||||
if (!mDoingStableStates) {
|
||||
CleanupIDBTransactions(RecursionDepth());
|
||||
} else {
|
||||
// Don't need a RefPtr to this here as we know this->ProcessStableStateQueue is on the stack
|
||||
nsCOMPtr<nsIRunnable> cleanupRunnable = NS_NewRunnableFunction(
|
||||
[this, rec = RecursionDepth()] {
|
||||
MOZ_ASSERT(mDoingStableStates);
|
||||
// As this is called from ProcessStableStateQueue, mDoingStableStates == true.
|
||||
// Switch the flag while CleanupIDBTransactions executes.
|
||||
mDoingStableStates = false;
|
||||
CleanupIDBTransactions(rec);
|
||||
mDoingStableStates = true;
|
||||
});
|
||||
RunInStableState(cleanupRunnable.forget());
|
||||
};
|
||||
}
|
||||
|
||||
uint32_t
|
||||
CycleCollectedJSContext::RecursionDepth()
|
||||
CycleCollectedJSContext::RecursionDepth() const
|
||||
{
|
||||
return mOwningThread->RecursionDepth();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ public:
|
|||
virtual void BeforeProcessTask(bool aMightBlock);
|
||||
virtual void AfterProcessTask(uint32_t aRecursionDepth);
|
||||
|
||||
uint32_t RecursionDepth();
|
||||
uint32_t RecursionDepth() const;
|
||||
|
||||
// Run in stable state (call through nsContentUtils)
|
||||
void RunInStableState(already_AddRefed<nsIRunnable>&& aRunnable);
|
||||
|
|
@ -397,12 +397,12 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
bool IsInMicroTask()
|
||||
bool IsInMicroTask() const
|
||||
{
|
||||
return mMicroTaskLevel != 0;
|
||||
}
|
||||
|
||||
uint32_t MicroTaskLevel()
|
||||
uint32_t MicroTaskLevel() const
|
||||
{
|
||||
return mMicroTaskLevel;
|
||||
}
|
||||
|
|
@ -416,6 +416,11 @@ public:
|
|||
|
||||
void PerformDebuggerMicroTaskCheckpoint();
|
||||
|
||||
bool IsInStableOrMetaStableState() const
|
||||
{
|
||||
return mDoingStableStates;
|
||||
}
|
||||
|
||||
// Storage for watching rejected promises waiting for some client to
|
||||
// consume their rejection.
|
||||
|
||||
|
|
|
|||
|
|
@ -247,6 +247,9 @@
|
|||
ERROR(NS_ERROR_REMOTE_XUL, FAILURE(75)),
|
||||
/* The request resulted in an error page being displayed. */
|
||||
ERROR(NS_ERROR_LOAD_SHOWED_ERRORPAGE, FAILURE(77)),
|
||||
/* The request occurred in docshell that lacks a treeowner, so it is
|
||||
* probably in the process of being torn down. */
|
||||
ERROR(NS_ERROR_DOCSHELL_DYING, FAILURE(78)),
|
||||
|
||||
|
||||
/* FTP specific error codes: */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue