1 // Copyright 2013 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.
5 #include "chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h"
8 #include "base/debug/leak_annotations.h"
9 #include "base/logging.h"
10 #include "chrome/browser/ui/views/frame/global_menu_bar_x11.h"
11 #include "content/public/browser/browser_thread.h"
13 using content::BrowserThread
;
17 const char kAppMenuRegistrarName
[] = "com.canonical.AppMenu.Registrar";
18 const char kAppMenuRegistrarPath
[] = "/com/canonical/AppMenu/Registrar";
23 GlobalMenuBarRegistrarX11
* GlobalMenuBarRegistrarX11::GetInstance() {
24 return Singleton
<GlobalMenuBarRegistrarX11
>::get();
27 void GlobalMenuBarRegistrarX11::OnWindowMapped(unsigned long xid
) {
28 live_xids_
.insert(xid
);
34 void GlobalMenuBarRegistrarX11::OnWindowUnmapped(unsigned long xid
) {
38 live_xids_
.erase(xid
);
41 GlobalMenuBarRegistrarX11::GlobalMenuBarRegistrarX11()
42 : registrar_proxy_(NULL
) {
43 // libdbusmenu uses the gio version of dbus; I tried using the code in dbus/,
44 // but it looks like that's isn't sharing the bus name with the gio version,
45 // even when |connection_type| is set to SHARED.
46 g_dbus_proxy_new_for_bus(
48 static_cast<GDBusProxyFlags
>(
49 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
|
50 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS
|
51 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START
),
53 kAppMenuRegistrarName
,
54 kAppMenuRegistrarPath
,
55 kAppMenuRegistrarName
,
56 NULL
, // TODO: Probalby want a real cancelable.
57 static_cast<GAsyncReadyCallback
>(OnProxyCreatedThunk
),
61 GlobalMenuBarRegistrarX11::~GlobalMenuBarRegistrarX11() {
62 if (registrar_proxy_
) {
63 g_signal_handlers_disconnect_by_func(
65 reinterpret_cast<void*>(OnNameOwnerChangedThunk
),
67 g_object_unref(registrar_proxy_
);
71 void GlobalMenuBarRegistrarX11::RegisterXID(unsigned long xid
) {
72 DCHECK(registrar_proxy_
);
73 std::string path
= GlobalMenuBarX11::GetPathForWindow(xid
);
75 ANNOTATE_SCOPED_MEMORY_LEAK
; // http://crbug.com/314087
76 // TODO(erg): The mozilla implementation goes to a lot of callback trouble
77 // just to make sure that they react to make sure there's some sort of
78 // cancelable object; including making a whole callback just to handle the
81 // I don't see any reason why we should care if "RegisterWindow" completes or
83 g_dbus_proxy_call(registrar_proxy_
,
85 g_variant_new("(uo)", xid
, path
.c_str()),
86 G_DBUS_CALL_FLAGS_NONE
, -1,
92 void GlobalMenuBarRegistrarX11::UnregisterXID(unsigned long xid
) {
93 DCHECK(registrar_proxy_
);
94 std::string path
= GlobalMenuBarX11::GetPathForWindow(xid
);
96 ANNOTATE_SCOPED_MEMORY_LEAK
; // http://crbug.com/314087
97 // TODO(erg): The mozilla implementation goes to a lot of callback trouble
98 // just to make sure that they react to make sure there's some sort of
99 // cancelable object; including making a whole callback just to handle the
102 // I don't see any reason why we should care if "UnregisterWindow" completes
104 g_dbus_proxy_call(registrar_proxy_
,
106 g_variant_new("(u)", xid
),
107 G_DBUS_CALL_FLAGS_NONE
, -1,
113 void GlobalMenuBarRegistrarX11::OnProxyCreated(GObject
* source
,
114 GAsyncResult
* result
) {
115 GError
* error
= NULL
;
116 GDBusProxy
* proxy
= g_dbus_proxy_new_for_bus_finish(result
, &error
);
122 // TODO(erg): Mozilla's implementation has a workaround for GDBus
123 // cancellation here. However, it's marked as fixed. If there's weird
124 // problems with cancelation, look at how they fixed their issues.
126 registrar_proxy_
= proxy
;
128 g_signal_connect(registrar_proxy_
, "notify::g-name-owner",
129 G_CALLBACK(OnNameOwnerChangedThunk
), this);
131 OnNameOwnerChanged(NULL
, NULL
);
134 void GlobalMenuBarRegistrarX11::OnNameOwnerChanged(GObject
* /* ignored */,
135 GParamSpec
* /* ignored */) {
136 // If the name owner changed, we need to reregister all the live xids with
138 for (std::set
<unsigned long>::const_iterator it
= live_xids_
.begin();
139 it
!= live_xids_
.end(); ++it
) {