diff options
8 files changed, 135 insertions, 22 deletions
diff --git a/mojo/examples/embedded_app/embedded_app.cc b/mojo/examples/embedded_app/embedded_app.cc index 139e313..73f7f93 100644 --- a/mojo/examples/embedded_app/embedded_app.cc +++ b/mojo/examples/embedded_app/embedded_app.cc @@ -19,7 +19,7 @@ class EmbeddedApp : public Application { private: // Overridden from Application: virtual void Initialize() MOJO_OVERRIDE { - view_manager_ = new view_manager::ViewManager(this); + view_manager_ = view_manager::ViewManager::CreateBlocking(this); view_manager::View* view = view_manager::View::Create(view_manager_); view_manager_->tree()->SetActiveView(view); view->SetColor(SK_ColorYELLOW); diff --git a/mojo/examples/window_manager/window_manager.cc b/mojo/examples/window_manager/window_manager.cc index 8aa52a3..e3e88ac 100644 --- a/mojo/examples/window_manager/window_manager.cc +++ b/mojo/examples/window_manager/window_manager.cc @@ -19,7 +19,7 @@ class WindowManager : public Application { private: // Overridden from Application: virtual void Initialize() MOJO_OVERRIDE { - view_manager_ = new view_manager::ViewManager(this); + view_manager_ = view_manager::ViewManager::CreateBlocking(this); view_manager::ViewTreeNode* node = view_manager::ViewTreeNode::Create(view_manager_); view_manager_->tree()->AddChild(node); diff --git a/mojo/services/public/cpp/view_manager/lib/view_manager.cc b/mojo/services/public/cpp/view_manager/lib/view_manager.cc index 74fa699..936387f1 100644 --- a/mojo/services/public/cpp/view_manager/lib/view_manager.cc +++ b/mojo/services/public/cpp/view_manager/lib/view_manager.cc @@ -4,23 +4,27 @@ #include "mojo/services/public/cpp/view_manager/view_manager.h" -#include "base/message_loop/message_loop.h" +#include "base/bind.h" +#include "base/run_loop.h" #include "mojo/public/cpp/application/application.h" +#include "mojo/services/public/cpp/view_manager/lib/view_manager_private.h" #include "mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h" #include "mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h" #include "mojo/services/public/cpp/view_manager/view.h" namespace mojo { namespace view_manager { +namespace { -ViewManager::ViewManager(Application* application) - : synchronizer_(NULL), - tree_(NULL) { - application->AddService<ViewManagerSynchronizer>(this); - // Block in a nested message loop until the ViewManagerSynchronizer is set up. - base::MessageLoop::current()->Run(); +void OnViewManagerReady(base::RunLoop* loop, ViewManager* manager) { + loop->Quit(); } +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// ViewManager, public: + ViewManager::~ViewManager() { while (!nodes_.empty()) { IdToNodeMap::iterator it = nodes_.begin(); @@ -38,6 +42,23 @@ ViewManager::~ViewManager() { } } +// static +ViewManager* ViewManager::CreateBlocking(Application* application) { + base::RunLoop init_loop; + ViewManager* manager = new ViewManager( + application, + base::Bind(&OnViewManagerReady, &init_loop)); + init_loop.Run(); + return manager; +} + +// static +void ViewManager::Create( + Application* application, + const base::Callback<void(ViewManager*)> ready_callback) { + new ViewManager(application, ready_callback); +} + ViewTreeNode* ViewManager::GetNodeById(TransportNodeId id) { IdToNodeMap::const_iterator it = nodes_.find(id); return it != nodes_.end() ? it->second : NULL; @@ -52,5 +73,17 @@ void ViewManager::Embed(const String& url, ViewTreeNode* node) { synchronizer_->Embed(url, node->id()); } +//////////////////////////////////////////////////////////////////////////////// +// ViewManager, private: + +ViewManager::ViewManager( + Application* application, + const base::Callback<void(ViewManager*)> ready_callback) + : ready_callback_(ready_callback), + synchronizer_(NULL), + tree_(NULL) { + application->AddService<ViewManagerSynchronizer>(this); +} + } // namespace view_manager } // namespace mojo diff --git a/mojo/services/public/cpp/view_manager/lib/view_manager_private.h b/mojo/services/public/cpp/view_manager/lib/view_manager_private.h index a2b2aab..1c091ed 100644 --- a/mojo/services/public/cpp/view_manager/lib/view_manager_private.h +++ b/mojo/services/public/cpp/view_manager/lib/view_manager_private.h @@ -19,6 +19,10 @@ class ViewManagerPrivate { explicit ViewManagerPrivate(ViewManager* manager); ~ViewManagerPrivate(); + void NotifyReady() { + manager_->ready_callback_.Run(manager_); + } + ViewManagerSynchronizer* synchronizer() { return manager_->synchronizer_; } diff --git a/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc b/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc index 7d1d489..258aeae 100644 --- a/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc +++ b/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc @@ -560,12 +560,10 @@ void ViewManagerSynchronizer::OnViewManagerConnectionEstablished( connection_id_ = connection_id; next_server_change_id_ = next_server_change_id; - ViewManagerPrivate(view_manager()).set_root( - BuildNodeTree(view_manager(), nodes)); - + ViewManagerPrivate private_manager(view_manager()); + private_manager.set_root(BuildNodeTree(view_manager(), nodes)); Sync(); - - base::MessageLoop::current()->Quit(); + private_manager.NotifyReady(); } void ViewManagerSynchronizer::OnServerChangeIdAdvanced( diff --git a/mojo/services/public/cpp/view_manager/tests/DEPS b/mojo/services/public/cpp/view_manager/tests/DEPS new file mode 100644 index 0000000..a024069 --- /dev/null +++ b/mojo/services/public/cpp/view_manager/tests/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+mojo/service_manager", +] diff --git a/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc b/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc index 90bbb6c..7c70b45 100644 --- a/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc +++ b/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc @@ -6,6 +6,8 @@ #include "base/bind.h" #include "base/logging.h" +#include "mojo/public/cpp/application/application.h" +#include "mojo/service_manager/service_manager.h" #include "mojo/services/public/cpp/view_manager/lib/view_manager_private.h" #include "mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h" #include "mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h" @@ -20,6 +22,8 @@ namespace mojo { namespace view_manager { namespace { +const char kTestServiceURL[] = "mojo:test_url"; + base::RunLoop* current_run_loop = NULL; void DoRunLoop() { @@ -44,6 +48,33 @@ void WaitForAllChangesToBeAcked(ViewManager* manager) { ViewManagerPrivate(manager).synchronizer()->ClearChangesAckedCallback(); } +// Used with IViewManager::Connect(). Creates a TestViewManagerClientConnection, +// which creates and owns the ViewManagerProxy. +class ConnectServiceLoader : public ServiceLoader { + public: + explicit ConnectServiceLoader(base::Callback<void(ViewManager*)> callback) + : callback_(callback) {} + virtual ~ConnectServiceLoader() {} + + // ServiceLoader: + virtual void LoadService(ServiceManager* manager, + const GURL& url, + ScopedMessagePipeHandle shell_handle) OVERRIDE { + scoped_ptr<Application> app(new Application(shell_handle.Pass())); + ViewManager::Create(app.get(), callback_); + apps_.push_back(app.release()); + } + virtual void OnServiceError(ServiceManager* manager, + const GURL& url) OVERRIDE { + } + + private: + ScopedVector<Application> apps_; + base::Callback<void(ViewManager*)> callback_; + + DISALLOW_COPY_AND_ASSIGN(ConnectServiceLoader); +}; + class ActiveViewChangedObserver : public ViewTreeNodeObserver { public: explicit ActiveViewChangedObserver(ViewTreeNode* node) @@ -276,10 +307,45 @@ class ViewManagerTest : public testing::Test { // Overridden from testing::Test: virtual void SetUp() OVERRIDE { test_helper_.Init(); + ConnectServiceLoader* loader = + new ConnectServiceLoader( + base::Bind(&ViewManagerTest::OnViewManagerLoaded, + base::Unretained(this))); + test_helper_.SetLoaderForURL( + scoped_ptr<ServiceLoader>(loader), + GURL(kTestServiceURL)); + + ConnectToService(test_helper_.service_provider(), + "mojo:mojo_view_manager", + &view_manager_init_); + ASSERT_TRUE(ViewManagerInitConnect(view_manager_init_.get(), + kTestServiceURL)); + } + + void ViewManagerInitConnectCallback(bool* result_cache, + bool result) { + *result_cache = result; + } + + bool ViewManagerInitConnect(IViewManagerInit* view_manager_init, + const std::string& url) { + bool result = false; + view_manager_init->Connect( + url, + base::Bind(&ViewManagerTest::ViewManagerInitConnectCallback, + base::Unretained(this), &result)); + init_loop_.Run(); + return result; + } + + void OnViewManagerLoaded(ViewManager* view_manager) { + init_loop_.Quit(); } base::MessageLoop loop_; + base::RunLoop init_loop_; shell::ShellTestHelper test_helper_; + IViewManagerInitPtr view_manager_init_; ViewManager* view_manager_1_; ViewManager* view_manager_2_; int commit_count_; @@ -336,6 +402,9 @@ class HierarchyChanged_NodeCreatedObserver : public TreeObserverBase { // TODO(beng): reenable these once converted to new way of connecting. +TEST_F(ViewManagerTest, SetUp) { +} + TEST_F(ViewManagerTest, DISABLED_HierarchyChanged_NodeCreated) { HierarchyChanged_NodeCreatedObserver observer(view_manager_2()); ViewTreeNode* node1 = ViewTreeNode::Create(view_manager_1()); diff --git a/mojo/services/public/cpp/view_manager/view_manager.h b/mojo/services/public/cpp/view_manager/view_manager.h index edfe2c1..34db8e7 100644 --- a/mojo/services/public/cpp/view_manager/view_manager.h +++ b/mojo/services/public/cpp/view_manager/view_manager.h @@ -8,6 +8,7 @@ #include <map> #include "base/basictypes.h" +#include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "mojo/public/cpp/bindings/callback.h" #include "mojo/services/public/cpp/view_manager/view_tree_node.h" @@ -27,16 +28,16 @@ class ViewTreeNode; // TODO: displays class ViewManager { public: - // Blocks on establishing the connection and subsequently receiving a node - // tree from the service. - // TODO(beng): blocking is currently achieved by running a nested runloop, - // which will dispatch all messages on all pipes while blocking. - // we should instead wait on the client pipe receiving a - // connection established message. - // TODO(beng): this method could optionally not block if supplied a callback. - explicit ViewManager(Application* application); ~ViewManager(); + // |ready_callback| is run when the ViewManager connection is established + // and ready to use. + static void Create( + Application* application, + const base::Callback<void(ViewManager*)> ready_callback); + // Blocks until ViewManager is ready to use. + static ViewManager* CreateBlocking(Application* application); + ViewTreeNode* tree() { return tree_; } ViewTreeNode* GetNodeById(TransportNodeId id); @@ -49,6 +50,11 @@ class ViewManager { typedef std::map<TransportNodeId, ViewTreeNode*> IdToNodeMap; typedef std::map<TransportViewId, View*> IdToViewMap; + ViewManager(Application* application, + const base::Callback<void(ViewManager*)> ready_callback); + + base::Callback<void(ViewManager*)> ready_callback_; + ViewManagerSynchronizer* synchronizer_; ViewTreeNode* tree_; |