| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <string> | 5 #include <string> |
| 6 #include <vector> | 6 #include <vector> |
| 7 | 7 |
| 8 #include "base/auto_reset.h" | 8 #include "base/auto_reset.h" |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 RunMainLoop(); | 130 RunMainLoop(); |
| 131 return result; | 131 return result; |
| 132 } | 132 } |
| 133 void GetNodeTree(Id node_id, std::vector<TestNode>* nodes) { | 133 void GetNodeTree(Id node_id, std::vector<TestNode>* nodes) { |
| 134 changes_.clear(); | 134 changes_.clear(); |
| 135 view_manager_->GetNodeTree(node_id, | 135 view_manager_->GetNodeTree(node_id, |
| 136 base::Bind(&ViewManagerProxy::GotNodeTree, | 136 base::Bind(&ViewManagerProxy::GotNodeTree, |
| 137 base::Unretained(this), nodes)); | 137 base::Unretained(this), nodes)); |
| 138 RunMainLoop(); | 138 RunMainLoop(); |
| 139 } | 139 } |
| 140 bool Connect(const std::vector<Id>& nodes) { | 140 bool Embed(const std::vector<Id>& nodes) { |
| 141 changes_.clear(); | 141 changes_.clear(); |
| 142 base::AutoReset<bool> auto_reset(&in_connect_, true); | 142 base::AutoReset<bool> auto_reset(&in_embed_, true); |
| 143 bool result = false; | 143 bool result = false; |
| 144 view_manager_->Connect(kTestServiceURL, Array<Id>::From(nodes), | 144 view_manager_->Embed(kTestServiceURL, Array<Id>::From(nodes), |
| 145 base::Bind(&ViewManagerProxy::GotResult, | 145 base::Bind(&ViewManagerProxy::GotResult, |
| 146 base::Unretained(this), &result)); | 146 base::Unretained(this), &result)); |
| 147 RunMainLoop(); | 147 RunMainLoop(); |
| 148 return result; | 148 return result; |
| 149 } | 149 } |
| 150 bool DeleteNode(Id node_id) { | 150 bool DeleteNode(Id node_id) { |
| 151 changes_.clear(); | 151 changes_.clear(); |
| 152 bool result = false; | 152 bool result = false; |
| 153 view_manager_->DeleteNode(node_id, | 153 view_manager_->DeleteNode(node_id, |
| 154 base::Bind(&ViewManagerProxy::GotResult, | 154 base::Bind(&ViewManagerProxy::GotResult, |
| 155 base::Unretained(this), &result)); | 155 base::Unretained(this), &result)); |
| 156 RunMainLoop(); | 156 RunMainLoop(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 | 199 |
| 200 void CopyChangesFromTracker() { | 200 void CopyChangesFromTracker() { |
| 201 std::vector<Change> changes; | 201 std::vector<Change> changes; |
| 202 tracker_->changes()->swap(changes); | 202 tracker_->changes()->swap(changes); |
| 203 changes_.swap(changes); | 203 changes_.swap(changes); |
| 204 } | 204 } |
| 205 | 205 |
| 206 static void SetInstance(ViewManagerProxy* instance) { | 206 static void SetInstance(ViewManagerProxy* instance) { |
| 207 DCHECK(!instance_); | 207 DCHECK(!instance_); |
| 208 instance_ = instance; | 208 instance_ = instance; |
| 209 // Connect() runs its own run loop that is quit when the result is | 209 // Embed() runs its own run loop that is quit when the result is |
| 210 // received. Connect() also results in a new instance. If we quit here while | 210 // received. Embed() also results in a new instance. If we quit here while |
| 211 // waiting for a Connect() we would prematurely return before we got the | 211 // waiting for a Embed() we would prematurely return before we got the |
| 212 // result from Connect(). | 212 // result from Embed(). |
| 213 if (!in_connect_ && main_run_loop_) | 213 if (!in_embed_ && main_run_loop_) |
| 214 main_run_loop_->Quit(); | 214 main_run_loop_->Quit(); |
| 215 } | 215 } |
| 216 | 216 |
| 217 // Callbacks from the various IViewManager functions. | 217 // Callbacks from the various IViewManager functions. |
| 218 void GotResult(bool* result_cache, bool result) { | 218 void GotResult(bool* result_cache, bool result) { |
| 219 *result_cache = result; | 219 *result_cache = result; |
| 220 DCHECK(main_run_loop_); | 220 DCHECK(main_run_loop_); |
| 221 main_run_loop_->Quit(); | 221 main_run_loop_->Quit(); |
| 222 } | 222 } |
| 223 | 223 |
| 224 void GotNodeTree(std::vector<TestNode>* nodes, Array<INodePtr> results) { | 224 void GotNodeTree(std::vector<TestNode>* nodes, Array<INodePtr> results) { |
| 225 INodesToTestNodes(results, nodes); | 225 INodesToTestNodes(results, nodes); |
| 226 DCHECK(main_run_loop_); | 226 DCHECK(main_run_loop_); |
| 227 main_run_loop_->Quit(); | 227 main_run_loop_->Quit(); |
| 228 } | 228 } |
| 229 | 229 |
| 230 // TestChangeTracker::Delegate: | 230 // TestChangeTracker::Delegate: |
| 231 virtual void OnChangeAdded() OVERRIDE { | 231 virtual void OnChangeAdded() OVERRIDE { |
| 232 if (quit_count_ > 0 && --quit_count_ == 0) | 232 if (quit_count_ > 0 && --quit_count_ == 0) |
| 233 QuitCountReached(); | 233 QuitCountReached(); |
| 234 } | 234 } |
| 235 | 235 |
| 236 static ViewManagerProxy* instance_; | 236 static ViewManagerProxy* instance_; |
| 237 static base::RunLoop* main_run_loop_; | 237 static base::RunLoop* main_run_loop_; |
| 238 static bool in_connect_; | 238 static bool in_embed_; |
| 239 | 239 |
| 240 TestChangeTracker* tracker_; | 240 TestChangeTracker* tracker_; |
| 241 | 241 |
| 242 // MessageLoop of the test. | 242 // MessageLoop of the test. |
| 243 base::MessageLoop* main_loop_; | 243 base::MessageLoop* main_loop_; |
| 244 | 244 |
| 245 IViewManager* view_manager_; | 245 IViewManager* view_manager_; |
| 246 | 246 |
| 247 // Number of changes we're waiting on until we quit the current loop. | 247 // Number of changes we're waiting on until we quit the current loop. |
| 248 size_t quit_count_; | 248 size_t quit_count_; |
| 249 | 249 |
| 250 std::vector<Change> changes_; | 250 std::vector<Change> changes_; |
| 251 | 251 |
| 252 mojo::internal::Router* router_; | 252 mojo::internal::Router* router_; |
| 253 | 253 |
| 254 DISALLOW_COPY_AND_ASSIGN(ViewManagerProxy); | 254 DISALLOW_COPY_AND_ASSIGN(ViewManagerProxy); |
| 255 }; | 255 }; |
| 256 | 256 |
| 257 // static | 257 // static |
| 258 ViewManagerProxy* ViewManagerProxy::instance_ = NULL; | 258 ViewManagerProxy* ViewManagerProxy::instance_ = NULL; |
| 259 | 259 |
| 260 // static | 260 // static |
| 261 base::RunLoop* ViewManagerProxy::main_run_loop_ = NULL; | 261 base::RunLoop* ViewManagerProxy::main_run_loop_ = NULL; |
| 262 | 262 |
| 263 // static | 263 // static |
| 264 bool ViewManagerProxy::in_connect_ = false; | 264 bool ViewManagerProxy::in_embed_ = false; |
| 265 | 265 |
| 266 class TestViewManagerClientConnection | 266 class TestViewManagerClientConnection |
| 267 : public InterfaceImpl<IViewManagerClient> { | 267 : public InterfaceImpl<IViewManagerClient> { |
| 268 public: | 268 public: |
| 269 TestViewManagerClientConnection() : connection_(&tracker_) { | 269 TestViewManagerClientConnection() : connection_(&tracker_) { |
| 270 tracker_.set_delegate(&connection_); | 270 tracker_.set_delegate(&connection_); |
| 271 } | 271 } |
| 272 | 272 |
| 273 // InterfaceImp: | 273 // InterfaceImp: |
| 274 virtual void OnConnectionEstablished() OVERRIDE { | 274 virtual void OnConnectionEstablished() OVERRIDE { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 tracker_.OnViewInputEvent(view_id, event.Pass()); | 321 tracker_.OnViewInputEvent(view_id, event.Pass()); |
| 322 } | 322 } |
| 323 | 323 |
| 324 private: | 324 private: |
| 325 TestChangeTracker tracker_; | 325 TestChangeTracker tracker_; |
| 326 ViewManagerProxy connection_; | 326 ViewManagerProxy connection_; |
| 327 | 327 |
| 328 DISALLOW_COPY_AND_ASSIGN(TestViewManagerClientConnection); | 328 DISALLOW_COPY_AND_ASSIGN(TestViewManagerClientConnection); |
| 329 }; | 329 }; |
| 330 | 330 |
| 331 // Used with IViewManager::Connect(). Creates a TestViewManagerClientConnection, | 331 // Used with IViewManager::Embed(). Creates a TestViewManagerClientConnection, |
| 332 // which creates and owns the ViewManagerProxy. | 332 // which creates and owns the ViewManagerProxy. |
| 333 class ConnectServiceLoader : public ServiceLoader { | 333 class EmbedServiceLoader : public ServiceLoader { |
| 334 public: | 334 public: |
| 335 ConnectServiceLoader() {} | 335 EmbedServiceLoader() {} |
| 336 virtual ~ConnectServiceLoader() {} | 336 virtual ~EmbedServiceLoader() {} |
| 337 | 337 |
| 338 // ServiceLoader: | 338 // ServiceLoader: |
| 339 virtual void LoadService(ServiceManager* manager, | 339 virtual void LoadService(ServiceManager* manager, |
| 340 const GURL& url, | 340 const GURL& url, |
| 341 ScopedMessagePipeHandle shell_handle) OVERRIDE { | 341 ScopedMessagePipeHandle shell_handle) OVERRIDE { |
| 342 scoped_ptr<Application> app(new Application(shell_handle.Pass())); | 342 scoped_ptr<Application> app(new Application(shell_handle.Pass())); |
| 343 app->AddService<TestViewManagerClientConnection>(); | 343 app->AddService<TestViewManagerClientConnection>(); |
| 344 apps_.push_back(app.release()); | 344 apps_.push_back(app.release()); |
| 345 } | 345 } |
| 346 virtual void OnServiceError(ServiceManager* manager, | 346 virtual void OnServiceError(ServiceManager* manager, |
| 347 const GURL& url) OVERRIDE { | 347 const GURL& url) OVERRIDE { |
| 348 } | 348 } |
| 349 | 349 |
| 350 private: | 350 private: |
| 351 ScopedVector<Application> apps_; | 351 ScopedVector<Application> apps_; |
| 352 | 352 |
| 353 DISALLOW_COPY_AND_ASSIGN(ConnectServiceLoader); | 353 DISALLOW_COPY_AND_ASSIGN(EmbedServiceLoader); |
| 354 }; | 354 }; |
| 355 | 355 |
| 356 // Creates an id used for transport from the specified parameters. | 356 // Creates an id used for transport from the specified parameters. |
| 357 Id BuildNodeId(ConnectionSpecificId connection_id, | 357 Id BuildNodeId(ConnectionSpecificId connection_id, |
| 358 ConnectionSpecificId node_id) { | 358 ConnectionSpecificId node_id) { |
| 359 return (connection_id << 16) | node_id; | 359 return (connection_id << 16) | node_id; |
| 360 } | 360 } |
| 361 | 361 |
| 362 // Creates an id used for transport from the specified parameters. | 362 // Creates an id used for transport from the specified parameters. |
| 363 Id BuildViewId(ConnectionSpecificId connection_id, | 363 Id BuildViewId(ConnectionSpecificId connection_id, |
| 364 ConnectionSpecificId view_id) { | 364 ConnectionSpecificId view_id) { |
| 365 return (connection_id << 16) | view_id; | 365 return (connection_id << 16) | view_id; |
| 366 } | 366 } |
| 367 | 367 |
| 368 // Callback from ViewManagerInitConnect(). |result| is the result of the | 368 // Callback from EmbedRoot(). |result| is the result of the |
| 369 // Connect() call and |run_loop| the nested RunLoop. | 369 // Embed() call and |run_loop| the nested RunLoop. |
| 370 void ViewManagerInitConnectCallback(bool* result_cache, | 370 void EmbedRootCallback(bool* result_cache, |
| 371 base::RunLoop* run_loop, | 371 base::RunLoop* run_loop, |
| 372 bool result) { | 372 bool result) { |
| 373 *result_cache = result; | 373 *result_cache = result; |
| 374 run_loop->Quit(); | 374 run_loop->Quit(); |
| 375 } | 375 } |
| 376 | 376 |
| 377 // Resposible for establishing connection to the viewmanager. Blocks until get | 377 // Resposible for establishing the initial IViewManager connection. Blocks until |
| 378 // back result. | 378 // result is determined. |
| 379 bool ViewManagerInitConnect(IViewManagerInit* view_manager_init, | 379 bool EmbedRoot(IViewManagerInit* view_manager_init, const std::string& url) { |
| 380 const std::string& url) { | |
| 381 bool result = false; | 380 bool result = false; |
| 382 base::RunLoop run_loop; | 381 base::RunLoop run_loop; |
| 383 view_manager_init->Connect(url, | 382 view_manager_init->EmbedRoot(url, base::Bind(&EmbedRootCallback, |
| 384 base::Bind(&ViewManagerInitConnectCallback, | 383 &result, &run_loop)); |
| 385 &result, &run_loop)); | |
| 386 run_loop.Run(); | 384 run_loop.Run(); |
| 387 return result; | 385 return result; |
| 388 } | 386 } |
| 389 | 387 |
| 390 } // namespace | 388 } // namespace |
| 391 | 389 |
| 392 typedef std::vector<std::string> Changes; | 390 typedef std::vector<std::string> Changes; |
| 393 | 391 |
| 394 class ViewManagerConnectionTest : public testing::Test { | 392 class ViewManagerConnectionTest : public testing::Test { |
| 395 public: | 393 public: |
| 396 ViewManagerConnectionTest() : connection_(NULL), connection2_(NULL) {} | 394 ViewManagerConnectionTest() : connection_(NULL), connection2_(NULL) {} |
| 397 | 395 |
| 398 virtual void SetUp() OVERRIDE { | 396 virtual void SetUp() OVERRIDE { |
| 399 test_helper_.Init(); | 397 test_helper_.Init(); |
| 400 | 398 |
| 401 test_helper_.SetLoaderForURL( | 399 test_helper_.SetLoaderForURL( |
| 402 scoped_ptr<ServiceLoader>(new ConnectServiceLoader()), | 400 scoped_ptr<ServiceLoader>(new EmbedServiceLoader()), |
| 403 GURL(kTestServiceURL)); | 401 GURL(kTestServiceURL)); |
| 404 | 402 |
| 405 ConnectToService(test_helper_.service_provider(), | 403 ConnectToService(test_helper_.service_provider(), |
| 406 "mojo:mojo_view_manager", | 404 "mojo:mojo_view_manager", |
| 407 &view_manager_init_); | 405 &view_manager_init_); |
| 408 ASSERT_TRUE(ViewManagerInitConnect(view_manager_init_.get(), | 406 ASSERT_TRUE(EmbedRoot(view_manager_init_.get(), kTestServiceURL)); |
| 409 kTestServiceURL)); | |
| 410 | 407 |
| 411 connection_ = ViewManagerProxy::WaitForInstance(); | 408 connection_ = ViewManagerProxy::WaitForInstance(); |
| 412 ASSERT_TRUE(connection_ != NULL); | 409 ASSERT_TRUE(connection_ != NULL); |
| 413 connection_->DoRunLoopUntilChangesCount(1); | 410 connection_->DoRunLoopUntilChangesCount(1); |
| 414 } | 411 } |
| 415 | 412 |
| 416 virtual void TearDown() OVERRIDE { | 413 virtual void TearDown() OVERRIDE { |
| 417 if (connection2_) | 414 if (connection2_) |
| 418 connection2_->Destroy(); | 415 connection2_->Destroy(); |
| 419 if (connection_) | 416 if (connection_) |
| 420 connection_->Destroy(); | 417 connection_->Destroy(); |
| 421 } | 418 } |
| 422 | 419 |
| 423 protected: | 420 protected: |
| 424 void EstablishSecondConnectionWithRoots(Id id1, Id id2) { | 421 void EstablishSecondConnectionWithRoots(Id id1, Id id2) { |
| 425 std::vector<Id> node_ids; | 422 std::vector<Id> node_ids; |
| 426 node_ids.push_back(id1); | 423 node_ids.push_back(id1); |
| 427 if (id2 != 0) | 424 if (id2 != 0) |
| 428 node_ids.push_back(id2); | 425 node_ids.push_back(id2); |
| 429 ASSERT_TRUE(connection_->Connect(node_ids)); | 426 ASSERT_TRUE(connection_->Embed(node_ids)); |
| 430 connection2_ = ViewManagerProxy::WaitForInstance(); | 427 connection2_ = ViewManagerProxy::WaitForInstance(); |
| 431 ASSERT_TRUE(connection2_ != NULL); | 428 ASSERT_TRUE(connection2_ != NULL); |
| 432 connection2_->DoRunLoopUntilChangesCount(1); | 429 connection2_->DoRunLoopUntilChangesCount(1); |
| 433 ASSERT_EQ(1u, connection2_->changes().size()); | 430 ASSERT_EQ(1u, connection2_->changes().size()); |
| 434 } | 431 } |
| 435 | 432 |
| 436 // Creates a second connection to the viewmanager. | 433 // Creates a second connection to the viewmanager. |
| 437 void EstablishSecondConnection(bool create_initial_node) { | 434 void EstablishSecondConnection(bool create_initial_node) { |
| 438 if (create_initial_node) | 435 if (create_initial_node) |
| 439 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); | 436 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); |
| (...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1199 TEST_F(ViewManagerConnectionTest, ConnectTwice) { | 1196 TEST_F(ViewManagerConnectionTest, ConnectTwice) { |
| 1200 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); | 1197 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); |
| 1201 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); | 1198 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); |
| 1202 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); | 1199 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); |
| 1203 | 1200 |
| 1204 // Try to connect again to 1,1, this should fail as already connected to that | 1201 // Try to connect again to 1,1, this should fail as already connected to that |
| 1205 // root. | 1202 // root. |
| 1206 { | 1203 { |
| 1207 std::vector<Id> node_ids; | 1204 std::vector<Id> node_ids; |
| 1208 node_ids.push_back(BuildNodeId(1, 1)); | 1205 node_ids.push_back(BuildNodeId(1, 1)); |
| 1209 ASSERT_FALSE(connection_->Connect(node_ids)); | 1206 ASSERT_FALSE(connection_->Embed(node_ids)); |
| 1210 } | 1207 } |
| 1211 | 1208 |
| 1212 // Connecting to 1,2 should succeed and end up in connection2. | 1209 // Connecting to 1,2 should succeed and end up in connection2. |
| 1213 { | 1210 { |
| 1214 std::vector<Id> node_ids; | 1211 std::vector<Id> node_ids; |
| 1215 node_ids.push_back(BuildNodeId(1, 2)); | 1212 node_ids.push_back(BuildNodeId(1, 2)); |
| 1216 ASSERT_TRUE(connection_->Connect(node_ids)); | 1213 ASSERT_TRUE(connection_->Embed(node_ids)); |
| 1217 connection2_->DoRunLoopUntilChangesCount(1); | 1214 connection2_->DoRunLoopUntilChangesCount(1); |
| 1218 const Changes changes(ChangesToDescription1(connection2_->changes())); | 1215 const Changes changes(ChangesToDescription1(connection2_->changes())); |
| 1219 ASSERT_EQ(1u, changes.size()); | 1216 ASSERT_EQ(1u, changes.size()); |
| 1220 EXPECT_EQ("OnRootsAdded", changes[0]); | 1217 EXPECT_EQ("OnRootsAdded", changes[0]); |
| 1221 EXPECT_EQ("[node=1,2 parent=null view=null]", | 1218 EXPECT_EQ("[node=1,2 parent=null view=null]", |
| 1222 ChangeNodeDescription(connection2_->changes())); | 1219 ChangeNodeDescription(connection2_->changes())); |
| 1223 } | 1220 } |
| 1224 } | 1221 } |
| 1225 | 1222 |
| 1226 // TODO(sky): add coverage of test that destroys connections and ensures other | 1223 // TODO(sky): add coverage of test that destroys connections and ensures other |
| 1227 // connections get deletion notification (or advanced server id). | 1224 // connections get deletion notification (or advanced server id). |
| 1228 | 1225 |
| 1229 // TODO(sky): need to better track changes to initial connection. For example, | 1226 // TODO(sky): need to better track changes to initial connection. For example, |
| 1230 // that SetBounsdNodes/AddNode and the like don't result in messages to the | 1227 // that SetBounsdNodes/AddNode and the like don't result in messages to the |
| 1231 // originating connection. | 1228 // originating connection. |
| 1232 | 1229 |
| 1233 } // namespace service | 1230 } // namespace service |
| 1234 } // namespace view_manager | 1231 } // namespace view_manager |
| 1235 } // namespace mojo | 1232 } // namespace mojo |
| OLD | NEW |