Line data Source code
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/. */
6 :
7 : #include "Logging.h"
8 :
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"
15 :
16 : #include "nsDocShellLoadTypes.h"
17 : #include "nsIChannel.h"
18 : #include "nsIInterfaceRequestorUtils.h"
19 : #include "nsISelectionPrivate.h"
20 : #include "nsTraceRefcnt.h"
21 : #include "nsIWebProgress.h"
22 : #include "prenv.h"
23 : #include "nsIDocShellTreeItem.h"
24 : #include "nsIURI.h"
25 : #include "mozilla/dom/Element.h"
26 :
27 : using namespace mozilla;
28 : using namespace mozilla::a11y;
29 :
30 : ////////////////////////////////////////////////////////////////////////////////
31 : // Logging helpers
32 :
33 : static uint32_t sModules = 0;
34 :
35 : struct ModuleRep {
36 : const char* mStr;
37 : logging::EModules mModule;
38 : };
39 :
40 : static ModuleRep sModuleMap[] = {
41 : { "docload", logging::eDocLoad },
42 : { "doccreate", logging::eDocCreate },
43 : { "docdestroy", logging::eDocDestroy },
44 : { "doclifecycle", logging::eDocLifeCycle },
45 :
46 : { "events", logging::eEvents },
47 : { "eventTree", logging::eEventTree },
48 : { "platforms", logging::ePlatforms },
49 : { "text", logging::eText },
50 : { "tree", logging::eTree },
51 :
52 : { "DOMEvents", logging::eDOMEvents },
53 : { "focus", logging::eFocus },
54 : { "selection", logging::eSelection },
55 : { "notifications", logging::eNotifications },
56 :
57 : { "stack", logging::eStack },
58 : { "verbose", logging::eVerbose }
59 : };
60 :
61 : static void
62 0 : EnableLogging(const char* aModulesStr)
63 : {
64 0 : sModules = 0;
65 0 : if (!aModulesStr)
66 0 : return;
67 :
68 0 : const char* token = aModulesStr;
69 0 : while (*token != '\0') {
70 0 : size_t tokenLen = strcspn(token, ",");
71 0 : for (unsigned int idx = 0; idx < ArrayLength(sModuleMap); idx++) {
72 0 : if (strncmp(token, sModuleMap[idx].mStr, tokenLen) == 0) {
73 : #if !defined(MOZ_PROFILING) && (!defined(DEBUG) || defined(MOZ_OPTIMIZE))
74 : // Stack tracing on profiling enabled or debug not optimized builds.
75 : if (strncmp(token, "stack", tokenLen) == 0)
76 : break;
77 : #endif
78 0 : sModules |= sModuleMap[idx].mModule;
79 0 : printf("\n\nmodule enabled: %s\n", sModuleMap[idx].mStr);
80 0 : break;
81 : }
82 : }
83 0 : token += tokenLen;
84 :
85 0 : if (*token == ',')
86 0 : token++; // skip ',' char
87 : }
88 : }
89 :
90 : static void
91 0 : LogDocURI(nsIDocument* aDocumentNode)
92 : {
93 0 : printf("uri: %s", aDocumentNode->GetDocumentURI()->GetSpecOrDefault().get());
94 0 : }
95 :
96 : static void
97 0 : LogDocShellState(nsIDocument* aDocumentNode)
98 : {
99 0 : printf("docshell busy: ");
100 :
101 0 : nsAutoCString docShellBusy;
102 0 : nsCOMPtr<nsIDocShell> docShell = aDocumentNode->GetDocShell();
103 0 : uint32_t busyFlags = nsIDocShell::BUSY_FLAGS_NONE;
104 0 : docShell->GetBusyFlags(&busyFlags);
105 0 : if (busyFlags == nsIDocShell::BUSY_FLAGS_NONE) {
106 0 : printf("'none'");
107 : }
108 0 : if (busyFlags & nsIDocShell::BUSY_FLAGS_BUSY) {
109 0 : printf("'busy'");
110 : }
111 0 : if (busyFlags & nsIDocShell::BUSY_FLAGS_BEFORE_PAGE_LOAD) {
112 0 : printf(", 'before page load'");
113 : }
114 0 : if (busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING) {
115 0 : printf(", 'page loading'");
116 : }
117 0 : }
118 :
119 : static void
120 0 : LogDocType(nsIDocument* aDocumentNode)
121 : {
122 0 : if (aDocumentNode->IsActive()) {
123 0 : bool isContent = nsCoreUtils::IsContentDocument(aDocumentNode);
124 0 : printf("%s document", (isContent ? "content" : "chrome"));
125 : } else {
126 0 : printf("document type: [failed]");\
127 : }
128 0 : }
129 :
130 : static void
131 0 : LogDocShellTree(nsIDocument* aDocumentNode)
132 : {
133 0 : if (aDocumentNode->IsActive()) {
134 0 : nsCOMPtr<nsIDocShellTreeItem> treeItem(aDocumentNode->GetDocShell());
135 0 : nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
136 0 : treeItem->GetParent(getter_AddRefs(parentTreeItem));
137 0 : nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
138 0 : treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
139 0 : printf("docshell hierarchy, parent: %p, root: %p, is tab document: %s;",
140 0 : static_cast<void*>(parentTreeItem), static_cast<void*>(rootTreeItem),
141 0 : (nsCoreUtils::IsTabDocument(aDocumentNode) ? "yes" : "no"));
142 : }
143 0 : }
144 :
145 : static void
146 0 : LogDocState(nsIDocument* aDocumentNode)
147 : {
148 0 : const char* docState = nullptr;
149 0 : nsIDocument::ReadyState docStateFlag = aDocumentNode->GetReadyStateEnum();
150 0 : switch (docStateFlag) {
151 : case nsIDocument::READYSTATE_UNINITIALIZED:
152 0 : docState = "uninitialized";
153 0 : break;
154 : case nsIDocument::READYSTATE_LOADING:
155 0 : docState = "loading";
156 0 : break;
157 : case nsIDocument::READYSTATE_INTERACTIVE:
158 0 : docState = "interactive";
159 0 : break;
160 : case nsIDocument::READYSTATE_COMPLETE:
161 0 : docState = "complete";
162 0 : break;
163 : }
164 :
165 0 : printf("doc state: %s", docState);
166 0 : printf(", %sinitial", aDocumentNode->IsInitialDocument() ? "" : "not ");
167 0 : printf(", %sshowing", aDocumentNode->IsShowing() ? "" : "not ");
168 0 : printf(", %svisible", aDocumentNode->IsVisible() ? "" : "not ");
169 0 : printf(", %svisible considering ancestors", aDocumentNode->IsVisibleConsideringAncestors() ? "" : "not ");
170 0 : printf(", %sactive", aDocumentNode->IsActive() ? "" : "not ");
171 0 : printf(", %sresource", aDocumentNode->IsResourceDoc() ? "" : "not ");
172 :
173 0 : dom::Element* rootEl = aDocumentNode->GetBodyElement();
174 0 : if (!rootEl) {
175 0 : rootEl = aDocumentNode->GetRootElement();
176 : }
177 0 : printf(", has %srole content", rootEl ? "" : "no ");
178 0 : }
179 :
180 : static void
181 0 : LogPresShell(nsIDocument* aDocumentNode)
182 : {
183 0 : nsIPresShell* ps = aDocumentNode->GetShell();
184 0 : printf("presshell: %p", static_cast<void*>(ps));
185 :
186 0 : nsIScrollableFrame* sf = nullptr;
187 0 : if (ps) {
188 0 : printf(", is %s destroying", (ps->IsDestroying() ? "" : "not"));
189 0 : sf = ps->GetRootScrollFrameAsScrollable();
190 : }
191 0 : printf(", root scroll frame: %p", static_cast<void*>(sf));
192 0 : }
193 :
194 : static void
195 0 : LogDocLoadGroup(nsIDocument* aDocumentNode)
196 : {
197 0 : nsCOMPtr<nsILoadGroup> loadGroup = aDocumentNode->GetDocumentLoadGroup();
198 0 : printf("load group: %p", static_cast<void*>(loadGroup));
199 0 : }
200 :
201 : static void
202 0 : LogDocParent(nsIDocument* aDocumentNode)
203 : {
204 0 : nsIDocument* parentDoc = aDocumentNode->GetParentDocument();
205 0 : printf("parent DOM document: %p", static_cast<void*>(parentDoc));
206 0 : if (parentDoc) {
207 : printf(", parent acc document: %p",
208 0 : static_cast<void*>(GetExistingDocAccessible(parentDoc)));
209 0 : printf("\n parent ");
210 0 : LogDocURI(parentDoc);
211 0 : printf("\n");
212 : }
213 0 : }
214 :
215 : static void
216 0 : LogDocInfo(nsIDocument* aDocumentNode, DocAccessible* aDocument)
217 : {
218 : printf(" DOM document: %p, acc document: %p\n ",
219 0 : static_cast<void*>(aDocumentNode), static_cast<void*>(aDocument));
220 :
221 : // log document info
222 0 : if (aDocumentNode) {
223 0 : LogDocURI(aDocumentNode);
224 0 : printf("\n ");
225 0 : LogDocShellState(aDocumentNode);
226 0 : printf("; ");
227 0 : LogDocType(aDocumentNode);
228 0 : printf("\n ");
229 0 : LogDocShellTree(aDocumentNode);
230 0 : printf("\n ");
231 0 : LogDocState(aDocumentNode);
232 0 : printf("\n ");
233 0 : LogPresShell(aDocumentNode);
234 0 : printf("\n ");
235 0 : LogDocLoadGroup(aDocumentNode);
236 0 : printf(", ");
237 0 : LogDocParent(aDocumentNode);
238 0 : printf("\n");
239 : }
240 0 : }
241 :
242 : static void
243 0 : LogShellLoadType(nsIDocShell* aDocShell)
244 : {
245 0 : printf("load type: ");
246 :
247 0 : uint32_t loadType = 0;
248 0 : aDocShell->GetLoadType(&loadType);
249 0 : switch (loadType) {
250 : case LOAD_NORMAL:
251 0 : printf("normal; ");
252 0 : break;
253 : case LOAD_NORMAL_REPLACE:
254 0 : printf("normal replace; ");
255 0 : break;
256 : case LOAD_NORMAL_EXTERNAL:
257 0 : printf("normal external; ");
258 0 : break;
259 : case LOAD_HISTORY:
260 0 : printf("history; ");
261 0 : break;
262 : case LOAD_NORMAL_BYPASS_CACHE:
263 0 : printf("normal bypass cache; ");
264 0 : break;
265 : case LOAD_NORMAL_BYPASS_PROXY:
266 0 : printf("normal bypass proxy; ");
267 0 : break;
268 : case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
269 0 : printf("normal bypass proxy and cache; ");
270 0 : break;
271 : case LOAD_NORMAL_ALLOW_MIXED_CONTENT:
272 0 : printf("normal allow mixed content; ");
273 0 : break;
274 : case LOAD_RELOAD_NORMAL:
275 0 : printf("reload normal; ");
276 0 : break;
277 : case LOAD_RELOAD_BYPASS_CACHE:
278 0 : printf("reload bypass cache; ");
279 0 : break;
280 : case LOAD_RELOAD_BYPASS_PROXY:
281 0 : printf("reload bypass proxy; ");
282 0 : break;
283 : case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
284 0 : printf("reload bypass proxy and cache; ");
285 0 : break;
286 : case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
287 0 : printf("reload allow mixed content; ");
288 0 : break;
289 : case LOAD_LINK:
290 0 : printf("link; ");
291 0 : break;
292 : case LOAD_REFRESH:
293 0 : printf("refresh; ");
294 0 : break;
295 : case LOAD_RELOAD_CHARSET_CHANGE:
296 0 : printf("reload charset change; ");
297 0 : break;
298 : case LOAD_BYPASS_HISTORY:
299 0 : printf("bypass history; ");
300 0 : break;
301 : case LOAD_STOP_CONTENT:
302 0 : printf("stop content; ");
303 0 : break;
304 : case LOAD_STOP_CONTENT_AND_REPLACE:
305 0 : printf("stop content and replace; ");
306 0 : break;
307 : case LOAD_PUSHSTATE:
308 0 : printf("load pushstate; ");
309 0 : break;
310 : case LOAD_REPLACE_BYPASS_CACHE:
311 0 : printf("replace bypass cache; ");
312 0 : break;
313 : case LOAD_ERROR_PAGE:
314 0 : printf("error page;");
315 0 : break;
316 : default:
317 0 : printf("unknown");
318 : }
319 0 : }
320 :
321 : static void
322 0 : LogRequest(nsIRequest* aRequest)
323 : {
324 0 : if (aRequest) {
325 0 : nsAutoCString name;
326 0 : aRequest->GetName(name);
327 0 : printf(" request spec: %s\n", name.get());
328 0 : uint32_t loadFlags = 0;
329 0 : aRequest->GetLoadFlags(&loadFlags);
330 0 : printf(" request load flags: %x; ", loadFlags);
331 0 : if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI)
332 0 : printf("document uri; ");
333 0 : if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI)
334 0 : printf("retargeted document uri; ");
335 0 : if (loadFlags & nsIChannel::LOAD_REPLACE)
336 0 : printf("replace; ");
337 0 : if (loadFlags & nsIChannel::LOAD_INITIAL_DOCUMENT_URI)
338 0 : printf("initial document uri; ");
339 0 : if (loadFlags & nsIChannel::LOAD_TARGETED)
340 0 : printf("targeted; ");
341 0 : if (loadFlags & nsIChannel::LOAD_CALL_CONTENT_SNIFFERS)
342 0 : printf("call content sniffers; ");
343 0 : if (loadFlags & nsIChannel::LOAD_CLASSIFY_URI)
344 0 : printf("classify uri; ");
345 : } else {
346 0 : printf(" no request");
347 : }
348 0 : }
349 :
350 : static void
351 0 : LogDocAccState(DocAccessible* aDocument)
352 : {
353 0 : printf("document acc state: ");
354 0 : if (aDocument->HasLoadState(DocAccessible::eCompletelyLoaded))
355 0 : printf("completely loaded;");
356 0 : else if (aDocument->HasLoadState(DocAccessible::eReady))
357 0 : printf("ready;");
358 0 : else if (aDocument->HasLoadState(DocAccessible::eDOMLoaded))
359 0 : printf("DOM loaded;");
360 0 : else if (aDocument->HasLoadState(DocAccessible::eTreeConstructed))
361 0 : printf("tree constructed;");
362 0 : }
363 :
364 : static void
365 0 : GetDocLoadEventType(AccEvent* aEvent, nsACString& aEventType)
366 : {
367 0 : uint32_t type = aEvent->GetEventType();
368 0 : if (type == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED) {
369 0 : aEventType.AssignLiteral("load stopped");
370 0 : } else if (type == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE) {
371 0 : aEventType.AssignLiteral("load complete");
372 0 : } else if (type == nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD) {
373 0 : aEventType.AssignLiteral("reload");
374 0 : } else if (type == nsIAccessibleEvent::EVENT_STATE_CHANGE) {
375 0 : AccStateChangeEvent* event = downcast_accEvent(aEvent);
376 0 : if (event->GetState() == states::BUSY) {
377 0 : aEventType.AssignLiteral("busy ");
378 0 : if (event->IsStateEnabled())
379 0 : aEventType.AppendLiteral("true");
380 : else
381 0 : aEventType.AppendLiteral("false");
382 : }
383 : }
384 0 : }
385 :
386 : ////////////////////////////////////////////////////////////////////////////////
387 : // namespace logging:: document life cycle logging methods
388 :
389 : static const char* sDocLoadTitle = "DOCLOAD";
390 : static const char* sDocCreateTitle = "DOCCREATE";
391 : static const char* sDocDestroyTitle = "DOCDESTROY";
392 : static const char* sDocEventTitle = "DOCEVENT";
393 : static const char* sFocusTitle = "FOCUS";
394 :
395 : void
396 0 : logging::DocLoad(const char* aMsg, nsIWebProgress* aWebProgress,
397 : nsIRequest* aRequest, uint32_t aStateFlags)
398 : {
399 0 : MsgBegin(sDocLoadTitle, "%s", aMsg);
400 :
401 0 : nsCOMPtr<mozIDOMWindowProxy> DOMWindow;
402 0 : aWebProgress->GetDOMWindow(getter_AddRefs(DOMWindow));
403 0 : nsPIDOMWindowOuter* window = nsPIDOMWindowOuter::From(DOMWindow);
404 0 : if (!window) {
405 0 : MsgEnd();
406 0 : return;
407 : }
408 :
409 0 : nsCOMPtr<nsIDocument> documentNode = window->GetDoc();
410 0 : if (!documentNode) {
411 0 : MsgEnd();
412 0 : return;
413 : }
414 :
415 0 : DocAccessible* document = GetExistingDocAccessible(documentNode);
416 :
417 0 : LogDocInfo(documentNode, document);
418 :
419 0 : nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
420 0 : printf("\n ");
421 0 : LogShellLoadType(docShell);
422 0 : printf("\n");
423 0 : LogRequest(aRequest);
424 0 : printf("\n");
425 0 : printf(" state flags: %x", aStateFlags);
426 : bool isDocLoading;
427 0 : aWebProgress->GetIsLoadingDocument(&isDocLoading);
428 0 : printf(", document is %sloading\n", (isDocLoading ? "" : "not "));
429 :
430 0 : MsgEnd();
431 : }
432 :
433 : void
434 0 : logging::DocLoad(const char* aMsg, nsIDocument* aDocumentNode)
435 : {
436 0 : MsgBegin(sDocLoadTitle, "%s", aMsg);
437 :
438 0 : DocAccessible* document = GetExistingDocAccessible(aDocumentNode);
439 0 : LogDocInfo(aDocumentNode, document);
440 :
441 0 : MsgEnd();
442 0 : }
443 :
444 : void
445 0 : logging::DocCompleteLoad(DocAccessible* aDocument, bool aIsLoadEventTarget)
446 : {
447 0 : MsgBegin(sDocLoadTitle, "document loaded *completely*");
448 :
449 : printf(" DOM document: %p, acc document: %p\n",
450 0 : static_cast<void*>(aDocument->DocumentNode()),
451 0 : static_cast<void*>(aDocument));
452 :
453 0 : printf(" ");
454 0 : LogDocURI(aDocument->DocumentNode());
455 0 : printf("\n");
456 :
457 0 : printf(" ");
458 0 : LogDocAccState(aDocument);
459 0 : printf("\n");
460 :
461 0 : printf(" document is load event target: %s\n",
462 0 : (aIsLoadEventTarget ? "true" : "false"));
463 :
464 0 : MsgEnd();
465 0 : }
466 :
467 : void
468 0 : logging::DocLoadEventFired(AccEvent* aEvent)
469 : {
470 0 : nsAutoCString strEventType;
471 0 : GetDocLoadEventType(aEvent, strEventType);
472 0 : if (!strEventType.IsEmpty())
473 0 : printf(" fire: %s\n", strEventType.get());
474 0 : }
475 :
476 : void
477 0 : logging::DocLoadEventHandled(AccEvent* aEvent)
478 : {
479 0 : nsAutoCString strEventType;
480 0 : GetDocLoadEventType(aEvent, strEventType);
481 0 : if (strEventType.IsEmpty())
482 0 : return;
483 :
484 0 : MsgBegin(sDocEventTitle, "handled '%s' event", strEventType.get());
485 :
486 0 : DocAccessible* document = aEvent->GetAccessible()->AsDoc();
487 0 : if (document)
488 0 : LogDocInfo(document->DocumentNode(), document);
489 :
490 0 : MsgEnd();
491 : }
492 :
493 : void
494 0 : logging::DocCreate(const char* aMsg, nsIDocument* aDocumentNode,
495 : DocAccessible* aDocument)
496 : {
497 0 : DocAccessible* document = aDocument ?
498 0 : aDocument : GetExistingDocAccessible(aDocumentNode);
499 :
500 0 : MsgBegin(sDocCreateTitle, "%s", aMsg);
501 0 : LogDocInfo(aDocumentNode, document);
502 0 : MsgEnd();
503 0 : }
504 :
505 : void
506 0 : logging::DocDestroy(const char* aMsg, nsIDocument* aDocumentNode,
507 : DocAccessible* aDocument)
508 : {
509 0 : DocAccessible* document = aDocument ?
510 0 : aDocument : GetExistingDocAccessible(aDocumentNode);
511 :
512 0 : MsgBegin(sDocDestroyTitle, "%s", aMsg);
513 0 : LogDocInfo(aDocumentNode, document);
514 0 : MsgEnd();
515 0 : }
516 :
517 : void
518 0 : logging::OuterDocDestroy(OuterDocAccessible* aOuterDoc)
519 : {
520 0 : MsgBegin(sDocDestroyTitle, "outerdoc shutdown");
521 0 : logging::Address("outerdoc", aOuterDoc);
522 0 : MsgEnd();
523 0 : }
524 :
525 : void
526 0 : logging::FocusNotificationTarget(const char* aMsg, const char* aTargetDescr,
527 : Accessible* aTarget)
528 : {
529 0 : MsgBegin(sFocusTitle, "%s", aMsg);
530 0 : AccessibleNNode(aTargetDescr, aTarget);
531 0 : MsgEnd();
532 0 : }
533 :
534 : void
535 0 : logging::FocusNotificationTarget(const char* aMsg, const char* aTargetDescr,
536 : nsINode* aTargetNode)
537 : {
538 0 : MsgBegin(sFocusTitle, "%s", aMsg);
539 0 : Node(aTargetDescr, aTargetNode);
540 0 : MsgEnd();
541 0 : }
542 :
543 : void
544 0 : logging::FocusNotificationTarget(const char* aMsg, const char* aTargetDescr,
545 : nsISupports* aTargetThing)
546 : {
547 0 : MsgBegin(sFocusTitle, "%s", aMsg);
548 :
549 0 : if (aTargetThing) {
550 0 : nsCOMPtr<nsINode> targetNode(do_QueryInterface(aTargetThing));
551 0 : if (targetNode)
552 0 : AccessibleNNode(aTargetDescr, targetNode);
553 : else
554 : printf(" %s: %p, window\n", aTargetDescr,
555 0 : static_cast<void*>(aTargetThing));
556 : }
557 :
558 0 : MsgEnd();
559 0 : }
560 :
561 : void
562 0 : logging::ActiveItemChangeCausedBy(const char* aCause, Accessible* aTarget)
563 : {
564 0 : SubMsgBegin();
565 0 : printf(" Caused by: %s\n", aCause);
566 0 : AccessibleNNode("Item", aTarget);
567 0 : SubMsgEnd();
568 0 : }
569 :
570 : void
571 0 : logging::ActiveWidget(Accessible* aWidget)
572 : {
573 0 : SubMsgBegin();
574 :
575 0 : AccessibleNNode("Widget", aWidget);
576 0 : printf(" Widget is active: %s, has operable items: %s\n",
577 0 : (aWidget && aWidget->IsActiveWidget() ? "true" : "false"),
578 0 : (aWidget && aWidget->AreItemsOperable() ? "true" : "false"));
579 :
580 0 : SubMsgEnd();
581 0 : }
582 :
583 : void
584 0 : logging::FocusDispatched(Accessible* aTarget)
585 : {
586 0 : SubMsgBegin();
587 0 : AccessibleNNode("A11y target", aTarget);
588 0 : SubMsgEnd();
589 0 : }
590 :
591 : void
592 0 : logging::SelChange(nsISelection* aSelection, DocAccessible* aDocument,
593 : int16_t aReason)
594 : {
595 0 : nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(aSelection));
596 :
597 0 : int16_t type = 0;
598 0 : privSel->GetType(&type);
599 :
600 0 : const char* strType = 0;
601 0 : if (type == nsISelectionController::SELECTION_NORMAL)
602 0 : strType = "normal";
603 0 : else if (type == nsISelectionController::SELECTION_SPELLCHECK)
604 0 : strType = "spellcheck";
605 : else
606 0 : strType = "unknown";
607 :
608 0 : bool isIgnored = !aDocument || !aDocument->IsContentLoaded();
609 0 : printf("\nSelection changed, selection type: %s, notification %s, reason: %d\n",
610 0 : strType, (isIgnored ? "ignored" : "pending"), aReason);
611 :
612 0 : Stack();
613 0 : }
614 :
615 : void
616 0 : logging::TreeInfo(const char* aMsg, uint32_t aExtraFlags, ...)
617 : {
618 0 : if (IsEnabledAll(logging::eTree | aExtraFlags)) {
619 : va_list vl;
620 0 : va_start(vl, aExtraFlags);
621 0 : const char* descr = va_arg(vl, const char*);
622 0 : if (descr) {
623 0 : Accessible* acc = va_arg(vl, Accessible*);
624 0 : MsgBegin("TREE", "%s; doc: %p", aMsg, acc ? acc->Document() : nullptr);
625 0 : AccessibleInfo(descr, acc);
626 0 : while ((descr = va_arg(vl, const char*))) {
627 0 : AccessibleInfo(descr, va_arg(vl, Accessible*));
628 : }
629 : }
630 : else {
631 0 : MsgBegin("TREE", "%s", aMsg);
632 : }
633 0 : va_end(vl);
634 0 : MsgEnd();
635 :
636 0 : if (aExtraFlags & eStack) {
637 0 : Stack();
638 : }
639 : }
640 0 : }
641 :
642 : void
643 0 : logging::TreeInfo(const char* aMsg, uint32_t aExtraFlags,
644 : const char* aMsg1, Accessible* aAcc,
645 : const char* aMsg2, nsINode* aNode)
646 : {
647 0 : if (IsEnabledAll(logging::eTree | aExtraFlags)) {
648 0 : MsgBegin("TREE", "%s; doc: %p", aMsg, aAcc ? aAcc->Document() : nullptr);
649 0 : AccessibleInfo(aMsg1, aAcc);
650 0 : Accessible* acc = aAcc ? aAcc->Document()->GetAccessible(aNode) : nullptr;
651 0 : if (acc) {
652 0 : AccessibleInfo(aMsg2, acc);
653 : }
654 : else {
655 0 : Node(aMsg2, aNode);
656 : }
657 0 : MsgEnd();
658 : }
659 0 : }
660 :
661 :
662 : void
663 0 : logging::TreeInfo(const char* aMsg, uint32_t aExtraFlags, Accessible* aParent)
664 : {
665 0 : if (IsEnabledAll(logging::eTree | aExtraFlags)) {
666 0 : MsgBegin("TREE", "%s; doc: %p", aMsg, aParent->Document());
667 0 : AccessibleInfo("container", aParent);
668 0 : for (uint32_t idx = 0; idx < aParent->ChildCount(); idx++) {
669 0 : AccessibleInfo("child", aParent->GetChildAt(idx));
670 : }
671 0 : MsgEnd();
672 : }
673 0 : }
674 :
675 : void
676 0 : logging::Tree(const char* aTitle, const char* aMsgText,
677 : Accessible* aRoot, GetTreePrefix aPrefixFunc,
678 : void* aGetTreePrefixData)
679 : {
680 0 : logging::MsgBegin(aTitle, "%s", aMsgText);
681 :
682 0 : nsAutoString level;
683 0 : Accessible* root = aRoot;
684 0 : do {
685 0 : const char* prefix = aPrefixFunc ? aPrefixFunc(aGetTreePrefixData, root) : "";
686 0 : printf("%s", NS_ConvertUTF16toUTF8(level).get());
687 0 : logging::AccessibleInfo(prefix, root);
688 0 : if (root->FirstChild() && !root->FirstChild()->IsDoc()) {
689 0 : level.Append(NS_LITERAL_STRING(" "));
690 0 : root = root->FirstChild();
691 0 : continue;
692 : }
693 0 : int32_t idxInParent = root != aRoot && root->mParent ?
694 0 : root->mParent->mChildren.IndexOf(root) : -1;
695 0 : if (idxInParent != -1 &&
696 0 : idxInParent < static_cast<int32_t>(root->mParent->mChildren.Length() - 1)) {
697 0 : root = root->mParent->mChildren.ElementAt(idxInParent + 1);
698 0 : continue;
699 : }
700 0 : while (root != aRoot && (root = root->Parent())) {
701 0 : level.Cut(0, 2);
702 0 : int32_t idxInParent = !root->IsDoc() && root->mParent ?
703 0 : root->mParent->mChildren.IndexOf(root) : -1;
704 0 : if (idxInParent != -1 &&
705 0 : idxInParent < static_cast<int32_t>(root->mParent->mChildren.Length() - 1)) {
706 0 : root = root->mParent->mChildren.ElementAt(idxInParent + 1);
707 0 : break;
708 : }
709 : }
710 : }
711 0 : while (root && root != aRoot);
712 :
713 0 : logging::MsgEnd();
714 0 : }
715 :
716 : void
717 0 : logging::DOMTree(const char* aTitle, const char* aMsgText,
718 : DocAccessible* aDocument)
719 : {
720 0 : logging::MsgBegin(aTitle, "%s", aMsgText);
721 0 : nsAutoString level;
722 0 : nsINode* root = aDocument->DocumentNode();
723 0 : do {
724 0 : printf("%s", NS_ConvertUTF16toUTF8(level).get());
725 0 : logging::Node("", root);
726 0 : if (root->GetFirstChild()) {
727 0 : level.Append(NS_LITERAL_STRING(" "));
728 0 : root = root->GetFirstChild();
729 0 : continue;
730 : }
731 0 : if (root->GetNextSibling()) {
732 0 : root = root->GetNextSibling();
733 0 : continue;
734 : }
735 0 : while ((root = root->GetParentNode())) {
736 0 : level.Cut(0, 2);
737 0 : if (root->GetNextSibling()) {
738 0 : root = root->GetNextSibling();
739 0 : break;
740 : }
741 : }
742 : }
743 0 : while (root);
744 0 : logging::MsgEnd();
745 0 : }
746 :
747 : void
748 0 : logging::MsgBegin(const char* aTitle, const char* aMsgText, ...)
749 : {
750 0 : printf("\nA11Y %s: ", aTitle);
751 :
752 : va_list argptr;
753 0 : va_start(argptr, aMsgText);
754 0 : vprintf(aMsgText, argptr);
755 0 : va_end(argptr);
756 :
757 0 : PRIntervalTime time = PR_IntervalNow();
758 0 : uint32_t mins = (PR_IntervalToSeconds(time) / 60) % 60;
759 0 : uint32_t secs = PR_IntervalToSeconds(time) % 60;
760 0 : uint32_t msecs = PR_IntervalToMilliseconds(time) % 1000;
761 0 : printf("; %02d:%02d.%03d", mins, secs, msecs);
762 :
763 0 : printf("\n {\n");
764 0 : }
765 :
766 : void
767 0 : logging::MsgEnd()
768 : {
769 0 : printf(" }\n");
770 0 : }
771 :
772 : void
773 0 : logging::SubMsgBegin()
774 : {
775 0 : printf(" {\n");
776 0 : }
777 :
778 : void
779 0 : logging::SubMsgEnd()
780 : {
781 0 : printf(" }\n");
782 0 : }
783 :
784 : void
785 0 : logging::MsgEntry(const char* aEntryText, ...)
786 : {
787 0 : printf(" ");
788 :
789 : va_list argptr;
790 0 : va_start(argptr, aEntryText);
791 0 : vprintf(aEntryText, argptr);
792 0 : va_end(argptr);
793 :
794 0 : printf("\n");
795 0 : }
796 :
797 : void
798 0 : logging::Text(const char* aText)
799 : {
800 0 : printf(" %s\n", aText);
801 0 : }
802 :
803 : void
804 0 : logging::Address(const char* aDescr, Accessible* aAcc)
805 : {
806 0 : if (!aAcc->IsDoc()) {
807 : printf(" %s accessible: %p, node: %p\n", aDescr,
808 0 : static_cast<void*>(aAcc), static_cast<void*>(aAcc->GetNode()));
809 : }
810 :
811 0 : DocAccessible* doc = aAcc->Document();
812 0 : nsIDocument* docNode = doc->DocumentNode();
813 : printf(" document: %p, node: %p\n",
814 0 : static_cast<void*>(doc), static_cast<void*>(docNode));
815 :
816 0 : printf(" ");
817 0 : LogDocURI(docNode);
818 0 : printf("\n");
819 0 : }
820 :
821 : void
822 0 : logging::Node(const char* aDescr, nsINode* aNode)
823 : {
824 0 : printf(" ");
825 :
826 0 : if (!aNode) {
827 0 : printf("%s: null\n", aDescr);
828 0 : return;
829 : }
830 :
831 0 : if (aNode->IsNodeOfType(nsINode::eDOCUMENT)) {
832 0 : printf("%s: %p, document\n", aDescr, static_cast<void*>(aNode));
833 0 : return;
834 : }
835 :
836 0 : nsINode* parentNode = aNode->GetParentNode();
837 0 : int32_t idxInParent = parentNode ? parentNode->IndexOf(aNode) : - 1;
838 :
839 0 : if (aNode->IsNodeOfType(nsINode::eTEXT)) {
840 : printf("%s: %p, text node, idx in parent: %d\n",
841 0 : aDescr, static_cast<void*>(aNode), idxInParent);
842 0 : return;
843 : }
844 :
845 0 : if (!aNode->IsElement()) {
846 : printf("%s: %p, not accessible node type, idx in parent: %d\n",
847 0 : aDescr, static_cast<void*>(aNode), idxInParent);
848 0 : return;
849 : }
850 :
851 0 : dom::Element* elm = aNode->AsElement();
852 :
853 0 : nsAutoCString tag;
854 0 : elm->NodeInfo()->NameAtom()->ToUTF8String(tag);
855 :
856 0 : nsIAtom* idAtom = elm->GetID();
857 0 : nsAutoCString id;
858 0 : if (idAtom)
859 0 : idAtom->ToUTF8String(id);
860 :
861 0 : printf("%s: %p, %s@id='%s', idx in parent: %d\n",
862 0 : aDescr, static_cast<void*>(elm), tag.get(), id.get(), idxInParent);
863 : }
864 :
865 : void
866 0 : logging::Document(DocAccessible* aDocument)
867 : {
868 : printf(" Document: %p, document node: %p\n",
869 : static_cast<void*>(aDocument),
870 0 : static_cast<void*>(aDocument->DocumentNode()));
871 :
872 0 : printf(" Document ");
873 0 : LogDocURI(aDocument->DocumentNode());
874 0 : printf("\n");
875 0 : }
876 :
877 : void
878 0 : logging::AccessibleInfo(const char* aDescr, Accessible* aAccessible)
879 : {
880 0 : printf(" %s: %p; ", aDescr, static_cast<void*>(aAccessible));
881 0 : if (!aAccessible) {
882 0 : printf("\n");
883 0 : return;
884 : }
885 0 : if (aAccessible->IsDefunct()) {
886 0 : printf("defunct\n");
887 0 : return;
888 : }
889 0 : if (!aAccessible->Document() || aAccessible->Document()->IsDefunct()) {
890 0 : printf("document is shutting down, no info\n");
891 0 : return;
892 : }
893 :
894 0 : nsAutoString role;
895 0 : GetAccService()->GetStringRole(aAccessible->Role(), role);
896 0 : printf("role: %s", NS_ConvertUTF16toUTF8(role).get());
897 :
898 0 : nsAutoString name;
899 0 : aAccessible->Name(name);
900 0 : if (!name.IsEmpty()) {
901 0 : printf(", name: '%s'", NS_ConvertUTF16toUTF8(name).get());
902 : }
903 :
904 0 : printf(", idx: %d", aAccessible->IndexInParent());
905 :
906 0 : nsINode* node = aAccessible->GetNode();
907 0 : if (!node) {
908 0 : printf(", node: null\n");
909 : }
910 0 : else if (node->IsNodeOfType(nsINode::eDOCUMENT)) {
911 0 : printf(", document node: %p\n", static_cast<void*>(node));
912 : }
913 0 : else if (node->IsNodeOfType(nsINode::eTEXT)) {
914 0 : printf(", text node: %p\n", static_cast<void*>(node));
915 : }
916 0 : else if (node->IsElement()) {
917 0 : dom::Element* el = node->AsElement();
918 :
919 0 : nsAutoCString tag;
920 0 : el->NodeInfo()->NameAtom()->ToUTF8String(tag);
921 :
922 0 : nsIAtom* idAtom = el->GetID();
923 0 : nsAutoCString id;
924 0 : if (idAtom) {
925 0 : idAtom->ToUTF8String(id);
926 : }
927 :
928 0 : printf(", element node: %p, %s@id='%s'\n",
929 0 : static_cast<void*>(el), tag.get(), id.get());
930 : }
931 : }
932 :
933 : void
934 0 : logging::AccessibleNNode(const char* aDescr, Accessible* aAccessible)
935 : {
936 0 : printf(" %s: %p; ", aDescr, static_cast<void*>(aAccessible));
937 0 : if (!aAccessible)
938 0 : return;
939 :
940 0 : nsAutoString role;
941 0 : GetAccService()->GetStringRole(aAccessible->Role(), role);
942 0 : nsAutoString name;
943 0 : aAccessible->Name(name);
944 :
945 0 : printf("role: %s, name: '%s';\n", NS_ConvertUTF16toUTF8(role).get(),
946 0 : NS_ConvertUTF16toUTF8(name).get());
947 :
948 0 : nsAutoCString nodeDescr(aDescr);
949 0 : nodeDescr.AppendLiteral(" node");
950 0 : Node(nodeDescr.get(), aAccessible->GetNode());
951 :
952 0 : Document(aAccessible->Document());
953 : }
954 :
955 : void
956 0 : logging::AccessibleNNode(const char* aDescr, nsINode* aNode)
957 : {
958 : DocAccessible* document =
959 0 : GetAccService()->GetDocAccessible(aNode->OwnerDoc());
960 :
961 0 : if (document) {
962 0 : Accessible* accessible = document->GetAccessible(aNode);
963 0 : if (accessible) {
964 0 : AccessibleNNode(aDescr, accessible);
965 0 : return;
966 : }
967 : }
968 :
969 0 : nsAutoCString nodeDescr("[not accessible] ");
970 0 : nodeDescr.Append(aDescr);
971 0 : Node(nodeDescr.get(), aNode);
972 :
973 0 : if (document) {
974 0 : Document(document);
975 0 : return;
976 : }
977 :
978 0 : printf(" [contained by not accessible document]:\n");
979 0 : LogDocInfo(aNode->OwnerDoc(), document);
980 0 : printf("\n");
981 : }
982 :
983 : void
984 0 : logging::DOMEvent(const char* aDescr, nsINode* aOrigTarget,
985 : const nsAString& aEventType)
986 : {
987 0 : logging::MsgBegin("DOMEvents", "event '%s' %s",
988 0 : NS_ConvertUTF16toUTF8(aEventType).get(), aDescr);
989 0 : logging::AccessibleNNode("Target", aOrigTarget);
990 0 : logging::MsgEnd();
991 0 : }
992 :
993 : void
994 0 : logging::Stack()
995 : {
996 0 : if (IsEnabled(eStack)) {
997 0 : printf(" stack: \n");
998 0 : nsTraceRefcnt::WalkTheStack(stdout);
999 : }
1000 0 : }
1001 :
1002 : ////////////////////////////////////////////////////////////////////////////////
1003 : // namespace logging:: initialization
1004 :
1005 : bool
1006 0 : logging::IsEnabled(uint32_t aModules)
1007 : {
1008 0 : return sModules & aModules;
1009 : }
1010 :
1011 : bool
1012 0 : logging::IsEnabledAll(uint32_t aModules)
1013 : {
1014 0 : return (sModules & aModules) == aModules;
1015 : }
1016 :
1017 : bool
1018 0 : logging::IsEnabled(const nsAString& aModuleStr)
1019 : {
1020 0 : for (unsigned int idx = 0; idx < ArrayLength(sModuleMap); idx++) {
1021 0 : if (aModuleStr.EqualsASCII(sModuleMap[idx].mStr))
1022 0 : return sModules & sModuleMap[idx].mModule;
1023 : }
1024 :
1025 0 : return false;
1026 : }
1027 :
1028 : void
1029 0 : logging::Enable(const nsCString& aModules)
1030 : {
1031 0 : EnableLogging(aModules.get());
1032 0 : }
1033 :
1034 :
1035 : void
1036 0 : logging::CheckEnv()
1037 : {
1038 0 : EnableLogging(PR_GetEnv("A11YLOG"));
1039 0 : }
|