exo_parts.cc 5.33 KB
Newer Older
reveman's avatar
reveman committed
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "chrome/browser/exo_parts.h"
reveman's avatar
reveman committed
6

7 8
#include "base/memory/ptr_util.h"

9 10 11 12
#if defined(USE_GLIB)
#include <glib.h>
#endif

reveman's avatar
reveman committed
13
#include "base/command_line.h"
14
#include "base/macros.h"
15
#include "base/memory/ptr_util.h"
reveman's avatar
reveman committed
16
#include "base/message_loop/message_loop.h"
17
#include "chrome/browser/chromeos/file_manager/path_util.h"
reveman's avatar
reveman committed
18 19 20
#include "chrome/browser/ui/ash/ash_util.h"
#include "chrome/common/chrome_switches.h"
#include "components/exo/display.h"
21
#include "components/exo/file_helper.h"
reveman's avatar
reveman committed
22
#include "components/exo/wayland/server.h"
23
#include "components/exo/wm_helper.h"
reveman's avatar
reveman committed
24
#include "content/public/browser/browser_thread.h"
25
#include "ui/arc/notification/arc_notification_surface_manager_impl.h"
reveman's avatar
reveman committed
26

27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
namespace {

constexpr char kMimeTypeArcUriList[] = "application/x-arc-uri-list";

class ChromeFileHelper : public exo::FileHelper {
 public:
  ChromeFileHelper() {}
  ~ChromeFileHelper() override {}

  // exo::FileHelper:
  std::string GetMimeTypeForUriList() const override {
    return kMimeTypeArcUriList;
  }
  bool ConvertPathToUrl(const base::FilePath& path, GURL* out) override {
    return file_manager::util::ConvertPathToArcUrl(path, out);
  }
};

}  // namespace

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
#if defined(USE_GLIB)
namespace {

struct GLibWaylandSource : public GSource {
  // Note: The GLibWaylandSource is created and destroyed by GLib. So its
  // constructor/destructor may or may not get called.
  exo::wayland::Server* server;
  GPollFD* poll_fd;
};

gboolean WaylandSourcePrepare(GSource* source, gint* timeout_ms) {
  *timeout_ms = -1;
  return FALSE;
}

gboolean WaylandSourceCheck(GSource* source) {
  GLibWaylandSource* wayland_source = static_cast<GLibWaylandSource*>(source);
  return (wayland_source->poll_fd->revents & G_IO_IN) ? TRUE : FALSE;
}

gboolean WaylandSourceDispatch(GSource* source,
                               GSourceFunc unused_func,
                               gpointer data) {
  GLibWaylandSource* wayland_source = static_cast<GLibWaylandSource*>(source);
  wayland_source->server->Dispatch(base::TimeDelta());
  wayland_source->server->Flush();
  return TRUE;
}

GSourceFuncs g_wayland_source_funcs = {WaylandSourcePrepare, WaylandSourceCheck,
                                       WaylandSourceDispatch, nullptr};

}  // namespace

81
class ExoParts::WaylandWatcher {
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
 public:
  explicit WaylandWatcher(exo::wayland::Server* server)
      : wayland_poll_(new GPollFD),
        wayland_source_(static_cast<GLibWaylandSource*>(
            g_source_new(&g_wayland_source_funcs, sizeof(GLibWaylandSource)))) {
    wayland_poll_->fd = server->GetFileDescriptor();
    wayland_poll_->events = G_IO_IN;
    wayland_poll_->revents = 0;
    wayland_source_->server = server;
    wayland_source_->poll_fd = wayland_poll_.get();
    g_source_add_poll(wayland_source_, wayland_poll_.get());
    g_source_set_can_recurse(wayland_source_, TRUE);
    g_source_set_callback(wayland_source_, nullptr, nullptr, nullptr);
    g_source_attach(wayland_source_, g_main_context_default());
  }
  ~WaylandWatcher() {
    g_source_destroy(wayland_source_);
    g_source_unref(wayland_source_);
  }

 private:
  // The poll attached to |wayland_source_|.
104
  std::unique_ptr<GPollFD> wayland_poll_;
105 106 107 108 109 110 111

  // The GLib event source for wayland events.
  GLibWaylandSource* wayland_source_;

  DISALLOW_COPY_AND_ASSIGN(WaylandWatcher);
};
#else
112
class ExoParts::WaylandWatcher : public base::MessagePumpLibevent::Watcher {
reveman's avatar
reveman committed
113
 public:
114 115
  explicit WaylandWatcher(exo::wayland::Server* server)
      : controller_(FROM_HERE), server_(server) {
reveman's avatar
reveman committed
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
    base::MessageLoopForUI::current()->WatchFileDescriptor(
        server_->GetFileDescriptor(),
        true,  // persistent
        base::MessagePumpLibevent::WATCH_READ, &controller_, this);
  }

  // base::MessagePumpLibevent::Watcher:
  void OnFileCanReadWithoutBlocking(int fd) override {
    server_->Dispatch(base::TimeDelta());
    server_->Flush();
  }
  void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); }

 private:
  base::MessagePumpLibevent::FileDescriptorWatcher controller_;
  exo::wayland::Server* const server_;

  DISALLOW_COPY_AND_ASSIGN(WaylandWatcher);
};
135
#endif
reveman's avatar
reveman committed
136

137 138
// static
std::unique_ptr<ExoParts> ExoParts::CreateIfNecessary() {
139 140 141
  // For mash, exosphere will not run in the browser process.
  if (ash_util::IsRunningInMash())
    return nullptr;
142 143 144 145
  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kEnableWaylandServer)) {
    return nullptr;
  }
reveman's avatar
reveman committed
146

147 148
  return base::WrapUnique(new ExoParts());
}
reveman's avatar
reveman committed
149

150 151 152 153 154 155
ExoParts::~ExoParts() {
  wayland_watcher_.reset();
  wayland_server_.reset();
  exo::WMHelper::SetInstance(nullptr);
  wm_helper_.reset();
}
reveman's avatar
reveman committed
156

157
ExoParts::ExoParts() {
penghuang's avatar
penghuang committed
158
  arc_notification_surface_manager_ =
159
      base::MakeUnique<arc::ArcNotificationSurfaceManagerImpl>();
160
  DCHECK(!ash_util::IsRunningInMash());
161
  wm_helper_ = base::MakeUnique<exo::WMHelper>();
penghuang's avatar
penghuang committed
162 163
  exo::WMHelper::SetInstance(wm_helper_.get());
  display_ =
164 165
      base::MakeUnique<exo::Display>(arc_notification_surface_manager_.get(),
                                     base::MakeUnique<ChromeFileHelper>());
penghuang's avatar
penghuang committed
166
  wayland_server_ = exo::wayland::Server::Create(display_.get());
167
  // Wayland server creation can fail if XDG_RUNTIME_DIR is not set correctly.
168 169
  if (wayland_server_)
    wayland_watcher_ = base::MakeUnique<WaylandWatcher>(wayland_server_.get());
reveman's avatar
reveman committed
170
}