global_menu_bar_registrar_x11.cc 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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.
  4. #include "shell/browser/ui/views/global_menu_bar_registrar_x11.h"
  5. #include <string>
  6. #include "base/debug/leak_annotations.h"
  7. #include "base/functional/bind.h"
  8. #include "base/memory/singleton.h"
  9. #include "content/public/browser/browser_thread.h"
  10. #include "shell/browser/ui/views/global_menu_bar_x11.h"
  11. using content::BrowserThread;
  12. namespace {
  13. const char kAppMenuRegistrarName[] = "com.canonical.AppMenu.Registrar";
  14. const char kAppMenuRegistrarPath[] = "/com/canonical/AppMenu/Registrar";
  15. } // namespace
  16. // static
  17. GlobalMenuBarRegistrarX11* GlobalMenuBarRegistrarX11::GetInstance() {
  18. return base::Singleton<GlobalMenuBarRegistrarX11>::get();
  19. }
  20. void GlobalMenuBarRegistrarX11::OnWindowMapped(x11::Window window) {
  21. live_windows_.insert(window);
  22. if (registrar_proxy_)
  23. RegisterXWindow(window);
  24. }
  25. void GlobalMenuBarRegistrarX11::OnWindowUnmapped(x11::Window window) {
  26. if (registrar_proxy_)
  27. UnregisterXWindow(window);
  28. live_windows_.erase(window);
  29. }
  30. GlobalMenuBarRegistrarX11::GlobalMenuBarRegistrarX11() {
  31. // libdbusmenu uses the gio version of dbus; I tried using the code in dbus/,
  32. // but it looks like that's isn't sharing the bus name with the gio version,
  33. // even when |connection_type| is set to SHARED.
  34. g_dbus_proxy_new_for_bus(
  35. G_BUS_TYPE_SESSION,
  36. static_cast<GDBusProxyFlags>(G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
  37. G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
  38. G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START),
  39. nullptr, kAppMenuRegistrarName, kAppMenuRegistrarPath,
  40. kAppMenuRegistrarName,
  41. nullptr, // Probably want a real cancelable.
  42. static_cast<GAsyncReadyCallback>(OnProxyCreated), this);
  43. }
  44. GlobalMenuBarRegistrarX11::~GlobalMenuBarRegistrarX11() {
  45. if (registrar_proxy_) {
  46. g_object_unref(registrar_proxy_);
  47. }
  48. }
  49. void GlobalMenuBarRegistrarX11::RegisterXWindow(x11::Window window) {
  50. DCHECK(registrar_proxy_);
  51. std::string path = electron::GlobalMenuBarX11::GetPathForWindow(window);
  52. ANNOTATE_SCOPED_MEMORY_LEAK; // http://crbug.com/314087
  53. // TODO(erg): The mozilla implementation goes to a lot of callback trouble
  54. // just to make sure that they react to make sure there's some sort of
  55. // cancelable object; including making a whole callback just to handle the
  56. // cancelable.
  57. //
  58. // I don't see any reason why we should care if "RegisterWindow" completes or
  59. // not.
  60. g_dbus_proxy_call(registrar_proxy_, "RegisterWindow",
  61. g_variant_new("(uo)", window, path.c_str()),
  62. G_DBUS_CALL_FLAGS_NONE, -1, nullptr, nullptr, nullptr);
  63. }
  64. void GlobalMenuBarRegistrarX11::UnregisterXWindow(x11::Window window) {
  65. DCHECK(registrar_proxy_);
  66. ANNOTATE_SCOPED_MEMORY_LEAK; // http://crbug.com/314087
  67. // TODO(erg): The mozilla implementation goes to a lot of callback trouble
  68. // just to make sure that they react to make sure there's some sort of
  69. // cancelable object; including making a whole callback just to handle the
  70. // cancelable.
  71. //
  72. // I don't see any reason why we should care if "UnregisterWindow" completes
  73. // or not.
  74. g_dbus_proxy_call(registrar_proxy_, "UnregisterWindow",
  75. g_variant_new("(u)", window), G_DBUS_CALL_FLAGS_NONE, -1,
  76. nullptr, nullptr, nullptr);
  77. }
  78. void GlobalMenuBarRegistrarX11::OnProxyCreated(GObject* source,
  79. GAsyncResult* result,
  80. gpointer user_data) {
  81. GlobalMenuBarRegistrarX11* that =
  82. static_cast<GlobalMenuBarRegistrarX11*>(user_data);
  83. DCHECK(that);
  84. GError* error = nullptr;
  85. GDBusProxy* proxy = g_dbus_proxy_new_for_bus_finish(result, &error);
  86. if (error) {
  87. g_error_free(error);
  88. return;
  89. }
  90. // TODO(erg): Mozilla's implementation has a workaround for GDBus
  91. // cancellation here. However, it's marked as fixed. If there's weird
  92. // problems with cancelation, look at how they fixed their issues.
  93. that->SetRegistrarProxy(proxy);
  94. that->OnNameOwnerChanged(nullptr, nullptr);
  95. }
  96. void GlobalMenuBarRegistrarX11::SetRegistrarProxy(GDBusProxy* proxy) {
  97. registrar_proxy_ = proxy;
  98. signal_ = ScopedGSignal(
  99. registrar_proxy_, "notify::g-name-owner",
  100. base::BindRepeating(&GlobalMenuBarRegistrarX11::OnNameOwnerChanged,
  101. base::Unretained(this)));
  102. }
  103. void GlobalMenuBarRegistrarX11::OnNameOwnerChanged(GDBusProxy* /* ignored */,
  104. GParamSpec* /* ignored */) {
  105. // If the name owner changed, we need to reregister all the live x11::Window
  106. // with the system.
  107. for (const auto& window : live_windows_) {
  108. RegisterXWindow(window);
  109. }
  110. }