1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// found in the LICENSE file. 4010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "mojo/services/public/cpp/view_manager/view_manager.h" 6010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/auto_reset.h" 8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/bind.h" 9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/logging.h" 1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "mojo/public/cpp/application/application.h" 1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "mojo/service_manager/service_manager.h" 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "mojo/services/public/cpp/view_manager/lib/node_private.h" 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.h" 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "mojo/services/public/cpp/view_manager/node_observer.h" 15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "mojo/services/public/cpp/view_manager/util.h" 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "mojo/services/public/cpp/view_manager/view.h" 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "mojo/services/public/cpp/view_manager/view_manager_delegate.h" 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "mojo/services/public/cpp/view_manager/view_observer.h" 19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "mojo/shell/shell_test_helper.h" 20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace mojo { 23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace view_manager { 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace { 25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kWindowManagerURL[] = "mojo:window_manager"; 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kEmbeddedApp1URL[] = "mojo:embedded_app_1"; 2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)base::RunLoop* current_run_loop = NULL; 30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DoRunLoop() { 32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::RunLoop run_loop; 33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) current_run_loop = &run_loop; 34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) current_run_loop->Run(); 35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) current_run_loop = NULL; 36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void QuitRunLoop() { 39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) current_run_loop->Quit(); 40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void WaitForAllChangesToBeAcked(ViewManagerClientImpl* client) { 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) client->set_changes_acked_callback(base::Bind(&QuitRunLoop)); 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DoRunLoop(); 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) client->ClearChangesAckedCallback(); 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class ConnectServiceLoader : public ServiceLoader, 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public ViewManagerDelegate { 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public: 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) typedef base::Callback<void(ViewManager*, Node*)> LoadedCallback; 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) explicit ConnectServiceLoader(const LoadedCallback& callback) 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : callback_(callback) { 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual ~ConnectServiceLoader() {} 5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private: 5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Overridden from ServiceLoader: 6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual void LoadService(ServiceManager* manager, 6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const GURL& url, 6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ScopedMessagePipeHandle shell_handle) OVERRIDE { 6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<Application> app(new Application(shell_handle.Pass())); 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ViewManager::Create(app.get(), this); 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) apps_.push_back(app.release()); 6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual void OnServiceError(ServiceManager* manager, 6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const GURL& url) OVERRIDE { 6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Overridden from ViewManagerDelegate: 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual void OnRootAdded(ViewManager* view_manager, 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* root) OVERRIDE { 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) callback_.Run(view_manager, root); 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ScopedVector<Application> apps_; 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LoadedCallback callback_; 7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ConnectServiceLoader); 8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}; 8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class ActiveViewChangedObserver : public NodeObserver { 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) explicit ActiveViewChangedObserver(Node* node) 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : node_(node) {} 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual ~ActiveViewChangedObserver() {} 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Overridden from NodeObserver: 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual void OnNodeActiveViewChange(Node* node, 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) View* old_view, 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) View* new_view, 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DispositionChangePhase phase) OVERRIDE { 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_EQ(node, node_); 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) QuitRunLoop(); 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node_; 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ActiveViewChangedObserver); 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Waits until the active view id of the supplied node changes. 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void WaitForActiveViewToChange(Node* node) { 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ActiveViewChangedObserver observer(node); 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) node->AddObserver(&observer); 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DoRunLoop(); 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) node->RemoveObserver(&observer); 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class BoundsChangeObserver : public NodeObserver { 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) explicit BoundsChangeObserver(Node* node) : node_(node) {} 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual ~BoundsChangeObserver() {} 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Overridden from NodeObserver: 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual void OnNodeBoundsChange(Node* node, 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const gfx::Rect& old_bounds, 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const gfx::Rect& new_bounds, 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DispositionChangePhase phase) OVERRIDE { 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_EQ(node, node_); 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (phase != NodeObserver::DISPOSITION_CHANGED) 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) QuitRunLoop(); 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node_; 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver); 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Wait until the bounds of the supplied node change. 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void WaitForBoundsToChange(Node* node) { 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BoundsChangeObserver observer(node); 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) node->AddObserver(&observer); 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DoRunLoop(); 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) node->RemoveObserver(&observer); 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Spins a runloop until the tree beginning at |root| has |tree_size| nodes 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// (including |root|). 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class TreeSizeMatchesObserver : public NodeObserver { 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) TreeSizeMatchesObserver(Node* tree, size_t tree_size) 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : tree_(tree), 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) tree_size_(tree_size) {} 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual ~TreeSizeMatchesObserver() {} 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool IsTreeCorrectSize() { 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return CountNodes(tree_) == tree_size_; 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Overridden from NodeObserver: 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void OnTreeChange(const TreeChangeParams& params) OVERRIDE { 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (IsTreeCorrectSize()) 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) QuitRunLoop(); 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t CountNodes(const Node* node) const { 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t count = 1; 164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node::Children::const_iterator it = node->children().begin(); 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (; it != node->children().end(); ++it) 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) count += CountNodes(*it); 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return count; 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* tree_; 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t tree_size_; 17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TreeSizeMatchesObserver); 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void WaitForTreeSizeToMatch(Node* node, size_t tree_size) { 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TreeSizeMatchesObserver observer(node, tree_size); 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (observer.IsTreeCorrectSize()) 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) node->AddObserver(&observer); 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DoRunLoop(); 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) node->RemoveObserver(&observer); 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Utility class that waits for the destruction of some number of nodes and 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// views. 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class DestructionObserver : public NodeObserver, public ViewObserver { 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |nodes| or |views| can be NULL. 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DestructionObserver(std::set<Id>* nodes, std::set<Id>* views) 192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : nodes_(nodes), 193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) views_(views) {} 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Overridden from NodeObserver: 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void OnNodeDestroy( 198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node, 199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NodeObserver::DispositionChangePhase phase) OVERRIDE { 200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (phase != NodeObserver::DISPOSITION_CHANGED) 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 2026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) std::set<Id>::iterator it = nodes_->find(node->id()); 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (it != nodes_->end()) 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) nodes_->erase(it); 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (CanQuit()) 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) QuitRunLoop(); 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Overridden from ViewObserver: 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void OnViewDestroy( 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) View* view, 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ViewObserver::DispositionChangePhase phase) OVERRIDE { 213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (phase != ViewObserver::DISPOSITION_CHANGED) 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 2156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) std::set<Id>::iterator it = views_->find(view->id()); 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (it != views_->end()) 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) views_->erase(it); 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (CanQuit()) 219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) QuitRunLoop(); 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool CanQuit() { 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return (!nodes_ || nodes_->empty()) && (!views_ || views_->empty()); 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::set<Id>* nodes_; 227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::set<Id>* views_; 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DestructionObserver); 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void WaitForDestruction(ViewManager* view_manager, 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::set<Id>* nodes, 234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::set<Id>* views) { 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DestructionObserver observer(nodes, views); 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(nodes || views); 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (nodes) { 238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (std::set<Id>::const_iterator it = nodes->begin(); 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) it != nodes->end(); ++it) { 240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) view_manager->GetNodeById(*it)->AddObserver(&observer); 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (views) { 244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (std::set<Id>::const_iterator it = views->begin(); 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) it != views->end(); ++it) { 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) view_manager->GetViewById(*it)->AddObserver(&observer); 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DoRunLoop(); 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class OrderChangeObserver : public NodeObserver { 253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public: 254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OrderChangeObserver(Node* node) : node_(node) { 255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) node_->AddObserver(this); 256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual ~OrderChangeObserver() { 258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) node_->RemoveObserver(this); 259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private: 262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Overridden from NodeObserver: 263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual void OnNodeReordered(Node* node, 264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* relative_node, 265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OrderDirection direction, 266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DispositionChangePhase phase) OVERRIDE { 267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (phase != NodeObserver::DISPOSITION_CHANGED) 268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_EQ(node, node_); 271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) QuitRunLoop(); 272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node_; 275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver); 277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void WaitForOrderChange(ViewManager* view_manager, Node* node) { 280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OrderChangeObserver observer(node); 281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DoRunLoop(); 282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Tracks a node's destruction. Query is_valid() for current state. 285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class NodeTracker : public NodeObserver { 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) explicit NodeTracker(Node* node) : node_(node) { 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) node_->AddObserver(this); 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual ~NodeTracker() { 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (node_) 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) node_->RemoveObserver(this); 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool is_valid() const { return !!node_; } 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Overridden from NodeObserver: 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void OnNodeDestroy( 300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node, 301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NodeObserver::DispositionChangePhase phase) OVERRIDE { 302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (phase != NodeObserver::DISPOSITION_CHANGED) 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_EQ(node, node_); 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) node_ = NULL; 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int id_; 309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node_; 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(NodeTracker); 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 316010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// ViewManager ----------------------------------------------------------------- 317010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 3180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// These tests model synchronization of two peer connections to the view manager 3190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// service, that are given access to some root node. 3200de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)class ViewManagerTest : public testing::Test { 322010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) public: 32346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManagerTest() 32446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : connect_loop_(NULL), 32546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) loaded_view_manager_(NULL), 32646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) window_manager_(NULL), 32746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) commit_count_(0) {} 328010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 329010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) protected: 33046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* window_manager() { return window_manager_; } 331010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* CreateNodeInParent(Node* parent) { 333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ViewManager* parent_manager = NodePrivate(parent).view_manager(); 334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(parent_manager); 3350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) parent->AddChild(node); 3360de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) return node; 3370de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 3380de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 33946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Embeds another version of the test app @ node. 340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ViewManager* Embed(ViewManager* view_manager, Node* node) { 341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_EQ(view_manager, NodePrivate(node).view_manager()); 34246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node->Embed(kEmbeddedApp1URL); 34346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) RunRunLoop(); 34446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return GetLoadedViewManager(); 34546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 34646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 34746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // TODO(beng): remove these methods once all the tests are migrated. 34846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void DestroyViewManager1() {} 34946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* view_manager_1() { return NULL; } 35046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* view_manager_2() { return NULL; } 35146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 35246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* GetLoadedViewManager() { 35346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* view_manager = loaded_view_manager_; 35446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) loaded_view_manager_ = NULL; 35546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return view_manager; 35646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 35846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void UnloadApplication(const GURL& url) { 35946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) test_helper_.SetLoaderForURL(scoped_ptr<ServiceLoader>(), url); 360010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 361010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 362010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) private: 363010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Overridden from testing::Test: 364010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual void SetUp() OVERRIDE { 365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ConnectServiceLoader::LoadedCallback ready_callback = 36646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&ViewManagerTest::OnViewManagerLoaded, 36746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Unretained(this)); 368010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) test_helper_.Init(); 36946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) test_helper_.SetLoaderForURL( 37046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<ServiceLoader>(new ConnectServiceLoader(ready_callback)), 37146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) GURL(kWindowManagerURL)); 37246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) test_helper_.SetLoaderForURL( 37346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<ServiceLoader>(new ConnectServiceLoader(ready_callback)), 37446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) GURL(kEmbeddedApp1URL)); 37546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 37646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ConnectToService(test_helper_.service_provider(), 37746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "mojo:mojo_view_manager", 37846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &view_manager_init_); 379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_TRUE(EmbedRoot(view_manager_init_.get(), kWindowManagerURL)); 380010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 381010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void EmbedRootCallback(bool* result_cache, bool result) { 38346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) *result_cache = result; 384010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 385010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool EmbedRoot(ViewManagerInitService* view_manager_init, 387f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& url) { 38846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool result = false; 389f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) view_manager_init->EmbedRoot( 39046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) url, 391f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Bind(&ViewManagerTest::EmbedRootCallback, base::Unretained(this), 392f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &result)); 39346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) RunRunLoop(); 39446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) window_manager_ = GetLoadedViewManager(); 39546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return result; 396010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 397010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 398f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void OnViewManagerLoaded(ViewManager* view_manager, Node* root) { 39946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) loaded_view_manager_ = view_manager; 40046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) connect_loop_->Quit(); 401010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 402010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 40346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void RunRunLoop() { 40446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::RunLoop run_loop; 40546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) connect_loop_ = &run_loop; 40646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) connect_loop_->Run(); 40746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) connect_loop_ = NULL; 408010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 409010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 41046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::MessageLoop loop_; 41146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::RunLoop* connect_loop_; 41246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) shell::ShellTestHelper test_helper_; 413f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ViewManagerInitServicePtr view_manager_init_; 41446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Used to receive the most recent view manager loaded by an embed action. 41546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* loaded_view_manager_; 41646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // The View Manager connection held by the window manager (app running at the 41746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // root node). 41846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* window_manager_; 41946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int commit_count_; 420010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 42146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ViewManagerTest); 422010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}; 423010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 42446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, SetUp) {} 425010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 42646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, Embed) { 427f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 428f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 42946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 43046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(NULL != embedded); 431010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node_in_embedded = embedded->GetRoots().front(); 433f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ(node->parent(), window_manager()->GetRoots().front()); 43446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(NULL, node_in_embedded->parent()); 435010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 436010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 43746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// When Window Manager embeds A @ N, then creates N2 and parents to N, N becomes 43846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// visible to A. 43946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// TODO(beng): verify whether or not this is a policy we like. 44046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, HierarchyChanged_NodeAdded) { 441f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 442f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 44346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 444f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* nested = Node::Create(window_manager()); 44546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node->AddChild(nested); 446f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WaitForTreeSizeToMatch(embedded->GetRoots().front(), 2); 447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ(embedded->GetRoots().front()->children().front()->id(), 448f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) nested->id()); 44946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 4500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 45146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Window manager has two nodes, N1 & N2. Embeds A at N1. Creates node N21, 45246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// a child of N2. Reparents N2 to N1. N1 should become visible to A. 45346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// TODO(beng): verify whether or not this is a policy we like. 45446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, HierarchyChanged_NodeMoved) { 455f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node1 = Node::Create(window_manager()); 456f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node1); 45746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node1); 458f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WaitForTreeSizeToMatch(embedded->GetRoots().front(), 1); 45946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 460f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node2 = Node::Create(window_manager()); 461f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node2); 462f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WaitForTreeSizeToMatch(embedded->GetRoots().front(), 1); 463f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_TRUE(embedded->GetRoots().front()->children().empty()); 46446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 465f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node21 = Node::Create(window_manager()); 46646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node2->AddChild(node21); 467f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WaitForTreeSizeToMatch(embedded->GetRoots().front(), 1); 468f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_TRUE(embedded->GetRoots().front()->children().empty()); 46946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 47046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Makes node21 visible to |embedded|. 47146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node1->AddChild(node21); 472f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WaitForTreeSizeToMatch(embedded->GetRoots().front(), 2); 473f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_FALSE(embedded->GetRoots().front()->children().empty()); 474f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ(embedded->GetRoots().front()->children().front()->id(), 475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) node21->id()); 47646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 4770de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 47846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Window manager has two nodes, N1 and N11. Embeds A at N1. Removes N11 from 47946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// N1. N11 should disappear from A. 48046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// TODO(beng): verify whether or not this is a policy we like. 48146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, HierarchyChanged_NodeRemoved) { 482f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 484f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* nested = Node::Create(window_manager()); 48546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node->AddChild(nested); 48646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 48746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ(embedded->GetRoots().front()->children().front()->id(), 489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) nested->id()); 49046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 49146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node->RemoveChild(nested); 492f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WaitForTreeSizeToMatch(embedded->GetRoots().front(), 1); 493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_TRUE(embedded->GetRoots().front()->children().empty()); 4940de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 4950de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 49646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Window manager has two nodes, N1 and N11. Embeds A at N1. Destroys N11. 49746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// N11 should disappear from A. 49846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// TODO(beng): verify whether or not this is a policy we like. 49946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, NodeDestroyed) { 500f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 502f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* nested = Node::Create(window_manager()); 50346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node->AddChild(nested); 5040de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 50546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 506f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ(embedded->GetRoots().front()->children().front()->id(), 507f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) nested->id()); 50846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 50946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // |nested| will be deleted after calling Destroy() below. 510f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Id id = nested->id(); 51146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) nested->Destroy(); 5120de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::set<Id> nodes; 514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) nodes.insert(id); 51546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WaitForDestruction(embedded, &nodes, NULL); 5160de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_TRUE(embedded->GetRoots().front()->children().empty()); 51846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(NULL, embedded->GetNodeById(id)); 519cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 5200de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 52146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNode) { 522f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 523f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 52446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 52546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 526f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Id node_id = node->id(); 52746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 52846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) UnloadApplication(GURL(kWindowManagerURL)); 5290de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 530f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::set<Id> nodes; 53146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) nodes.insert(node_id); 53246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WaitForDestruction(embedded, &nodes, NULL); 5330de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 534f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_TRUE(embedded->GetRoots().empty()); 5350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 5360de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 53746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, SetActiveView) { 538f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 539f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 54046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 541cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 54246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) View* view = View::Create(window_manager()); 54346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node->SetActiveView(view); 544cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 545f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node_in_embedded = embedded->GetNodeById(node->id()); 54646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WaitForActiveViewToChange(node_in_embedded); 547cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 54846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(node_in_embedded->active_view()->id(), view->id()); 549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 550cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 55146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, DestroyView) { 552f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 553f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 55446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 55546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 55646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) View* view = View::Create(window_manager()); 55746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node->SetActiveView(view); 558cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 559f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node_in_embedded = embedded->GetNodeById(node->id()); 56046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WaitForActiveViewToChange(node_in_embedded); 561cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 56246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(node_in_embedded->active_view()->id(), view->id()); 563cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 564f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Id view_id = view->id(); 56546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) view->Destroy(); 566cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 567f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::set<Id> views; 56846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) views.insert(view_id); 56946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WaitForDestruction(embedded, NULL, &views); 57046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(NULL, node_in_embedded->active_view()); 57146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(NULL, embedded->GetViewById(view_id)); 572cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 573cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 574cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Destroying the connection that created a node and view should result in that 575cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// node and view disappearing from all connections that see them. 57646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNodeAndView) { 577f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 578f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 57946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) View* view = View::Create(window_manager()); 58046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node->SetActiveView(view); 58146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 582cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 583f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Id node_id = node->id(); 584f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Id view_id = view->id(); 585cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 58646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) UnloadApplication(GURL(kWindowManagerURL)); 587cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 588f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::set<Id> observed_nodes; 58946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) observed_nodes.insert(node_id); 590f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::set<Id> observed_views; 59146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) observed_views.insert(view_id); 59246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WaitForDestruction(embedded, &observed_nodes, &observed_views); 593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 594f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_TRUE(embedded->GetRoots().empty()); 59546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(NULL, embedded->GetNodeById(node_id)); 59646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(NULL, embedded->GetViewById(view_id)); 597cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 598cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 599cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This test validates the following scenario: 600cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// - a node originating from one connection 601cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// - a view originating from a second connection 602cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// + the connection originating the node is destroyed 603cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// -> the view should still exist (since the second connection is live) but 604cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// should be disconnected from any nodes. 605cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(ViewManagerTest, 60646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManagerDestroyed_CleanupNodeAndViewFromDifferentConnections) { 607f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 608f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 60946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 61046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) View* view_in_embedded = View::Create(embedded); 611f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node_in_embedded = embedded->GetNodeById(node->id()); 61246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node_in_embedded->SetActiveView(view_in_embedded); 613cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 61446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WaitForActiveViewToChange(node); 615cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 616f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Id node_id = node->id(); 617f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Id view_id = view_in_embedded->id(); 6180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 61946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) UnloadApplication(GURL(kWindowManagerURL)); 620f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::set<Id> nodes; 62146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) nodes.insert(node_id); 62246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WaitForDestruction(embedded, &nodes, NULL); 62346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 624f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_TRUE(embedded->GetRoots().empty()); 62546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // node was owned by the window manager, so it should be gone. 62646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(NULL, embedded->GetNodeById(node_id)); 62746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // view_in_embedded was owned by the embedded app, so it should still exist, 62846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // but disconnected from the node tree. 62946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(view_in_embedded, embedded->GetViewById(view_id)); 63046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(NULL, view_in_embedded->node()); 631cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 632cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 633cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This test verifies that it is not possible to set the active view to a view 634cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// defined in a different connection. 635f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// TODO(beng): write these tests for Node::AddChild(), RemoveChild() and 636cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Contains(). 63746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, SetActiveViewAcrossConnection) { 638f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 639f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 64046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 641cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 64246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) View* view_in_embedded = View::Create(embedded); 64346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_DEATH(node->SetActiveView(view_in_embedded), ""); 644cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 645cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 646cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This test verifies that a node hierarchy constructed in one connection 647cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// becomes entirely visible to the second connection when the hierarchy is 648cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// attached. 64946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, MapSubtreeOnAttach) { 650f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 651f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 65246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 65346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 65446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Create a subtree private to the window manager and make some changes to it. 655f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* child1 = Node::Create(window_manager()); 656f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* child11 = Node::Create(window_manager()); 65746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) child1->AddChild(child11); 65846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) gfx::Rect child11_bounds(800, 600); 65946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) child11->SetBounds(child11_bounds); 66046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) View* view11 = View::Create(window_manager()); 66146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) child11->SetActiveView(view11); 662f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WaitForAllChangesToBeAcked( 663f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static_cast<ViewManagerClientImpl*>(window_manager())); 66446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 66546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // When added to the shared node, the entire hierarchy and all property 66646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // changes should become visible to the embedded app. 66746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node->AddChild(child1); 668f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WaitForTreeSizeToMatch(embedded->GetRoots().front(), 3); 66946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 670f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* child11_in_embedded = embedded->GetNodeById(child11->id()); 67146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) View* view11_in_embedded = embedded->GetViewById(view11->id()); 67246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(child11_in_embedded != NULL); 67346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(view11_in_embedded, child11_in_embedded->active_view()); 67446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(child11_bounds, child11_in_embedded->bounds()); 675cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 676cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 677cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Verifies that bounds changes applied to a node hierarchy in one connection 678cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// are reflected to another. 67946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, SetBounds) { 680f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 681f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 68246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 68346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 684f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node_in_embedded = embedded->GetNodeById(node->id()); 68546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(node->bounds(), node_in_embedded->bounds()); 68646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 68746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node->SetBounds(gfx::Rect(100, 100)); 68846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_NE(node->bounds(), node_in_embedded->bounds()); 68946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WaitForBoundsToChange(node_in_embedded); 69046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(node->bounds(), node_in_embedded->bounds()); 691cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 692cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 693cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Verifies that bounds changes applied to a node owned by a different 694cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// connection are refused. 69546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, SetBoundsSecurity) { 696f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 697f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 69846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 69946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 700f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node_in_embedded = embedded->GetNodeById(node->id()); 70146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node->SetBounds(gfx::Rect(800, 600)); 70246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WaitForBoundsToChange(node_in_embedded); 703cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 70446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node_in_embedded->SetBounds(gfx::Rect(1024, 768)); 705cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Bounds change should have been rejected. 70646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(node->bounds(), node_in_embedded->bounds()); 707cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 708cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 709cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Verifies that a node can only be destroyed by the connection that created it. 71046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, DestroySecurity) { 711f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 712f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 71346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 71446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 715f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node_in_embedded = embedded->GetNodeById(node->id()); 716cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 71746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) NodeTracker tracker2(node_in_embedded); 71846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node_in_embedded->Destroy(); 719cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Node should not have been destroyed. 720cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(tracker2.is_valid()); 721cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 72246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) NodeTracker tracker1(node); 72346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) node->Destroy(); 724cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE(tracker1.is_valid()); 7250de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 726010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 72746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(ViewManagerTest, MultiRoots) { 728f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node1 = Node::Create(window_manager()); 729f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node1); 730f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node2 = Node::Create(window_manager()); 731f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node2); 73246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded1 = Embed(window_manager(), node1); 73346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ViewManager* embedded2 = Embed(window_manager(), node2); 73446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(embedded1, embedded2); 73546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 73646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 737f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_F(ViewManagerTest, EmbeddingIdentity) { 738f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node = Node::Create(window_manager()); 739f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node); 740f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node); 741f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ(kWindowManagerURL, embedded->GetEmbedderURL()); 742f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 743f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 744f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_F(ViewManagerTest, Reorder) { 745f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node1 = Node::Create(window_manager()); 746f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window_manager()->GetRoots().front()->AddChild(node1); 747f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 748f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node11 = Node::Create(window_manager()); 749f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) node1->AddChild(node11); 750f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node12 = Node::Create(window_manager()); 751f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) node1->AddChild(node12); 752f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 753f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ViewManager* embedded = Embed(window_manager(), node1); 754f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 755f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Node* node1_in_embedded = embedded->GetNodeById(node1->id()); 756f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 757f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) { 758f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) node11->MoveToFront(); 759f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WaitForOrderChange(embedded, embedded->GetNodeById(node11->id())); 760f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 761f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ(node1_in_embedded->children().front(), 762f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) embedded->GetNodeById(node12->id())); 763f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ(node1_in_embedded->children().back(), 764f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) embedded->GetNodeById(node11->id())); 765f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 766f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 767f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) { 768f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) node11->MoveToBack(); 769f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WaitForOrderChange(embedded, embedded->GetNodeById(node11->id())); 770f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 771f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ(node1_in_embedded->children().front(), 772f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) embedded->GetNodeById(node11->id())); 773f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ(node1_in_embedded->children().back(), 774f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) embedded->GetNodeById(node12->id())); 775f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 776f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 777f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 778010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace view_manager 779010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace mojo 780