| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 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 "blimp/net/browser_connection_handler.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 | |
| 9 #include <string> | |
| 10 | |
| 11 #include "base/callback_helpers.h" | |
| 12 #include "base/location.h" | |
| 13 #include "base/memory/ptr_util.h" | |
| 14 #include "base/message_loop/message_loop.h" | |
| 15 #include "base/run_loop.h" | |
| 16 #include "base/single_thread_task_runner.h" | |
| 17 #include "base/threading/thread_task_runner_handle.h" | |
| 18 #include "blimp/common/proto/blimp_message.pb.h" | |
| 19 #include "blimp/net/blimp_message_processor.h" | |
| 20 #include "blimp/net/common.h" | |
| 21 #include "blimp/net/connection_error_observer.h" | |
| 22 #include "blimp/net/test_common.h" | |
| 23 #include "net/base/completion_callback.h" | |
| 24 #include "net/base/io_buffer.h" | |
| 25 #include "net/base/net_errors.h" | |
| 26 #include "net/base/test_completion_callback.h" | |
| 27 #include "testing/gmock/include/gmock/gmock.h" | |
| 28 #include "testing/gtest/include/gtest/gtest.h" | |
| 29 | |
| 30 using testing::_; | |
| 31 using testing::InSequence; | |
| 32 using testing::Return; | |
| 33 using testing::SaveArg; | |
| 34 | |
| 35 namespace blimp { | |
| 36 namespace { | |
| 37 | |
| 38 // Compares two blimp messages and ignores message_id field. | |
| 39 MATCHER_P(EqualsMessageIgnoringId, message, "") { | |
| 40 BlimpMessage expected_message = message; | |
| 41 expected_message.clear_message_id(); | |
| 42 BlimpMessage actual_message = arg; | |
| 43 actual_message.clear_message_id(); | |
| 44 | |
| 45 std::string expected_serialized; | |
| 46 std::string actual_serialized; | |
| 47 expected_message.SerializeToString(&expected_serialized); | |
| 48 actual_message.SerializeToString(&actual_serialized); | |
| 49 return expected_serialized == actual_serialized; | |
| 50 } | |
| 51 | |
| 52 class FakeFeature { | |
| 53 public: | |
| 54 FakeFeature(BlimpMessage::FeatureCase feature_case, | |
| 55 BrowserConnectionHandler* connection_handler) { | |
| 56 outgoing_message_processor_ = connection_handler->RegisterFeature( | |
| 57 feature_case, &incoming_message_processor_); | |
| 58 } | |
| 59 | |
| 60 ~FakeFeature() {} | |
| 61 | |
| 62 BlimpMessageProcessor* outgoing_message_processor() { | |
| 63 return outgoing_message_processor_.get(); | |
| 64 } | |
| 65 | |
| 66 MockBlimpMessageProcessor* incoming_message_processor() { | |
| 67 return &incoming_message_processor_; | |
| 68 } | |
| 69 | |
| 70 private: | |
| 71 testing::StrictMock<MockBlimpMessageProcessor> incoming_message_processor_; | |
| 72 std::unique_ptr<BlimpMessageProcessor> outgoing_message_processor_; | |
| 73 }; | |
| 74 | |
| 75 class FakeBlimpConnection : public BlimpConnection, | |
| 76 public BlimpMessageProcessor { | |
| 77 public: | |
| 78 FakeBlimpConnection() {} | |
| 79 ~FakeBlimpConnection() override {} | |
| 80 | |
| 81 void set_other_end(FakeBlimpConnection* other_end) { other_end_ = other_end; } | |
| 82 | |
| 83 ConnectionErrorObserver* error_observer() { return error_observer_; } | |
| 84 | |
| 85 // BlimpConnection implementation. | |
| 86 void AddConnectionErrorObserver(ConnectionErrorObserver* observer) override { | |
| 87 error_observer_ = observer; | |
| 88 } | |
| 89 | |
| 90 void SetIncomingMessageProcessor(BlimpMessageProcessor* processor) override { | |
| 91 incoming_message_processor_ = processor; | |
| 92 } | |
| 93 | |
| 94 BlimpMessageProcessor* GetOutgoingMessageProcessor() override { return this; } | |
| 95 | |
| 96 private: | |
| 97 void ForwardMessage(std::unique_ptr<BlimpMessage> message) { | |
| 98 other_end_->incoming_message_processor_->ProcessMessage( | |
| 99 std::move(message), net::CompletionCallback()); | |
| 100 } | |
| 101 | |
| 102 // BlimpMessageProcessor implementation. | |
| 103 void ProcessMessage(std::unique_ptr<BlimpMessage> message, | |
| 104 const net::CompletionCallback& callback) override { | |
| 105 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 106 FROM_HERE, base::Bind(&FakeBlimpConnection::ForwardMessage, | |
| 107 base::Unretained(this), base::Passed(&message))); | |
| 108 | |
| 109 callback.Run(net::OK); | |
| 110 } | |
| 111 | |
| 112 FakeBlimpConnection* other_end_ = nullptr; | |
| 113 ConnectionErrorObserver* error_observer_ = nullptr; | |
| 114 BlimpMessageProcessor* incoming_message_processor_ = nullptr; | |
| 115 }; | |
| 116 | |
| 117 std::unique_ptr<BlimpMessage> CreateInputMessage(int tab_id) { | |
| 118 std::unique_ptr<BlimpMessage> output(new BlimpMessage); | |
| 119 output->mutable_input(); | |
| 120 output->set_target_tab_id(tab_id); | |
| 121 return output; | |
| 122 } | |
| 123 | |
| 124 std::unique_ptr<BlimpMessage> CreateControlMessage(int tab_id) { | |
| 125 std::unique_ptr<BlimpMessage> output(new BlimpMessage); | |
| 126 output->mutable_tab_control(); | |
| 127 output->set_target_tab_id(tab_id); | |
| 128 return output; | |
| 129 } | |
| 130 | |
| 131 class BrowserConnectionHandlerTest : public testing::Test { | |
| 132 public: | |
| 133 BrowserConnectionHandlerTest() | |
| 134 : client_connection_handler_(new BrowserConnectionHandler), | |
| 135 engine_connection_handler_(new BrowserConnectionHandler) { | |
| 136 SetupConnections(); | |
| 137 | |
| 138 client_input_feature_.reset(new FakeFeature( | |
| 139 BlimpMessage::kInput, client_connection_handler_.get())); | |
| 140 engine_input_feature_.reset(new FakeFeature( | |
| 141 BlimpMessage::kInput, engine_connection_handler_.get())); | |
| 142 client_control_feature_.reset(new FakeFeature( | |
| 143 BlimpMessage::kTabControl, client_connection_handler_.get())); | |
| 144 engine_control_feature_.reset(new FakeFeature( | |
| 145 BlimpMessage::kTabControl, engine_connection_handler_.get())); | |
| 146 } | |
| 147 | |
| 148 ~BrowserConnectionHandlerTest() override {} | |
| 149 void TearDown() override { base::RunLoop().RunUntilIdle(); } | |
| 150 | |
| 151 protected: | |
| 152 void SetupConnections() { | |
| 153 client_connection_ = new FakeBlimpConnection(); | |
| 154 engine_connection_ = new FakeBlimpConnection(); | |
| 155 client_connection_->set_other_end(engine_connection_); | |
| 156 engine_connection_->set_other_end(client_connection_); | |
| 157 client_connection_handler_->HandleConnection( | |
| 158 base::WrapUnique(client_connection_)); | |
| 159 engine_connection_handler_->HandleConnection( | |
| 160 base::WrapUnique(engine_connection_)); | |
| 161 } | |
| 162 | |
| 163 base::MessageLoop message_loop_; | |
| 164 | |
| 165 FakeBlimpConnection* client_connection_; | |
| 166 FakeBlimpConnection* engine_connection_; | |
| 167 | |
| 168 std::unique_ptr<BrowserConnectionHandler> client_connection_handler_; | |
| 169 std::unique_ptr<BrowserConnectionHandler> engine_connection_handler_; | |
| 170 | |
| 171 std::unique_ptr<FakeFeature> client_input_feature_; | |
| 172 std::unique_ptr<FakeFeature> engine_input_feature_; | |
| 173 std::unique_ptr<FakeFeature> client_control_feature_; | |
| 174 std::unique_ptr<FakeFeature> engine_control_feature_; | |
| 175 }; | |
| 176 | |
| 177 TEST_F(BrowserConnectionHandlerTest, ExchangeMessages) { | |
| 178 std::unique_ptr<BlimpMessage> client_input_message = CreateInputMessage(1); | |
| 179 std::unique_ptr<BlimpMessage> client_control_message = | |
| 180 CreateControlMessage(1); | |
| 181 std::unique_ptr<BlimpMessage> engine_control_message = | |
| 182 CreateControlMessage(2); | |
| 183 | |
| 184 EXPECT_CALL( | |
| 185 *(engine_input_feature_->incoming_message_processor()), | |
| 186 MockableProcessMessage(EqualsMessageIgnoringId(*client_input_message), _)) | |
| 187 .RetiresOnSaturation(); | |
| 188 EXPECT_CALL(*(engine_control_feature_->incoming_message_processor()), | |
| 189 MockableProcessMessage( | |
| 190 EqualsMessageIgnoringId(*client_control_message), _)) | |
| 191 .RetiresOnSaturation(); | |
| 192 EXPECT_CALL(*(client_control_feature_->incoming_message_processor()), | |
| 193 MockableProcessMessage( | |
| 194 EqualsMessageIgnoringId(*engine_control_message), _)) | |
| 195 .RetiresOnSaturation(); | |
| 196 | |
| 197 client_input_feature_->outgoing_message_processor()->ProcessMessage( | |
| 198 std::move(client_input_message), net::CompletionCallback()); | |
| 199 client_control_feature_->outgoing_message_processor()->ProcessMessage( | |
| 200 std::move(client_control_message), net::CompletionCallback()); | |
| 201 engine_control_feature_->outgoing_message_processor()->ProcessMessage( | |
| 202 std::move(engine_control_message), net::CompletionCallback()); | |
| 203 } | |
| 204 | |
| 205 TEST_F(BrowserConnectionHandlerTest, ConnectionError) { | |
| 206 // Engine will not get message after connection error. | |
| 207 client_connection_->error_observer()->OnConnectionError(net::ERR_FAILED); | |
| 208 std::unique_ptr<BlimpMessage> client_input_message = CreateInputMessage(1); | |
| 209 client_input_feature_->outgoing_message_processor()->ProcessMessage( | |
| 210 std::move(client_input_message), net::CompletionCallback()); | |
| 211 } | |
| 212 | |
| 213 TEST_F(BrowserConnectionHandlerTest, ReconnectionAfterError) { | |
| 214 std::unique_ptr<BlimpMessage> client_input_message = CreateInputMessage(1); | |
| 215 EXPECT_CALL( | |
| 216 *(engine_input_feature_->incoming_message_processor()), | |
| 217 MockableProcessMessage(EqualsMessageIgnoringId(*client_input_message), _)) | |
| 218 .RetiresOnSaturation(); | |
| 219 | |
| 220 // Simulate a connection failure. | |
| 221 client_connection_->error_observer()->OnConnectionError(net::ERR_FAILED); | |
| 222 engine_connection_->error_observer()->OnConnectionError(net::ERR_FAILED); | |
| 223 | |
| 224 // Message will be queued to be transmitted when the connection is | |
| 225 // re-established. | |
| 226 client_input_feature_->outgoing_message_processor()->ProcessMessage( | |
| 227 std::move(client_input_message), net::CompletionCallback()); | |
| 228 | |
| 229 // Simulates reconnection. | |
| 230 SetupConnections(); | |
| 231 } | |
| 232 | |
| 233 } // namespace | |
| 234 } // namespace blimp | |
| OLD | NEW |