Bug 1568151 - Replace `target.getInspector()` by `target.getFront("inspector")`....
[gecko.git] / accessible / base / Logging.cpp
blob2cb83b491359466faa68ec3d636d2559a6a74c50
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "Logging.h"
9 #include "Accessible-inl.h"
10 #include "AccEvent.h"
11 #include "DocAccessible.h"
12 #include "nsAccessibilityService.h"
13 #include "nsCoreUtils.h"
14 #include "OuterDocAccessible.h"
16 #include "nsDocShellLoadTypes.h"
17 #include "nsIChannel.h"
18 #include "nsIInterfaceRequestorUtils.h"
19 #include "nsISelectionController.h"
20 #include "nsTraceRefcnt.h"
21 #include "nsIWebProgress.h"
22 #include "prenv.h"
23 #include "nsIDocShellTreeItem.h"
24 #include "nsIURI.h"
25 #include "mozilla/PresShell.h"
26 #include "mozilla/dom/Element.h"
27 #include "mozilla/dom/HTMLBodyElement.h"
28 #include "mozilla/dom/Selection.h"
30 using namespace mozilla;
31 using namespace mozilla::a11y;
33 ////////////////////////////////////////////////////////////////////////////////
34 // Logging helpers
36 static uint32_t sModules = 0;
38 struct ModuleRep {
39 const char* mStr;
40 logging::EModules mModule;
43 static ModuleRep sModuleMap[] = {{"docload", logging::eDocLoad},
44 {"doccreate", logging::eDocCreate},
45 {"docdestroy", logging::eDocDestroy},
46 {"doclifecycle", logging::eDocLifeCycle},
48 {"events", logging::eEvents},
49 {"eventTree", logging::eEventTree},
50 {"platforms", logging::ePlatforms},
51 {"text", logging::eText},
52 {"tree", logging::eTree},
54 {"DOMEvents", logging::eDOMEvents},
55 {"focus", logging::eFocus},
56 {"selection", logging::eSelection},
57 {"notifications", logging::eNotifications},
59 {"stack", logging::eStack},
60 {"verbose", logging::eVerbose}};
62 static void EnableLogging(const char* aModulesStr) {
63 sModules = 0;
64 if (!aModulesStr) return;
66 const char* token = aModulesStr;
67 while (*token != '\0') {
68 size_t tokenLen = strcspn(token, ",");
69 for (unsigned int idx = 0; idx < ArrayLength(sModuleMap); idx++) {
70 if (strncmp(token, sModuleMap[idx].mStr, tokenLen) == 0) {
71 #if !defined(MOZ_PROFILING) && (!defined(DEBUG) || defined(MOZ_OPTIMIZE))
72 // Stack tracing on profiling enabled or debug not optimized builds.
73 if (strncmp(token, "stack", tokenLen) == 0) break;
74 #endif
75 sModules |= sModuleMap[idx].mModule;
76 printf("\n\nmodule enabled: %s\n", sModuleMap[idx].mStr);
77 break;
80 token += tokenLen;
82 if (*token == ',') token++; // skip ',' char
86 static void LogDocURI(dom::Document* aDocumentNode) {
87 printf("uri: %s", aDocumentNode->GetDocumentURI()->GetSpecOrDefault().get());
90 static void LogDocShellState(dom::Document* aDocumentNode) {
91 printf("docshell busy: ");
93 nsAutoCString docShellBusy;
94 nsCOMPtr<nsIDocShell> docShell = aDocumentNode->GetDocShell();
95 nsIDocShell::BusyFlags busyFlags = nsIDocShell::BUSY_FLAGS_NONE;
96 docShell->GetBusyFlags(&busyFlags);
97 if (busyFlags == nsIDocShell::BUSY_FLAGS_NONE) {
98 printf("'none'");
100 if (busyFlags & nsIDocShell::BUSY_FLAGS_BUSY) {
101 printf("'busy'");
103 if (busyFlags & nsIDocShell::BUSY_FLAGS_BEFORE_PAGE_LOAD) {
104 printf(", 'before page load'");
106 if (busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING) {
107 printf(", 'page loading'");
111 static void LogDocType(dom::Document* aDocumentNode) {
112 if (aDocumentNode->IsActive()) {
113 bool isContent = nsCoreUtils::IsContentDocument(aDocumentNode);
114 printf("%s document", (isContent ? "content" : "chrome"));
115 } else {
116 printf("document type: [failed]");
120 static void LogDocShellTree(dom::Document* aDocumentNode) {
121 if (aDocumentNode->IsActive()) {
122 nsCOMPtr<nsIDocShellTreeItem> treeItem(aDocumentNode->GetDocShell());
123 nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
124 treeItem->GetInProcessParent(getter_AddRefs(parentTreeItem));
125 nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
126 treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
127 printf("docshell hierarchy, parent: %p, root: %p, is tab document: %s;",
128 static_cast<void*>(parentTreeItem), static_cast<void*>(rootTreeItem),
129 (nsCoreUtils::IsTabDocument(aDocumentNode) ? "yes" : "no"));
133 static void LogDocState(dom::Document* aDocumentNode) {
134 const char* docState = nullptr;
135 dom::Document::ReadyState docStateFlag = aDocumentNode->GetReadyStateEnum();
136 switch (docStateFlag) {
137 case dom::Document::READYSTATE_UNINITIALIZED:
138 docState = "uninitialized";
139 break;
140 case dom::Document::READYSTATE_LOADING:
141 docState = "loading";
142 break;
143 case dom::Document::READYSTATE_INTERACTIVE:
144 docState = "interactive";
145 break;
146 case dom::Document::READYSTATE_COMPLETE:
147 docState = "complete";
148 break;
151 printf("doc state: %s", docState);
152 printf(", %sinitial", aDocumentNode->IsInitialDocument() ? "" : "not ");
153 printf(", %sshowing", aDocumentNode->IsShowing() ? "" : "not ");
154 printf(", %svisible", aDocumentNode->IsVisible() ? "" : "not ");
155 printf(", %svisible considering ancestors",
156 aDocumentNode->IsVisibleConsideringAncestors() ? "" : "not ");
157 printf(", %sactive", aDocumentNode->IsActive() ? "" : "not ");
158 printf(", %sresource", aDocumentNode->IsResourceDoc() ? "" : "not ");
160 dom::Element* rootEl = aDocumentNode->GetBodyElement();
161 if (!rootEl) {
162 rootEl = aDocumentNode->GetRootElement();
164 printf(", has %srole content", rootEl ? "" : "no ");
167 static void LogPresShell(dom::Document* aDocumentNode) {
168 PresShell* presShell = aDocumentNode->GetPresShell();
169 printf("presshell: %p", static_cast<void*>(presShell));
171 nsIScrollableFrame* sf = nullptr;
172 if (presShell) {
173 printf(", is %s destroying", (presShell->IsDestroying() ? "" : "not"));
174 sf = presShell->GetRootScrollFrameAsScrollable();
176 printf(", root scroll frame: %p", static_cast<void*>(sf));
179 static void LogDocLoadGroup(dom::Document* aDocumentNode) {
180 nsCOMPtr<nsILoadGroup> loadGroup = aDocumentNode->GetDocumentLoadGroup();
181 printf("load group: %p", static_cast<void*>(loadGroup));
184 static void LogDocParent(dom::Document* aDocumentNode) {
185 dom::Document* parentDoc = aDocumentNode->GetInProcessParentDocument();
186 printf("parent DOM document: %p", static_cast<void*>(parentDoc));
187 if (parentDoc) {
188 printf(", parent acc document: %p",
189 static_cast<void*>(GetExistingDocAccessible(parentDoc)));
190 printf("\n parent ");
191 LogDocURI(parentDoc);
192 printf("\n");
196 static void LogDocInfo(dom::Document* aDocumentNode, DocAccessible* aDocument) {
197 printf(" DOM document: %p, acc document: %p\n ",
198 static_cast<void*>(aDocumentNode), static_cast<void*>(aDocument));
200 // log document info
201 if (aDocumentNode) {
202 LogDocURI(aDocumentNode);
203 printf("\n ");
204 LogDocShellState(aDocumentNode);
205 printf("; ");
206 LogDocType(aDocumentNode);
207 printf("\n ");
208 LogDocShellTree(aDocumentNode);
209 printf("\n ");
210 LogDocState(aDocumentNode);
211 printf("\n ");
212 LogPresShell(aDocumentNode);
213 printf("\n ");
214 LogDocLoadGroup(aDocumentNode);
215 printf(", ");
216 LogDocParent(aDocumentNode);
217 printf("\n");
221 static void LogShellLoadType(nsIDocShell* aDocShell) {
222 printf("load type: ");
224 uint32_t loadType = 0;
225 aDocShell->GetLoadType(&loadType);
226 switch (loadType) {
227 case LOAD_NORMAL:
228 printf("normal; ");
229 break;
230 case LOAD_NORMAL_REPLACE:
231 printf("normal replace; ");
232 break;
233 case LOAD_NORMAL_EXTERNAL:
234 printf("normal external; ");
235 break;
236 case LOAD_HISTORY:
237 printf("history; ");
238 break;
239 case LOAD_NORMAL_BYPASS_CACHE:
240 printf("normal bypass cache; ");
241 break;
242 case LOAD_NORMAL_BYPASS_PROXY:
243 printf("normal bypass proxy; ");
244 break;
245 case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
246 printf("normal bypass proxy and cache; ");
247 break;
248 case LOAD_NORMAL_ALLOW_MIXED_CONTENT:
249 printf("normal allow mixed content; ");
250 break;
251 case LOAD_RELOAD_NORMAL:
252 printf("reload normal; ");
253 break;
254 case LOAD_RELOAD_BYPASS_CACHE:
255 printf("reload bypass cache; ");
256 break;
257 case LOAD_RELOAD_BYPASS_PROXY:
258 printf("reload bypass proxy; ");
259 break;
260 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
261 printf("reload bypass proxy and cache; ");
262 break;
263 case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
264 printf("reload allow mixed content; ");
265 break;
266 case LOAD_LINK:
267 printf("link; ");
268 break;
269 case LOAD_REFRESH:
270 printf("refresh; ");
271 break;
272 case LOAD_RELOAD_CHARSET_CHANGE:
273 printf("reload charset change; ");
274 break;
275 case LOAD_BYPASS_HISTORY:
276 printf("bypass history; ");
277 break;
278 case LOAD_STOP_CONTENT:
279 printf("stop content; ");
280 break;
281 case LOAD_STOP_CONTENT_AND_REPLACE:
282 printf("stop content and replace; ");
283 break;
284 case LOAD_PUSHSTATE:
285 printf("load pushstate; ");
286 break;
287 case LOAD_REPLACE_BYPASS_CACHE:
288 printf("replace bypass cache; ");
289 break;
290 case LOAD_ERROR_PAGE:
291 printf("error page;");
292 break;
293 default:
294 printf("unknown");
298 static void LogRequest(nsIRequest* aRequest) {
299 if (aRequest) {
300 nsAutoCString name;
301 aRequest->GetName(name);
302 printf(" request spec: %s\n", name.get());
303 uint32_t loadFlags = 0;
304 aRequest->GetLoadFlags(&loadFlags);
305 printf(" request load flags: %x; ", loadFlags);
306 if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) printf("document uri; ");
307 if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI)
308 printf("retargeted document uri; ");
309 if (loadFlags & nsIChannel::LOAD_REPLACE) printf("replace; ");
310 if (loadFlags & nsIChannel::LOAD_INITIAL_DOCUMENT_URI)
311 printf("initial document uri; ");
312 if (loadFlags & nsIChannel::LOAD_TARGETED) printf("targeted; ");
313 if (loadFlags & nsIChannel::LOAD_CALL_CONTENT_SNIFFERS)
314 printf("call content sniffers; ");
315 if (loadFlags & nsIChannel::LOAD_BYPASS_URL_CLASSIFIER) {
316 printf("bypass classify uri; ");
318 } else {
319 printf(" no request");
323 static void LogDocAccState(DocAccessible* aDocument) {
324 printf("document acc state: ");
325 if (aDocument->HasLoadState(DocAccessible::eCompletelyLoaded))
326 printf("completely loaded;");
327 else if (aDocument->HasLoadState(DocAccessible::eReady))
328 printf("ready;");
329 else if (aDocument->HasLoadState(DocAccessible::eDOMLoaded))
330 printf("DOM loaded;");
331 else if (aDocument->HasLoadState(DocAccessible::eTreeConstructed))
332 printf("tree constructed;");
335 static void GetDocLoadEventType(AccEvent* aEvent, nsACString& aEventType) {
336 uint32_t type = aEvent->GetEventType();
337 if (type == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED) {
338 aEventType.AssignLiteral("load stopped");
339 } else if (type == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE) {
340 aEventType.AssignLiteral("load complete");
341 } else if (type == nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD) {
342 aEventType.AssignLiteral("reload");
343 } else if (type == nsIAccessibleEvent::EVENT_STATE_CHANGE) {
344 AccStateChangeEvent* event = downcast_accEvent(aEvent);
345 if (event->GetState() == states::BUSY) {
346 aEventType.AssignLiteral("busy ");
347 if (event->IsStateEnabled())
348 aEventType.AppendLiteral("true");
349 else
350 aEventType.AppendLiteral("false");
355 ////////////////////////////////////////////////////////////////////////////////
356 // namespace logging:: document life cycle logging methods
358 static const char* sDocLoadTitle = "DOCLOAD";
359 static const char* sDocCreateTitle = "DOCCREATE";
360 static const char* sDocDestroyTitle = "DOCDESTROY";
361 static const char* sDocEventTitle = "DOCEVENT";
362 static const char* sFocusTitle = "FOCUS";
364 void logging::DocLoad(const char* aMsg, nsIWebProgress* aWebProgress,
365 nsIRequest* aRequest, uint32_t aStateFlags) {
366 MsgBegin(sDocLoadTitle, "%s", aMsg);
368 nsCOMPtr<mozIDOMWindowProxy> DOMWindow;
369 aWebProgress->GetDOMWindow(getter_AddRefs(DOMWindow));
370 nsPIDOMWindowOuter* window = nsPIDOMWindowOuter::From(DOMWindow);
371 if (!window) {
372 MsgEnd();
373 return;
376 nsCOMPtr<dom::Document> documentNode = window->GetDoc();
377 if (!documentNode) {
378 MsgEnd();
379 return;
382 DocAccessible* document = GetExistingDocAccessible(documentNode);
384 LogDocInfo(documentNode, document);
386 nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
387 printf("\n ");
388 LogShellLoadType(docShell);
389 printf("\n");
390 LogRequest(aRequest);
391 printf("\n");
392 printf(" state flags: %x", aStateFlags);
393 bool isDocLoading;
394 aWebProgress->GetIsLoadingDocument(&isDocLoading);
395 printf(", document is %sloading\n", (isDocLoading ? "" : "not "));
397 MsgEnd();
400 void logging::DocLoad(const char* aMsg, dom::Document* aDocumentNode) {
401 MsgBegin(sDocLoadTitle, "%s", aMsg);
403 DocAccessible* document = GetExistingDocAccessible(aDocumentNode);
404 LogDocInfo(aDocumentNode, document);
406 MsgEnd();
409 void logging::DocCompleteLoad(DocAccessible* aDocument,
410 bool aIsLoadEventTarget) {
411 MsgBegin(sDocLoadTitle, "document loaded *completely*");
413 printf(" DOM document: %p, acc document: %p\n",
414 static_cast<void*>(aDocument->DocumentNode()),
415 static_cast<void*>(aDocument));
417 printf(" ");
418 LogDocURI(aDocument->DocumentNode());
419 printf("\n");
421 printf(" ");
422 LogDocAccState(aDocument);
423 printf("\n");
425 printf(" document is load event target: %s\n",
426 (aIsLoadEventTarget ? "true" : "false"));
428 MsgEnd();
431 void logging::DocLoadEventFired(AccEvent* aEvent) {
432 nsAutoCString strEventType;
433 GetDocLoadEventType(aEvent, strEventType);
434 if (!strEventType.IsEmpty()) printf(" fire: %s\n", strEventType.get());
437 void logging::DocLoadEventHandled(AccEvent* aEvent) {
438 nsAutoCString strEventType;
439 GetDocLoadEventType(aEvent, strEventType);
440 if (strEventType.IsEmpty()) return;
442 MsgBegin(sDocEventTitle, "handled '%s' event", strEventType.get());
444 DocAccessible* document = aEvent->GetAccessible()->AsDoc();
445 if (document) LogDocInfo(document->DocumentNode(), document);
447 MsgEnd();
450 void logging::DocCreate(const char* aMsg, dom::Document* aDocumentNode,
451 DocAccessible* aDocument) {
452 DocAccessible* document =
453 aDocument ? aDocument : GetExistingDocAccessible(aDocumentNode);
455 MsgBegin(sDocCreateTitle, "%s", aMsg);
456 LogDocInfo(aDocumentNode, document);
457 MsgEnd();
460 void logging::DocDestroy(const char* aMsg, dom::Document* aDocumentNode,
461 DocAccessible* aDocument) {
462 DocAccessible* document =
463 aDocument ? aDocument : GetExistingDocAccessible(aDocumentNode);
465 MsgBegin(sDocDestroyTitle, "%s", aMsg);
466 LogDocInfo(aDocumentNode, document);
467 MsgEnd();
470 void logging::OuterDocDestroy(OuterDocAccessible* aOuterDoc) {
471 MsgBegin(sDocDestroyTitle, "outerdoc shutdown");
472 logging::Address("outerdoc", aOuterDoc);
473 MsgEnd();
476 void logging::FocusNotificationTarget(const char* aMsg,
477 const char* aTargetDescr,
478 Accessible* aTarget) {
479 MsgBegin(sFocusTitle, "%s", aMsg);
480 AccessibleNNode(aTargetDescr, aTarget);
481 MsgEnd();
484 void logging::FocusNotificationTarget(const char* aMsg,
485 const char* aTargetDescr,
486 nsINode* aTargetNode) {
487 MsgBegin(sFocusTitle, "%s", aMsg);
488 Node(aTargetDescr, aTargetNode);
489 MsgEnd();
492 void logging::FocusNotificationTarget(const char* aMsg,
493 const char* aTargetDescr,
494 nsISupports* aTargetThing) {
495 MsgBegin(sFocusTitle, "%s", aMsg);
497 if (aTargetThing) {
498 nsCOMPtr<nsINode> targetNode(do_QueryInterface(aTargetThing));
499 if (targetNode)
500 AccessibleNNode(aTargetDescr, targetNode);
501 else
502 printf(" %s: %p, window\n", aTargetDescr,
503 static_cast<void*>(aTargetThing));
506 MsgEnd();
509 void logging::ActiveItemChangeCausedBy(const char* aCause,
510 Accessible* aTarget) {
511 SubMsgBegin();
512 printf(" Caused by: %s\n", aCause);
513 AccessibleNNode("Item", aTarget);
514 SubMsgEnd();
517 void logging::ActiveWidget(Accessible* aWidget) {
518 SubMsgBegin();
520 AccessibleNNode("Widget", aWidget);
521 printf(" Widget is active: %s, has operable items: %s\n",
522 (aWidget && aWidget->IsActiveWidget() ? "true" : "false"),
523 (aWidget && aWidget->AreItemsOperable() ? "true" : "false"));
525 SubMsgEnd();
528 void logging::FocusDispatched(Accessible* aTarget) {
529 SubMsgBegin();
530 AccessibleNNode("A11y target", aTarget);
531 SubMsgEnd();
534 void logging::SelChange(dom::Selection* aSelection, DocAccessible* aDocument,
535 int16_t aReason) {
536 SelectionType type = aSelection->GetType();
538 const char* strType = 0;
539 if (type == SelectionType::eNormal)
540 strType = "normal";
541 else if (type == SelectionType::eSpellCheck)
542 strType = "spellcheck";
543 else
544 strType = "unknown";
546 bool isIgnored = !aDocument || !aDocument->IsContentLoaded();
547 printf(
548 "\nSelection changed, selection type: %s, notification %s, reason: %d\n",
549 strType, (isIgnored ? "ignored" : "pending"), aReason);
551 Stack();
554 void logging::TreeInfo(const char* aMsg, uint32_t aExtraFlags, ...) {
555 if (IsEnabledAll(logging::eTree | aExtraFlags)) {
556 va_list vl;
557 va_start(vl, aExtraFlags);
558 const char* descr = va_arg(vl, const char*);
559 if (descr) {
560 Accessible* acc = va_arg(vl, Accessible*);
561 MsgBegin("TREE", "%s; doc: %p", aMsg, acc ? acc->Document() : nullptr);
562 AccessibleInfo(descr, acc);
563 while ((descr = va_arg(vl, const char*))) {
564 AccessibleInfo(descr, va_arg(vl, Accessible*));
566 } else {
567 MsgBegin("TREE", "%s", aMsg);
569 va_end(vl);
570 MsgEnd();
572 if (aExtraFlags & eStack) {
573 Stack();
578 void logging::TreeInfo(const char* aMsg, uint32_t aExtraFlags,
579 const char* aMsg1, Accessible* aAcc, const char* aMsg2,
580 nsINode* aNode) {
581 if (IsEnabledAll(logging::eTree | aExtraFlags)) {
582 MsgBegin("TREE", "%s; doc: %p", aMsg, aAcc ? aAcc->Document() : nullptr);
583 AccessibleInfo(aMsg1, aAcc);
584 Accessible* acc = aAcc ? aAcc->Document()->GetAccessible(aNode) : nullptr;
585 if (acc) {
586 AccessibleInfo(aMsg2, acc);
587 } else {
588 Node(aMsg2, aNode);
590 MsgEnd();
594 void logging::TreeInfo(const char* aMsg, uint32_t aExtraFlags,
595 Accessible* aParent) {
596 if (IsEnabledAll(logging::eTree | aExtraFlags)) {
597 MsgBegin("TREE", "%s; doc: %p", aMsg, aParent->Document());
598 AccessibleInfo("container", aParent);
599 for (uint32_t idx = 0; idx < aParent->ChildCount(); idx++) {
600 AccessibleInfo("child", aParent->GetChildAt(idx));
602 MsgEnd();
606 void logging::Tree(const char* aTitle, const char* aMsgText, Accessible* aRoot,
607 GetTreePrefix aPrefixFunc, void* aGetTreePrefixData) {
608 logging::MsgBegin(aTitle, "%s", aMsgText);
610 nsAutoString level;
611 Accessible* root = aRoot;
612 do {
613 const char* prefix =
614 aPrefixFunc ? aPrefixFunc(aGetTreePrefixData, root) : "";
615 printf("%s", NS_ConvertUTF16toUTF8(level).get());
616 logging::AccessibleInfo(prefix, root);
617 if (root->FirstChild() && !root->FirstChild()->IsDoc()) {
618 level.AppendLiteral(u" ");
619 root = root->FirstChild();
620 continue;
622 int32_t idxInParent = root != aRoot && root->mParent
623 ? root->mParent->mChildren.IndexOf(root)
624 : -1;
625 if (idxInParent != -1 &&
626 idxInParent <
627 static_cast<int32_t>(root->mParent->mChildren.Length() - 1)) {
628 root = root->mParent->mChildren.ElementAt(idxInParent + 1);
629 continue;
631 while (root != aRoot && (root = root->Parent())) {
632 level.Cut(0, 2);
633 int32_t idxInParent = !root->IsDoc() && root->mParent
634 ? root->mParent->mChildren.IndexOf(root)
635 : -1;
636 if (idxInParent != -1 &&
637 idxInParent <
638 static_cast<int32_t>(root->mParent->mChildren.Length() - 1)) {
639 root = root->mParent->mChildren.ElementAt(idxInParent + 1);
640 break;
643 } while (root && root != aRoot);
645 logging::MsgEnd();
648 void logging::DOMTree(const char* aTitle, const char* aMsgText,
649 DocAccessible* aDocument) {
650 logging::MsgBegin(aTitle, "%s", aMsgText);
651 nsAutoString level;
652 nsINode* root = aDocument->DocumentNode();
653 do {
654 printf("%s", NS_ConvertUTF16toUTF8(level).get());
655 logging::Node("", root);
656 if (root->GetFirstChild()) {
657 level.AppendLiteral(u" ");
658 root = root->GetFirstChild();
659 continue;
661 if (root->GetNextSibling()) {
662 root = root->GetNextSibling();
663 continue;
665 while ((root = root->GetParentNode())) {
666 level.Cut(0, 2);
667 if (root->GetNextSibling()) {
668 root = root->GetNextSibling();
669 break;
672 } while (root);
673 logging::MsgEnd();
676 void logging::MsgBegin(const char* aTitle, const char* aMsgText, ...) {
677 printf("\nA11Y %s: ", aTitle);
679 va_list argptr;
680 va_start(argptr, aMsgText);
681 vprintf(aMsgText, argptr);
682 va_end(argptr);
684 PRIntervalTime time = PR_IntervalNow();
685 uint32_t mins = (PR_IntervalToSeconds(time) / 60) % 60;
686 uint32_t secs = PR_IntervalToSeconds(time) % 60;
687 uint32_t msecs = PR_IntervalToMilliseconds(time) % 1000;
688 printf("; %02u:%02u.%03u", mins, secs, msecs);
690 printf("\n {\n");
693 void logging::MsgEnd() { printf(" }\n"); }
695 void logging::SubMsgBegin() { printf(" {\n"); }
697 void logging::SubMsgEnd() { printf(" }\n"); }
699 void logging::MsgEntry(const char* aEntryText, ...) {
700 printf(" ");
702 va_list argptr;
703 va_start(argptr, aEntryText);
704 vprintf(aEntryText, argptr);
705 va_end(argptr);
707 printf("\n");
710 void logging::Text(const char* aText) { printf(" %s\n", aText); }
712 void logging::Address(const char* aDescr, Accessible* aAcc) {
713 if (!aAcc->IsDoc()) {
714 printf(" %s accessible: %p, node: %p\n", aDescr,
715 static_cast<void*>(aAcc), static_cast<void*>(aAcc->GetNode()));
718 DocAccessible* doc = aAcc->Document();
719 dom::Document* docNode = doc->DocumentNode();
720 printf(" document: %p, node: %p\n", static_cast<void*>(doc),
721 static_cast<void*>(docNode));
723 printf(" ");
724 LogDocURI(docNode);
725 printf("\n");
728 void logging::Node(const char* aDescr, nsINode* aNode) {
729 printf(" ");
731 if (!aNode) {
732 printf("%s: null\n", aDescr);
733 return;
736 if (aNode->IsDocument()) {
737 printf("%s: %p, document\n", aDescr, static_cast<void*>(aNode));
738 return;
741 nsINode* parentNode = aNode->GetParentNode();
742 int32_t idxInParent = parentNode ? parentNode->ComputeIndexOf(aNode) : -1;
744 if (aNode->IsText()) {
745 printf("%s: %p, text node, idx in parent: %d\n", aDescr,
746 static_cast<void*>(aNode), idxInParent);
747 return;
750 if (!aNode->IsElement()) {
751 printf("%s: %p, not accessible node type, idx in parent: %d\n", aDescr,
752 static_cast<void*>(aNode), idxInParent);
753 return;
756 dom::Element* elm = aNode->AsElement();
758 nsAutoCString tag;
759 elm->NodeInfo()->NameAtom()->ToUTF8String(tag);
761 nsAtom* idAtom = elm->GetID();
762 nsAutoCString id;
763 if (idAtom) idAtom->ToUTF8String(id);
765 printf("%s: %p, %s@id='%s', idx in parent: %d\n", aDescr,
766 static_cast<void*>(elm), tag.get(), id.get(), idxInParent);
769 void logging::Document(DocAccessible* aDocument) {
770 printf(" Document: %p, document node: %p\n", static_cast<void*>(aDocument),
771 static_cast<void*>(aDocument->DocumentNode()));
773 printf(" Document ");
774 LogDocURI(aDocument->DocumentNode());
775 printf("\n");
778 void logging::AccessibleInfo(const char* aDescr, Accessible* aAccessible) {
779 printf(" %s: %p; ", aDescr, static_cast<void*>(aAccessible));
780 if (!aAccessible) {
781 printf("\n");
782 return;
784 if (aAccessible->IsDefunct()) {
785 printf("defunct\n");
786 return;
788 if (!aAccessible->Document() || aAccessible->Document()->IsDefunct()) {
789 printf("document is shutting down, no info\n");
790 return;
793 nsAutoString role;
794 GetAccService()->GetStringRole(aAccessible->Role(), role);
795 printf("role: %s", NS_ConvertUTF16toUTF8(role).get());
797 nsAutoString name;
798 aAccessible->Name(name);
799 if (!name.IsEmpty()) {
800 printf(", name: '%s'", NS_ConvertUTF16toUTF8(name).get());
803 printf(", idx: %d", aAccessible->IndexInParent());
805 nsINode* node = aAccessible->GetNode();
806 if (!node) {
807 printf(", node: null\n");
808 } else if (node->IsDocument()) {
809 printf(", document node: %p\n", static_cast<void*>(node));
810 } else if (node->IsText()) {
811 printf(", text node: %p\n", static_cast<void*>(node));
812 } else if (node->IsElement()) {
813 dom::Element* el = node->AsElement();
815 nsAutoCString tag;
816 el->NodeInfo()->NameAtom()->ToUTF8String(tag);
818 nsAtom* idAtom = el->GetID();
819 nsAutoCString id;
820 if (idAtom) {
821 idAtom->ToUTF8String(id);
824 printf(", element node: %p, %s@id='%s'\n", static_cast<void*>(el),
825 tag.get(), id.get());
829 void logging::AccessibleNNode(const char* aDescr, Accessible* aAccessible) {
830 printf(" %s: %p; ", aDescr, static_cast<void*>(aAccessible));
831 if (!aAccessible) return;
833 nsAutoString role;
834 GetAccService()->GetStringRole(aAccessible->Role(), role);
835 nsAutoString name;
836 aAccessible->Name(name);
838 printf("role: %s, name: '%s';\n", NS_ConvertUTF16toUTF8(role).get(),
839 NS_ConvertUTF16toUTF8(name).get());
841 nsAutoCString nodeDescr(aDescr);
842 nodeDescr.AppendLiteral(" node");
843 Node(nodeDescr.get(), aAccessible->GetNode());
845 Document(aAccessible->Document());
848 void logging::AccessibleNNode(const char* aDescr, nsINode* aNode) {
849 DocAccessible* document =
850 GetAccService()->GetDocAccessible(aNode->OwnerDoc());
852 if (document) {
853 Accessible* accessible = document->GetAccessible(aNode);
854 if (accessible) {
855 AccessibleNNode(aDescr, accessible);
856 return;
860 nsAutoCString nodeDescr("[not accessible] ");
861 nodeDescr.Append(aDescr);
862 Node(nodeDescr.get(), aNode);
864 if (document) {
865 Document(document);
866 return;
869 printf(" [contained by not accessible document]:\n");
870 LogDocInfo(aNode->OwnerDoc(), document);
871 printf("\n");
874 void logging::DOMEvent(const char* aDescr, nsINode* aOrigTarget,
875 const nsAString& aEventType) {
876 logging::MsgBegin("DOMEvents", "event '%s' %s",
877 NS_ConvertUTF16toUTF8(aEventType).get(), aDescr);
878 logging::AccessibleNNode("Target", aOrigTarget);
879 logging::MsgEnd();
882 void logging::Stack() {
883 if (IsEnabled(eStack)) {
884 printf(" stack: \n");
885 nsTraceRefcnt::WalkTheStack(stdout);
889 ////////////////////////////////////////////////////////////////////////////////
890 // namespace logging:: initialization
892 bool logging::IsEnabled(uint32_t aModules) { return sModules & aModules; }
894 bool logging::IsEnabledAll(uint32_t aModules) {
895 return (sModules & aModules) == aModules;
898 bool logging::IsEnabled(const nsAString& aModuleStr) {
899 for (unsigned int idx = 0; idx < ArrayLength(sModuleMap); idx++) {
900 if (aModuleStr.EqualsASCII(sModuleMap[idx].mStr))
901 return sModules & sModuleMap[idx].mModule;
904 return false;
907 void logging::Enable(const nsCString& aModules) {
908 EnableLogging(aModules.get());
911 void logging::CheckEnv() { EnableLogging(PR_GetEnv("A11YLOG")); }