From 7f20b1eab93cc5b1986214347bbee1c4e0e314bb Mon Sep 17 00:00:00 2001 From: Piotr Tworek Date: Mon, 14 Sep 2015 19:40:30 +0200 Subject: [PATCH] [embedlite} Make it possible to shut down the engine grecefully. With this in place applications like sailfish-browser should be able to request the engine to shut down and wait for the prcess to finish before terminating the mainloop. --- embedding/embedlite/EmbedLiteApp.cpp | 65 ++++++++++++------- embedding/embedlite/EmbedLiteApp.h | 8 ++- embedding/embedlite/EmbedLiteView.cpp | 19 ++++-- embedding/embedlite/EmbedLiteView.h | 15 ++++- embedding/embedlite/EmbedLiteWindow.cpp | 12 +++- embedding/embedlite/EmbedLiteWindow.h | 14 +++- embedding/embedlite/PEmbedLiteView.ipdl | 1 + embedding/embedlite/PEmbedLiteWindow.ipdl | 1 + .../embedshared/EmbedLitePuppetWidget.cpp | 2 - .../embedshared/EmbedLiteViewBaseChild.cpp | 1 + .../embedshared/EmbedLiteViewBaseParent.cpp | 14 +++- .../embedshared/EmbedLiteViewBaseParent.h | 3 + .../embedshared/EmbedLiteWindowBaseChild.cpp | 17 +++++ .../embedshared/EmbedLiteWindowBaseParent.cpp | 7 ++ .../embedshared/EmbedLiteWindowBaseParent.h | 1 + 15 files changed, 135 insertions(+), 45 deletions(-) diff --git a/embedding/embedlite/EmbedLiteApp.cpp b/embedding/embedlite/EmbedLiteApp.cpp index ddac0257a56bc..887990885e9dd 100644 --- a/embedding/embedlite/EmbedLiteApp.cpp +++ b/embedding/embedlite/EmbedLiteApp.cpp @@ -314,16 +314,15 @@ EmbedLiteApp::Stop() NS_ASSERTION(mState == STARTING || mState == INITIALIZED, "Wrong timing"); if (mState == INITIALIZED) { - if (mViews.empty()) { + if (mViews.empty() && mWindows.empty()) { mUILoop->PostTask(FROM_HERE, NewRunnableFunction(&EmbedLiteApp::PreDestroy, this)); } else { - std::map::iterator it; - for (it = mViews.begin(); it != mViews.end(); it++) { - EmbedLiteView* view = it->second; - delete view; - it->second = nullptr; - // NOTE: we still keep dangling keys here. They are supposed to be erased in ViewDestroyed(). + for (auto viewPair : mViews) { + viewPair.second->Destroy(); + } + for (auto winPair: mWindows) { + winPair.second->Destroy(); } } } @@ -441,7 +440,7 @@ EmbedLiteApp::CreateView(EmbedLiteWindow* aWindow, uint32_t aParent, bool aIsPri PEmbedLiteViewParent* viewParent = static_cast( mAppParent->SendPEmbedLiteViewConstructor(aWindow->GetUniqueID(), sViewCreateID, - aParent, aIsPrivateWindow)); + aParent, aIsPrivateWindow)); EmbedLiteView* view = new EmbedLiteView(this, aWindow, viewParent, sViewCreateID); mViews[sViewCreateID] = view; return view; @@ -517,11 +516,35 @@ EmbedLiteApp::ViewDestroyed(uint32_t id) LOGT("id:%i", id); std::map::iterator it = mViews.find(id); if (it != mViews.end()) { + EmbedLiteView* view = it->second; mViews.erase(it); + delete view; } - if (mState == DESTROYING && mViews.empty()) { - mUILoop->PostTask(FROM_HERE, - NewRunnableFunction(&EmbedLiteApp::PreDestroy, this)); + if (mViews.empty()) { + if (mListener) { + mListener->LastViewDestroyed(); + } + if (mState == DESTROYING) { + mUILoop->PostTask(FROM_HERE, + NewRunnableFunction(&EmbedLiteApp::PreDestroy, this)); + } + } +} + +void +EmbedLiteApp::WindowDestroyed(uint32_t id) +{ + LOGT("id:%i", id); + std::map::iterator it = mWindows.find(id); + if (it != mWindows.end()) { + EmbedLiteWindow* win = it->second; + mWindows.erase(it); + delete win; + } + if (mWindows.empty()) { + if (mListener) { + mListener->LastWindowDestroyed(); + } } } @@ -529,13 +552,9 @@ void EmbedLiteApp::DestroyView(EmbedLiteView* aView) { LOGT(); NS_ASSERTION(mState == INITIALIZED, "Wrong timing"); - std::map::iterator it; - for (it = mViews.begin(); it != mViews.end(); it++) { - if (it->second == aView) { - EmbedLiteView* view = it->second; - delete view; - it->second = nullptr; - mViews.erase(it); + for (auto elm : mViews) { + if (aView == elm.second) { + elm.second->Destroy(); return; } } @@ -546,13 +565,9 @@ void EmbedLiteApp::DestroyWindow(EmbedLiteWindow* aWindow) { LOGT(); NS_ASSERTION(mState == INITIALIZED, "Wrong timing"); - std::map::iterator it; - for (it = mWindows.begin(); it != mWindows.end(); it++) { - if (it->second == aWindow) { - EmbedLiteWindow* window = it->second; - delete window; - it->second = nullptr; - mWindows.erase(it); + for (auto elm : mWindows) { + if (aWindow == elm.second) { + elm.second->Destroy(); return; } } diff --git a/embedding/embedlite/EmbedLiteApp.h b/embedding/embedlite/EmbedLiteApp.h index 9204a9965f81f..5dcd46e7f2812 100644 --- a/embedding/embedlite/EmbedLiteApp.h +++ b/embedding/embedlite/EmbedLiteApp.h @@ -51,6 +51,8 @@ class EmbedLiteAppListener const char* uri, const uint32_t& contextFlags, EmbedLiteView* aParentView) { return 0; } + virtual void LastViewDestroyed() {}; + virtual void LastWindowDestroyed() {}; }; class EmbedLiteApp @@ -175,13 +177,13 @@ class EmbedLiteApp friend class EmbedLiteAppThreadParent; friend class EmbedLiteCompositorParent; friend class EmbedLitePuppetWidget; - friend class EmbedLiteViewBaseChild; - friend class EmbedLiteViewBaseParent; - friend class EmbedLiteViewThreadParent; + friend class EmbedLiteView; + friend class EmbedLiteWindow; EmbedLiteView* GetViewByID(uint32_t id); EmbedLiteWindow* GetWindowByID(uint32_t id); void ViewDestroyed(uint32_t id); + void WindowDestroyed(uint32_t id); void ChildReadyToDestroy(); uint32_t CreateWindowRequested(const uint32_t& chromeFlags, const char* uri, const uint32_t& contextFlags, const uint32_t& parentId); EmbedLiteAppListener* GetListener(); diff --git a/embedding/embedlite/EmbedLiteView.cpp b/embedding/embedlite/EmbedLiteView.cpp index 7b478ff9a73af..74fc50959fef3 100644 --- a/embedding/embedlite/EmbedLiteView.cpp +++ b/embedding/embedlite/EmbedLiteView.cpp @@ -40,18 +40,25 @@ EmbedLiteView::EmbedLiteView(EmbedLiteApp* aApp, EmbedLiteWindow* aWindow, PEmb EmbedLiteView::~EmbedLiteView() { LOGT("impl:%p", mViewImpl); - if (mViewParent) { - unused << mViewParent->SendDestroy(); - } else { - LOGNI(); - } if (mViewImpl) { mViewImpl->ViewAPIDestroyed(); } - mViewImpl = NULL; +} + +void +EmbedLiteView::Destroy() +{ + MOZ_ASSERT(mViewParent); + unused << mViewParent->SendDestroy(); +} + +void +EmbedLiteView::Destroyed() +{ if (mListener) { mListener->ViewDestroyed(); } + EmbedLiteApp::GetInstance()->ViewDestroyed(mUniqueID); } void diff --git a/embedding/embedlite/EmbedLiteView.h b/embedding/embedlite/EmbedLiteView.h index c69ba0633dee1..06adbd332cd42 100644 --- a/embedding/embedlite/EmbedLiteView.h +++ b/embedding/embedlite/EmbedLiteView.h @@ -115,12 +115,21 @@ class EmbedLiteView virtual uint32_t GetUniqueID(); -private: - friend class EmbedLiteViewThreadParent; +protected: friend class EmbedLiteApp; // Needs to destroy the view. - // EmbedLiteViews are supposed to be destroyed through EmbedLiteApp::DestroyView. virtual ~EmbedLiteView(); + // Request the view to be destroyed. Once this async process is done + // EmbedLiteViewListener::ViewDestroyed will be called. This interface + // should only be used by EmbedLiteApp. EmbedLite users should destroy + // EmbedLiteViews by calling EmbedLiteApp::DestroyView. + void Destroy(); + +private: + friend class EmbedLiteViewBaseParent; + friend class EmbedLiteViewThreadParent; + + void Destroyed(); EmbedLiteViewIface* GetImpl(); diff --git a/embedding/embedlite/EmbedLiteWindow.cpp b/embedding/embedlite/EmbedLiteWindow.cpp index 3782c98f6e69b..b391598bd25ea 100644 --- a/embedding/embedlite/EmbedLiteWindow.cpp +++ b/embedding/embedlite/EmbedLiteWindow.cpp @@ -32,14 +32,22 @@ EmbedLiteWindow::EmbedLiteWindow(EmbedLiteApp* app, PEmbedLiteWindowParent* pare EmbedLiteWindow::~EmbedLiteWindow() { MOZ_COUNT_DTOR(EmbedLiteWindow); - unused << mWindowParent->SendDestroy(); mWindowParent->SetEmbedAPIWindow(nullptr); +} + +void EmbedLiteWindow::Destroy() +{ + unused << mWindowParent->SendDestroy(); +} + +void EmbedLiteWindow::Destroyed() +{ if (mListener) { mListener->WindowDestroyed(); } + EmbedLiteApp::GetInstance()->WindowDestroyed(mUniqueID); } - void EmbedLiteWindow::SetListener(EmbedLiteWindowListener* aListener) { mListener = aListener; diff --git a/embedding/embedlite/EmbedLiteWindow.h b/embedding/embedlite/EmbedLiteWindow.h index 82df25f1d6afd..088b792e52708 100644 --- a/embedding/embedlite/EmbedLiteWindow.h +++ b/embedding/embedlite/EmbedLiteWindow.h @@ -75,11 +75,21 @@ class EmbedLiteWindow { virtual void ResumeRendering(); virtual void* GetPlatformImage(int* width, int* height); +protected: + friend class EmbedLiteApp; + + virtual ~EmbedLiteWindow(); + // Request the window to be destroyed. Once this async process is done + // EmbedLiteWindowListener::WindowDestroyed will be called. This interface + // should only be used by EmbedLiteApp. EmbedLite users should destroy + // EmbedLiteWindowss by calling EmbedLiteApp::DestroyWindow. + void Destroy(); + private: - friend class EmbedLiteApp; // Needs to destroy the window. + friend class EmbedLiteWindowBaseParent; // EmbedLiteWindowss are supposed to be destroyed through EmbedLiteApp::DestroyWindow. - virtual ~EmbedLiteWindow(); + void Destroyed(); EmbedLiteApp* mApp; EmbedLiteWindowListener* mListener; diff --git a/embedding/embedlite/PEmbedLiteView.ipdl b/embedding/embedlite/PEmbedLiteView.ipdl index 50c55354b650c..866d347b30610 100644 --- a/embedding/embedlite/PEmbedLiteView.ipdl +++ b/embedding/embedlite/PEmbedLiteView.ipdl @@ -70,6 +70,7 @@ child: parent: Initialized(); + Destroyed(); __delete__(); OnLocationChanged(nsCString aLocation, bool aCanGoBack, bool aCanGoForward); diff --git a/embedding/embedlite/PEmbedLiteWindow.ipdl b/embedding/embedlite/PEmbedLiteWindow.ipdl index 6fd3a1c74a8bd..0ef1b7155e514 100644 --- a/embedding/embedlite/PEmbedLiteWindow.ipdl +++ b/embedding/embedlite/PEmbedLiteWindow.ipdl @@ -20,6 +20,7 @@ child: parent: Initialized(); + Destroyed(); __delete__(); }; diff --git a/embedding/embedlite/embedshared/EmbedLitePuppetWidget.cpp b/embedding/embedlite/embedshared/EmbedLitePuppetWidget.cpp index 9e339e1bd1b33..176420c8cb913 100644 --- a/embedding/embedlite/embedshared/EmbedLitePuppetWidget.cpp +++ b/embedding/embedlite/embedshared/EmbedLitePuppetWidget.cpp @@ -101,8 +101,6 @@ EmbedLitePuppetWidget::EmbedLitePuppetWidget(EmbedLiteWindowBaseChild* window) : EmbedLitePuppetWidget(window, nullptr) { if (sUseExternalGLContext && sRequestGLContextEarly) { - // GetPlatform() should create compositor loop if it doesn't exist, yet. - gfxPlatform::GetPlatform(); CompositorParent::CompositorLoop()->PostTask(FROM_HERE, NewRunnableFunction(&CreateGLContextEarly, window->GetUniqueID())); } diff --git a/embedding/embedlite/embedshared/EmbedLiteViewBaseChild.cpp b/embedding/embedlite/embedshared/EmbedLiteViewBaseChild.cpp index 46bdb0c618ea9..375841ad5e4c2 100644 --- a/embedding/embedlite/embedshared/EmbedLiteViewBaseChild.cpp +++ b/embedding/embedlite/embedshared/EmbedLiteViewBaseChild.cpp @@ -145,6 +145,7 @@ bool EmbedLiteViewBaseChild::RecvDestroy() mChrome = nullptr; mDOMWindow = nullptr; mWebNavigation = nullptr; + unused << SendDestroyed(); PEmbedLiteViewChild::Send__delete__(this); return true; } diff --git a/embedding/embedlite/embedshared/EmbedLiteViewBaseParent.cpp b/embedding/embedlite/embedshared/EmbedLiteViewBaseParent.cpp index deec5ddb3cb18..c308d896d1bfa 100644 --- a/embedding/embedlite/embedshared/EmbedLiteViewBaseParent.cpp +++ b/embedding/embedlite/embedshared/EmbedLiteViewBaseParent.cpp @@ -5,7 +5,6 @@ #include "EmbedLog.h" -#include "EmbedLiteApp.h" #include "EmbedLiteView.h" #include "EmbedLiteViewBaseParent.h" #include "EmbedLiteWindowBaseParent.h" @@ -47,7 +46,6 @@ EmbedLiteViewBaseParent::~EmbedLiteViewBaseParent() LOGT("mView:%p, mCompositor:%p", mView, mCompositor.get()); mController = nullptr; mWindow.RemoveObserver(this); - EmbedLiteApp::GetInstance()->ViewDestroyed(mId); } void @@ -93,6 +91,18 @@ EmbedLiteViewBaseParent::RecvInitialized() return true; } +bool +EmbedLiteViewBaseParent::RecvDestroyed() +{ + if (mViewAPIDestroyed) { + return true; + } + + NS_ENSURE_TRUE(mView, false); + mView->Destroyed(); + return true; +} + bool EmbedLiteViewBaseParent::RecvOnLocationChanged(const nsCString& aLocation, const bool& aCanGoBack, diff --git a/embedding/embedlite/embedshared/EmbedLiteViewBaseParent.h b/embedding/embedlite/embedshared/EmbedLiteViewBaseParent.h index 90a4137275f58..980e9e531156f 100644 --- a/embedding/embedlite/embedshared/EmbedLiteViewBaseParent.h +++ b/embedding/embedlite/embedshared/EmbedLiteViewBaseParent.h @@ -38,6 +38,9 @@ class EmbedLiteViewBaseParent : public PEmbedLiteViewParent, virtual bool RecvInitialized() override; + virtual bool + RecvDestroyed() override; + virtual bool RecvOnLocationChanged(const nsCString& aLocation, const bool& aCanGoBack, const bool& aCanGoForward) override; diff --git a/embedding/embedlite/embedshared/EmbedLiteWindowBaseChild.cpp b/embedding/embedlite/embedshared/EmbedLiteWindowBaseChild.cpp index 4c35fb4c1cc9f..7d94e5ff2515e 100644 --- a/embedding/embedlite/embedshared/EmbedLiteWindowBaseChild.cpp +++ b/embedding/embedlite/embedshared/EmbedLiteWindowBaseChild.cpp @@ -12,12 +12,19 @@ #include "ScreenOrientation.h" #include "nsIScreen.h" #include "nsIScreenManager.h" +#include "gfxPlatform.h" using namespace mozilla::dom; namespace mozilla { + +namespace layers { +void ShutdownTileCache(); +} namespace embedlite { +static int sWindowCount = 0; + EmbedLiteWindowBaseChild::EmbedLiteWindowBaseChild(const uint32_t& aId) : mId(aId) , mWidget(nullptr) @@ -28,6 +35,10 @@ EmbedLiteWindowBaseChild::EmbedLiteWindowBaseChild(const uint32_t& aId) mCreateWidgetTask = NewRunnableMethod(this, &EmbedLiteWindowBaseChild::CreateWidget); MessageLoop::current()->PostTask(FROM_HERE, mCreateWidgetTask); + sWindowCount++; + + // Make sure gfx platform is initialized and ready to go. + gfxPlatform::GetPlatform(); } EmbedLiteWindowBaseChild::~EmbedLiteWindowBaseChild() @@ -38,6 +49,11 @@ EmbedLiteWindowBaseChild::~EmbedLiteWindowBaseChild() mCreateWidgetTask->Cancel(); mCreateWidgetTask = nullptr; } + + sWindowCount--; + if (sWindowCount == 0) { + mozilla::layers::ShutdownTileCache(); + } } EmbedLitePuppetWidget* EmbedLiteWindowBaseChild::GetWidget() const @@ -54,6 +70,7 @@ bool EmbedLiteWindowBaseChild::RecvDestroy() { LOGT("destroy"); mWidget = nullptr; + unused << SendDestroyed(); PEmbedLiteWindowChild::Send__delete__(this); return true; } diff --git a/embedding/embedlite/embedshared/EmbedLiteWindowBaseParent.cpp b/embedding/embedlite/embedshared/EmbedLiteWindowBaseParent.cpp index 785a37df2f421..c5763e14e4891 100644 --- a/embedding/embedlite/embedshared/EmbedLiteWindowBaseParent.cpp +++ b/embedding/embedlite/embedshared/EmbedLiteWindowBaseParent.cpp @@ -128,6 +128,13 @@ bool EmbedLiteWindowBaseParent::RecvInitialized() return true; } +bool EmbedLiteWindowBaseParent::RecvDestroyed() +{ + MOZ_ASSERT(mWindow); + mWindow->Destroyed(); + return true; +} + void EmbedLiteWindowBaseParent::SetCompositor(EmbedLiteCompositorParent* aCompositor) { LOGT("compositor:%p, observers:%d", aCompositor, mObservers.Length()); diff --git a/embedding/embedlite/embedshared/EmbedLiteWindowBaseParent.h b/embedding/embedlite/embedshared/EmbedLiteWindowBaseParent.h index 9bb32752f126d..b5c856ac314ee 100644 --- a/embedding/embedlite/embedshared/EmbedLiteWindowBaseParent.h +++ b/embedding/embedlite/embedshared/EmbedLiteWindowBaseParent.h @@ -49,6 +49,7 @@ class EmbedLiteWindowBaseParent : public PEmbedLiteWindowParent virtual void ActorDestroy(ActorDestroyReason aWhy) override; virtual bool RecvInitialized() override; + virtual bool RecvDestroyed() override; void SetEmbedAPIWindow(EmbedLiteWindow* window); void SetCompositor(EmbedLiteCompositorParent* aCompositor);