widget/windows/winrt/MetroApp.cpp

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "MetroApp.h"
     7 #include "MetroWidget.h"
     8 #include "mozilla/IOInterposer.h"
     9 #include "mozilla/widget/AudioSession.h"
    10 #include "nsIRunnable.h"
    11 #include "MetroUtils.h"
    12 #include "MetroAppShell.h"
    13 #include "nsICommandLineRunner.h"
    14 #include "FrameworkView.h"
    15 #include "nsAppDirectoryServiceDefs.h"
    16 #include "GeckoProfiler.h"
    17 #include <shellapi.h>
    19 using namespace ABI::Windows::ApplicationModel;
    20 using namespace ABI::Windows::ApplicationModel::Core;
    21 using namespace ABI::Windows::UI::Core;
    22 using namespace ABI::Windows::System;
    23 using namespace ABI::Windows::Foundation;
    24 using namespace Microsoft::WRL;
    25 using namespace Microsoft::WRL::Wrappers;
    26 using namespace mozilla::widget;
    28 // Metro specific XRE methods we call from here on an
    29 // appropriate thread.
    30 extern nsresult XRE_metroStartup(bool runXREMain);
    31 extern void XRE_metroShutdown();
    33 static const char* gGeckoThreadName = "GeckoMain";
    35 #ifdef PR_LOGGING
    36 extern PRLogModuleInfo* gWindowsLog;
    37 #endif
    39 namespace mozilla {
    40 namespace widget {
    41 namespace winrt {
    43 ComPtr<FrameworkView> sFrameworkView;
    44 ComPtr<MetroApp> sMetroApp;
    45 ComPtr<ICoreApplication> sCoreApp;
    46 bool MetroApp::sGeckoShuttingDown = false;
    48 ////////////////////////////////////////////////////
    49 // IFrameworkViewSource impl.
    51 // Called after CoreApplication::Run(app)
    52 HRESULT
    53 MetroApp::CreateView(ABI::Windows::ApplicationModel::Core::IFrameworkView **aViewProvider)
    54 {
    55   // This entry point is called on the metro main thread, but the thread won't
    56   // be recognized as such until after Run() is called below. XPCOM has not
    57   // gone through startup at this point.
    59   // Note that we create the view which creates our native window for us. The
    60   // gecko widget gets created by gecko, and the two get hooked up later in
    61   // MetroWidget::Create().
    63   LogFunction();
    65   sFrameworkView = Make<FrameworkView>(this);
    66   sFrameworkView.Get()->AddRef();
    67   *aViewProvider = sFrameworkView.Get();
    68   return !sFrameworkView ? E_FAIL : S_OK;
    69 }
    71 ////////////////////////////////////////////////////
    72 // MetroApp impl.
    74 void
    75 MetroApp::Run()
    76 {
    77   LogThread();
    79   // Name this thread for debugging and register it with the profiler
    80   // and IOInterposer as the main gecko thread.
    81   char aLocal;
    82   PR_SetCurrentThreadName(gGeckoThreadName);
    83   profiler_register_thread(gGeckoThreadName, &aLocal);
    84   IOInterposer::RegisterCurrentThread(true);
    86   HRESULT hr;
    87   hr = sCoreApp->add_Suspending(Callback<__FIEventHandler_1_Windows__CApplicationModel__CSuspendingEventArgs_t>(
    88     this, &MetroApp::OnSuspending).Get(), &mSuspendEvent);
    89   AssertHRESULT(hr);
    91   hr = sCoreApp->add_Resuming(Callback<__FIEventHandler_1_IInspectable_t>(
    92     this, &MetroApp::OnResuming).Get(), &mResumeEvent);
    93   AssertHRESULT(hr);
    95   WinUtils::Log("Calling XRE_metroStartup.");
    96   nsresult rv = XRE_metroStartup(true);
    97   WinUtils::Log("Exiting XRE_metroStartup.");
    98   if (NS_FAILED(rv)) {
    99     WinUtils::Log("XPCOM startup initialization failed, bailing. rv=%X", rv);
   100     CoreExit();
   101   }
   102 }
   104 // Free all xpcom related resources before calling the xre shutdown call.
   105 // Must be called on the metro main thread. Currently called from appshell.
   106 void
   107 MetroApp::Shutdown()
   108 {
   109   LogThread();
   111   if (sCoreApp) {
   112     sCoreApp->remove_Suspending(mSuspendEvent);
   113     sCoreApp->remove_Resuming(mResumeEvent);
   114   }
   116   if (sFrameworkView) {
   117     sFrameworkView->Shutdown();
   118   }
   120   MetroApp::sGeckoShuttingDown = true;
   122   // Shut down xpcom
   123   XRE_metroShutdown();
   125   // Unhook this thread from the profiler
   126   profiler_unregister_thread();
   127 }
   129 // Request a shutdown of the application
   130 void
   131 MetroApp::CoreExit()
   132 {
   133   LogFunction();
   134   HRESULT hr;
   135   ComPtr<ICoreApplicationExit> coreExit;
   136   HStringReference className(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication);
   137   hr = GetActivationFactory(className.Get(), coreExit.GetAddressOf());
   138   NS_ASSERTION(SUCCEEDED(hr), "Activation of ICoreApplicationExit");
   139   if (SUCCEEDED(hr)) {
   140     coreExit->Exit();
   141   }
   142 }
   144 void
   145 MetroApp::ActivateBaseView()
   146 {
   147   if (sFrameworkView) {
   148     sFrameworkView->ActivateView();
   149   }
   150 }
   152 /*
   153  * TBD: when we support multiple widgets, we'll need a way to sync up the view
   154  * created in CreateView with the widget gecko creates. Currently we only have
   155  * one view (sFrameworkView) and one main widget.
   156  */
   157 void
   158 MetroApp::SetWidget(MetroWidget* aPtr)
   159 {
   160   LogThread();
   162   NS_ASSERTION(aPtr, "setting null base widget?");
   164   // Both of these calls AddRef the ptr we pass in
   165   aPtr->SetView(sFrameworkView.Get());
   166   sFrameworkView->SetWidget(aPtr);
   167 }
   169 ////////////////////////////////////////////////////
   170 // MetroApp events
   172 HRESULT
   173 MetroApp::OnSuspending(IInspectable* aSender, ISuspendingEventArgs* aArgs)
   174 {
   175   LogThread();
   176   PostSuspendResumeProcessNotification(true);
   177   return S_OK;
   178 }
   180 HRESULT
   181 MetroApp::OnResuming(IInspectable* aSender, IInspectable* aArgs)
   182 {
   183   LogThread();
   184   PostSuspendResumeProcessNotification(false);
   185   return S_OK;
   186 }
   188 HRESULT
   189 MetroApp::OnAsyncTileCreated(ABI::Windows::Foundation::IAsyncOperation<bool>* aOperation,
   190                              AsyncStatus aStatus)
   191 {
   192   WinUtils::Log("Async operation status: %d", aStatus);
   193   MetroUtils::FireObserver("metro_on_async_tile_created");
   194   return S_OK;
   195 }
   197 // static
   198 void
   199 MetroApp::PostSuspendResumeProcessNotification(const bool aIsSuspend)
   200 {
   201   static bool isSuspend = false;
   202   if (isSuspend == aIsSuspend) {
   203     return;
   204   }
   205   isSuspend = aIsSuspend;
   206   MetroUtils::FireObserver(aIsSuspend ? "suspend_process_notification" :
   207                                         "resume_process_notification");
   208 }
   210 // static
   211 void
   212 MetroApp::PostSleepWakeNotification(const bool aIsSleep)
   213 {
   214   static bool isSleep = false;
   215   if (isSleep == aIsSleep) {
   216     return;
   217   }
   218   isSleep = aIsSleep;
   219   MetroUtils::FireObserver(aIsSleep ? "sleep_notification" :
   220                                       "wake_notification");
   221 }
   223 } } }
   226 static bool
   227 IsBackgroundSessionClosedStartup()
   228 {
   229   int argc;
   230   LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc);
   231   bool backgroundSessionClosed = argc > 1 && !wcsicmp(argv[1], L"-BackgroundSessionClosed");
   232   LocalFree(argv);
   233   return backgroundSessionClosed;
   234 }
   236 bool
   237 XRE_MetroCoreApplicationRun()
   238 {
   239   HRESULT hr;
   240   LogThread();
   242   using namespace mozilla::widget::winrt;
   244   sMetroApp = Make<MetroApp>();
   246   HStringReference className(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication);
   247   hr = GetActivationFactory(className.Get(), sCoreApp.GetAddressOf());
   248   if (FAILED(hr)) {
   249     LogHRESULT(hr);
   250     return false;
   251   }
   253   // Perform any cleanup for unclean shutdowns here, such as when the background session
   254   // is closed via the appbar on the left when outside of Metro.  Windows restarts the
   255   // process solely for cleanup reasons.
   256   if (IsBackgroundSessionClosedStartup() && SUCCEEDED(XRE_metroStartup(false))) {
   258     // Whether or  not to use sessionstore depends on if the bak exists.  Since host process
   259     // shutdown isn't a crash we shouldn't restore sessionstore.
   260     nsCOMPtr<nsIFile> sessionBAK;
   261     if (NS_FAILED(NS_GetSpecialDirectory("ProfDS", getter_AddRefs(sessionBAK)))) {
   262       return false;
   263     }
   265     sessionBAK->AppendNative(nsDependentCString("sessionstore.bak"));
   266     bool exists;
   267     if (NS_SUCCEEDED(sessionBAK->Exists(&exists)) && exists) {
   268       sessionBAK->Remove(false);
   269     }
   270     return false;
   271   }
   273   hr = sCoreApp->Run(sMetroApp.Get());
   275   WinUtils::Log("Exiting CoreApplication::Run");
   277   sCoreApp = nullptr;
   278   sMetroApp = nullptr;
   280   return true;
   281 }

mercurial