Skip to content

Commit f62002a

Browse files
krockotCommit bot
authored and
Commit bot
committed
Adds associated interface support between RenderFrameHost and RenderFrame.
Introduces a new content::AssociatedInterfaceRegistry and content::AssociatedInterfaceProvider to serve as Channel-associated interface counterparts to their shell namesakes. RenderFrameHost and RenderFrame each have both of these things on them, and they're routed to the other side using a new RouteProvider interface buried in RenderProcessHostImpl / ChildThreadImpl on either end. Also adds a WebContentsInterfaceRegistry to every WebContents, and a helper WebContentsFrameBindingSet<T> to allow consumers to very easily manage the lifetime of associated interface bindings for each frame in a WebContents. See the follow-up patch for example usage. Part a series of CLs to enable and demonstrate WebContents associated interfaces: 1. https://codereview.chromium.org/2309513002 2. https://codereview.chromium.org/2316963005 3. This CL 4. https://codereview.chromium.org/2310583002 BUG=612500 CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_site_isolation Review-Url: https://codereview.chromium.org/2310563002 Cr-Commit-Position: refs/heads/master@{#418717}
1 parent 751cb04 commit f62002a

33 files changed

+870
-68
lines changed

content/browser/frame_host/render_frame_host_delegate.h

+8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <stdint.h>
99

10+
#include <string>
1011
#include <vector>
1112

1213
#include "base/i18n/rtl.h"
@@ -17,6 +18,7 @@
1718
#include "content/public/browser/site_instance.h"
1819
#include "content/public/common/javascript_message_type.h"
1920
#include "content/public/common/media_stream_request.h"
21+
#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
2022
#include "net/http/http_response_headers.h"
2123

2224
#if defined(OS_WIN)
@@ -54,6 +56,12 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
5456
virtual bool OnMessageReceived(RenderFrameHost* render_frame_host,
5557
const IPC::Message& message);
5658

59+
// Allows the delegate to filter incoming associated inteface requests.
60+
virtual void OnAssociatedInterfaceRequest(
61+
RenderFrameHost* render_frame_host,
62+
const std::string& interface_name,
63+
mojo::ScopedInterfaceEndpointHandle handle) {}
64+
5765
// Gets the last committed URL. See WebContents::GetLastCommittedURL for a
5866
// description of the semantics.
5967
virtual const GURL& GetMainFrameLastCommittedURL() const;

content/browser/frame_host/render_frame_host_impl.cc

+36
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
#include "content/browser/websockets/websocket_manager.h"
5454
#include "content/browser/webui/web_ui_controller_factory_registry.h"
5555
#include "content/common/accessibility_messages.h"
56+
#include "content/common/associated_interface_provider_impl.h"
57+
#include "content/common/associated_interfaces.mojom.h"
5658
#include "content/common/frame_messages.h"
5759
#include "content/common/frame_owner_properties.h"
5860
#include "content/common/input_messages.h"
@@ -87,6 +89,7 @@
8789
#include "device/vibration/vibration_manager_impl.h"
8890
#include "media/mojo/interfaces/media_service.mojom.h"
8991
#include "media/mojo/interfaces/service_factory.mojom.h"
92+
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
9093
#include "services/shell/public/cpp/connector.h"
9194
#include "services/shell/public/cpp/interface_provider.h"
9295
#include "ui/accessibility/ax_tree.h"
@@ -500,6 +503,28 @@ shell::InterfaceProvider* RenderFrameHostImpl::GetRemoteInterfaces() {
500503
return remote_interfaces_.get();
501504
}
502505

506+
AssociatedInterfaceProvider*
507+
RenderFrameHostImpl::GetRemoteAssociatedInterfaces() {
508+
if (!remote_associated_interfaces_) {
509+
mojom::AssociatedInterfaceProviderAssociatedPtr remote_interfaces;
510+
IPC::ChannelProxy* channel = GetProcess()->GetChannel();
511+
if (channel) {
512+
RenderProcessHostImpl* process =
513+
static_cast<RenderProcessHostImpl*>(GetProcess());
514+
process->GetRemoteRouteProvider()->GetRoute(
515+
GetRoutingID(),
516+
mojo::GetProxy(&remote_interfaces, channel->GetAssociatedGroup()));
517+
} else {
518+
// The channel may not be initialized in some tests environments. In this
519+
// case we set up a dummy interface provider.
520+
mojo::GetDummyProxyForTesting(&remote_interfaces);
521+
}
522+
remote_associated_interfaces_.reset(new AssociatedInterfaceProviderImpl(
523+
std::move(remote_interfaces)));
524+
}
525+
return remote_associated_interfaces_.get();
526+
}
527+
503528
blink::WebPageVisibilityState RenderFrameHostImpl::GetVisibilityState() {
504529
// Works around the crashes seen in https://crbug.com/501863, where the
505530
// active WebContents from a browser iterator may contain a render frame
@@ -643,6 +668,13 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
643668
return handled;
644669
}
645670

671+
void RenderFrameHostImpl::OnAssociatedInterfaceRequest(
672+
const std::string& interface_name,
673+
mojo::ScopedInterfaceEndpointHandle handle) {
674+
delegate_->OnAssociatedInterfaceRequest(
675+
this, interface_name, std::move(handle));
676+
}
677+
646678
void RenderFrameHostImpl::AccessibilitySetFocus(int object_id) {
647679
Send(new AccessibilityMsg_SetFocus(routing_id_, object_id));
648680
}
@@ -1463,6 +1495,10 @@ void RenderFrameHostImpl::OnRenderProcessGone(int status, int exit_code) {
14631495
iter.second.Run(ui::AXTreeUpdate());
14641496
ax_tree_snapshot_callbacks_.clear();
14651497

1498+
// Ensure that future remote interface requests are associated with the new
1499+
// process's channel.
1500+
remote_associated_interfaces_.reset();
1501+
14661502
if (!is_active()) {
14671503
// If the process has died, we don't need to wait for the swap out ack from
14681504
// this RenderFrame if it is pending deletion. Complete the swap out to

content/browser/frame_host/render_frame_host_impl.h

+8
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class WebBluetoothService;
7474

7575
namespace content {
7676

77+
class AssociatedInterfaceProviderImpl;
7778
class CrossProcessFrameConnector;
7879
class CrossSiteTransferringRequest;
7980
class FrameTree;
@@ -159,6 +160,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
159160
RenderViewHost* GetRenderViewHost() override;
160161
shell::InterfaceRegistry* GetInterfaceRegistry() override;
161162
shell::InterfaceProvider* GetRemoteInterfaces() override;
163+
AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() override;
162164
blink::WebPageVisibilityState GetVisibilityState() override;
163165
bool IsRenderFrameLive() override;
164166
int GetProxyCount() override;
@@ -177,6 +179,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
177179

178180
// IPC::Listener
179181
bool OnMessageReceived(const IPC::Message& msg) override;
182+
void OnAssociatedInterfaceRequest(
183+
const std::string& interface_name,
184+
mojo::ScopedInterfaceEndpointHandle handle) override;
180185

181186
// BrowserAccessibilityDelegate
182187
void AccessibilitySetFocus(int acc_obj_id) override;
@@ -1055,6 +1060,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
10551060

10561061
std::vector<std::unique_ptr<shell::InterfaceRegistry>> media_registries_;
10571062

1063+
std::unique_ptr<AssociatedInterfaceProviderImpl>
1064+
remote_associated_interfaces_;
1065+
10581066
// NOTE: This must be the last member.
10591067
base::WeakPtrFactory<RenderFrameHostImpl> weak_ptr_factory_;
10601068

content/browser/renderer_host/render_process_host_impl.cc

+82-39
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,9 @@ RenderProcessHostImpl::RenderProcessHostImpl(
675675
child_token_(mojo::edk::GenerateRandomToken()),
676676
service_worker_ref_count_(0),
677677
shared_worker_ref_count_(0),
678+
route_provider_binding_(this),
679+
associated_interface_provider_bindings_(
680+
mojo::BindingSetDispatchMode::WITH_CONTEXT),
678681
visible_widgets_(0),
679682
is_process_backgrounded_(false),
680683
is_initialized_(false),
@@ -815,10 +818,7 @@ RenderProcessHostImpl::~RenderProcessHostImpl() {
815818
#endif
816819
// We may have some unsent messages at this point, but that's OK.
817820
channel_.reset();
818-
while (!queued_messages_.empty()) {
819-
delete queued_messages_.front();
820-
queued_messages_.pop();
821-
}
821+
queued_messages_ = MessageQueue{};
822822

823823
UnregisterHost(GetID());
824824

@@ -941,10 +941,19 @@ bool RenderProcessHostImpl::Init() {
941941
base::Bind(&RenderProcessHostImpl::OnMojoError,
942942
weak_factory_.GetWeakPtr(),
943943
base::ThreadTaskRunnerHandle::Get())));
944+
channel_->Pause();
944945

945946
fast_shutdown_started_ = false;
946947
}
947948

949+
// Push any pending messages to the channel now. Note that if the child
950+
// process is still launching, the channel will be paused and outgoing
951+
// messages will be queued internally by the channel.
952+
while (!queued_messages_.empty()) {
953+
channel_->Send(queued_messages_.front().release());
954+
queued_messages_.pop();
955+
}
956+
948957
if (!gpu_observer_registered_) {
949958
gpu_observer_registered_ = true;
950959
ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
@@ -967,24 +976,23 @@ std::unique_ptr<IPC::ChannelProxy> RenderProcessHostImpl::CreateChannelProxy(
967976
IPC::ChannelMojo::CreateServerFactory(
968977
bootstrap.PassInterface().PassHandle(), runner);
969978

979+
std::unique_ptr<IPC::ChannelProxy> channel;
970980
// Do NOT expand ifdef or run time condition checks here! Synchronous
971981
// IPCs from browser process are banned. It is only narrowly allowed
972982
// for Android WebView to maintain backward compatibility.
973983
// See crbug.com/526842 for details.
974984
#if defined(OS_ANDROID)
975-
if (GetContentClient()->UsingSynchronousCompositing()) {
976-
return IPC::SyncChannel::Create(
977-
std::move(channel_factory), this, runner.get(), true, &never_signaled_);
978-
}
985+
if (GetContentClient()->UsingSynchronousCompositing())
986+
channel = IPC::SyncChannel::Create(this, runner.get(), &never_signaled_);
979987
#endif // OS_ANDROID
980-
981-
std::unique_ptr<IPC::ChannelProxy> channel(
982-
new IPC::ChannelProxy(this, runner.get()));
988+
if (!channel)
989+
channel.reset(new IPC::ChannelProxy(this, runner.get()));
983990
#if USE_ATTACHMENT_BROKER
984991
IPC::AttachmentBroker::GetGlobal()->RegisterCommunicationChannel(
985992
channel.get(), runner);
986993
#endif
987-
channel->Init(std::move(channel_factory), true);
994+
channel->Init(std::move(channel_factory), true /* create_pipe_now */);
995+
988996
return channel;
989997
}
990998

@@ -1186,6 +1194,10 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
11861194
interface_registry_android_.get());
11871195
#endif
11881196

1197+
channel_->AddAssociatedInterface(
1198+
base::Bind(&RenderProcessHostImpl::OnRouteProviderRequest,
1199+
base::Unretained(this)));
1200+
11891201
#if !defined(OS_ANDROID)
11901202
AddUIThreadInterface(
11911203
registry.get(), base::Bind(&device::BatteryMonitorImpl::Create));
@@ -1261,6 +1273,25 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
12611273
mojo_shell_connection->AddConnectionFilter(std::move(connection_filter));
12621274
}
12631275

1276+
void RenderProcessHostImpl::GetRoute(
1277+
int32_t routing_id,
1278+
mojom::AssociatedInterfaceProviderAssociatedRequest request) {
1279+
DCHECK(request.is_pending());
1280+
associated_interface_provider_bindings_.AddBinding(
1281+
this, std::move(request),
1282+
reinterpret_cast<void*>(static_cast<uintptr_t>(routing_id)));
1283+
}
1284+
1285+
void RenderProcessHostImpl::GetAssociatedInterface(
1286+
const std::string& name,
1287+
mojom::AssociatedInterfaceAssociatedRequest request) {
1288+
int32_t routing_id = static_cast<int32_t>(reinterpret_cast<uintptr_t>(
1289+
associated_interface_provider_bindings_.dispatch_context()));
1290+
IPC::Listener* listener = listeners_.Lookup(routing_id);
1291+
if (listener)
1292+
listener->OnAssociatedInterfaceRequest(name, request.PassHandle());
1293+
}
1294+
12641295
void RenderProcessHostImpl::CreateStoragePartitionService(
12651296
mojo::InterfaceRequest<mojom::StoragePartitionService> request) {
12661297
// DO NOT REMOVE THIS COMMAND LINE CHECK WITHOUT SECURITY REVIEW!
@@ -1347,6 +1378,14 @@ void RenderProcessHostImpl::PurgeAndSuspend() {
13471378
Send(new ChildProcessMsg_PurgeAndSuspend());
13481379
}
13491380

1381+
mojom::RouteProvider* RenderProcessHostImpl::GetRemoteRouteProvider() {
1382+
if (!remote_route_provider_) {
1383+
DCHECK(channel_);
1384+
channel_->GetRemoteAssociatedInterface(&remote_route_provider_);
1385+
}
1386+
return remote_route_provider_.get();
1387+
}
1388+
13501389
void RenderProcessHostImpl::AddRoute(int32_t routing_id,
13511390
IPC::Listener* listener) {
13521391
CHECK(!listeners_.Lookup(routing_id)) << "Found Routing ID Conflict: "
@@ -1355,7 +1394,7 @@ void RenderProcessHostImpl::AddRoute(int32_t routing_id,
13551394
}
13561395

13571396
void RenderProcessHostImpl::RemoveRoute(int32_t routing_id) {
1358-
DCHECK(listeners_.Lookup(routing_id) != NULL);
1397+
DCHECK(listeners_.Lookup(routing_id) != nullptr);
13591398
listeners_.Remove(routing_id);
13601399
Cleanup();
13611400
}
@@ -1861,38 +1900,33 @@ bool RenderProcessHostImpl::FastShutdownIfPossible() {
18611900

18621901
bool RenderProcessHostImpl::Send(IPC::Message* msg) {
18631902
TRACE_EVENT0("renderer_host", "RenderProcessHostImpl::Send");
1903+
1904+
std::unique_ptr<IPC::Message> message(msg);
1905+
18641906
#if !defined(OS_ANDROID)
1865-
DCHECK(!msg->is_sync());
1907+
DCHECK(!message->is_sync());
18661908
#endif
18671909

18681910
if (!channel_) {
18691911
#if defined(OS_ANDROID)
1870-
if (msg->is_sync()) {
1871-
delete msg;
1912+
if (message->is_sync())
18721913
return false;
1873-
}
18741914
#endif
18751915
if (!is_initialized_) {
1876-
queued_messages_.push(msg);
1916+
queued_messages_.emplace(std::move(message));
18771917
return true;
1878-
} else {
1879-
delete msg;
1880-
return false;
18811918
}
1919+
return false;
18821920
}
18831921

1884-
if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) {
18851922
#if defined(OS_ANDROID)
1886-
if (msg->is_sync()) {
1887-
delete msg;
1888-
return false;
1889-
}
1890-
#endif
1891-
queued_messages_.push(msg);
1892-
return true;
1923+
if (child_process_launcher_.get() && child_process_launcher_->IsStarting() &&
1924+
message->is_sync()) {
1925+
return false;
18931926
}
1927+
#endif
18941928

1895-
return channel_->Send(msg);
1929+
return channel_->Send(message.release());
18961930
}
18971931

18981932
bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
@@ -2548,6 +2582,13 @@ void RenderProcessHostImpl::CreateSharedRendererHistogramAllocator() {
25482582
shm_handle, metrics_allocator_->shared_memory()->mapped_size()));
25492583
}
25502584

2585+
void RenderProcessHostImpl::OnRouteProviderRequest(
2586+
mojom::RouteProviderAssociatedRequest request) {
2587+
if (route_provider_binding_.is_bound())
2588+
return;
2589+
route_provider_binding_.Bind(std::move(request));
2590+
}
2591+
25512592
void RenderProcessHostImpl::ProcessDied(bool already_dead,
25522593
RendererClosedDetails* known_details) {
25532594
// Our child process has died. If we didn't expect it, it's a crash.
@@ -2592,10 +2633,8 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead,
25922633
channel_.get());
25932634
#endif
25942635
channel_.reset();
2595-
while (!queued_messages_.empty()) {
2596-
delete queued_messages_.front();
2597-
queued_messages_.pop();
2598-
}
2636+
queued_messages_ = MessageQueue{};
2637+
25992638
UpdateProcessPriority();
26002639
DCHECK(!is_process_backgrounded_);
26012640

@@ -2746,6 +2785,12 @@ void RenderProcessHostImpl::OnProcessLaunched() {
27462785
DCHECK(child_process_launcher_->GetProcess().IsValid());
27472786
DCHECK(!is_process_backgrounded_);
27482787

2788+
// Unpause the channel now that the process is launched. We don't flush it
2789+
// yet to ensure that any initialization messages sent here (e.g., things
2790+
// done in response to NOTIFICATION_RENDER_PROCESS_CREATED; see below)
2791+
// preempt already queued messages.
2792+
channel_->Unpause(false /* flush */);
2793+
27492794
if (mojo_child_connection_) {
27502795
mojo_child_connection_->SetProcessHandle(
27512796
child_process_launcher_->GetProcess().Handle());
@@ -2770,7 +2815,7 @@ void RenderProcessHostImpl::OnProcessLaunched() {
27702815
CreateSharedRendererHistogramAllocator();
27712816
}
27722817

2773-
// NOTE: This needs to be before sending queued messages because
2818+
// NOTE: This needs to be before flushing queued messages, because
27742819
// ExtensionService uses this notification to initialize the renderer process
27752820
// with state that must be there before any JavaScript executes.
27762821
//
@@ -2781,10 +2826,8 @@ void RenderProcessHostImpl::OnProcessLaunched() {
27812826
Source<RenderProcessHost>(this),
27822827
NotificationService::NoDetails());
27832828

2784-
while (!queued_messages_.empty()) {
2785-
Send(queued_messages_.front());
2786-
queued_messages_.pop();
2787-
}
2829+
if (child_process_launcher_)
2830+
channel_->Flush();
27882831

27892832
if (IsReady()) {
27902833
DCHECK(!sent_render_process_ready_);

0 commit comments

Comments
 (0)