1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/remote_cocoa/app_shim/application_bridge.h"
#include <tuple>
#include "base/functional/bind.h"
#include "base/no_destructor.h"
#include "components/remote_cocoa/app_shim/alert.h"
#include "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
#include "components/remote_cocoa/app_shim/native_widget_ns_window_host_helper.h"
#include "components/system_media_controls/mac/remote_cocoa/system_media_controls_bridge.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#include "ui/base/cocoa/remote_accessibility_api.h"
namespace remote_cocoa {
namespace {
class NativeWidgetBridgeOwner : public NativeWidgetNSWindowHostHelper {
public:
NativeWidgetBridgeOwner(
uint64_t bridge_id,
mojo::PendingAssociatedReceiver<mojom::NativeWidgetNSWindow>
bridge_receiver,
mojo::PendingAssociatedRemote<mojom::NativeWidgetNSWindowHost>
host_remote,
mojo::PendingAssociatedRemote<mojom::TextInputHost>
text_input_host_remote) {
host_remote_.Bind(std::move(host_remote),
ui::WindowResizeHelperMac::Get()->task_runner());
text_input_host_remote_.Bind(
std::move(text_input_host_remote),
ui::WindowResizeHelperMac::Get()->task_runner());
bridge_ = std::make_unique<NativeWidgetNSWindowBridge>(
bridge_id, host_remote_.get(), this, text_input_host_remote_.get());
bridge_->BindReceiver(
std::move(bridge_receiver),
base::BindOnce(&NativeWidgetBridgeOwner::OnMojoDisconnect,
base::Unretained(this)));
}
private:
~NativeWidgetBridgeOwner() override = default;
void OnMojoDisconnect() { delete this; }
// NativeWidgetNSWindowHostHelper:
id GetNativeViewAccessible() override {
if (!remote_accessibility_element_) {
base::ProcessId browser_pid = base::kNullProcessId;
std::vector<uint8_t> element_token;
host_remote_->GetRootViewAccessibilityToken(&browser_pid, &element_token);
[NSAccessibilityRemoteUIElement
registerRemoteUIProcessIdentifier:browser_pid];
remote_accessibility_element_ =
ui::RemoteAccessibility::GetRemoteElementFromToken(element_token);
}
return remote_accessibility_element_;
}
void DispatchKeyEvent(ui::KeyEvent* event) override {
bool event_handled = false;
host_remote_->DispatchKeyEventRemote(std::make_unique<ui::KeyEvent>(*event),
&event_handled);
if (event_handled)
event->SetHandled();
}
bool DispatchKeyEventToMenuController(ui::KeyEvent* event) override {
bool event_swallowed = false;
bool event_handled = false;
host_remote_->DispatchKeyEventToMenuControllerRemote(
std::make_unique<ui::KeyEvent>(*event), &event_swallowed,
&event_handled);
if (event_handled)
event->SetHandled();
return event_swallowed;
}
void GetWordAt(const gfx::Point& location_in_content,
bool* found_word,
gfx::DecoratedText* decorated_word,
gfx::Point* baseline_point) override {
*found_word = false;
}
remote_cocoa::DragDropClient* GetDragDropClient() override {
// Drag-drop only doesn't work across mojo yet.
return nullptr;
}
ui::TextInputClient* GetTextInputClient() override {
// Text input doesn't work across mojo yet.
return nullptr;
}
bool MustPostTaskToRunModalSheetAnimation() const override { return true; }
mojo::AssociatedRemote<mojom::NativeWidgetNSWindowHost> host_remote_;
mojo::AssociatedRemote<mojom::TextInputHost> text_input_host_remote_;
std::unique_ptr<NativeWidgetNSWindowBridge> bridge_;
NSAccessibilityRemoteUIElement* __strong remote_accessibility_element_;
};
} // namespace
// static
ApplicationBridge* ApplicationBridge::Get() {
static base::NoDestructor<ApplicationBridge> application_bridge;
return application_bridge.get();
}
void ApplicationBridge::BindReceiver(
mojo::PendingAssociatedReceiver<mojom::Application> receiver) {
receiver_.Bind(std::move(receiver),
ui::WindowResizeHelperMac::Get()->task_runner());
}
void ApplicationBridge::SetContentNSViewCreateCallbacks(
RenderWidgetHostNSViewCreateCallback render_widget_host_create_callback,
WebContentsNSViewCreateCallback web_contents_create_callback) {
render_widget_host_create_callback_ = render_widget_host_create_callback;
web_contents_create_callback_ = web_contents_create_callback;
}
void ApplicationBridge::CreateAlert(
mojo::PendingReceiver<mojom::AlertBridge> bridge_receiver) {
// The resulting object manages its own lifetime.
std::ignore = new AlertBridge(std::move(bridge_receiver));
}
void ApplicationBridge::CreateNativeWidgetNSWindow(
uint64_t bridge_id,
mojo::PendingAssociatedReceiver<mojom::NativeWidgetNSWindow>
bridge_receiver,
mojo::PendingAssociatedRemote<mojom::NativeWidgetNSWindowHost> host,
mojo::PendingAssociatedRemote<mojom::TextInputHost> text_input_host) {
// The resulting object will be destroyed when its message pipe is closed.
std::ignore =
new NativeWidgetBridgeOwner(bridge_id, std::move(bridge_receiver),
std::move(host), std::move(text_input_host));
}
void ApplicationBridge::CreateRenderWidgetHostNSView(
uint64_t view_id,
mojo::PendingAssociatedRemote<mojom::StubInterface> host,
mojo::PendingAssociatedReceiver<mojom::StubInterface> view_receiver) {
if (!render_widget_host_create_callback_)
return;
render_widget_host_create_callback_.Run(view_id, host.PassHandle(),
view_receiver.PassHandle());
}
void ApplicationBridge::CreateSystemMediaControlsBridge(
mojo::PendingReceiver<system_media_controls::mojom::SystemMediaControls>
receiver,
mojo::PendingRemote<
system_media_controls::mojom::SystemMediaControlsObserver> host) {
if (!system_media_controls_bridge_) {
system_media_controls_bridge_ =
std::make_unique<system_media_controls::SystemMediaControlsBridge>(
std::move(receiver), std::move(host));
} else {
// It's possible that ApplicationBridge is asked to make an SMCBridge for an
// App when one has already been made. This is the case for duplicate PWAs,
// ie. when a user has 2 of the same PWA open, and plays audio in both.
// In that case, we just need to rebind the mojo connections.
system_media_controls_bridge_->BindMojoConnections(std::move(receiver),
std::move(host));
}
}
void ApplicationBridge::CreateWebContentsNSView(
uint64_t view_id,
mojo::PendingAssociatedRemote<mojom::StubInterface> host,
mojo::PendingAssociatedReceiver<mojom::StubInterface> view_receiver) {
if (!web_contents_create_callback_) {
return;
}
web_contents_create_callback_.Run(view_id, host.PassHandle(),
view_receiver.PassHandle());
}
void ApplicationBridge::ForwardCutCopyPaste(
mojom::CutCopyPasteCommand command) {
ForwardCutCopyPasteToNSApp(command);
}
// static
void ApplicationBridge::ForwardCutCopyPasteToNSApp(
mojom::CutCopyPasteCommand command) {
switch (command) {
case mojom::CutCopyPasteCommand::kCut:
[NSApp sendAction:@selector(cut:) to:nil from:nil];
break;
case mojom::CutCopyPasteCommand::kCopy:
[NSApp sendAction:@selector(copy:) to:nil from:nil];
break;
case mojom::CutCopyPasteCommand::kPaste:
[NSApp sendAction:@selector(paste:) to:nil from:nil];
break;
}
}
ApplicationBridge::ApplicationBridge() = default;
ApplicationBridge::~ApplicationBridge() = default;
} // namespace remote_cocoa
|