gfx/src/X11Util.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * vim: sw=2 ts=8 et :
     3  */
     4 /* This Source Code Form is subject to the terms of the Mozilla Public
     5  * License, v. 2.0. If a copy of the MPL was not distributed with this
     6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     8 #ifndef mozilla_X11Util_h
     9 #define mozilla_X11Util_h
    11 // Utilities common to all X clients, regardless of UI toolkit.
    13 #if defined(MOZ_WIDGET_GTK)
    14 #  include <gdk/gdk.h>
    15 #  include <gdk/gdkx.h>
    16 #elif defined(MOZ_WIDGET_QT)
    17 #include "gfxQtPlatform.h"
    18 #undef CursorShape
    19 #  include <X11/Xlib.h>
    20 #else
    21 #  error Unknown toolkit
    22 #endif 
    24 #include <string.h>                     // for memset
    25 #include "gfxCore.h"                    // for NS_GFX
    26 #include "mozilla/Scoped.h"             // for SCOPED_TEMPLATE
    28 namespace mozilla {
    30 /**
    31  * Return the default X Display created and used by the UI toolkit.
    32  */
    33 inline Display*
    34 DefaultXDisplay()
    35 {
    36 #if defined(MOZ_WIDGET_GTK)
    37   return GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
    38 #elif defined(MOZ_WIDGET_QT)
    39   return gfxQtPlatform::GetXDisplay();
    40 #endif
    41 }
    43 /**
    44  * Sets *aVisual to point to aDisplay's Visual struct corresponding to
    45  * aVisualID, and *aDepth to its depth.  When aVisualID is None, these are set
    46  * to nullptr and 0 respectively.  Both out-parameter pointers are assumed
    47  * non-nullptr.
    48  */
    49 void
    50 FindVisualAndDepth(Display* aDisplay, VisualID aVisualID,
    51                    Visual** aVisual, int* aDepth);
    54 /**
    55  * Ensure that all X requests have been processed.
    56  *
    57  * This is similar to XSync, but doesn't need a round trip if the previous
    58  * request was synchronous or if events have been received since the last
    59  * request.  Subsequent FinishX calls will be noops if there have been no
    60  * intermediate requests.
    61  */
    63 void
    64 FinishX(Display* aDisplay);
    66 /**
    67  * Invoke XFree() on a pointer to memory allocated by Xlib (if the
    68  * pointer is nonnull) when this class goes out of scope.
    69  */
    70 template <typename T>
    71 struct ScopedXFreePtrTraits
    72 {
    73   typedef T *type;
    74   static T *empty() { return nullptr; }
    75   static void release(T *ptr) { if (ptr != nullptr) XFree(ptr); }
    76 };
    77 SCOPED_TEMPLATE(ScopedXFree, ScopedXFreePtrTraits)
    79 /**
    80  * On construction, set a graceful X error handler that doesn't crash the application and records X errors.
    81  * On destruction, restore the X error handler to what it was before construction.
    82  * 
    83  * The SyncAndGetError() method allows to know whether a X error occurred, optionally allows to get the full XErrorEvent,
    84  * and resets the recorded X error state so that a single X error will be reported only once.
    85  *
    86  * Nesting is correctly handled: multiple nested ScopedXErrorHandler's don't interfere with each other's state. However,
    87  * if SyncAndGetError is not called on the nested ScopedXErrorHandler, then any X errors caused by X calls made while the nested
    88  * ScopedXErrorHandler was in place may then be caught by the other ScopedXErrorHandler. This is just a result of X being
    89  * asynchronous and us not doing any implicit syncing: the only method in this class what causes syncing is SyncAndGetError().
    90  *
    91  * This class is not thread-safe at all. It is assumed that only one thread is using any ScopedXErrorHandler's. Given that it's
    92  * not used on Mac, it should be easy to make it thread-safe by using thread-local storage with __thread.
    93  */
    94 class NS_GFX ScopedXErrorHandler
    95 {
    96 public:
    97     // trivial wrapper around XErrorEvent, just adding ctor initializing by zero.
    98     struct ErrorEvent
    99     {
   100         XErrorEvent mError;
   102         ErrorEvent()
   103         {
   104             memset(this, 0, sizeof(ErrorEvent));
   105         }
   106     };
   108 private:
   110     // this ScopedXErrorHandler's ErrorEvent object
   111     ErrorEvent mXError;
   113     // static pointer for use by the error handler
   114     static ErrorEvent* sXErrorPtr;
   116     // what to restore sXErrorPtr to on destruction
   117     ErrorEvent* mOldXErrorPtr;
   119     // what to restore the error handler to on destruction
   120     int (*mOldErrorHandler)(Display *, XErrorEvent *);
   122 public:
   124     static int
   125     ErrorHandler(Display *, XErrorEvent *ev);
   127     ScopedXErrorHandler();
   129     ~ScopedXErrorHandler();
   131     /** \returns true if a X error occurred since the last time this method was called on this ScopedXErrorHandler object,
   132      *           or since the creation of this ScopedXErrorHandler object if this method was never called on it.
   133      *
   134      * \param ev this optional parameter, if set, will be filled with the XErrorEvent object. If multiple errors occurred,
   135      *           the first one will be returned.
   136      */
   137     bool SyncAndGetError(Display *dpy, XErrorEvent *ev = nullptr);
   138 };
   140 } // namespace mozilla
   142 #endif  // mozilla_X11Util_h

mercurial