Sat, 03 Jan 2015 20:18:00 +0100
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 | } |