Commit da75e657 authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

RemoteMacViews: Add BridgeFactory to create remote BridgedNativeWidgets

Create a views_bridge_mac::mojom::BridgedFactory interface to create
remote views_bridge_mac::mojom::BridgedNativeWidget instances. The
chrome::mojom::AppShim interface will be updated in a follow-on patch
to have a method to provide a BridgedFactory instance.

Create a views_bridge_mac::mojom::BridgeFactoryImpl to instantiate
in the app shim process, to own the bridges.

Add a CreateWindow method to views_bridge_mac::mojom::BridgedFactory
to create a window in the app shim process. This function is not yet
expressive enough to encompass all window types needed, but is
sufficient for testing.

Add a BridgedNativeWidgetHostImpl::CreateRemoteBridge function to
create a remote bridge.

Bug: 859152
Change-Id: Iea81da4af7f3787f70474f49ba45c1c831d2fcc3
Reviewed-on: https://chromium-review.googlesource.com/1226251
Commit-Queue: ccameron <ccameron@chromium.org>
Reviewed-by: default avatarElly Fong-Jones <ellyjones@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#591920}
parent 3ee21463
......@@ -438,6 +438,8 @@ jumbo_component("views") {
# Internal sources. TODO(https://crbug.com/871123): Move more headers from
# public into this list, along with the implementation file.
sources += [
"cocoa/bridge_factory_impl.h",
"cocoa/bridge_factory_impl.mm",
"cocoa/bridged_content_view.h",
"cocoa/bridged_content_view.mm",
"cocoa/bridged_content_view_touch_bar.mm",
......@@ -481,6 +483,7 @@ jumbo_component("views") {
"//base:i18n",
"//base/third_party/dynamic_annotations",
"//cc/paint",
"//mojo/public/cpp/bindings",
"//services/ws/public/mojom",
"//skia",
"//third_party/icu",
......
......@@ -2,6 +2,7 @@ include_rules = [
"+cc/paint",
"+components/crash/core/common/crash_key.h",
"+components/vector_icons",
"+mojo/public/cpp/bindings",
"+services/ws/public/mojom",
"+skia/ext",
"+third_party/iaccessible2",
......
// Copyright 2018 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.
#ifndef UI_VIEWS_COCOA_BRIDGE_FACTORY_IMPL_H_
#define UI_VIEWS_COCOA_BRIDGE_FACTORY_IMPL_H_
#include "ui/views/views_export.h"
#include "ui/views_bridge_mac/mojo/bridge_factory.mojom.h"
#include "ui/views_bridge_mac/mojo/bridged_native_widget.mojom.h"
#include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h"
// TODO(ccameron): This file is to be moved to /ui/views_bridge_mac when
// possible. For now, put it in the namespace of that path.
namespace views_bridge_mac {
// The factory that creates BridgedNativeWidget instances. This object is to
// be instantiated in app shim processes.
class VIEWS_EXPORT BridgeFactoryImpl : public mojom::BridgeFactory {
public:
static BridgeFactoryImpl* Get();
void CreateBridge(uint64_t bridge_id,
mojom::BridgedNativeWidgetRequest bridge_request,
mojom::BridgedNativeWidgetHostPtr host) override;
void DestroyBridge(uint64_t bridge_id) override;
};
} // namespace views_bridge_mac
#endif // UI_VIEWS_COCOA_BRIDGE_FACTORY_IMPL_H_
// Copyright 2018 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.
#include "ui/views/cocoa/bridge_factory_impl.h"
#include "base/no_destructor.h"
#include "ui/views/cocoa/bridged_native_widget.h"
#include "ui/views/cocoa/bridged_native_widget_host.h"
namespace views_bridge_mac {
using views::BridgedNativeWidgetImpl;
using views::BridgedNativeWidgetHostHelper;
namespace {
class Bridge : public BridgedNativeWidgetHostHelper {
public:
Bridge(uint64_t bridge_id,
mojom::BridgedNativeWidgetHostPtr host_ptr,
mojom::BridgedNativeWidgetRequest bridge_request) {
host_ptr_ = std::move(host_ptr);
bridge_impl_ = std::make_unique<BridgedNativeWidgetImpl>(
bridge_id, host_ptr_.get(), this);
bridge_impl_->BindRequest(std::move(bridge_request));
}
~Bridge() override {}
// BridgedNativeWidgetHostHelper:
NSView* GetNativeViewAccessible() override { return nil; }
void DispatchKeyEvent(ui::KeyEvent* event) override {}
bool DispatchKeyEventToMenuController(ui::KeyEvent* event) override {
return false;
}
void GetWordAt(const gfx::Point& location_in_content,
bool* found_word,
gfx::DecoratedText* decorated_word,
gfx::Point* baseline_point) override {
*found_word = false;
}
double SheetPositionY() override { return 0; }
mojom::BridgedNativeWidgetHostPtr host_ptr_;
std::unique_ptr<BridgedNativeWidgetImpl> bridge_impl_;
};
std::map<uint64_t, std::unique_ptr<Bridge>>& GetBridgeMap() {
static base::NoDestructor<std::map<uint64_t, std::unique_ptr<Bridge>>> map;
return *map;
}
} // namespace
// static
BridgeFactoryImpl* BridgeFactoryImpl::Get() {
static base::NoDestructor<BridgeFactoryImpl> factory;
return factory.get();
}
void BridgeFactoryImpl::CreateBridge(
uint64_t bridge_id,
mojom::BridgedNativeWidgetRequest bridge_request,
mojom::BridgedNativeWidgetHostPtr host_ptr) {
GetBridgeMap()[bridge_id] = std::make_unique<Bridge>(
bridge_id, std::move(host_ptr), std::move(bridge_request));
}
void BridgeFactoryImpl::DestroyBridge(uint64_t bridge_id) {
GetBridgeMap().erase(bridge_id);
}
} // namespace views_bridge_mac
......@@ -13,6 +13,7 @@
#import "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "ui/accelerated_widget_mac/ca_transaction_observer.h"
#include "ui/accelerated_widget_mac/display_ca_layer_tree.h"
#include "ui/base/ime/text_input_client.h"
......@@ -70,11 +71,16 @@ class VIEWS_EXPORT BridgedNativeWidgetImpl
// Retrieve a BridgedNativeWidgetImpl* from its id.
static BridgedNativeWidgetImpl* GetFromId(uint64_t bridged_native_widget_id);
// Create an NSWindow for the specified parameters.
static base::scoped_nsobject<NativeWidgetMacNSWindow> CreateNSWindow(
views_bridge_mac::mojom::CreateWindowParams* params);
// Creates one side of the bridge. |host| and |parent| must not be NULL.
BridgedNativeWidgetImpl(uint64_t bridged_native_widget_id,
BridgedNativeWidgetHost* host,
BridgedNativeWidgetHostHelper* host_helper);
~BridgedNativeWidgetImpl() override;
void BindRequest(views_bridge_mac::mojom::BridgedNativeWidgetRequest request);
// Initialize the NSWindow by taking ownership of the specified object.
// TODO(ccameron): When a BridgedNativeWidgetImpl is allocated across a
......@@ -204,6 +210,8 @@ class VIEWS_EXPORT BridgedNativeWidgetImpl
base::TimeDelta PreCommitTimeout() override;
// views_bridge_mac::mojom::BridgedNativeWidget:
void CreateWindow(views_bridge_mac::mojom::CreateWindowParamsPtr params,
uint64_t parent_id) override;
void InitWindow(views_bridge_mac::mojom::BridgedNativeWidgetInitParamsPtr
params) override;
void InitCompositorView() override;
......@@ -343,6 +351,8 @@ class VIEWS_EXPORT BridgedNativeWidgetImpl
// shadow needs to be invalidated when a frame is received for the new shape.
bool invalidate_shadow_on_frame_swap_ = false;
mojo::Binding<views_bridge_mac::mojom::BridgedNativeWidget>
bridge_mojo_binding_;
DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetImpl);
};
......
......@@ -18,6 +18,7 @@
#include "base/strings/sys_string_conversions.h"
#include "ui/base/cocoa/cocoa_base_utils.h"
#import "ui/base/cocoa/constrained_window/constrained_window_animation.h"
#import "ui/base/cocoa/window_size_constants.h"
#include "ui/base/hit_test.h"
#include "ui/base/layout.h"
#include "ui/base/ui_base_switches.h"
......@@ -249,11 +250,27 @@ BridgedNativeWidgetImpl* BridgedNativeWidgetImpl::GetFromId(
return found->second;
}
// static
base::scoped_nsobject<NativeWidgetMacNSWindow>
BridgedNativeWidgetImpl::CreateNSWindow(
views_bridge_mac::mojom::CreateWindowParams* params) {
base::scoped_nsobject<NativeWidgetMacNSWindow> result(
[[NativeWidgetMacNSWindow alloc]
initWithContentRect:ui::kWindowSizeDeterminedLater
styleMask:params->style_mask
backing:NSBackingStoreBuffered
defer:NO]);
return result;
}
BridgedNativeWidgetImpl::BridgedNativeWidgetImpl(
uint64_t bridged_native_widget_id,
BridgedNativeWidgetHost* host,
BridgedNativeWidgetHostHelper* host_helper)
: id_(bridged_native_widget_id), host_(host), host_helper_(host_helper) {
: id_(bridged_native_widget_id),
host_(host),
host_helper_(host_helper),
bridge_mojo_binding_(this) {
DCHECK(GetIdToWidgetImplMap().find(id_) == GetIdToWidgetImplMap().end());
GetIdToWidgetImplMap().insert(std::make_pair(id_, this));
}
......@@ -276,6 +293,11 @@ BridgedNativeWidgetImpl::~BridgedNativeWidgetImpl() {
DestroyContentView();
}
void BridgedNativeWidgetImpl::BindRequest(
views_bridge_mac::mojom::BridgedNativeWidgetRequest request) {
bridge_mojo_binding_.Bind(std::move(request));
}
void BridgedNativeWidgetImpl::SetWindow(
base::scoped_nsobject<NativeWidgetMacNSWindow> window) {
DCHECK(!window_);
......@@ -322,6 +344,16 @@ void BridgedNativeWidgetImpl::SetParent(NSView* new_parent) {
NSWindowCollectionBehaviorTransient];
}
void BridgedNativeWidgetImpl::CreateWindow(
views_bridge_mac::mojom::CreateWindowParamsPtr params,
uint64_t parent_id) {
SetWindow(CreateNSWindow(params.get()));
BridgedNativeWidgetImpl* parent_bridge =
BridgedNativeWidgetImpl::GetFromId(parent_id);
if (parent_bridge)
SetParent(parent_bridge->ns_view());
}
void BridgedNativeWidgetImpl::InitWindow(
views_bridge_mac::mojom::BridgedNativeWidgetInitParamsPtr params) {
modal_type_ = params->modal_type;
......
......@@ -9,6 +9,7 @@
#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/accelerated_widget_mac/display_link_mac.h"
#include "ui/base/ime/input_method_delegate.h"
......@@ -18,6 +19,7 @@
#include "ui/views/views_export.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_observer.h"
#include "ui/views_bridge_mac/mojo/bridge_factory.mojom.h"
#include "ui/views_bridge_mac/mojo/bridged_native_widget.mojom.h"
#include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h"
......@@ -67,6 +69,12 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
return native_widget_mac_;
}
// The bridge factory that was used to create the true NSWindow for this
// widget. This is nullptr for in-process windows.
views_bridge_mac::mojom::BridgeFactory* bridge_factory() const {
return bridge_factory_;
}
// A NSWindow that is guaranteed to exist in this process. If the bridge
// object for this host is in this process, then this points to the bridge's
// NSWindow. Otherwise, it mirrors the id and bounds of the child window.
......@@ -87,6 +95,12 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
void CreateLocalBridge(base::scoped_nsobject<NativeWidgetMacNSWindow> window,
NSView* parent);
// Create and set the bridge object to be potentially in another process.
void CreateRemoteBridge(
views_bridge_mac::mojom::BridgeFactory* bridge_factory,
views_bridge_mac::mojom::CreateWindowParamsPtr window_create_params,
uint64_t parent_bridge_id);
void InitWindow(const Widget::InitParams& params);
// Changes the bounds of the window and the hosted layer if present. The
......@@ -268,10 +282,20 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
const uint64_t id_;
views::NativeWidgetMac* const native_widget_mac_; // Weak. Owns |this_|.
// The factory that was used to create |bridge_ptr_|.
// TODO(ccameron): The lifetime of this pointer is not correctly managed yet,
// and has no way to be set to nullptr when the bridge is deleted (this
// pointer is never non-nullptr in production).
views_bridge_mac::mojom::BridgeFactory* bridge_factory_ = nullptr;
Widget::InitParams::Type widget_type_ = Widget::InitParams::TYPE_WINDOW;
views::View* root_view_ = nullptr; // Weak. Owned by |native_widget_mac_|.
// The mojo pointer to a BridgedNativeWidget, which may exist in another
// process.
views_bridge_mac::mojom::BridgedNativeWidgetPtr bridge_ptr_;
// TODO(ccameron): Rather than instantiate a BridgedNativeWidgetImpl here,
// we will instantiate a mojo BridgedNativeWidgetImpl interface to a Cocoa
// instance that may be in another process.
......@@ -312,6 +336,8 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
// Contains NativeViewHost->gfx::NativeView associations.
std::map<const views::View*, NSView*> associated_views_;
mojo::Binding<views_bridge_mac::mojom::BridgedNativeWidgetHost>
host_mojo_binding_;
DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetHostImpl);
};
......
......@@ -74,7 +74,9 @@ BridgedNativeWidgetHostImpl* BridgedNativeWidgetHostImpl::GetFromId(
BridgedNativeWidgetHostImpl::BridgedNativeWidgetHostImpl(
NativeWidgetMac* parent)
: id_(++g_last_bridged_native_widget_id), native_widget_mac_(parent) {
: id_(++g_last_bridged_native_widget_id),
native_widget_mac_(parent),
host_mojo_binding_(this) {
DCHECK(GetIdToWidgetHostImplMap().find(id_) ==
GetIdToWidgetHostImplMap().end());
GetIdToWidgetHostImplMap().insert(std::make_pair(id_, this));
......@@ -104,6 +106,8 @@ NativeWidgetMacNSWindow* BridgedNativeWidgetHostImpl::GetLocalNSWindow() const {
views_bridge_mac::mojom::BridgedNativeWidget*
BridgedNativeWidgetHostImpl::bridge() const {
if (bridge_ptr_)
return bridge_ptr_.get();
if (bridge_impl_)
return bridge_impl_.get();
return nullptr;
......@@ -119,6 +123,28 @@ void BridgedNativeWidgetHostImpl::CreateLocalBridge(
bridge_impl_->SetParent(parent);
}
void BridgedNativeWidgetHostImpl::CreateRemoteBridge(
views_bridge_mac::mojom::BridgeFactory* bridge_factory,
views_bridge_mac::mojom::CreateWindowParamsPtr window_create_params,
uint64_t parent_bridge_id) {
bridge_factory_ = bridge_factory;
// Create the local window with the same parameters as will be used in the
// other process.
local_window_ =
BridgedNativeWidgetImpl::CreateNSWindow(window_create_params.get());
[local_window_ setBridgedNativeWidgetId:id_];
// Initialize |bridge_ptr_| to point to a bridge created by |factory|.
views_bridge_mac::mojom::BridgedNativeWidgetHostPtr host_ptr;
host_mojo_binding_.Bind(mojo::MakeRequest(&host_ptr));
bridge_factory_->CreateBridge(id_, mojo::MakeRequest(&bridge_ptr_),
std::move(host_ptr));
// Create the window in its process, and attach it to its parent window.
bridge()->CreateWindow(std::move(window_create_params), parent_bridge_id);
}
void BridgedNativeWidgetHostImpl::InitWindow(const Widget::InitParams& params) {
// Tooltip Widgets shouldn't have their own tooltip manager, but tooltips are
// native on Mac, so nothing should ever want one in Widget form.
......
......@@ -109,9 +109,33 @@ int NativeWidgetMac::SheetPositionY() {
void NativeWidgetMac::InitNativeWidget(const Widget::InitParams& params) {
ownership_ = params.ownership;
name_ = params.name;
base::scoped_nsobject<NativeWidgetMacNSWindow> window(
[CreateNSWindow(params) retain]);
bridge_host_->CreateLocalBridge(std::move(window), params.parent);
// Determine the factory through which to create the bridge.
// TODO(ccameron): Make widgets inherit their bridge factory from their
// parent, or, from the hosting process. At the moment, this path is
// unreachable.
BridgedNativeWidgetHostImpl* parent_host =
BridgedNativeWidgetHostImpl::GetFromNativeWindow([params.parent window]);
views_bridge_mac::mojom::BridgeFactory* bridge_factory = nullptr;
if (parent_host)
bridge_factory = parent_host->bridge_factory();
if (bridge_factory) {
// Compute the parameters to describe the NSWindow.
// TODO(ccameron): This is not yet adequate to capture all NSWindow
// sub-classes that may be used. Make the parameter structure more
// expressive.
auto create_window_params =
views_bridge_mac::mojom::CreateWindowParams::New();
create_window_params->style_mask = StyleMaskForParams(params);
bridge_host_->CreateRemoteBridge(
bridge_factory, std::move(create_window_params),
parent_host ? parent_host->bridged_native_widget_id() : 0);
} else {
base::scoped_nsobject<NativeWidgetMacNSWindow> window(
[CreateNSWindow(params) retain]);
bridge_host_->CreateLocalBridge(std::move(window), params.parent);
}
bridge_host_->InitWindow(params);
// Only set always-on-top here if it is true since setting it may affect how
......
......@@ -8,6 +8,7 @@ mojom("mojo") {
cpp_only = true
sources = [
"mojo/bridge_factory.mojom",
"mojo/bridged_native_widget.mojom",
"mojo/bridged_native_widget_host.mojom",
]
......
// Copyright 2018 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.
module views_bridge_mac.mojom;
import "ui/views_bridge_mac/mojo/bridged_native_widget.mojom";
import "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom";
// The interface through which a bridge is created and connected to its host.
interface BridgeFactory {
CreateBridge(
uint64 bridge_id,
BridgedNativeWidget& bridge_request,
BridgedNativeWidgetHost host);
DestroyBridge(uint64 bridge_id);
};
......@@ -9,6 +9,13 @@ import "ui/base/mojo/ui_base_types.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
import "ui/gfx/mojo/ca_layer_params.mojom";
// Parameters used to described creation of an NSWindow.
// TODO(ccameron): Add additional members to support all window sub-classes.
struct CreateWindowParams {
// The NSWindowStyleMask for the window.
uint64 style_mask;
};
// Ways of changing the visibility of the bridged NSWindow.
enum WindowVisibilityState {
// Hides with -[NSWindow orderOut:].
......@@ -38,6 +45,10 @@ struct BridgedNativeWidgetInitParams {
// The interface through which a NativeWidgetMac may interact with an NSWindow
// in another process.
interface BridgedNativeWidget {
// Create and set the NSWindow for the bridge, and assign it the parent
// NSWindow specified by |parent_id|.
CreateWindow(CreateWindowParams params, uint64 parent_id);
// Initialize the window's style.
InitWindow(BridgedNativeWidgetInitParams params);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment