toolkit/xre/nsX11ErrorHandler.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsX11ErrorHandler.h"
michael@0 7
michael@0 8 #include "prenv.h"
michael@0 9 #include "nsXULAppAPI.h"
michael@0 10 #include "nsExceptionHandler.h"
michael@0 11 #include "nsDebug.h"
michael@0 12
michael@0 13 #include "mozilla/X11Util.h"
michael@0 14 #include <X11/Xlib.h>
michael@0 15
michael@0 16 #define BUFSIZE 2048 // What Xlib uses with XGetErrorDatabaseText
michael@0 17
michael@0 18 extern "C" {
michael@0 19 static int
michael@0 20 X11Error(Display *display, XErrorEvent *event) {
michael@0 21 // Get an indication of how long ago the request that caused the error was
michael@0 22 // made.
michael@0 23 unsigned long age = NextRequest(display) - event->serial;
michael@0 24
michael@0 25 // Get a string to represent the request that caused the error.
michael@0 26 nsAutoCString message;
michael@0 27 if (event->request_code < 128) {
michael@0 28 // Core protocol request
michael@0 29 message.AppendInt(event->request_code);
michael@0 30 } else {
michael@0 31 // Extension request
michael@0 32
michael@0 33 // man XSetErrorHandler says "the error handler should not call any
michael@0 34 // functions (directly or indirectly) on the display that will generate
michael@0 35 // protocol requests or that will look for input events" so we use another
michael@0 36 // temporary Display to request extension information. This assumes on
michael@0 37 // the DISPLAY environment variable has been set and matches what was used
michael@0 38 // to open |display|.
michael@0 39 Display *tmpDisplay = XOpenDisplay(nullptr);
michael@0 40 if (tmpDisplay) {
michael@0 41 int nExts;
michael@0 42 char** extNames = XListExtensions(tmpDisplay, &nExts);
michael@0 43 int first_error;
michael@0 44 if (extNames) {
michael@0 45 for (int i = 0; i < nExts; ++i) {
michael@0 46 int major_opcode, first_event;
michael@0 47 if (XQueryExtension(tmpDisplay, extNames[i],
michael@0 48 &major_opcode, &first_event, &first_error)
michael@0 49 && major_opcode == event->request_code) {
michael@0 50 message.Append(extNames[i]);
michael@0 51 message.Append('.');
michael@0 52 message.AppendInt(event->minor_code);
michael@0 53 break;
michael@0 54 }
michael@0 55 }
michael@0 56
michael@0 57 XFreeExtensionList(extNames);
michael@0 58 }
michael@0 59 XCloseDisplay(tmpDisplay);
michael@0 60
michael@0 61 #if (MOZ_WIDGET_GTK == 2)
michael@0 62 // GDK2 calls XCloseDevice the devices that it opened on startup, but
michael@0 63 // the XI protocol no longer ensures that the devices will still exist.
michael@0 64 // If they have been removed, then a BadDevice error results. Ignore
michael@0 65 // this error.
michael@0 66 if (message.EqualsLiteral("XInputExtension.4") &&
michael@0 67 event->error_code == first_error + 0) {
michael@0 68 return 0;
michael@0 69 }
michael@0 70 #endif
michael@0 71 }
michael@0 72 }
michael@0 73
michael@0 74 char buffer[BUFSIZE];
michael@0 75 if (message.IsEmpty()) {
michael@0 76 buffer[0] = '\0';
michael@0 77 } else {
michael@0 78 XGetErrorDatabaseText(display, "XRequest", message.get(), "",
michael@0 79 buffer, sizeof(buffer));
michael@0 80 }
michael@0 81
michael@0 82 nsAutoCString notes;
michael@0 83 if (buffer[0]) {
michael@0 84 notes.Append(buffer);
michael@0 85 } else {
michael@0 86 notes.Append("Request ");
michael@0 87 notes.AppendInt(event->request_code);
michael@0 88 notes.Append('.');
michael@0 89 notes.AppendInt(event->minor_code);
michael@0 90 }
michael@0 91
michael@0 92 notes.Append(": ");
michael@0 93
michael@0 94 // Get a string to describe the error.
michael@0 95 XGetErrorText(display, event->error_code, buffer, sizeof(buffer));
michael@0 96 notes.Append(buffer);
michael@0 97
michael@0 98 // For requests where Xlib gets the reply synchronously, |age| will be 1
michael@0 99 // and the stack will include the function making the request. For
michael@0 100 // asynchronous requests, the current stack will often be unrelated to the
michael@0 101 // point of making the request, even if |age| is 1, but sometimes this may
michael@0 102 // help us count back to the point of the request. With XSynchronize on,
michael@0 103 // the stack will include the function making the request, even though
michael@0 104 // |age| will be 2 for asynchronous requests because XSynchronize is
michael@0 105 // implemented by an empty request from an XSync, which has not yet been
michael@0 106 // processed.
michael@0 107 if (age > 1) {
michael@0 108 // XSynchronize returns the previous "after function". If a second
michael@0 109 // XSynchronize call returns the same function after an enable call then
michael@0 110 // synchronization must have already been enabled.
michael@0 111 if (XSynchronize(display, True) == XSynchronize(display, False)) {
michael@0 112 notes.Append("; sync");
michael@0 113 } else {
michael@0 114 notes.Append("; ");
michael@0 115 notes.AppendInt(uint32_t(age));
michael@0 116 notes.Append(" requests ago");
michael@0 117 }
michael@0 118 }
michael@0 119
michael@0 120 #ifdef MOZ_CRASHREPORTER
michael@0 121 switch (XRE_GetProcessType()) {
michael@0 122 case GeckoProcessType_Default:
michael@0 123 case GeckoProcessType_Plugin:
michael@0 124 case GeckoProcessType_Content:
michael@0 125 CrashReporter::AppendAppNotesToCrashReport(notes);
michael@0 126 break;
michael@0 127 default:
michael@0 128 ; // crash report notes not supported.
michael@0 129 }
michael@0 130 #endif
michael@0 131
michael@0 132 #ifdef DEBUG
michael@0 133 // The resource id is unlikely to be useful in a crash report without
michael@0 134 // context of other ids, but add it to the debug console output.
michael@0 135 notes.Append("; id=0x");
michael@0 136 notes.AppendInt(uint32_t(event->resourceid), 16);
michael@0 137 #ifdef MOZ_X11
michael@0 138 // Actually, for requests where Xlib gets the reply synchronously,
michael@0 139 // MOZ_X_SYNC=1 will not be necessary, but we don't have a table to tell us
michael@0 140 // which requests get a synchronous reply.
michael@0 141 if (!PR_GetEnv("MOZ_X_SYNC")) {
michael@0 142 notes.Append("\nRe-running with MOZ_X_SYNC=1 in the environment may give a more helpful backtrace.");
michael@0 143 }
michael@0 144 #endif
michael@0 145 #endif
michael@0 146
michael@0 147 #ifdef MOZ_WIDGET_QT
michael@0 148 // We should not abort here if MOZ_X_SYNC is not set
michael@0 149 // until http://bugreports.qt.nokia.com/browse/QTBUG-4042
michael@0 150 // not fixed, just print error value
michael@0 151 if (!PR_GetEnv("MOZ_X_SYNC")) {
michael@0 152 fprintf(stderr, "XError: %s\n", notes.get());
michael@0 153 return 0; // temporary workaround for bug 161472
michael@0 154 }
michael@0 155 #endif
michael@0 156
michael@0 157 NS_RUNTIMEABORT(notes.get());
michael@0 158 return 0; // not reached
michael@0 159 }
michael@0 160 }
michael@0 161
michael@0 162 void
michael@0 163 InstallX11ErrorHandler()
michael@0 164 {
michael@0 165 XSetErrorHandler(X11Error);
michael@0 166
michael@0 167 Display *display = mozilla::DefaultXDisplay();
michael@0 168 NS_ASSERTION(display, "No X display");
michael@0 169 if (PR_GetEnv("MOZ_X_SYNC")) {
michael@0 170 XSynchronize(display, True);
michael@0 171 }
michael@0 172 }

mercurial