| Index: content/browser/renderer_host/render_process_host_impl.cc | 
| diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc | 
| index 7a225cf71b03d35c77ce75c3c717b481640fabee..38f13d5bbf9e3e1b798920cc18501f98e35c28ad 100644 | 
| --- a/content/browser/renderer_host/render_process_host_impl.cc | 
| +++ b/content/browser/renderer_host/render_process_host_impl.cc | 
| @@ -672,6 +672,7 @@ RenderProcessHostImpl::RenderProcessHostImpl( | 
| #endif | 
| pending_views_(0), | 
| child_token_(mojo::edk::GenerateRandomToken()), | 
| +      route_provider_binding_(this), | 
| visible_widgets_(0), | 
| is_process_backgrounded_(false), | 
| is_initialized_(false), | 
| @@ -827,10 +828,8 @@ RenderProcessHostImpl::~RenderProcessHostImpl() { | 
| #endif | 
| // We may have some unsent messages at this point, but that's OK. | 
| channel_.reset(); | 
| -  while (!queued_messages_.empty()) { | 
| -    delete queued_messages_.front(); | 
| +  while (!queued_messages_.empty()) | 
| queued_messages_.pop(); | 
| -  } | 
|  | 
| UnregisterHost(GetID()); | 
|  | 
| @@ -979,24 +978,33 @@ std::unique_ptr<IPC::ChannelProxy> RenderProcessHostImpl::CreateChannelProxy( | 
| IPC::ChannelMojo::CreateServerFactory( | 
| bootstrap.PassInterface().PassHandle(), runner); | 
|  | 
| +  std::unique_ptr<IPC::ChannelProxy> channel; | 
| // Do NOT expand ifdef or run time condition checks here! Synchronous | 
| // IPCs from browser process are banned. It is only narrowly allowed | 
| // for Android WebView to maintain backward compatibility. | 
| // See crbug.com/526842 for details. | 
| #if defined(OS_ANDROID) | 
| -  if (GetContentClient()->UsingSynchronousCompositing()) { | 
| -    return IPC::SyncChannel::Create( | 
| -        std::move(channel_factory), this, runner.get(), true, &never_signaled_); | 
| -  } | 
| +  if (GetContentClient()->UsingSynchronousCompositing()) | 
| +    channel = IPC::SyncChannel::Create(this, runner.get(), &never_signaled_); | 
| #endif  // OS_ANDROID | 
| - | 
| -  std::unique_ptr<IPC::ChannelProxy> channel( | 
| -      new IPC::ChannelProxy(this, runner.get())); | 
| +  if (!channel) | 
| +    channel.reset(new IPC::ChannelProxy(this, runner.get())); | 
| #if USE_ATTACHMENT_BROKER | 
| IPC::AttachmentBroker::GetGlobal()->RegisterCommunicationChannel( | 
| channel.get(), runner); | 
| #endif | 
| -  channel->Init(std::move(channel_factory), true); | 
| +  // The channel remains paused until OnProcessLaunched() so we can allow some | 
| +  // initialization messages there to preempt all other messages. | 
| +  channel->Init(std::move(channel_factory), true /* create_pipe_now */, | 
| +                true /* create_paused */); | 
| + | 
| +  // Queue all pending messages in the channel now. This allows them to be | 
| +  // ordered with respect to Mojo interface requests and method calls. | 
| +  while (!queued_messages_.empty()) { | 
| +    channel->Send(queued_messages_.front().release()); | 
| +    queued_messages_.pop(); | 
| +  } | 
| + | 
| return channel; | 
| } | 
|  | 
| @@ -1198,6 +1206,10 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() { | 
| interface_registry_android_.get()); | 
| #endif | 
|  | 
| +  channel_->AddAssociatedInterface( | 
| +      base::Bind(&RenderProcessHostImpl::OnRouteProviderRequest, | 
| +                 base::Unretained(this))); | 
| + | 
| #if !defined(OS_ANDROID) | 
| AddUIThreadInterface( | 
| registry.get(), base::Bind(&device::BatteryMonitorImpl::Create)); | 
| @@ -1271,6 +1283,17 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() { | 
| mojo_shell_connection->AddConnectionFilter(std::move(connection_filter)); | 
| } | 
|  | 
| +void RenderProcessHostImpl::GetRoutedInterfaces( | 
| +    int32_t routing_id, | 
| +    mojom::RoutedInterfaceProviderAssociatedRequest request) { | 
| +  auto it = routed_interface_providers_.find(routing_id); | 
| +  if (it == routed_interface_providers_.end()) | 
| +    return; | 
| +  DCHECK(request.is_pending()); | 
| +  routed_interface_provider_bindings_.AddBinding(it->second, | 
| +                                                 std::move(request)); | 
| +} | 
| + | 
| void RenderProcessHostImpl::CreateStoragePartitionService( | 
| mojo::InterfaceRequest<mojom::StoragePartitionService> request) { | 
| // DO NOT REMOVE THIS COMMAND LINE CHECK WITHOUT SECURITY REVIEW! | 
| @@ -1297,6 +1320,14 @@ shell::InterfaceProvider* RenderProcessHostImpl::GetRemoteInterfaces() { | 
| return mojo_child_connection_->GetRemoteInterfaces(); | 
| } | 
|  | 
| +mojom::RouteProvider* RenderProcessHostImpl::GetRemoteRouteProvider() { | 
| +  if (!remote_route_provider_) { | 
| +    DCHECK(channel_); | 
| +    channel_->GetRemoteAssociatedInterface(&remote_route_provider_); | 
| +  } | 
| +  return remote_route_provider_.get(); | 
| +} | 
| + | 
| std::unique_ptr<base::SharedPersistentMemoryAllocator> | 
| RenderProcessHostImpl::TakeMetricsAllocator() { | 
| return std::move(metrics_allocator_); | 
| @@ -1350,11 +1381,27 @@ void RenderProcessHostImpl::AddRoute(int32_t routing_id, | 
| } | 
|  | 
| void RenderProcessHostImpl::RemoveRoute(int32_t routing_id) { | 
| -  DCHECK(listeners_.Lookup(routing_id) != NULL); | 
| +  DCHECK(listeners_.Lookup(routing_id) != nullptr); | 
| listeners_.Remove(routing_id); | 
| +  routed_interface_providers_.erase(routing_id); | 
| Cleanup(); | 
| } | 
|  | 
| +void RenderProcessHostImpl::AddRoutedInterfaces( | 
| +    int32_t routing_id, | 
| +    mojom::RoutedInterfaceProvider* provider) { | 
| +  auto result = | 
| +      routed_interface_providers_.insert(std::make_pair(routing_id, provider)); | 
| +  DCHECK(result.second); | 
| +} | 
| + | 
| +mojo::AssociatedGroup* RenderProcessHostImpl::GetRoutedInterfaceGroup() { | 
| +  // Ensure that our route provider interface is bound. | 
| +  ignore_result(GetRemoteInterfaces()); | 
| +  DCHECK(remote_route_provider_); | 
| +  return remote_route_provider_.associated_group(); | 
| +} | 
| + | 
| void RenderProcessHostImpl::AddObserver(RenderProcessHostObserver* observer) { | 
| observers_.AddObserver(observer); | 
| } | 
| @@ -1855,38 +1902,33 @@ bool RenderProcessHostImpl::FastShutdownIfPossible() { | 
|  | 
| bool RenderProcessHostImpl::Send(IPC::Message* msg) { | 
| TRACE_EVENT0("renderer_host", "RenderProcessHostImpl::Send"); | 
| + | 
| +  std::unique_ptr<IPC::Message> message(msg); | 
| + | 
| #if !defined(OS_ANDROID) | 
| -  DCHECK(!msg->is_sync()); | 
| +  DCHECK(!message->is_sync()); | 
| #endif | 
|  | 
| if (!channel_) { | 
| #if defined(OS_ANDROID) | 
| -    if (msg->is_sync()) { | 
| -      delete msg; | 
| +    if (message->is_sync()) | 
| return false; | 
| -    } | 
| #endif | 
| if (!is_initialized_) { | 
| -      queued_messages_.push(msg); | 
| +      queued_messages_.emplace(std::move(message)); | 
| return true; | 
| -    } else { | 
| -      delete msg; | 
| -      return false; | 
| } | 
| +    return false; | 
| } | 
|  | 
| -  if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) { | 
| #if defined(OS_ANDROID) | 
| -    if (msg->is_sync()) { | 
| -      delete msg; | 
| -      return false; | 
| -    } | 
| -#endif | 
| -    queued_messages_.push(msg); | 
| -    return true; | 
| +  if (child_process_launcher_.get() && child_process_launcher_->IsStarting() && | 
| +      message->is_sync()) { | 
| +    return false; | 
| } | 
| +#endif | 
|  | 
| -  return channel_->Send(msg); | 
| +  return channel_->Send(message.release()); | 
| } | 
|  | 
| bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) { | 
| @@ -2542,6 +2584,13 @@ void RenderProcessHostImpl::CreateSharedRendererHistogramAllocator() { | 
| shm_handle, metrics_allocator_->shared_memory()->mapped_size())); | 
| } | 
|  | 
| +void RenderProcessHostImpl::OnRouteProviderRequest( | 
| +    mojom::RouteProviderAssociatedRequest request) { | 
| +  if (route_provider_binding_.is_bound()) | 
| +    return; | 
| +  route_provider_binding_.Bind(std::move(request)); | 
| +} | 
| + | 
| void RenderProcessHostImpl::ProcessDied(bool already_dead, | 
| RendererClosedDetails* known_details) { | 
| // Our child process has died.  If we didn't expect it, it's a crash. | 
| @@ -2586,10 +2635,8 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead, | 
| channel_.get()); | 
| #endif | 
| channel_.reset(); | 
| -  while (!queued_messages_.empty()) { | 
| -    delete queued_messages_.front(); | 
| +  while (!queued_messages_.empty()) | 
| queued_messages_.pop(); | 
| -  } | 
| UpdateProcessPriority(); | 
| DCHECK(!is_process_backgrounded_); | 
|  | 
| @@ -2736,6 +2783,12 @@ void RenderProcessHostImpl::OnProcessLaunched() { | 
| if (deleting_soon_) | 
| return; | 
|  | 
| +  // Unpause the channel now that the process is launched. We don't flush it yet | 
| +  // to ensure that any initialization messages sent here (e.g., things done in | 
| +  // response to NOTIFICATION_RENDER_PROCESS_CREATED; see below) preempt already | 
| +  // queued messages. | 
| +  channel_->Unpause(false /* flush */); | 
| + | 
| if (child_process_launcher_) { | 
| DCHECK(child_process_launcher_->GetProcess().IsValid()); | 
| DCHECK(!is_process_backgrounded_); | 
| @@ -2764,7 +2817,7 @@ void RenderProcessHostImpl::OnProcessLaunched() { | 
| CreateSharedRendererHistogramAllocator(); | 
| } | 
|  | 
| -  // NOTE: This needs to be before sending queued messages because | 
| +  // NOTE: This needs to be before flushing queued messages, because | 
| // ExtensionService uses this notification to initialize the renderer process | 
| // with state that must be there before any JavaScript executes. | 
| // | 
| @@ -2775,10 +2828,7 @@ void RenderProcessHostImpl::OnProcessLaunched() { | 
| Source<RenderProcessHost>(this), | 
| NotificationService::NoDetails()); | 
|  | 
| -  while (!queued_messages_.empty()) { | 
| -    Send(queued_messages_.front()); | 
| -    queued_messages_.pop(); | 
| -  } | 
| +  channel_->Flush(); | 
|  | 
| if (IsReady()) { | 
| DCHECK(!sent_render_process_ready_); | 
|  |