1// Copyright 2018 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 5#include "components/remote_cocoa/app_shim/application_bridge.h" 6 7#include "base/bind.h" 8#include "base/no_destructor.h" 9#include "components/remote_cocoa/app_shim/alert.h" 10#include "components/remote_cocoa/app_shim/color_panel_bridge.h" 11#include "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h" 12#include "components/remote_cocoa/app_shim/native_widget_ns_window_host_helper.h" 13#include "mojo/public/cpp/bindings/associated_remote.h" 14#include "mojo/public/cpp/bindings/self_owned_receiver.h" 15#include "ui/accelerated_widget_mac/window_resize_helper_mac.h" 16#include "ui/base/cocoa/remote_accessibility_api.h" 17 18namespace remote_cocoa { 19 20namespace { 21 22class NativeWidgetBridgeOwner : public NativeWidgetNSWindowHostHelper { 23 public: 24 NativeWidgetBridgeOwner( 25 uint64_t bridge_id, 26 mojo::PendingAssociatedReceiver<mojom::NativeWidgetNSWindow> 27 bridge_receiver, 28 mojo::PendingAssociatedRemote<mojom::NativeWidgetNSWindowHost> 29 host_remote, 30 mojo::PendingAssociatedRemote<mojom::TextInputHost> 31 text_input_host_remote) { 32 host_remote_.Bind(std::move(host_remote), 33 ui::WindowResizeHelperMac::Get()->task_runner()); 34 text_input_host_remote_.Bind( 35 std::move(text_input_host_remote), 36 ui::WindowResizeHelperMac::Get()->task_runner()); 37 bridge_ = std::make_unique<NativeWidgetNSWindowBridge>( 38 bridge_id, host_remote_.get(), this, text_input_host_remote_.get()); 39 bridge_->BindReceiver( 40 std::move(bridge_receiver), 41 base::BindOnce(&NativeWidgetBridgeOwner::OnMojoDisconnect, 42 base::Unretained(this))); 43 } 44 45 private: 46 ~NativeWidgetBridgeOwner() override {} 47 48 void OnMojoDisconnect() { delete this; } 49 50 // NativeWidgetNSWindowHostHelper: 51 id GetNativeViewAccessible() override { 52 if (!remote_accessibility_element_) { 53 int64_t browser_pid = 0; 54 std::vector<uint8_t> element_token; 55 host_remote_->GetRootViewAccessibilityToken(&browser_pid, &element_token); 56 [NSAccessibilityRemoteUIElement 57 registerRemoteUIProcessIdentifier:browser_pid]; 58 remote_accessibility_element_ = 59 ui::RemoteAccessibility::GetRemoteElementFromToken(element_token); 60 } 61 return remote_accessibility_element_.get(); 62 } 63 void DispatchKeyEvent(ui::KeyEvent* event) override { 64 bool event_handled = false; 65 host_remote_->DispatchKeyEventRemote(std::make_unique<ui::KeyEvent>(*event), 66 &event_handled); 67 if (event_handled) 68 event->SetHandled(); 69 } 70 bool DispatchKeyEventToMenuController(ui::KeyEvent* event) override { 71 bool event_swallowed = false; 72 bool event_handled = false; 73 host_remote_->DispatchKeyEventToMenuControllerRemote( 74 std::make_unique<ui::KeyEvent>(*event), &event_swallowed, 75 &event_handled); 76 if (event_handled) 77 event->SetHandled(); 78 return event_swallowed; 79 } 80 void GetWordAt(const gfx::Point& location_in_content, 81 bool* found_word, 82 gfx::DecoratedText* decorated_word, 83 gfx::Point* baseline_point) override { 84 *found_word = false; 85 } 86 remote_cocoa::DragDropClient* GetDragDropClient() override { 87 // Drag-drop only doesn't work across mojo yet. 88 return nullptr; 89 } 90 ui::TextInputClient* GetTextInputClient() override { 91 // Text input doesn't work across mojo yet. 92 return nullptr; 93 } 94 95 mojo::AssociatedRemote<mojom::NativeWidgetNSWindowHost> host_remote_; 96 mojo::AssociatedRemote<mojom::TextInputHost> text_input_host_remote_; 97 98 std::unique_ptr<NativeWidgetNSWindowBridge> bridge_; 99 base::scoped_nsobject<NSAccessibilityRemoteUIElement> 100 remote_accessibility_element_; 101}; 102 103} // namespace 104 105// static 106ApplicationBridge* ApplicationBridge::Get() { 107 static base::NoDestructor<ApplicationBridge> application_bridge; 108 return application_bridge.get(); 109} 110 111void ApplicationBridge::BindReceiver( 112 mojo::PendingAssociatedReceiver<mojom::Application> receiver) { 113 receiver_.Bind(std::move(receiver), 114 ui::WindowResizeHelperMac::Get()->task_runner()); 115} 116 117void ApplicationBridge::SetContentNSViewCreateCallbacks( 118 RenderWidgetHostNSViewCreateCallback render_widget_host_create_callback, 119 WebContentsNSViewCreateCallback web_conents_create_callback) { 120 render_widget_host_create_callback_ = render_widget_host_create_callback; 121 web_conents_create_callback_ = web_conents_create_callback; 122} 123 124void ApplicationBridge::CreateAlert( 125 mojo::PendingReceiver<mojom::AlertBridge> bridge_receiver) { 126 // The resulting object manages its own lifetime. 127 ignore_result(new AlertBridge(std::move(bridge_receiver))); 128} 129 130void ApplicationBridge::ShowColorPanel( 131 mojo::PendingReceiver<mojom::ColorPanel> receiver, 132 mojo::PendingRemote<mojom::ColorPanelHost> host) { 133 mojo::MakeSelfOwnedReceiver( 134 std::make_unique<ColorPanelBridge>(std::move(host)), std::move(receiver)); 135} 136 137void ApplicationBridge::CreateNativeWidgetNSWindow( 138 uint64_t bridge_id, 139 mojo::PendingAssociatedReceiver<mojom::NativeWidgetNSWindow> 140 bridge_receiver, 141 mojo::PendingAssociatedRemote<mojom::NativeWidgetNSWindowHost> host, 142 mojo::PendingAssociatedRemote<mojom::TextInputHost> text_input_host) { 143 // The resulting object will be destroyed when its message pipe is closed. 144 ignore_result( 145 new NativeWidgetBridgeOwner(bridge_id, std::move(bridge_receiver), 146 std::move(host), std::move(text_input_host))); 147} 148 149void ApplicationBridge::CreateRenderWidgetHostNSView( 150 mojo::PendingAssociatedRemote<mojom::StubInterface> host, 151 mojo::PendingAssociatedReceiver<mojom::StubInterface> view_receiver) { 152 if (!render_widget_host_create_callback_) 153 return; 154 render_widget_host_create_callback_.Run(host.PassHandle(), 155 view_receiver.PassHandle()); 156} 157 158void ApplicationBridge::CreateWebContentsNSView( 159 uint64_t view_id, 160 mojo::PendingAssociatedRemote<mojom::StubInterface> host, 161 mojo::PendingAssociatedReceiver<mojom::StubInterface> view_receiver) { 162 if (!web_conents_create_callback_) 163 return; 164 web_conents_create_callback_.Run(view_id, host.PassHandle(), 165 view_receiver.PassHandle()); 166} 167 168ApplicationBridge::ApplicationBridge() = default; 169 170ApplicationBridge::~ApplicationBridge() = default; 171 172} // namespace remote_cocoa 173