Bug 907410 - Winrt async input - rework shutdown logic. r=bbondy
authorJim Mathies <jmathies@mozilla.com>
Fri, 06 Sep 2013 08:11:16 -0500
changeset 158824 1e80d8e1784154b88ce48b85e3c4374fd92bda27
parent 158823 eaad370c10c1eb0d398f2e9f2b5d30f4ca2bfd79
child 158825 1fbc0073fcf474ca476d6bf2106107c79398b376
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbondy
bugs907410
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 907410 - Winrt async input - rework shutdown logic. r=bbondy
widget/windows/winrt/FrameworkView.cpp
widget/windows/winrt/FrameworkView.h
widget/windows/winrt/MetroAppShell.cpp
widget/windows/winrt/MetroAppShell.h
--- a/widget/windows/winrt/FrameworkView.cpp
+++ b/widget/windows/winrt/FrameworkView.cpp
@@ -72,36 +72,16 @@ FrameworkView::Initialize(ICoreApplicati
   //CoCreateInstance(CLSID_WICImagingFactory, nullptr,
   //                 CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&mWicFactory));
   return S_OK;
 }
 
 HRESULT
 FrameworkView::Uninitialize()
 {
-  LogFunction();
-  mShuttingDown = true;
-
-  if (mAutomationProvider) {
-    ComPtr<IUIABridge> provider;
-    mAutomationProvider.As(&provider);
-    if (provider) {
-      provider->Disconnect();
-    }
-  }
-  mAutomationProvider = nullptr;
-
-  mMetroInput = nullptr;
-  mD2DWindowSurface = nullptr;
-  delete sSettingsArray;
-  sSettingsArray = nullptr;
-  mWidget = nullptr;
-  mMetroApp = nullptr;
-  mWindow = nullptr;
-
   return S_OK;
 }
 
 HRESULT
 FrameworkView::Load(HSTRING aEntryPoint)
 {
   return S_OK;
 }
@@ -112,16 +92,17 @@ FrameworkView::Run()
 {
   LogFunction();
 
   // Initialize XPCOM, create mWidget and go! We get a
   // callback in MetroAppShell::Run, in which we kick
   // off normal browser execution / event dispatching.
   mMetroApp->Run();
 
+  // Gecko is completely shut down at this point.
   Log("Exiting FrameworkView::Run()");
 
   return S_OK;
 }
 
 HRESULT
 FrameworkView::ActivateView()
 {
@@ -198,17 +179,35 @@ FrameworkView::AddEventHandlers() {
     }
   }
 }
 
 // Called by MetroApp
 void
 FrameworkView::ShutdownXPCOM()
 {
-  Uninitialize();
+  LogFunction();
+  mShuttingDown = true;
+
+  if (mAutomationProvider) {
+    ComPtr<IUIABridge> provider;
+    mAutomationProvider.As(&provider);
+    if (provider) {
+      provider->Disconnect();
+    }
+  }
+  mAutomationProvider = nullptr;
+
+  mMetroInput = nullptr;
+  mD2DWindowSurface = nullptr;
+  delete sSettingsArray;
+  sSettingsArray = nullptr;
+  mWidget = nullptr;
+  mMetroApp = nullptr;
+  mWindow = nullptr;
 }
 
 void
 FrameworkView::SetCursor(CoreCursorType aCursorType, DWORD aCustomId)
 {
   if (mShuttingDown) {
     return;
   }
--- a/widget/windows/winrt/FrameworkView.h
+++ b/widget/windows/winrt/FrameworkView.h
@@ -77,18 +77,16 @@ public:
   STDMETHODIMP Load(HSTRING aEntryPoint);
   STDMETHODIMP Run();
   STDMETHODIMP Uninitialize();
 
   HRESULT ActivateView();
 
   // Public apis for MetroWidget
   void ShutdownXPCOM();
-  bool Render();
-  bool Render(const nsIntRegion& aInvalidRegion);
   float GetDPI() { return mDPI; }
   ICoreWindow* GetCoreWindow() { return mWindow.Get(); }
   void SetWidget(MetroWidget* aWidget);
   MetroWidget* GetWidget() { return mWidget.Get(); }
   void GetBounds(nsIntRect &aRect);
   void GetActivationURI(nsAString &aActivationURI) { aActivationURI = mActivationURI; }
   void SetCursor(ABI::Windows::UI::Core::CoreCursorType aCursorType, DWORD aCustomId = 0);
   void ClearCursor();
--- a/widget/windows/winrt/MetroAppShell.cpp
+++ b/widget/windows/winrt/MetroAppShell.cpp
@@ -108,16 +108,22 @@ MetroAppShell::Run(void)
       // Just exit
       rv = NS_ERROR_NOT_IMPLEMENTED;
     break;
     case GeckoProcessType_Default:
       mozilla::widget::StartAudioSession();
       sFrameworkView->ActivateView();
       rv = nsBaseAppShell::Run();
       mozilla::widget::StopAudioSession();
+      // This calls XRE_metroShutdown() in xre. This will also destroy
+      // MessagePump.
+      sMetroApp->ShutdownXPCOM();
+      // This will free the real main thread in CoreApplication::Run()
+      // once winrt cleans up this thread.
+      sMetroApp->CoreExit();
     break;
   }
 
   return rv;
 }
 
 static void
 ProcessNativeEvents(CoreProcessEventsOption eventOption)
@@ -159,49 +165,21 @@ MetroAppShell::ProcessNextNativeEvent(bo
   if (mayWait) {
     DWORD result = ::MsgWaitForMultipleObjectsEx(0, NULL, MSG_WAIT_TIMEOUT, MOZ_QS_ALLEVENT,
                                                  MWMO_INPUTAVAILABLE|MWMO_ALERTABLE);
     NS_WARN_IF_FALSE(result != WAIT_FAILED, "Wait failed");
   }
   return ProcessOneNativeEventIfPresent();
 }
 
-// Results from a call to appstartup->quit, which fires a final nsAppExitEvent
-// event which calls us here. This is on the metro main thread. We want to
-// call xpcom shutdown here, but we need to wait until the runnable that fires
-// this is off the stack. See NativeEventCallback below.
-NS_IMETHODIMP
-MetroAppShell::Exit(void)
-{
-  LogFunction();
-  mExiting = true;
-  return NS_OK;
-}
-
 void
 MetroAppShell::NativeCallback()
 {
   NS_ASSERTION(NS_IsMainThread(), "Native callbacks must be on the metro main thread");
   NativeEventCallback();
-
-  // Handle shutdown after Exit() is called and unwinds.
-  if (mExiting) {
-    // shutdown fires events, don't recurse
-    static bool sShutdown = false;
-    if (sShutdown)
-      return;
-    sShutdown = true;
-    if (sMetroApp) {
-      // This calls XRE_metroShutdown() in xre
-      sMetroApp->ShutdownXPCOM();
-      // This will free the real main thread in CoreApplication::Run()
-      // once winrt cleans up this thread.
-      sMetroApp->CoreExit();
-    }
-  }
 }
 
 // static
 LRESULT CALLBACK
 MetroAppShell::EventWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
   if (uMsg == sAppShellGeckoMsgId) {
     MetroAppShell *as = reinterpret_cast<MetroAppShell *>(lParam);
--- a/widget/windows/winrt/MetroAppShell.h
+++ b/widget/windows/winrt/MetroAppShell.h
@@ -10,30 +10,32 @@
 #include "nsWindowsHelpers.h"
 #include "nsIObserver.h"
 
 class MetroAppShell : public nsBaseAppShell
 {
 public:
   NS_DECL_NSIOBSERVER
 
-  MetroAppShell() : mEventWnd(NULL), mExiting(false), mPowerRequestCount(0)
-  {}
+  MetroAppShell() :
+    mEventWnd(NULL),
+    mPowerRequestCount(0)
+  {
+  }
 
   nsresult Init();
   void DoProcessMoreGeckoEvents();
   void NativeCallback();
 
   static LRESULT CALLBACK EventWindowProc(HWND, UINT, WPARAM, LPARAM);
   static bool ProcessOneNativeEventIfPresent();
 
 protected:
-  HWND mEventWnd;
-  bool mExiting;
-  nsAutoHandle mPowerRequest;
-  ULONG mPowerRequestCount;
+  NS_IMETHOD Run();
 
-  NS_IMETHOD Run();
-  NS_IMETHOD Exit();
   virtual void ScheduleNativeEventCallback();
   virtual bool ProcessNextNativeEvent(bool mayWait);
   virtual ~MetroAppShell();
+
+  HWND mEventWnd;
+  nsAutoHandle mPowerRequest;
+  ULONG mPowerRequestCount;
 };