1 // Copyright 2016 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 "mojo/public/cpp/bindings/lib/binding_state.h"
6 #include "mojo/public/cpp/bindings/lib/task_runner_helper.h"
7 #include "mojo/public/cpp/bindings/mojo_buildflags.h"
8 
9 #if BUILDFLAG(MOJO_RANDOM_DELAYS_ENABLED)
10 #include "mojo/public/cpp/bindings/lib/test_random_mojo_delays.h"
11 #endif
12 
13 namespace mojo {
14 namespace internal {
15 
16 BindingStateBase::BindingStateBase() = default;
17 
18 BindingStateBase::~BindingStateBase() = default;
19 
SetFilter(std::unique_ptr<MessageFilter> filter)20 void BindingStateBase::SetFilter(std::unique_ptr<MessageFilter> filter) {
21   DCHECK(endpoint_client_);
22   endpoint_client_->SetFilter(std::move(filter));
23 }
24 
HasAssociatedInterfaces() const25 bool BindingStateBase::HasAssociatedInterfaces() const {
26   return router_ ? router_->HasAssociatedEndpoints() : false;
27 }
28 
PauseIncomingMethodCallProcessing()29 void BindingStateBase::PauseIncomingMethodCallProcessing() {
30   DCHECK(router_);
31   router_->PauseIncomingMethodCallProcessing();
32 }
33 
ResumeIncomingMethodCallProcessing()34 void BindingStateBase::ResumeIncomingMethodCallProcessing() {
35   DCHECK(router_);
36   router_->ResumeIncomingMethodCallProcessing();
37 }
38 
WaitForIncomingMethodCall()39 bool BindingStateBase::WaitForIncomingMethodCall() {
40   DCHECK(router_);
41   return router_->WaitForIncomingMessage();
42 }
43 
PauseRemoteCallbacksUntilFlushCompletes(PendingFlush flush)44 void BindingStateBase::PauseRemoteCallbacksUntilFlushCompletes(
45     PendingFlush flush) {
46   router_->PausePeerUntilFlushCompletes(std::move(flush));
47 }
48 
FlushAsync(AsyncFlusher flusher)49 void BindingStateBase::FlushAsync(AsyncFlusher flusher) {
50   router_->FlushAsync(std::move(flusher));
51 }
52 
Close()53 void BindingStateBase::Close() {
54   if (!router_)
55     return;
56 
57   weak_ptr_factory_.InvalidateWeakPtrs();
58 
59   endpoint_client_.reset();
60   router_->CloseMessagePipe();
61   router_ = nullptr;
62 }
63 
CloseWithReason(uint32_t custom_reason,const std::string & description)64 void BindingStateBase::CloseWithReason(uint32_t custom_reason,
65                                        const std::string& description) {
66   if (endpoint_client_)
67     endpoint_client_->CloseWithReason(custom_reason, description);
68 
69   Close();
70 }
71 
GetBadMessageCallback()72 ReportBadMessageCallback BindingStateBase::GetBadMessageCallback() {
73   return base::BindOnce(
74       [](ReportBadMessageCallback inner_callback,
75          base::WeakPtr<BindingStateBase> binding, const std::string& error) {
76         std::move(inner_callback).Run(error);
77         if (binding)
78           binding->Close();
79       },
80       mojo::GetBadMessageCallback(), weak_ptr_factory_.GetWeakPtr());
81 }
82 
FlushForTesting()83 void BindingStateBase::FlushForTesting() {
84   endpoint_client_->FlushForTesting();
85 }
86 
EnableBatchDispatch()87 void BindingStateBase::EnableBatchDispatch() {
88   DCHECK(is_bound());
89   router_->EnableBatchDispatch();
90 }
91 
EnableTestingMode()92 void BindingStateBase::EnableTestingMode() {
93   DCHECK(is_bound());
94   router_->EnableTestingMode();
95 }
96 
RouterForTesting()97 scoped_refptr<internal::MultiplexRouter> BindingStateBase::RouterForTesting() {
98   return router_;
99 }
100 
BindInternal(PendingReceiverState * receiver_state,scoped_refptr<base::SequencedTaskRunner> runner,const char * interface_name,std::unique_ptr<MessageReceiver> request_validator,bool passes_associated_kinds,bool has_sync_methods,MessageReceiverWithResponderStatus * stub,uint32_t interface_version)101 void BindingStateBase::BindInternal(
102     PendingReceiverState* receiver_state,
103     scoped_refptr<base::SequencedTaskRunner> runner,
104     const char* interface_name,
105     std::unique_ptr<MessageReceiver> request_validator,
106     bool passes_associated_kinds,
107     bool has_sync_methods,
108     MessageReceiverWithResponderStatus* stub,
109     uint32_t interface_version) {
110   DCHECK(!is_bound()) << "Attempting to bind interface that is already bound: "
111                       << interface_name;
112 
113   auto sequenced_runner =
114       GetTaskRunnerToUseFromUserProvidedTaskRunner(std::move(runner));
115 
116   MultiplexRouter::Config config =
117       passes_associated_kinds
118           ? MultiplexRouter::MULTI_INTERFACE
119           : (has_sync_methods
120                  ? MultiplexRouter::SINGLE_INTERFACE_WITH_SYNC_METHODS
121                  : MultiplexRouter::SINGLE_INTERFACE);
122   router_ = new MultiplexRouter(std::move(receiver_state->pipe), config, false,
123                                 sequenced_runner, interface_name);
124   router_->SetConnectionGroup(std::move(receiver_state->connection_group));
125 
126   endpoint_client_.reset(new InterfaceEndpointClient(
127       router_->CreateLocalEndpointHandle(kPrimaryInterfaceId), stub,
128       std::move(request_validator), has_sync_methods,
129       std::move(sequenced_runner), interface_version, interface_name));
130   endpoint_client_->SetIdleTrackingEnabledCallback(
131       base::BindOnce(&MultiplexRouter::SetConnectionGroup, router_));
132 
133 #if BUILDFLAG(MOJO_RANDOM_DELAYS_ENABLED)
134   MakeBindingRandomlyPaused(base::SequencedTaskRunnerHandle::Get(),
135                             weak_ptr_factory_.GetWeakPtr());
136 #endif
137 }
138 
139 }  // namespace internal
140 }  // namespace mojo
141