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.

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

mercurial