Home | History | Annotate | Download | only in view_manager
      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
      3 // found in the LICENSE file.
      4 
      5 #include <string>
      6 #include <vector>
      7 
      8 #include "base/at_exit.h"
      9 #include "base/auto_reset.h"
     10 #include "base/bind.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/memory/scoped_vector.h"
     13 #include "base/message_loop/message_loop.h"
     14 #include "base/run_loop.h"
     15 #include "base/strings/stringprintf.h"
     16 #include "mojo/application_manager/application_manager.h"
     17 #include "mojo/common/common_type_converters.h"
     18 #include "mojo/public/cpp/application/application_connection.h"
     19 #include "mojo/public/cpp/application/application_delegate.h"
     20 #include "mojo/public/cpp/application/application_impl.h"
     21 #include "mojo/public/cpp/application/connect.h"
     22 #include "mojo/public/cpp/bindings/lib/router.h"
     23 #include "mojo/public/interfaces/application/service_provider.mojom.h"
     24 #include "mojo/services/public/cpp/geometry/geometry_type_converters.h"
     25 #include "mojo/services/public/cpp/view_manager/types.h"
     26 #include "mojo/services/public/cpp/view_manager/util.h"
     27 #include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h"
     28 #include "mojo/services/view_manager/ids.h"
     29 #include "mojo/services/view_manager/test_change_tracker.h"
     30 #include "mojo/shell/shell_test_helper.h"
     31 #include "testing/gtest/include/gtest/gtest.h"
     32 #include "ui/gfx/geometry/rect.h"
     33 
     34 #if defined(OS_WIN)
     35 #include "ui/gfx/win/window_impl.h"
     36 #endif
     37 
     38 namespace mojo {
     39 namespace service {
     40 
     41 namespace {
     42 
     43 const char kTestServiceURL[] = "mojo:test_url";
     44 const char kTestServiceURL2[] = "mojo:test_url2";
     45 
     46 // ViewManagerProxy is a proxy to an ViewManagerService. It handles invoking
     47 // ViewManagerService functions on the right thread in a synchronous manner
     48 // (each ViewManagerService cover function blocks until the response from the
     49 // ViewManagerService is returned). In addition it tracks the set of
     50 // ViewManagerClient messages received by way of a vector of Changes. Use
     51 // DoRunLoopUntilChangesCount() to wait for a certain number of messages to be
     52 // received.
     53 class ViewManagerProxy : public TestChangeTracker::Delegate {
     54  public:
     55   explicit ViewManagerProxy(TestChangeTracker* tracker)
     56       : tracker_(tracker),
     57         main_loop_(NULL),
     58         view_manager_(NULL),
     59         quit_count_(0),
     60         router_(NULL) {
     61     SetInstance(this);
     62   }
     63 
     64   virtual ~ViewManagerProxy() {
     65   }
     66 
     67   // Returns true if in an initial state. If this returns false it means the
     68   // last test didn't clean up properly, or most likely didn't invoke
     69   // WaitForInstance() when it needed to.
     70   static bool IsInInitialState() { return instance_ == NULL; }
     71 
     72   // Runs a message loop until the single instance has been created.
     73   static ViewManagerProxy* WaitForInstance() {
     74     if (!instance_)
     75       RunMainLoop();
     76     ViewManagerProxy* instance = instance_;
     77     instance_ = NULL;
     78     return instance;
     79   }
     80 
     81   ViewManagerService* view_manager() { return view_manager_; }
     82 
     83   // Runs the main loop until |count| changes have been received.
     84   std::vector<Change> DoRunLoopUntilChangesCount(size_t count) {
     85     DCHECK_EQ(0u, quit_count_);
     86     if (tracker_->changes()->size() >= count) {
     87       CopyChangesFromTracker();
     88       return changes_;
     89     }
     90     quit_count_ = count - tracker_->changes()->size();
     91     // Run the current message loop. When |count| Changes have been received,
     92     // we'll quit.
     93     RunMainLoop();
     94     return changes_;
     95   }
     96 
     97   const std::vector<Change>& changes() const { return changes_; }
     98 
     99   // Destroys the connection, blocking until done.
    100   void Destroy() {
    101     router_->CloseMessagePipe();
    102   }
    103 
    104   void ClearChanges() {
    105     changes_.clear();
    106     tracker_->changes()->clear();
    107   }
    108 
    109   void CopyChangesFromTracker() {
    110     std::vector<Change> changes;
    111     tracker_->changes()->swap(changes);
    112     changes_.swap(changes);
    113   }
    114 
    115   // The following functions are cover methods for ViewManagerService. They
    116   // block until the result is received.
    117   bool CreateView(Id view_id) {
    118     changes_.clear();
    119     ErrorCode result = ERROR_CODE_NONE;
    120     view_manager_->CreateView(
    121         view_id,
    122         base::Bind(&ViewManagerProxy::GotResultWithErrorCode,
    123                    base::Unretained(this),
    124                    &result));
    125     RunMainLoop();
    126     return result == ERROR_CODE_NONE;
    127   }
    128   ErrorCode CreateViewWithErrorCode(Id view_id) {
    129     changes_.clear();
    130     ErrorCode result = ERROR_CODE_NONE;
    131     view_manager_->CreateView(
    132         view_id,
    133         base::Bind(&ViewManagerProxy::GotResultWithErrorCode,
    134                    base::Unretained(this),
    135                    &result));
    136     RunMainLoop();
    137     return result;
    138   }
    139   bool AddView(Id parent, Id child) {
    140     changes_.clear();
    141     bool result = false;
    142     view_manager_->AddView(parent, child,
    143                            base::Bind(&ViewManagerProxy::GotResult,
    144                                       base::Unretained(this), &result));
    145     RunMainLoop();
    146     return result;
    147   }
    148   bool RemoveViewFromParent(Id view_id) {
    149     changes_.clear();
    150     bool result = false;
    151     view_manager_->RemoveViewFromParent(
    152         view_id,
    153         base::Bind(
    154             &ViewManagerProxy::GotResult, base::Unretained(this), &result));
    155     RunMainLoop();
    156     return result;
    157   }
    158   bool ReorderView(Id view_id, Id relative_view_id, OrderDirection direction) {
    159     changes_.clear();
    160     bool result = false;
    161     view_manager_->ReorderView(
    162         view_id,
    163         relative_view_id,
    164         direction,
    165         base::Bind(
    166             &ViewManagerProxy::GotResult, base::Unretained(this), &result));
    167     RunMainLoop();
    168     return result;
    169   }
    170   void GetViewTree(Id view_id, std::vector<TestView>* views) {
    171     changes_.clear();
    172     view_manager_->GetViewTree(
    173         view_id,
    174         base::Bind(
    175             &ViewManagerProxy::GotViewTree, base::Unretained(this), views));
    176     RunMainLoop();
    177   }
    178   bool Embed(const Id view_id, const char* url) {
    179     changes_.clear();
    180     base::AutoReset<bool> auto_reset(&in_embed_, true);
    181     bool result = false;
    182     ServiceProviderPtr services;
    183     view_manager_->Embed(
    184         url,
    185         view_id,
    186         services.Pass(),
    187         base::Bind(
    188             &ViewManagerProxy::GotResult, base::Unretained(this), &result));
    189     RunMainLoop();
    190     return result;
    191   }
    192   bool DeleteView(Id view_id) {
    193     changes_.clear();
    194     bool result = false;
    195     view_manager_->DeleteView(
    196         view_id,
    197         base::Bind(
    198             &ViewManagerProxy::GotResult, base::Unretained(this), &result));
    199     RunMainLoop();
    200     return result;
    201   }
    202   bool SetViewBounds(Id view_id, const gfx::Rect& bounds) {
    203     changes_.clear();
    204     bool result = false;
    205     view_manager_->SetViewBounds(
    206         view_id,
    207         Rect::From(bounds),
    208         base::Bind(
    209             &ViewManagerProxy::GotResult, base::Unretained(this), &result));
    210     RunMainLoop();
    211     return result;
    212   }
    213   bool SetViewVisibility(Id view_id, bool visible) {
    214     changes_.clear();
    215     bool result = false;
    216     view_manager_->SetViewVisibility(
    217         view_id,
    218         visible,
    219         base::Bind(
    220             &ViewManagerProxy::GotResult, base::Unretained(this), &result));
    221     RunMainLoop();
    222     return result;
    223   }
    224 
    225  private:
    226   friend class TestViewManagerClientConnection;
    227 
    228   void set_router(mojo::internal::Router* router) { router_ = router; }
    229 
    230   void set_view_manager(ViewManagerService* view_manager) {
    231     view_manager_ = view_manager;
    232   }
    233 
    234   static void RunMainLoop() {
    235     DCHECK(!main_run_loop_);
    236     main_run_loop_ = new base::RunLoop;
    237     main_run_loop_->Run();
    238     delete main_run_loop_;
    239     main_run_loop_ = NULL;
    240   }
    241 
    242   void QuitCountReached() {
    243     CopyChangesFromTracker();
    244     main_run_loop_->Quit();
    245   }
    246 
    247   static void SetInstance(ViewManagerProxy* instance) {
    248     DCHECK(!instance_);
    249     instance_ = instance;
    250     // Embed() runs its own run loop that is quit when the result is
    251     // received. Embed() also results in a new instance. If we quit here while
    252     // waiting for a Embed() we would prematurely return before we got the
    253     // result from Embed().
    254     if (!in_embed_ && main_run_loop_)
    255       main_run_loop_->Quit();
    256   }
    257 
    258   // Callbacks from the various ViewManagerService functions.
    259   void GotResult(bool* result_cache, bool result) {
    260     *result_cache = result;
    261     DCHECK(main_run_loop_);
    262     main_run_loop_->Quit();
    263   }
    264 
    265   void GotResultWithErrorCode(ErrorCode* error_code_cache,
    266                               ErrorCode error_code) {
    267     *error_code_cache = error_code;
    268     DCHECK(main_run_loop_);
    269     main_run_loop_->Quit();
    270   }
    271 
    272   void GotViewTree(std::vector<TestView>* views, Array<ViewDataPtr> results) {
    273     ViewDatasToTestViews(results, views);
    274     DCHECK(main_run_loop_);
    275     main_run_loop_->Quit();
    276   }
    277 
    278   // TestChangeTracker::Delegate:
    279   virtual void OnChangeAdded() OVERRIDE {
    280     if (quit_count_ > 0 && --quit_count_ == 0)
    281       QuitCountReached();
    282   }
    283 
    284   static ViewManagerProxy* instance_;
    285   static base::RunLoop* main_run_loop_;
    286   static bool in_embed_;
    287 
    288   TestChangeTracker* tracker_;
    289 
    290   // MessageLoop of the test.
    291   base::MessageLoop* main_loop_;
    292 
    293   ViewManagerService* view_manager_;
    294 
    295   // Number of changes we're waiting on until we quit the current loop.
    296   size_t quit_count_;
    297 
    298   std::vector<Change> changes_;
    299 
    300   mojo::internal::Router* router_;
    301 
    302   DISALLOW_COPY_AND_ASSIGN(ViewManagerProxy);
    303 };
    304 
    305 // static
    306 ViewManagerProxy* ViewManagerProxy::instance_ = NULL;
    307 
    308 // static
    309 base::RunLoop* ViewManagerProxy::main_run_loop_ = NULL;
    310 
    311 // static
    312 bool ViewManagerProxy::in_embed_ = false;
    313 
    314 class TestViewManagerClientConnection
    315     : public InterfaceImpl<ViewManagerClient> {
    316  public:
    317   TestViewManagerClientConnection() : connection_(&tracker_) {
    318     tracker_.set_delegate(&connection_);
    319   }
    320 
    321   // InterfaceImpl:
    322   virtual void OnConnectionEstablished() OVERRIDE {
    323     connection_.set_router(internal_state()->router());
    324     connection_.set_view_manager(client());
    325   }
    326 
    327   // ViewManagerClient:
    328   virtual void OnEmbed(
    329       ConnectionSpecificId connection_id,
    330       const String& creator_url,
    331       ViewDataPtr root,
    332       InterfaceRequest<ServiceProvider> services) OVERRIDE {
    333     tracker_.OnEmbed(connection_id, creator_url, root.Pass());
    334   }
    335   virtual void OnViewBoundsChanged(Id view_id,
    336                                    RectPtr old_bounds,
    337                                    RectPtr new_bounds) OVERRIDE {
    338     tracker_.OnViewBoundsChanged(view_id, old_bounds.Pass(), new_bounds.Pass());
    339   }
    340   virtual void OnViewHierarchyChanged(Id view,
    341                                       Id new_parent,
    342                                       Id old_parent,
    343                                       Array<ViewDataPtr> views) OVERRIDE {
    344     tracker_.OnViewHierarchyChanged(view, new_parent, old_parent, views.Pass());
    345   }
    346   virtual void OnViewReordered(Id view_id,
    347                                Id relative_view_id,
    348                                OrderDirection direction) OVERRIDE {
    349     tracker_.OnViewReordered(view_id, relative_view_id, direction);
    350   }
    351   virtual void OnViewDeleted(Id view) OVERRIDE { tracker_.OnViewDeleted(view); }
    352   virtual void OnViewVisibilityChanged(uint32_t view, bool visible) OVERRIDE {
    353     tracker_.OnViewVisibilityChanged(view, visible);
    354   }
    355   virtual void OnViewDrawnStateChanged(uint32_t view, bool drawn) OVERRIDE {
    356     tracker_.OnViewDrawnStateChanged(view, drawn);
    357   }
    358   virtual void OnViewInputEvent(Id view_id,
    359                                 EventPtr event,
    360                                 const Callback<void()>& callback) OVERRIDE {
    361     tracker_.OnViewInputEvent(view_id, event.Pass());
    362   }
    363   virtual void Embed(
    364       const String& url,
    365       InterfaceRequest<ServiceProvider> service_provider) OVERRIDE {
    366     tracker_.DelegateEmbed(url);
    367   }
    368   virtual void DispatchOnViewInputEvent(mojo::EventPtr event) OVERRIDE {
    369   }
    370 
    371  private:
    372   TestChangeTracker tracker_;
    373   ViewManagerProxy connection_;
    374 
    375   DISALLOW_COPY_AND_ASSIGN(TestViewManagerClientConnection);
    376 };
    377 
    378 // Used with ViewManagerService::Embed(). Creates a
    379 // TestViewManagerClientConnection, which creates and owns the ViewManagerProxy.
    380 class EmbedApplicationLoader : public ApplicationLoader,
    381                                ApplicationDelegate,
    382                                public InterfaceFactory<ViewManagerClient> {
    383  public:
    384   EmbedApplicationLoader() {}
    385   virtual ~EmbedApplicationLoader() {}
    386 
    387   // ApplicationLoader implementation:
    388   virtual void Load(ApplicationManager* manager,
    389                     const GURL& url,
    390                     scoped_refptr<LoadCallbacks> callbacks) OVERRIDE {
    391     ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
    392     if (!shell_handle.is_valid())
    393       return;
    394     scoped_ptr<ApplicationImpl> app(new ApplicationImpl(this,
    395                                                         shell_handle.Pass()));
    396     apps_.push_back(app.release());
    397   }
    398   virtual void OnApplicationError(ApplicationManager* manager,
    399                                   const GURL& url) OVERRIDE {}
    400 
    401   // ApplicationDelegate implementation:
    402   virtual bool ConfigureIncomingConnection(ApplicationConnection* connection)
    403       OVERRIDE {
    404     connection->AddService(this);
    405     return true;
    406   }
    407 
    408   // InterfaceFactory<ViewManagerClient> implementation:
    409   virtual void Create(ApplicationConnection* connection,
    410                       InterfaceRequest<ViewManagerClient> request) OVERRIDE {
    411     BindToRequest(new TestViewManagerClientConnection, &request);
    412   }
    413 
    414  private:
    415   ScopedVector<ApplicationImpl> apps_;
    416 
    417   DISALLOW_COPY_AND_ASSIGN(EmbedApplicationLoader);
    418 };
    419 
    420 // Creates an id used for transport from the specified parameters.
    421 Id BuildViewId(ConnectionSpecificId connection_id,
    422                ConnectionSpecificId view_id) {
    423   return (connection_id << 16) | view_id;
    424 }
    425 
    426 // Callback from Embed(). |result| is the result of the
    427 // Embed() call and |run_loop| the nested RunLoop.
    428 void EmbedCallback(bool* result_cache, base::RunLoop* run_loop, bool result) {
    429   *result_cache = result;
    430   run_loop->Quit();
    431 }
    432 
    433 // Embed from an application that does not yet have a view manager connection.
    434 // Blocks until result is determined.
    435 bool InitEmbed(ViewManagerInitService* view_manager_init,
    436                const std::string& url,
    437                size_t number_of_calls) {
    438   bool result = false;
    439   base::RunLoop run_loop;
    440   for (size_t i = 0; i < number_of_calls; ++i) {
    441     ServiceProviderPtr sp;
    442     view_manager_init->Embed(url, sp.Pass(),
    443                              base::Bind(&EmbedCallback, &result, &run_loop));
    444   }
    445   run_loop.Run();
    446   return result;
    447 }
    448 
    449 }  // namespace
    450 
    451 typedef std::vector<std::string> Changes;
    452 
    453 class ViewManagerTest : public testing::Test {
    454  public:
    455   ViewManagerTest()
    456       : connection_(NULL),
    457         connection2_(NULL),
    458         connection3_(NULL) {}
    459 
    460   virtual void SetUp() OVERRIDE {
    461     ASSERT_TRUE(ViewManagerProxy::IsInInitialState());
    462     test_helper_.Init();
    463 
    464 #if defined(OS_WIN)
    465     // As we unload the wndproc of window classes we need to be sure to
    466     // unregister them.
    467     gfx::WindowImpl::UnregisterClassesAtExit();
    468 #endif
    469 
    470     test_helper_.SetLoaderForURL(
    471         scoped_ptr<ApplicationLoader>(new EmbedApplicationLoader()),
    472         GURL(kTestServiceURL));
    473 
    474     test_helper_.SetLoaderForURL(
    475         scoped_ptr<ApplicationLoader>(new EmbedApplicationLoader()),
    476         GURL(kTestServiceURL2));
    477 
    478     test_helper_.application_manager()->ConnectToService(
    479         GURL("mojo:mojo_view_manager"), &view_manager_init_);
    480     ASSERT_TRUE(InitEmbed(view_manager_init_.get(), kTestServiceURL, 1));
    481 
    482     connection_ = ViewManagerProxy::WaitForInstance();
    483     ASSERT_TRUE(connection_ != NULL);
    484     connection_->DoRunLoopUntilChangesCount(1);
    485   }
    486 
    487   virtual void TearDown() OVERRIDE {
    488     if (connection3_)
    489       connection3_->Destroy();
    490     if (connection2_)
    491       connection2_->Destroy();
    492     if (connection_)
    493       connection_->Destroy();
    494   }
    495 
    496  protected:
    497   void EstablishSecondConnectionWithRoot(Id root_id) {
    498     ASSERT_TRUE(connection_->Embed(root_id, kTestServiceURL));
    499     connection2_ = ViewManagerProxy::WaitForInstance();
    500     ASSERT_TRUE(connection2_ != NULL);
    501     connection2_->DoRunLoopUntilChangesCount(1);
    502     ASSERT_EQ(1u, connection2_->changes().size());
    503   }
    504 
    505   // Creates a second connection to the viewmanager.
    506   void EstablishSecondConnection(bool create_initial_view) {
    507     if (create_initial_view)
    508       ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 1)));
    509     ASSERT_NO_FATAL_FAILURE(
    510         EstablishSecondConnectionWithRoot(BuildViewId(1, 1)));
    511     const std::vector<Change>& changes(connection2_->changes());
    512     ASSERT_EQ(1u, changes.size());
    513     EXPECT_EQ("OnEmbed creator=mojo:test_url",
    514               ChangesToDescription1(changes)[0]);
    515     if (create_initial_view)
    516       EXPECT_EQ("[view=1,1 parent=null]", ChangeViewDescription(changes));
    517   }
    518 
    519   void EstablishThirdConnection(ViewManagerProxy* owner, Id root_id) {
    520     ASSERT_TRUE(connection3_ == NULL);
    521     ASSERT_TRUE(owner->Embed(root_id, kTestServiceURL2));
    522     connection3_ = ViewManagerProxy::WaitForInstance();
    523     ASSERT_TRUE(connection3_ != NULL);
    524     connection3_->DoRunLoopUntilChangesCount(1);
    525     ASSERT_EQ(1u, connection3_->changes().size());
    526     EXPECT_EQ("OnEmbed creator=mojo:test_url",
    527               ChangesToDescription1(connection3_->changes())[0]);
    528   }
    529 
    530   void DestroySecondConnection() {
    531     connection2_->Destroy();
    532     connection2_ = NULL;
    533   }
    534 
    535   base::ShadowingAtExitManager at_exit_;
    536   shell::ShellTestHelper test_helper_;
    537 
    538   ViewManagerInitServicePtr view_manager_init_;
    539 
    540   // NOTE: this connection is the root. As such, it has special permissions.
    541   ViewManagerProxy* connection_;
    542   ViewManagerProxy* connection2_;
    543   ViewManagerProxy* connection3_;
    544 
    545   DISALLOW_COPY_AND_ASSIGN(ViewManagerTest);
    546 };
    547 
    548 TEST_F(ViewManagerTest, SecondEmbedRoot_InitService) {
    549   ASSERT_TRUE(InitEmbed(view_manager_init_.get(), kTestServiceURL, 1));
    550   connection_->DoRunLoopUntilChangesCount(1);
    551   EXPECT_EQ(kTestServiceURL, connection_->changes()[0].embed_url);
    552 }
    553 
    554 TEST_F(ViewManagerTest, SecondEmbedRoot_Service) {
    555   ASSERT_TRUE(connection_->Embed(BuildViewId(0, 0), kTestServiceURL));
    556   connection_->DoRunLoopUntilChangesCount(1);
    557   EXPECT_EQ(kTestServiceURL, connection_->changes()[0].embed_url);
    558 }
    559 
    560 TEST_F(ViewManagerTest, MultipleEmbedRootsBeforeWTHReady) {
    561   ASSERT_TRUE(InitEmbed(view_manager_init_.get(), kTestServiceURL, 2));
    562   connection_->DoRunLoopUntilChangesCount(2);
    563   EXPECT_EQ(kTestServiceURL, connection_->changes()[0].embed_url);
    564   EXPECT_EQ(kTestServiceURL, connection_->changes()[1].embed_url);
    565 }
    566 
    567 // Verifies client gets a valid id.
    568 // http://crbug.com/396492
    569 TEST_F(ViewManagerTest, DISABLED_ValidId) {
    570   // TODO(beng): this should really have the URL of the application that
    571   //             connected to ViewManagerInit.
    572   EXPECT_EQ("OnEmbed creator=",
    573             ChangesToDescription1(connection_->changes())[0]);
    574 
    575   // All these tests assume 1 for the client id. The only real assertion here is
    576   // the client id is not zero, but adding this as rest of code here assumes 1.
    577   EXPECT_EQ(1, connection_->changes()[0].connection_id);
    578 }
    579 
    580 // Verifies two clients/connections get different ids.
    581 TEST_F(ViewManagerTest, TwoClientsGetDifferentConnectionIds) {
    582   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
    583   EXPECT_EQ("OnEmbed creator=mojo:test_url",
    584             ChangesToDescription1(connection2_->changes())[0]);
    585 
    586   // It isn't strictly necessary that the second connection gets 2, but these
    587   // tests are written assuming that is the case. The key thing is the
    588   // connection ids of |connection_| and |connection2_| differ.
    589   EXPECT_EQ(2, connection2_->changes()[0].connection_id);
    590 }
    591 
    592 // Verifies when Embed() is invoked any child views are removed.
    593 TEST_F(ViewManagerTest, ViewsRemovedWhenEmbedding) {
    594   // Two views 1 and 2. 2 is parented to 1.
    595   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 1)));
    596   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 2)));
    597   ASSERT_TRUE(connection_->AddView(BuildViewId(1, 1), BuildViewId(1, 2)));
    598 
    599   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false));
    600   EXPECT_EQ("[view=1,1 parent=null]",
    601             ChangeViewDescription(connection2_->changes()));
    602 
    603   // Embed() removed view 2.
    604   {
    605     std::vector<TestView> views;
    606     connection_->GetViewTree(BuildViewId(1, 2), &views);
    607     ASSERT_EQ(1u, views.size());
    608     EXPECT_EQ("view=1,2 parent=null", views[0].ToString());
    609   }
    610 
    611   // |connection2_| should not see view 2.
    612   {
    613     std::vector<TestView> views;
    614     connection2_->GetViewTree(BuildViewId(1, 1), &views);
    615     ASSERT_EQ(1u, views.size());
    616     EXPECT_EQ("view=1,1 parent=null", views[0].ToString());
    617   }
    618   {
    619     std::vector<TestView> views;
    620     connection2_->GetViewTree(BuildViewId(1, 2), &views);
    621     EXPECT_TRUE(views.empty());
    622   }
    623 
    624   // Views 3 and 4 in connection 2.
    625   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 3)));
    626   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 4)));
    627   ASSERT_TRUE(connection2_->AddView(BuildViewId(2, 3), BuildViewId(2, 4)));
    628 
    629   // Connection 3 rooted at 2.
    630   ASSERT_NO_FATAL_FAILURE(
    631       EstablishThirdConnection(connection2_, BuildViewId(2, 3)));
    632 
    633   // View 4 should no longer have a parent.
    634   {
    635     std::vector<TestView> views;
    636     connection2_->GetViewTree(BuildViewId(2, 3), &views);
    637     ASSERT_EQ(1u, views.size());
    638     EXPECT_EQ("view=2,3 parent=null", views[0].ToString());
    639 
    640     views.clear();
    641     connection2_->GetViewTree(BuildViewId(2, 4), &views);
    642     ASSERT_EQ(1u, views.size());
    643     EXPECT_EQ("view=2,4 parent=null", views[0].ToString());
    644   }
    645 
    646   // And view 4 should not be visible to connection 3.
    647   {
    648     std::vector<TestView> views;
    649     connection3_->GetViewTree(BuildViewId(2, 3), &views);
    650     ASSERT_EQ(1u, views.size());
    651     EXPECT_EQ("view=2,3 parent=null", views[0].ToString());
    652   }
    653 }
    654 
    655 // Verifies once Embed() has been invoked the parent connection can't see any
    656 // children.
    657 TEST_F(ViewManagerTest, CantAccessChildrenOfEmbeddedView) {
    658   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
    659 
    660   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 2)));
    661   ASSERT_TRUE(connection2_->AddView(BuildViewId(1, 1), BuildViewId(2, 2)));
    662 
    663   ASSERT_NO_FATAL_FAILURE(
    664       EstablishThirdConnection(connection2_, BuildViewId(2, 2)));
    665 
    666   ASSERT_TRUE(connection3_->CreateView(BuildViewId(3, 3)));
    667   ASSERT_TRUE(connection3_->AddView(BuildViewId(2, 2), BuildViewId(3, 3)));
    668 
    669   // Even though 3 is a child of 2 connection 2 can't see 3 as it's from a
    670   // different connection.
    671   {
    672     std::vector<TestView> views;
    673     connection2_->GetViewTree(BuildViewId(2, 2), &views);
    674     ASSERT_EQ(1u, views.size());
    675     EXPECT_EQ("view=2,2 parent=1,1", views[0].ToString());
    676   }
    677 
    678   {
    679     std::vector<TestView> views;
    680     connection2_->GetViewTree(BuildViewId(3, 3), &views);
    681     EXPECT_TRUE(views.empty());
    682   }
    683 
    684   // Connection 2 shouldn't be able to get view 3 at all.
    685   {
    686     std::vector<TestView> views;
    687     connection2_->GetViewTree(BuildViewId(3, 3), &views);
    688     EXPECT_TRUE(views.empty());
    689   }
    690 
    691   // Connection 1 should be able to see it all (its the root).
    692   {
    693     std::vector<TestView> views;
    694     connection_->GetViewTree(BuildViewId(1, 1), &views);
    695     ASSERT_EQ(3u, views.size());
    696     EXPECT_EQ("view=1,1 parent=null", views[0].ToString());
    697     EXPECT_EQ("view=2,2 parent=1,1", views[1].ToString());
    698     EXPECT_EQ("view=3,3 parent=2,2", views[2].ToString());
    699   }
    700 }
    701 
    702 // Verifies once Embed() has been invoked the parent can't mutate the children.
    703 TEST_F(ViewManagerTest, CantModifyChildrenOfEmbeddedView) {
    704   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
    705 
    706   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 2)));
    707   ASSERT_TRUE(connection2_->AddView(BuildViewId(1, 1), BuildViewId(2, 2)));
    708 
    709   ASSERT_NO_FATAL_FAILURE(
    710       EstablishThirdConnection(connection2_, BuildViewId(2, 2)));
    711 
    712   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 3)));
    713   // Connection 2 shouldn't be able to add anything to the view anymore.
    714   ASSERT_FALSE(connection2_->AddView(BuildViewId(2, 2), BuildViewId(2, 3)));
    715 
    716   // Create view 3 in connection 3 and add it to view 3.
    717   ASSERT_TRUE(connection3_->CreateView(BuildViewId(3, 3)));
    718   ASSERT_TRUE(connection3_->AddView(BuildViewId(2, 2), BuildViewId(3, 3)));
    719 
    720   // Connection 2 shouldn't be able to remove view 3.
    721   ASSERT_FALSE(connection2_->RemoveViewFromParent(BuildViewId(3, 3)));
    722 }
    723 
    724 // Verifies client gets a valid id.
    725 TEST_F(ViewManagerTest, CreateView) {
    726   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 1)));
    727   EXPECT_TRUE(connection_->changes().empty());
    728 
    729   // Can't create a view with the same id.
    730   ASSERT_EQ(ERROR_CODE_VALUE_IN_USE,
    731             connection_->CreateViewWithErrorCode(BuildViewId(1, 1)));
    732   EXPECT_TRUE(connection_->changes().empty());
    733 
    734   // Can't create a view with a bogus connection id.
    735   EXPECT_EQ(ERROR_CODE_ILLEGAL_ARGUMENT,
    736             connection_->CreateViewWithErrorCode(BuildViewId(2, 1)));
    737   EXPECT_TRUE(connection_->changes().empty());
    738 }
    739 
    740 // Verifies AddView fails when view is already in position.
    741 TEST_F(ViewManagerTest, AddViewWithNoChange) {
    742   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 2)));
    743   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 3)));
    744 
    745   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
    746 
    747   // Make 3 a child of 2.
    748   ASSERT_TRUE(connection_->AddView(BuildViewId(1, 2), BuildViewId(1, 3)));
    749 
    750   // Try again, this should fail.
    751   EXPECT_FALSE(connection_->AddView(BuildViewId(1, 2), BuildViewId(1, 3)));
    752 }
    753 
    754 // Verifies AddView fails when view is already in position.
    755 TEST_F(ViewManagerTest, AddAncestorFails) {
    756   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 2)));
    757   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 3)));
    758 
    759   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
    760 
    761   // Make 3 a child of 2.
    762   ASSERT_TRUE(connection_->AddView(BuildViewId(1, 2), BuildViewId(1, 3)));
    763 
    764   // Try to make 2 a child of 3, this should fail since 2 is an ancestor of 3.
    765   EXPECT_FALSE(connection_->AddView(BuildViewId(1, 3), BuildViewId(1, 2)));
    766 }
    767 
    768 // Verifies adding to root sends right notifications.
    769 TEST_F(ViewManagerTest, AddToRoot) {
    770   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 21)));
    771   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 3)));
    772 
    773   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
    774 
    775   // Make 3 a child of 21.
    776   ASSERT_TRUE(connection_->AddView(BuildViewId(1, 21), BuildViewId(1, 3)));
    777 
    778   // Make 21 a child of 1.
    779   ASSERT_TRUE(connection_->AddView(BuildViewId(1, 1), BuildViewId(1, 21)));
    780 
    781   // Connection 2 should not be told anything (because the view is from a
    782   // different connection). Create a view to ensure we got a response from
    783   // the server.
    784   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 100)));
    785   connection2_->CopyChangesFromTracker();
    786   EXPECT_TRUE(connection2_->changes().empty());
    787 }
    788 
    789 // Verifies HierarchyChanged is correctly sent for various adds/removes.
    790 TEST_F(ViewManagerTest, ViewHierarchyChangedViews) {
    791   // 1,2->1,11.
    792   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 2)));
    793   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 11)));
    794   ASSERT_TRUE(connection_->AddView(BuildViewId(1, 2), BuildViewId(1, 11)));
    795 
    796   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
    797 
    798   // 1,1->1,2->1,11
    799   {
    800     // Client 2 should not get anything (1,2 is from another connection).
    801     connection2_->ClearChanges();
    802     ASSERT_TRUE(connection_->AddView(BuildViewId(1, 1), BuildViewId(1, 2)));
    803     ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 100)));
    804     connection2_->CopyChangesFromTracker();
    805     EXPECT_TRUE(connection2_->changes().empty());
    806   }
    807 
    808   // 0,1->1,1->1,2->1,11.
    809   {
    810     // Client 2 is now connected to the root, so it should have gotten a drawn
    811     // notification.
    812     ASSERT_TRUE(connection_->AddView(BuildViewId(0, 1), BuildViewId(1, 1)));
    813     connection2_->DoRunLoopUntilChangesCount(1);
    814     ASSERT_EQ(1u, connection2_->changes().size());
    815     EXPECT_EQ("DrawnStateChanged view=1,1 drawn=true",
    816               ChangesToDescription1(connection2_->changes())[0]);
    817   }
    818 
    819   // 1,1->1,2->1,11.
    820   {
    821     // Client 2 is no longer connected to the root, should get drawn state
    822     // changed.
    823     ASSERT_TRUE(connection_->RemoveViewFromParent(BuildViewId(1, 1)));
    824     connection2_->DoRunLoopUntilChangesCount(1);
    825     ASSERT_EQ(1u, connection2_->changes().size());
    826     EXPECT_EQ("DrawnStateChanged view=1,1 drawn=false",
    827               ChangesToDescription1(connection2_->changes())[0]);
    828   }
    829 
    830   // 1,1->1,2->1,11->1,111.
    831   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 111)));
    832   {
    833     connection2_->ClearChanges();
    834     ASSERT_TRUE(connection_->AddView(BuildViewId(1, 11), BuildViewId(1, 111)));
    835     ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 103)));
    836     connection2_->CopyChangesFromTracker();
    837     EXPECT_TRUE(connection2_->changes().empty());
    838   }
    839 
    840   // 0,1->1,1->1,2->1,11->1,111
    841   {
    842     connection2_->ClearChanges();
    843     ASSERT_TRUE(connection_->AddView(BuildViewId(0, 1), BuildViewId(1, 1)));
    844     connection2_->DoRunLoopUntilChangesCount(1);
    845     ASSERT_EQ(1u, connection2_->changes().size());
    846     EXPECT_EQ("DrawnStateChanged view=1,1 drawn=true",
    847               ChangesToDescription1(connection2_->changes())[0]);
    848   }
    849 }
    850 
    851 TEST_F(ViewManagerTest, ViewHierarchyChangedAddingKnownToUnknown) {
    852   // Create the following structure: root -> 1 -> 11 and 2->21 (2 has no
    853   // parent).
    854   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
    855 
    856   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 11)));
    857   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 2)));
    858   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 21)));
    859 
    860   // Set up the hierarchy.
    861   ASSERT_TRUE(connection_->AddView(BuildViewId(0, 1), BuildViewId(1, 1)));
    862   ASSERT_TRUE(connection2_->AddView(BuildViewId(1, 1), BuildViewId(2, 11)));
    863   ASSERT_TRUE(connection2_->AddView(BuildViewId(2, 2), BuildViewId(2, 21)));
    864 
    865   // Remove 11, should result in a hierarchy change for the root.
    866   {
    867     connection_->ClearChanges();
    868     ASSERT_TRUE(connection2_->RemoveViewFromParent(BuildViewId(2, 11)));
    869 
    870     connection_->DoRunLoopUntilChangesCount(1);
    871     const Changes changes(ChangesToDescription1(connection_->changes()));
    872     ASSERT_EQ(1u, changes.size());
    873     EXPECT_EQ("HierarchyChanged view=2,11 new_parent=null old_parent=1,1",
    874               changes[0]);
    875   }
    876 
    877   // Add 2 to 1.
    878   {
    879     ASSERT_TRUE(connection2_->AddView(BuildViewId(1, 1), BuildViewId(2, 2)));
    880 
    881     connection_->DoRunLoopUntilChangesCount(1);
    882     const Changes changes(ChangesToDescription1(connection_->changes()));
    883     ASSERT_EQ(1u, changes.size());
    884     EXPECT_EQ("HierarchyChanged view=2,2 new_parent=1,1 old_parent=null",
    885               changes[0]);
    886     EXPECT_EQ(
    887         "[view=2,2 parent=1,1],"
    888         "[view=2,21 parent=2,2]",
    889         ChangeViewDescription(connection_->changes()));
    890   }
    891 }
    892 
    893 TEST_F(ViewManagerTest, ReorderView) {
    894   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
    895 
    896   Id view1_id = BuildViewId(2, 1);
    897   Id view2_id = BuildViewId(2, 2);
    898   Id view3_id = BuildViewId(2, 3);
    899   Id view4_id = BuildViewId(1, 4);  // Peer to 1,1
    900   Id view5_id = BuildViewId(1, 5);  // Peer to 1,1
    901   Id view6_id = BuildViewId(2, 6);  // Child of 1,2.
    902   Id view7_id = BuildViewId(2, 7);  // Unparented.
    903   Id view8_id = BuildViewId(2, 8);  // Unparented.
    904   ASSERT_TRUE(connection2_->CreateView(view1_id));
    905   ASSERT_TRUE(connection2_->CreateView(view2_id));
    906   ASSERT_TRUE(connection2_->CreateView(view3_id));
    907   ASSERT_TRUE(connection_->CreateView(view4_id));
    908   ASSERT_TRUE(connection_->CreateView(view5_id));
    909   ASSERT_TRUE(connection2_->CreateView(view6_id));
    910   ASSERT_TRUE(connection2_->CreateView(view7_id));
    911   ASSERT_TRUE(connection2_->CreateView(view8_id));
    912   ASSERT_TRUE(connection2_->AddView(view1_id, view2_id));
    913   ASSERT_TRUE(connection2_->AddView(view2_id, view6_id));
    914   ASSERT_TRUE(connection2_->AddView(view1_id, view3_id));
    915   ASSERT_TRUE(
    916       connection_->AddView(ViewIdToTransportId(RootViewId()), view4_id));
    917   ASSERT_TRUE(
    918       connection_->AddView(ViewIdToTransportId(RootViewId()), view5_id));
    919 
    920   ASSERT_TRUE(
    921       connection_->AddView(ViewIdToTransportId(RootViewId()), view1_id));
    922 
    923   {
    924     ASSERT_TRUE(
    925         connection2_->ReorderView(view2_id, view3_id, ORDER_DIRECTION_ABOVE));
    926 
    927     connection_->DoRunLoopUntilChangesCount(1);
    928     const Changes changes(ChangesToDescription1(connection_->changes()));
    929     ASSERT_EQ(1u, changes.size());
    930     EXPECT_EQ("Reordered view=2,2 relative=2,3 direction=above", changes[0]);
    931   }
    932 
    933   {
    934     ASSERT_TRUE(
    935         connection2_->ReorderView(view2_id, view3_id, ORDER_DIRECTION_BELOW));
    936 
    937     connection_->DoRunLoopUntilChangesCount(1);
    938     const Changes changes(ChangesToDescription1(connection_->changes()));
    939     ASSERT_EQ(1u, changes.size());
    940     EXPECT_EQ("Reordered view=2,2 relative=2,3 direction=below", changes[0]);
    941   }
    942 
    943   // view2 is already below view3.
    944   EXPECT_FALSE(
    945       connection2_->ReorderView(view2_id, view3_id, ORDER_DIRECTION_BELOW));
    946 
    947   // view4 & 5 are unknown to connection2_.
    948   EXPECT_FALSE(
    949       connection2_->ReorderView(view4_id, view5_id, ORDER_DIRECTION_ABOVE));
    950 
    951   // view6 & view3 have different parents.
    952   EXPECT_FALSE(
    953       connection_->ReorderView(view3_id, view6_id, ORDER_DIRECTION_ABOVE));
    954 
    955   // Non-existent view-ids
    956   EXPECT_FALSE(connection_->ReorderView(
    957       BuildViewId(1, 27), BuildViewId(1, 28), ORDER_DIRECTION_ABOVE));
    958 
    959   // view7 & view8 are un-parented.
    960   EXPECT_FALSE(
    961       connection_->ReorderView(view7_id, view8_id, ORDER_DIRECTION_ABOVE));
    962 }
    963 
    964 // Verifies DeleteView works.
    965 TEST_F(ViewManagerTest, DeleteView) {
    966   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
    967   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 2)));
    968 
    969   // Make 2 a child of 1.
    970   {
    971     ASSERT_TRUE(connection2_->AddView(BuildViewId(1, 1), BuildViewId(2, 2)));
    972     connection_->DoRunLoopUntilChangesCount(1);
    973     const Changes changes(ChangesToDescription1(connection_->changes()));
    974     ASSERT_EQ(1u, changes.size());
    975     EXPECT_EQ("HierarchyChanged view=2,2 new_parent=1,1 old_parent=null",
    976               changes[0]);
    977   }
    978 
    979   // Delete 2.
    980   {
    981     ASSERT_TRUE(connection2_->DeleteView(BuildViewId(2, 2)));
    982     EXPECT_TRUE(connection2_->changes().empty());
    983 
    984     connection_->DoRunLoopUntilChangesCount(1);
    985     const Changes changes(ChangesToDescription1(connection_->changes()));
    986     ASSERT_EQ(1u, changes.size());
    987     EXPECT_EQ("ViewDeleted view=2,2", changes[0]);
    988   }
    989 }
    990 
    991 // Verifies DeleteView isn't allowed from a separate connection.
    992 TEST_F(ViewManagerTest, DeleteViewFromAnotherConnectionDisallowed) {
    993   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
    994   EXPECT_FALSE(connection2_->DeleteView(BuildViewId(1, 1)));
    995 }
    996 
    997 // Verifies if a view was deleted and then reused that other clients are
    998 // properly notified.
    999 TEST_F(ViewManagerTest, ReuseDeletedViewId) {
   1000   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
   1001   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 2)));
   1002 
   1003   // Add 2 to 1.
   1004   {
   1005     ASSERT_TRUE(connection2_->AddView(BuildViewId(1, 1), BuildViewId(2, 2)));
   1006 
   1007     connection_->DoRunLoopUntilChangesCount(1);
   1008     const Changes changes(ChangesToDescription1(connection_->changes()));
   1009     EXPECT_EQ("HierarchyChanged view=2,2 new_parent=1,1 old_parent=null",
   1010               changes[0]);
   1011     EXPECT_EQ("[view=2,2 parent=1,1]",
   1012               ChangeViewDescription(connection_->changes()));
   1013   }
   1014 
   1015   // Delete 2.
   1016   {
   1017     ASSERT_TRUE(connection2_->DeleteView(BuildViewId(2, 2)));
   1018 
   1019     connection_->DoRunLoopUntilChangesCount(1);
   1020     const Changes changes(ChangesToDescription1(connection_->changes()));
   1021     ASSERT_EQ(1u, changes.size());
   1022     EXPECT_EQ("ViewDeleted view=2,2", changes[0]);
   1023   }
   1024 
   1025   // Create 2 again, and add it back to 1. Should get the same notification.
   1026   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 2)));
   1027   {
   1028     ASSERT_TRUE(connection2_->AddView(BuildViewId(1, 1), BuildViewId(2, 2)));
   1029 
   1030     connection_->DoRunLoopUntilChangesCount(1);
   1031     const Changes changes(ChangesToDescription1(connection_->changes()));
   1032     EXPECT_EQ("HierarchyChanged view=2,2 new_parent=1,1 old_parent=null",
   1033               changes[0]);
   1034     EXPECT_EQ("[view=2,2 parent=1,1]",
   1035               ChangeViewDescription(connection_->changes()));
   1036   }
   1037 }
   1038 
   1039 // Assertions for GetViewTree.
   1040 TEST_F(ViewManagerTest, GetViewTree) {
   1041   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
   1042 
   1043   // Create 11 in first connection and make it a child of 1.
   1044   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 11)));
   1045   ASSERT_TRUE(connection_->AddView(BuildViewId(0, 1), BuildViewId(1, 1)));
   1046   ASSERT_TRUE(connection_->AddView(BuildViewId(1, 1), BuildViewId(1, 11)));
   1047 
   1048   // Create two views in second connection, 2 and 3, both children of 1.
   1049   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 2)));
   1050   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 3)));
   1051   ASSERT_TRUE(connection2_->AddView(BuildViewId(1, 1), BuildViewId(2, 2)));
   1052   ASSERT_TRUE(connection2_->AddView(BuildViewId(1, 1), BuildViewId(2, 3)));
   1053 
   1054   // Verifies GetViewTree() on the root. The root connection sees all.
   1055   {
   1056     std::vector<TestView> views;
   1057     connection_->GetViewTree(BuildViewId(0, 1), &views);
   1058     ASSERT_EQ(5u, views.size());
   1059     EXPECT_EQ("view=0,1 parent=null", views[0].ToString());
   1060     EXPECT_EQ("view=1,1 parent=0,1", views[1].ToString());
   1061     EXPECT_EQ("view=1,11 parent=1,1", views[2].ToString());
   1062     EXPECT_EQ("view=2,2 parent=1,1", views[3].ToString());
   1063     EXPECT_EQ("view=2,3 parent=1,1", views[4].ToString());
   1064   }
   1065 
   1066   // Verifies GetViewTree() on the view 1,1. This does not include any children
   1067   // as they are not from this connection.
   1068   {
   1069     std::vector<TestView> views;
   1070     connection2_->GetViewTree(BuildViewId(1, 1), &views);
   1071     ASSERT_EQ(1u, views.size());
   1072     EXPECT_EQ("view=1,1 parent=null", views[0].ToString());
   1073   }
   1074 
   1075   // Connection 2 shouldn't be able to get the root tree.
   1076   {
   1077     std::vector<TestView> views;
   1078     connection2_->GetViewTree(BuildViewId(0, 1), &views);
   1079     ASSERT_EQ(0u, views.size());
   1080   }
   1081 }
   1082 
   1083 TEST_F(ViewManagerTest, SetViewBounds) {
   1084   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 1)));
   1085   ASSERT_TRUE(connection_->AddView(BuildViewId(0, 1), BuildViewId(1, 1)));
   1086 
   1087   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false));
   1088 
   1089   ASSERT_TRUE(
   1090       connection_->SetViewBounds(BuildViewId(1, 1), gfx::Rect(0, 0, 100, 100)));
   1091 
   1092   connection2_->DoRunLoopUntilChangesCount(1);
   1093   const Changes changes(ChangesToDescription1(connection2_->changes()));
   1094   ASSERT_EQ(1u, changes.size());
   1095   EXPECT_EQ("BoundsChanged view=1,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100",
   1096             changes[0]);
   1097 
   1098   // Should not be possible to change the bounds of a view created by another
   1099   // connection.
   1100   ASSERT_FALSE(
   1101       connection2_->SetViewBounds(BuildViewId(1, 1), gfx::Rect(0, 0, 0, 0)));
   1102 }
   1103 
   1104 // Verify AddView fails when trying to manipulate views in other roots.
   1105 TEST_F(ViewManagerTest, CantMoveViewsFromOtherRoot) {
   1106   // Create 1 and 2 in the first connection.
   1107   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 1)));
   1108   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 2)));
   1109 
   1110   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false));
   1111 
   1112   // Try to move 2 to be a child of 1 from connection 2. This should fail as 2
   1113   // should not be able to access 1.
   1114   ASSERT_FALSE(connection2_->AddView(BuildViewId(1, 1), BuildViewId(1, 2)));
   1115 
   1116   // Try to reparent 1 to the root. A connection is not allowed to reparent its
   1117   // roots.
   1118   ASSERT_FALSE(connection2_->AddView(BuildViewId(0, 1), BuildViewId(1, 1)));
   1119 }
   1120 
   1121 // Verify RemoveViewFromParent fails for views that are descendants of the
   1122 // roots.
   1123 TEST_F(ViewManagerTest, CantRemoveViewsInOtherRoots) {
   1124   // Create 1 and 2 in the first connection and parent both to the root.
   1125   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 1)));
   1126   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 2)));
   1127 
   1128   ASSERT_TRUE(connection_->AddView(BuildViewId(0, 1), BuildViewId(1, 1)));
   1129   ASSERT_TRUE(connection_->AddView(BuildViewId(0, 1), BuildViewId(1, 2)));
   1130 
   1131   // Establish the second connection and give it the root 1.
   1132   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false));
   1133 
   1134   // Connection 2 should not be able to remove view 2 or 1 from its parent.
   1135   ASSERT_FALSE(connection2_->RemoveViewFromParent(BuildViewId(1, 2)));
   1136   ASSERT_FALSE(connection2_->RemoveViewFromParent(BuildViewId(1, 1)));
   1137 
   1138   // Create views 10 and 11 in 2.
   1139   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 10)));
   1140   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 11)));
   1141 
   1142   // Parent 11 to 10.
   1143   ASSERT_TRUE(connection2_->AddView(BuildViewId(2, 10), BuildViewId(2, 11)));
   1144   // Remove 11 from 10.
   1145   ASSERT_TRUE(connection2_->RemoveViewFromParent(BuildViewId(2, 11)));
   1146 
   1147   // Verify nothing was actually removed.
   1148   {
   1149     std::vector<TestView> views;
   1150     connection_->GetViewTree(BuildViewId(0, 1), &views);
   1151     ASSERT_EQ(3u, views.size());
   1152     EXPECT_EQ("view=0,1 parent=null", views[0].ToString());
   1153     EXPECT_EQ("view=1,1 parent=0,1", views[1].ToString());
   1154     EXPECT_EQ("view=1,2 parent=0,1", views[2].ToString());
   1155   }
   1156 }
   1157 
   1158 // Verify GetViewTree fails for views that are not descendants of the roots.
   1159 TEST_F(ViewManagerTest, CantGetViewTreeOfOtherRoots) {
   1160   // Create 1 and 2 in the first connection and parent both to the root.
   1161   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 1)));
   1162   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 2)));
   1163 
   1164   ASSERT_TRUE(connection_->AddView(BuildViewId(0, 1), BuildViewId(1, 1)));
   1165   ASSERT_TRUE(connection_->AddView(BuildViewId(0, 1), BuildViewId(1, 2)));
   1166 
   1167   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false));
   1168 
   1169   std::vector<TestView> views;
   1170 
   1171   // Should get nothing for the root.
   1172   connection2_->GetViewTree(BuildViewId(0, 1), &views);
   1173   ASSERT_TRUE(views.empty());
   1174 
   1175   // Should get nothing for view 2.
   1176   connection2_->GetViewTree(BuildViewId(1, 2), &views);
   1177   ASSERT_TRUE(views.empty());
   1178 
   1179   // Should get view 1 if asked for.
   1180   connection2_->GetViewTree(BuildViewId(1, 1), &views);
   1181   ASSERT_EQ(1u, views.size());
   1182   EXPECT_EQ("view=1,1 parent=null", views[0].ToString());
   1183 }
   1184 
   1185 TEST_F(ViewManagerTest, OnViewInput) {
   1186   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 1)));
   1187   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false));
   1188 
   1189   // Dispatch an event to the view and verify its received.
   1190   {
   1191     EventPtr event(Event::New());
   1192     event->action = static_cast<EventType>(1);
   1193     connection_->view_manager()->DispatchOnViewInputEvent(BuildViewId(1, 1),
   1194                                                           event.Pass());
   1195     connection2_->DoRunLoopUntilChangesCount(1);
   1196     const Changes changes(ChangesToDescription1(connection2_->changes()));
   1197     ASSERT_EQ(1u, changes.size());
   1198     EXPECT_EQ("InputEvent view=1,1 event_action=1", changes[0]);
   1199   }
   1200 }
   1201 
   1202 TEST_F(ViewManagerTest, EmbedWithSameViewId) {
   1203   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
   1204 
   1205   ASSERT_NO_FATAL_FAILURE(
   1206       EstablishThirdConnection(connection_, BuildViewId(1, 1)));
   1207 
   1208   // Connection2 should have been told the view was deleted.
   1209   {
   1210     connection2_->DoRunLoopUntilChangesCount(1);
   1211     const Changes changes(ChangesToDescription1(connection2_->changes()));
   1212     ASSERT_EQ(1u, changes.size());
   1213     EXPECT_EQ("ViewDeleted view=1,1", changes[0]);
   1214   }
   1215 
   1216   // Connection2 has no root. Verify it can't see view 1,1 anymore.
   1217   {
   1218     std::vector<TestView> views;
   1219     connection2_->GetViewTree(BuildViewId(1, 1), &views);
   1220     EXPECT_TRUE(views.empty());
   1221   }
   1222 }
   1223 
   1224 TEST_F(ViewManagerTest, EmbedWithSameViewId2) {
   1225   ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
   1226 
   1227   ASSERT_NO_FATAL_FAILURE(
   1228       EstablishThirdConnection(connection_, BuildViewId(1, 1)));
   1229 
   1230   // Connection2 should have been told the view was deleted.
   1231   connection2_->DoRunLoopUntilChangesCount(1);
   1232   connection2_->ClearChanges();
   1233 
   1234   // Create a view in the third connection and parent it to the root.
   1235   ASSERT_TRUE(connection3_->CreateView(BuildViewId(3, 1)));
   1236   ASSERT_TRUE(connection3_->AddView(BuildViewId(1, 1), BuildViewId(3, 1)));
   1237 
   1238   // Connection 1 should have been told about the add (it owns the view).
   1239   {
   1240     connection_->DoRunLoopUntilChangesCount(1);
   1241     const Changes changes(ChangesToDescription1(connection_->changes()));
   1242     ASSERT_EQ(1u, changes.size());
   1243     EXPECT_EQ("HierarchyChanged view=3,1 new_parent=1,1 old_parent=null",
   1244               changes[0]);
   1245   }
   1246 
   1247   // Embed 1,1 again.
   1248   {
   1249     // We should get a new connection for the new embedding.
   1250     ASSERT_TRUE(connection_->Embed(BuildViewId(1, 1), kTestServiceURL));
   1251     ViewManagerProxy* connection4 = ViewManagerProxy::WaitForInstance();
   1252     connection4->DoRunLoopUntilChangesCount(1);
   1253     const std::vector<Change>& changes(connection4->changes());
   1254     ASSERT_EQ(1u, changes.size());
   1255     EXPECT_EQ("OnEmbed creator=mojo:test_url",
   1256               ChangesToDescription1(changes)[0]);
   1257     EXPECT_EQ("[view=1,1 parent=null]", ChangeViewDescription(changes));
   1258 
   1259     // And 3 should get a delete.
   1260     connection3_->DoRunLoopUntilChangesCount(1);
   1261     ASSERT_EQ(1u, connection3_->changes().size());
   1262     EXPECT_EQ("ViewDeleted view=1,1",
   1263               ChangesToDescription1(connection3_->changes())[0]);
   1264   }
   1265 
   1266   // Connection3_ has no root. Verify it can't see view 1,1 anymore.
   1267   {
   1268     std::vector<TestView> views;
   1269     connection3_->GetViewTree(BuildViewId(1, 1), &views);
   1270     EXPECT_TRUE(views.empty());
   1271   }
   1272 
   1273   // Verify 3,1 is no longer parented to 1,1. We have to do this from 1,1 as
   1274   // connection3_ can no longer see 1,1.
   1275   {
   1276     std::vector<TestView> views;
   1277     connection_->GetViewTree(BuildViewId(1, 1), &views);
   1278     ASSERT_EQ(1u, views.size());
   1279     EXPECT_EQ("view=1,1 parent=null", views[0].ToString());
   1280   }
   1281 
   1282   // Verify connection3_ can still see the view it created 3,1.
   1283   {
   1284     std::vector<TestView> views;
   1285     connection3_->GetViewTree(BuildViewId(3, 1), &views);
   1286     ASSERT_EQ(1u, views.size());
   1287     EXPECT_EQ("view=3,1 parent=null", views[0].ToString());
   1288   }
   1289 }
   1290 
   1291 // Assertions for SetViewVisibility.
   1292 TEST_F(ViewManagerTest, SetViewVisibility) {
   1293   // Create 1 and 2 in the first connection and parent both to the root.
   1294   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 1)));
   1295   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 2)));
   1296 
   1297   ASSERT_TRUE(connection_->AddView(BuildViewId(0, 1), BuildViewId(1, 1)));
   1298   {
   1299     std::vector<TestView> views;
   1300     connection_->GetViewTree(BuildViewId(0, 1), &views);
   1301     ASSERT_EQ(2u, views.size());
   1302     EXPECT_EQ("view=0,1 parent=null visible=true drawn=true",
   1303               views[0].ToString2());
   1304     EXPECT_EQ("view=1,1 parent=0,1 visible=true drawn=true",
   1305               views[1].ToString2());
   1306   }
   1307 
   1308   // Hide 1.
   1309   ASSERT_TRUE(connection_->SetViewVisibility(BuildViewId(1, 1), false));
   1310   {
   1311     std::vector<TestView> views;
   1312     connection_->GetViewTree(BuildViewId(1, 1), &views);
   1313     ASSERT_EQ(1u, views.size());
   1314     EXPECT_EQ("view=1,1 parent=0,1 visible=false drawn=false",
   1315               views[0].ToString2());
   1316   }
   1317 
   1318   // Attach 2 to 1.
   1319   ASSERT_TRUE(connection_->AddView(BuildViewId(1, 1), BuildViewId(1, 2)));
   1320   {
   1321     std::vector<TestView> views;
   1322     connection_->GetViewTree(BuildViewId(1, 1), &views);
   1323     ASSERT_EQ(2u, views.size());
   1324     EXPECT_EQ("view=1,1 parent=0,1 visible=false drawn=false",
   1325               views[0].ToString2());
   1326     EXPECT_EQ("view=1,2 parent=1,1 visible=true drawn=false",
   1327               views[1].ToString2());
   1328   }
   1329 
   1330   // Show 1.
   1331   ASSERT_TRUE(connection_->SetViewVisibility(BuildViewId(1, 1), true));
   1332   {
   1333     std::vector<TestView> views;
   1334     connection_->GetViewTree(BuildViewId(1, 1), &views);
   1335     ASSERT_EQ(2u, views.size());
   1336     EXPECT_EQ("view=1,1 parent=0,1 visible=true drawn=true",
   1337               views[0].ToString2());
   1338     EXPECT_EQ("view=1,2 parent=1,1 visible=true drawn=true",
   1339               views[1].ToString2());
   1340   }
   1341 }
   1342 
   1343 // Assertions for SetViewVisibility sending notifications.
   1344 TEST_F(ViewManagerTest, SetViewVisibilityNotifications) {
   1345   // Create 1,1 and 1,2, 1,2 and child of 1,1 and 1,1 a child of the root.
   1346   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 1)));
   1347   ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 2)));
   1348   ASSERT_TRUE(connection_->AddView(BuildViewId(0, 1), BuildViewId(1, 1)));
   1349   ASSERT_TRUE(connection_->AddView(BuildViewId(1, 1), BuildViewId(1, 2)));
   1350 
   1351   // Establish the second connection at 1,2.
   1352   ASSERT_NO_FATAL_FAILURE(
   1353       EstablishSecondConnectionWithRoot(BuildViewId(1, 2)));
   1354 
   1355   // Add 2,3 as a child of 1,2.
   1356   ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 3)));
   1357   connection_->ClearChanges();
   1358   ASSERT_TRUE(connection2_->AddView(BuildViewId(1, 2), BuildViewId(2, 3)));
   1359   connection_->DoRunLoopUntilChangesCount(1);
   1360 
   1361   // Hide 1,2 from connection 1. Connection 2 should see this.
   1362   ASSERT_TRUE(connection_->SetViewVisibility(BuildViewId(1, 2), false));
   1363   {
   1364     connection2_->DoRunLoopUntilChangesCount(1);
   1365     ASSERT_EQ(1u, connection2_->changes().size());
   1366     EXPECT_EQ("VisibilityChanged view=1,2 visible=false",
   1367               ChangesToDescription1(connection2_->changes())[0]);
   1368   }
   1369 
   1370   // Show 1,2 from connection 2, connection 1 should be notified.
   1371   ASSERT_TRUE(connection2_->SetViewVisibility(BuildViewId(1, 2), true));
   1372   {
   1373     connection_->DoRunLoopUntilChangesCount(1);
   1374     ASSERT_EQ(1u, connection_->changes().size());
   1375     EXPECT_EQ("VisibilityChanged view=1,2 visible=true",
   1376               ChangesToDescription1(connection_->changes())[0]);
   1377   }
   1378 
   1379   // Hide 1,1, connection 2 should be told the draw state changed.
   1380   ASSERT_TRUE(connection_->SetViewVisibility(BuildViewId(1, 1), false));
   1381   {
   1382     connection2_->DoRunLoopUntilChangesCount(1);
   1383     ASSERT_EQ(1u, connection2_->changes().size());
   1384     EXPECT_EQ("DrawnStateChanged view=1,2 drawn=false",
   1385               ChangesToDescription1(connection2_->changes())[0]);
   1386   }
   1387 
   1388   // Show 1,1 from connection 1. Connection 2 should see this.
   1389   ASSERT_TRUE(connection_->SetViewVisibility(BuildViewId(1, 1), true));
   1390   {
   1391     connection2_->DoRunLoopUntilChangesCount(1);
   1392     ASSERT_EQ(1u, connection2_->changes().size());
   1393     EXPECT_EQ("DrawnStateChanged view=1,2 drawn=true",
   1394               ChangesToDescription1(connection2_->changes())[0]);
   1395   }
   1396 
   1397   // Change visibility of 2,3, connection 1 should see this.
   1398   connection_->ClearChanges();
   1399   ASSERT_TRUE(connection2_->SetViewVisibility(BuildViewId(2, 3), false));
   1400   {
   1401     connection_->DoRunLoopUntilChangesCount(1);
   1402     ASSERT_EQ(1u, connection_->changes().size());
   1403     EXPECT_EQ("VisibilityChanged view=2,3 visible=false",
   1404               ChangesToDescription1(connection_->changes())[0]);
   1405   }
   1406 
   1407   // Remove 1,1 from the root, connection 2 should see drawn state changed.
   1408   ASSERT_TRUE(connection_->RemoveViewFromParent(BuildViewId(1, 1)));
   1409   {
   1410     connection2_->DoRunLoopUntilChangesCount(1);
   1411     ASSERT_EQ(1u, connection2_->changes().size());
   1412     EXPECT_EQ("DrawnStateChanged view=1,2 drawn=false",
   1413               ChangesToDescription1(connection2_->changes())[0]);
   1414   }
   1415 
   1416   // Add 1,1 back to the root, connection 2 should see drawn state changed.
   1417   ASSERT_TRUE(connection_->AddView(BuildViewId(0, 1), BuildViewId(1, 1)));
   1418   {
   1419     connection2_->DoRunLoopUntilChangesCount(1);
   1420     ASSERT_EQ(1u, connection2_->changes().size());
   1421     EXPECT_EQ("DrawnStateChanged view=1,2 drawn=true",
   1422               ChangesToDescription1(connection2_->changes())[0]);
   1423   }
   1424 }
   1425 
   1426 // TODO(sky): add coverage of test that destroys connections and ensures other
   1427 // connections get deletion notification.
   1428 
   1429 // TODO(sky): need to better track changes to initial connection. For example,
   1430 // that SetBounsdViews/AddView and the like don't result in messages to the
   1431 // originating connection.
   1432 
   1433 }  // namespace service
   1434 }  // namespace mojo
   1435