/* -*- 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/. */
LocalAccessible* DocManager::FindAccessibleInCache(nsINode* aNode) const { for (constauto& docAccessible : mDocAccessibleCache.Values()) {
NS_ASSERTION(docAccessible, "No doc accessible for the object in doc accessible cache!");
if (docAccessible) {
LocalAccessible* accessible = docAccessible->GetAccessible(aNode); if (accessible) { return accessible;
}
}
} return nullptr;
}
if (aAllowServiceShutdown && !HasXPCDocuments()) {
MaybeShutdownAccService(nsAccessibilityService::eXPCOM);
}
}
}
void DocManager::NotifyOfDocumentShutdown(DocAccessible* aDocument,
Document* aDOMDocument, bool aAllowServiceShutdown) { // We need to remove listeners in both cases, when document is being shutdown // or when accessibility service is being shut down as well.
RemoveListeners(aDOMDocument);
// Document will already be removed when accessibility service is shutting // down so we do not need to remove it twice. if (nsAccessibilityService::IsShutdown()) { return;
}
if (!sRemoteXPCDocumentCache) {
sRemoteXPCDocumentCache = new nsRefPtrHashtable<nsPtrHashKey<const DocAccessibleParent>,
xpcAccessibleDocument>;
ClearOnShutdown(&sRemoteXPCDocumentCache);
}
MOZ_ASSERT(!aDoc->IsShutdown(), "Adding a shutdown doc to remote XPC cache");
doc = new xpcAccessibleDocument(aDoc);
sRemoteXPCDocumentCache->InsertOrUpdate(aDoc, RefPtr{doc});
return doc;
}
#ifdef DEBUG bool DocManager::IsProcessingRefreshDriverNotification() const { for (constauto& entry : mDocAccessibleCache) {
DocAccessible* docAccessible = entry.GetWeak();
NS_ASSERTION(docAccessible, "No doc accessible for the object in doc accessible cache!");
// Document was loaded. if (aStateFlags & STATE_STOP) { #ifdef A11Y_LOG if (logging::IsEnabled(logging::eDocLoad)) {
logging::DocLoad("document loaded", aWebProgress, aRequest, aStateFlags);
} #endif
// Figure out an event type to notify the document has been loaded.
uint32_t eventType = nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED;
// Some XUL documents get start state and then stop state with failure // status when everything is ok. Fire document load complete event in this // case. if (NS_SUCCEEDED(aStatus) || !document->IsContentDocument()) {
eventType = nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE;
}
// If end consumer has been retargeted for loaded content then do not fire // any event because it means no new document has been loaded, for example, // it happens when user clicks on file link. if (aRequest) {
uint32_t loadFlags = 0;
aRequest->GetLoadFlags(&loadFlags); if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) eventType = 0;
}
nsCOMPtr<Document> document = do_QueryInterface(aEvent->GetTarget());
NS_ASSERTION(document, "pagehide or DOMContentLoaded for non document!"); if (!document) return NS_OK;
if (type.EqualsLiteral("pagehide")) { // 'pagehide' event is registered on every DOM document we create an // accessible for, process the event for the target. This document // accessible and all its sub document accessible are shutdown as result of // processing.
// Shutdown this one and sub document accessibles.
// We're allowed to not remove listeners when accessible document is // shutdown since we don't keep strong reference on chrome event target and // listeners are removed automatically when chrome event target goes away.
DocAccessible* docAccessible = GetExistingDocAccessible(document); if (docAccessible) docAccessible->Shutdown();
return NS_OK;
}
// XXX: handle error pages loading separately since they get neither // webprogress notifications nor 'pageshow' event. if (type.EqualsLiteral("DOMContentLoaded") &&
nsCoreUtils::IsErrorPage(document)) { #ifdef A11Y_LOG if (logging::IsEnabled(logging::eDocLoad)) {
logging::DocLoad("handled 'DOMContentLoaded' event", document);
} #endif
void DocManager::HandleDOMDocumentLoad(Document* aDocument,
uint32_t aLoadEventType) { // Document accessible can be created before we were notified the DOM document // was loaded completely. However if it's not created yet then create it.
DocAccessible* docAcc = GetExistingDocAccessible(aDocument); if (!docAcc) {
docAcc = CreateDocOrRootAccessible(aDocument); if (!docAcc) return;
}
// Ignore documents without presshell. We must not ignore documents with no // root frame because DOM focus can hit such documents and ignoring them would // prevent a11y focus.
PresShell* presShell = aDocument->GetPresShell(); if (!presShell || presShell->IsDestroying()) { return nullptr;
}
DocAccessible* parentDocAcc = nullptr; if (!isRootDoc) { // XXXaaronl: ideally we would traverse the presshell chain. Since there's // no easy way to do that, we cheat and use the document hierarchy.
parentDocAcc = GetDocAccessible(aDocument->GetInProcessParentDocument()); // We should always get parentDocAcc except sometimes for background // extension pages, where the parent has an invisible DocShell but the child // does not. See bug 1888649.
NS_ASSERTION(
parentDocAcc ||
(BasePrincipal::Cast(aDocument->GetPrincipal())->AddonPolicy() &&
aDocument->GetInProcessParentDocument() &&
aDocument->GetInProcessParentDocument()->GetDocShell() &&
aDocument->GetInProcessParentDocument()
->GetDocShell()
->IsInvisible()), "Can't create an accessible for the document!"); if (!parentDocAcc) return nullptr;
}
// We only create root accessibles for the true root, otherwise create a // doc accessible.
RefPtr<DocAccessible> docAcc =
isRootDoc ? new RootAccessibleWrap(aDocument, presShell)
: new DocAccessibleWrap(aDocument, presShell);
// Cache the document accessible into document cache.
mDocAccessibleCache.InsertOrUpdate(aDocument, RefPtr{docAcc});
// Initialize the document accessible.
docAcc->Init();
// Bind the document to the tree. if (isRootDoc) { if (!ApplicationAcc()->AppendChild(docAcc)) {
docAcc->Shutdown(); return nullptr;
}
// Fire reorder event to notify new accessible document has been attached to // the tree. The reorder event is delivered after the document tree is // constructed because event processing and tree construction are done by // the same document. // Note: don't use AccReorderEvent to avoid coalsecense and special reorder // events processing.
docAcc->FireDelayedEvent(nsIAccessibleEvent::EVENT_REORDER,
ApplicationAcc());
void DocManager::ClearDocCache() { while (mDocAccessibleCache.Count() > 0) { auto iter = mDocAccessibleCache.Iter();
MOZ_ASSERT(!iter.Done());
DocAccessible* docAcc = iter.UserData();
NS_ASSERTION(docAcc, "No doc accessible for the object in doc accessible cache!"); if (docAcc) {
docAcc->Shutdown();
}
iter.Remove();
}
// Ensure that all xpcom accessible documents are shut down as well. while (mXPCDocumentCache.Count() > 0) { auto iter = mXPCDocumentCache.Iter();
MOZ_ASSERT(!iter.Done());
xpcAccessibleDocument* xpcDoc = iter.UserData();
NS_ASSERTION(xpcDoc, "No xpc doc for the object in xpc doc cache!");
if (xpcDoc) {
xpcDoc->Shutdown();
}
iter.Remove();
}
}
void DocManager::RemoteDocAdded(DocAccessibleParent* aDoc) { if (!sRemoteDocuments) {
sRemoteDocuments = new nsTArray<DocAccessibleParent*>;
ClearOnShutdown(&sRemoteDocuments);
}
MOZ_ASSERT(!sRemoteDocuments->Contains(aDoc), "How did we already have the doc!");
sRemoteDocuments->AppendElement(aDoc);
ProxyCreated(aDoc);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.