1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef UI_GFX_GTK_NATIVE_VIEW_ID_MANAGER_H_
6#define UI_GFX_GTK_NATIVE_VIEW_ID_MANAGER_H_
7
8#include <map>
9
10#include "base/synchronization/lock.h"
11#include "ui/gfx/gfx_export.h"
12#include "ui/gfx/native_widget_types.h"
13
14template <typename T> struct DefaultSingletonTraits;
15
16typedef unsigned long XID;
17struct _GtkPreserveWindow;
18
19// NativeViewIds are the opaque values which the renderer holds as a reference
20// to a window.
21//
22// We could make NativeViewIds be the X id of the window. However, at the
23// time when we need to tell the renderer about its NativeViewId, an XID isn't
24// availible and it goes very much against the grain of the code to make it so.
25// Also, we worry that GTK might choose to change the underlying X window id
26// when, say, the widget is hidden or repacked. Finally, if we used XIDs then a
27// compromised renderer could start asking questions about any X windows on the
28// system.
29//
30// Thus, we have this object. It produces random NativeViewIds from GtkWidget
31// pointers and observes the various signals from the widget for when an X
32// window is created, destroyed etc. Thus it provides a thread safe mapping
33// from NativeViewIds to the current XID for that widget.
34class GFX_EXPORT GtkNativeViewManager {
35 public:
36  // Returns the singleton instance.
37  static GtkNativeViewManager* GetInstance();
38
39  // Must be called from the UI thread:
40  //
41  // Return a NativeViewId for the given widget and attach to the various
42  // signals emitted by that widget. The NativeViewId is pseudo-randomly
43  // allocated so that a compromised renderer trying to guess values will fail
44  // with high probability. The NativeViewId will not be reused for the
45  // lifetime of the GtkWidget.
46  gfx::NativeViewId GetIdForWidget(gfx::NativeView widget);
47
48  // May be called from any thread:
49  //
50  // xid: (output) the resulting X window ID, or 0
51  // id: a value previously returned from GetIdForWidget
52  // returns: true if |id| is a valid id, false otherwise.
53  //
54  // If the widget referenced by |id| does not current have an X window id,
55  // |*xid| is set to 0.
56  bool GetXIDForId(XID* xid, gfx::NativeViewId id);
57
58  // May be called from the UI thread:
59  //
60  // Same as GetXIDForId except it returns the NativeView (GtkWidget*).
61  bool GetNativeViewForId(gfx::NativeView* xid, gfx::NativeViewId id);
62
63  // Must be called from the UI thread because we may need the associated
64  // widget to create a window.
65  //
66  // Keeping the XID permanent requires a bit of overhead, so it must
67  // be explicitly requested.
68  //
69  // xid: (output) the resulting X window
70  // id: a value previously returned from GetIdForWidget
71  // returns: true if |id| is a valid id, false otherwise.
72  bool GetPermanentXIDForId(XID* xid, gfx::NativeViewId id);
73
74  // Can be called from any thread.
75  // Will return false if the given XID isn't permanent or has already been
76  // released.
77  bool AddRefPermanentXID(XID xid);
78
79  // Must be called from the UI thread because we may need to access a
80  // GtkWidget or destroy a GdkWindow.
81  //
82  // If the widget associated with the XID is still alive, allow the widget
83  // to destroy the associated XID when it wants. Otherwise, destroy the
84  // GdkWindow associated with the XID.
85  void ReleasePermanentXID(XID xid);
86
87  // These are actually private functions, but need to be called from statics.
88  void OnRealize(gfx::NativeView widget);
89  void OnUnrealize(gfx::NativeView widget);
90  void OnDestroy(gfx::NativeView widget);
91
92 private:
93  // This object is a singleton:
94  GtkNativeViewManager();
95  ~GtkNativeViewManager();
96  friend struct DefaultSingletonTraits<GtkNativeViewManager>;
97
98  struct NativeViewInfo {
99    NativeViewInfo() : widget(NULL), x_window_id(0) {
100    }
101    gfx::NativeView widget;
102    XID x_window_id;
103  };
104
105  gfx::NativeViewId GetWidgetId(gfx::NativeView id);
106
107  // protects native_view_to_id_ and id_to_info_
108  base::Lock lock_;
109
110  // If asked for an id for the same widget twice, we want to return the same
111  // id. So this records the current mapping.
112  std::map<gfx::NativeView, gfx::NativeViewId> native_view_to_id_;
113  std::map<gfx::NativeViewId, NativeViewInfo> id_to_info_;
114
115  struct PermanentXIDInfo {
116    PermanentXIDInfo() : widget(NULL), ref_count(0) {
117    }
118    _GtkPreserveWindow* widget;
119    int ref_count;
120  };
121
122  // Used to maintain the reference count for permanent XIDs
123  // (referenced by GetPermanentXIDForId and dereferenced by
124  // ReleasePermanentXID). Only those XIDs with a positive reference count
125  // will be in the table.
126  //
127  // In general, several GTK widgets may share the same X window. We assume
128  // that is not true of the widgets stored in this registry.
129  //
130  // An XID will map to NULL, if there is an outstanding reference but the
131  // widget was destroyed. In this case, the destruction of the X window
132  // is deferred to the dropping of all references.
133  std::map<XID, PermanentXIDInfo> perm_xid_to_info_;
134
135  DISALLOW_COPY_AND_ASSIGN(GtkNativeViewManager);
136};
137
138#endif  // UI_GFX_GTK_NATIVE_VIEW_ID_MANAGER_H_
139