Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / views / frame / global_menu_bar_registrar_x11.cc
blobb112b0f2f81c823856dbce01e75f1bb4cbad03bf
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"
7 #include "base/bind.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;
15 namespace {
17 const char kAppMenuRegistrarName[] = "com.canonical.AppMenu.Registrar";
18 const char kAppMenuRegistrarPath[] = "/com/canonical/AppMenu/Registrar";
20 } // namespace
22 // static
23 GlobalMenuBarRegistrarX11* GlobalMenuBarRegistrarX11::GetInstance() {
24 return base::Singleton<GlobalMenuBarRegistrarX11>::get();
27 void GlobalMenuBarRegistrarX11::OnWindowMapped(unsigned long xid) {
28 live_xids_.insert(xid);
30 if (registrar_proxy_)
31 RegisterXID(xid);
34 void GlobalMenuBarRegistrarX11::OnWindowUnmapped(unsigned long xid) {
35 if (registrar_proxy_)
36 UnregisterXID(xid);
38 live_xids_.erase(xid);
41 GlobalMenuBarRegistrarX11::GlobalMenuBarRegistrarX11()
42 : registrar_proxy_(nullptr) {
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(
47 G_BUS_TYPE_SESSION,
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),
52 nullptr,
53 kAppMenuRegistrarName,
54 kAppMenuRegistrarPath,
55 kAppMenuRegistrarName,
56 nullptr, // TODO: Probalby want a real cancelable.
57 static_cast<GAsyncReadyCallback>(OnProxyCreatedThunk),
58 this);
61 GlobalMenuBarRegistrarX11::~GlobalMenuBarRegistrarX11() {
62 if (registrar_proxy_) {
63 g_signal_handlers_disconnect_by_func(
64 registrar_proxy_,
65 reinterpret_cast<void*>(OnNameOwnerChangedThunk),
66 this);
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
79 // cancelable.
81 // I don't see any reason why we should care if "RegisterWindow" completes or
82 // not.
83 g_dbus_proxy_call(registrar_proxy_,
84 "RegisterWindow",
85 g_variant_new("(uo)", xid, path.c_str()),
86 G_DBUS_CALL_FLAGS_NONE, -1,
87 nullptr,
88 nullptr,
89 nullptr);
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
100 // cancelable.
102 // I don't see any reason why we should care if "UnregisterWindow" completes
103 // or not.
104 g_dbus_proxy_call(registrar_proxy_,
105 "UnregisterWindow",
106 g_variant_new("(u)", xid),
107 G_DBUS_CALL_FLAGS_NONE, -1,
108 nullptr,
109 nullptr,
110 nullptr);
113 void GlobalMenuBarRegistrarX11::OnProxyCreated(GObject* source,
114 GAsyncResult* result) {
115 GError* error = nullptr;
116 GDBusProxy* proxy = g_dbus_proxy_new_for_bus_finish(result, &error);
117 if (error) {
118 g_error_free(error);
119 return;
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(nullptr, nullptr);
134 void GlobalMenuBarRegistrarX11::OnNameOwnerChanged(GObject* /* ignored */,
135 GParamSpec* /* ignored */) {
136 // If the name owner changed, we need to reregister all the live xids with
137 // the system.
138 for (std::set<unsigned long>::const_iterator it = live_xids_.begin();
139 it != live_xids_.end(); ++it) {
140 RegisterXID(*it);