1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/windows/winrt/MetroApp.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,282 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "MetroApp.h" 1.10 +#include "MetroWidget.h" 1.11 +#include "mozilla/IOInterposer.h" 1.12 +#include "mozilla/widget/AudioSession.h" 1.13 +#include "nsIRunnable.h" 1.14 +#include "MetroUtils.h" 1.15 +#include "MetroAppShell.h" 1.16 +#include "nsICommandLineRunner.h" 1.17 +#include "FrameworkView.h" 1.18 +#include "nsAppDirectoryServiceDefs.h" 1.19 +#include "GeckoProfiler.h" 1.20 +#include <shellapi.h> 1.21 + 1.22 +using namespace ABI::Windows::ApplicationModel; 1.23 +using namespace ABI::Windows::ApplicationModel::Core; 1.24 +using namespace ABI::Windows::UI::Core; 1.25 +using namespace ABI::Windows::System; 1.26 +using namespace ABI::Windows::Foundation; 1.27 +using namespace Microsoft::WRL; 1.28 +using namespace Microsoft::WRL::Wrappers; 1.29 +using namespace mozilla::widget; 1.30 + 1.31 +// Metro specific XRE methods we call from here on an 1.32 +// appropriate thread. 1.33 +extern nsresult XRE_metroStartup(bool runXREMain); 1.34 +extern void XRE_metroShutdown(); 1.35 + 1.36 +static const char* gGeckoThreadName = "GeckoMain"; 1.37 + 1.38 +#ifdef PR_LOGGING 1.39 +extern PRLogModuleInfo* gWindowsLog; 1.40 +#endif 1.41 + 1.42 +namespace mozilla { 1.43 +namespace widget { 1.44 +namespace winrt { 1.45 + 1.46 +ComPtr<FrameworkView> sFrameworkView; 1.47 +ComPtr<MetroApp> sMetroApp; 1.48 +ComPtr<ICoreApplication> sCoreApp; 1.49 +bool MetroApp::sGeckoShuttingDown = false; 1.50 + 1.51 +//////////////////////////////////////////////////// 1.52 +// IFrameworkViewSource impl. 1.53 + 1.54 +// Called after CoreApplication::Run(app) 1.55 +HRESULT 1.56 +MetroApp::CreateView(ABI::Windows::ApplicationModel::Core::IFrameworkView **aViewProvider) 1.57 +{ 1.58 + // This entry point is called on the metro main thread, but the thread won't 1.59 + // be recognized as such until after Run() is called below. XPCOM has not 1.60 + // gone through startup at this point. 1.61 + 1.62 + // Note that we create the view which creates our native window for us. The 1.63 + // gecko widget gets created by gecko, and the two get hooked up later in 1.64 + // MetroWidget::Create(). 1.65 + 1.66 + LogFunction(); 1.67 + 1.68 + sFrameworkView = Make<FrameworkView>(this); 1.69 + sFrameworkView.Get()->AddRef(); 1.70 + *aViewProvider = sFrameworkView.Get(); 1.71 + return !sFrameworkView ? E_FAIL : S_OK; 1.72 +} 1.73 + 1.74 +//////////////////////////////////////////////////// 1.75 +// MetroApp impl. 1.76 + 1.77 +void 1.78 +MetroApp::Run() 1.79 +{ 1.80 + LogThread(); 1.81 + 1.82 + // Name this thread for debugging and register it with the profiler 1.83 + // and IOInterposer as the main gecko thread. 1.84 + char aLocal; 1.85 + PR_SetCurrentThreadName(gGeckoThreadName); 1.86 + profiler_register_thread(gGeckoThreadName, &aLocal); 1.87 + IOInterposer::RegisterCurrentThread(true); 1.88 + 1.89 + HRESULT hr; 1.90 + hr = sCoreApp->add_Suspending(Callback<__FIEventHandler_1_Windows__CApplicationModel__CSuspendingEventArgs_t>( 1.91 + this, &MetroApp::OnSuspending).Get(), &mSuspendEvent); 1.92 + AssertHRESULT(hr); 1.93 + 1.94 + hr = sCoreApp->add_Resuming(Callback<__FIEventHandler_1_IInspectable_t>( 1.95 + this, &MetroApp::OnResuming).Get(), &mResumeEvent); 1.96 + AssertHRESULT(hr); 1.97 + 1.98 + WinUtils::Log("Calling XRE_metroStartup."); 1.99 + nsresult rv = XRE_metroStartup(true); 1.100 + WinUtils::Log("Exiting XRE_metroStartup."); 1.101 + if (NS_FAILED(rv)) { 1.102 + WinUtils::Log("XPCOM startup initialization failed, bailing. rv=%X", rv); 1.103 + CoreExit(); 1.104 + } 1.105 +} 1.106 + 1.107 +// Free all xpcom related resources before calling the xre shutdown call. 1.108 +// Must be called on the metro main thread. Currently called from appshell. 1.109 +void 1.110 +MetroApp::Shutdown() 1.111 +{ 1.112 + LogThread(); 1.113 + 1.114 + if (sCoreApp) { 1.115 + sCoreApp->remove_Suspending(mSuspendEvent); 1.116 + sCoreApp->remove_Resuming(mResumeEvent); 1.117 + } 1.118 + 1.119 + if (sFrameworkView) { 1.120 + sFrameworkView->Shutdown(); 1.121 + } 1.122 + 1.123 + MetroApp::sGeckoShuttingDown = true; 1.124 + 1.125 + // Shut down xpcom 1.126 + XRE_metroShutdown(); 1.127 + 1.128 + // Unhook this thread from the profiler 1.129 + profiler_unregister_thread(); 1.130 +} 1.131 + 1.132 +// Request a shutdown of the application 1.133 +void 1.134 +MetroApp::CoreExit() 1.135 +{ 1.136 + LogFunction(); 1.137 + HRESULT hr; 1.138 + ComPtr<ICoreApplicationExit> coreExit; 1.139 + HStringReference className(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication); 1.140 + hr = GetActivationFactory(className.Get(), coreExit.GetAddressOf()); 1.141 + NS_ASSERTION(SUCCEEDED(hr), "Activation of ICoreApplicationExit"); 1.142 + if (SUCCEEDED(hr)) { 1.143 + coreExit->Exit(); 1.144 + } 1.145 +} 1.146 + 1.147 +void 1.148 +MetroApp::ActivateBaseView() 1.149 +{ 1.150 + if (sFrameworkView) { 1.151 + sFrameworkView->ActivateView(); 1.152 + } 1.153 +} 1.154 + 1.155 +/* 1.156 + * TBD: when we support multiple widgets, we'll need a way to sync up the view 1.157 + * created in CreateView with the widget gecko creates. Currently we only have 1.158 + * one view (sFrameworkView) and one main widget. 1.159 + */ 1.160 +void 1.161 +MetroApp::SetWidget(MetroWidget* aPtr) 1.162 +{ 1.163 + LogThread(); 1.164 + 1.165 + NS_ASSERTION(aPtr, "setting null base widget?"); 1.166 + 1.167 + // Both of these calls AddRef the ptr we pass in 1.168 + aPtr->SetView(sFrameworkView.Get()); 1.169 + sFrameworkView->SetWidget(aPtr); 1.170 +} 1.171 + 1.172 +//////////////////////////////////////////////////// 1.173 +// MetroApp events 1.174 + 1.175 +HRESULT 1.176 +MetroApp::OnSuspending(IInspectable* aSender, ISuspendingEventArgs* aArgs) 1.177 +{ 1.178 + LogThread(); 1.179 + PostSuspendResumeProcessNotification(true); 1.180 + return S_OK; 1.181 +} 1.182 + 1.183 +HRESULT 1.184 +MetroApp::OnResuming(IInspectable* aSender, IInspectable* aArgs) 1.185 +{ 1.186 + LogThread(); 1.187 + PostSuspendResumeProcessNotification(false); 1.188 + return S_OK; 1.189 +} 1.190 + 1.191 +HRESULT 1.192 +MetroApp::OnAsyncTileCreated(ABI::Windows::Foundation::IAsyncOperation<bool>* aOperation, 1.193 + AsyncStatus aStatus) 1.194 +{ 1.195 + WinUtils::Log("Async operation status: %d", aStatus); 1.196 + MetroUtils::FireObserver("metro_on_async_tile_created"); 1.197 + return S_OK; 1.198 +} 1.199 + 1.200 +// static 1.201 +void 1.202 +MetroApp::PostSuspendResumeProcessNotification(const bool aIsSuspend) 1.203 +{ 1.204 + static bool isSuspend = false; 1.205 + if (isSuspend == aIsSuspend) { 1.206 + return; 1.207 + } 1.208 + isSuspend = aIsSuspend; 1.209 + MetroUtils::FireObserver(aIsSuspend ? "suspend_process_notification" : 1.210 + "resume_process_notification"); 1.211 +} 1.212 + 1.213 +// static 1.214 +void 1.215 +MetroApp::PostSleepWakeNotification(const bool aIsSleep) 1.216 +{ 1.217 + static bool isSleep = false; 1.218 + if (isSleep == aIsSleep) { 1.219 + return; 1.220 + } 1.221 + isSleep = aIsSleep; 1.222 + MetroUtils::FireObserver(aIsSleep ? "sleep_notification" : 1.223 + "wake_notification"); 1.224 +} 1.225 + 1.226 +} } } 1.227 + 1.228 + 1.229 +static bool 1.230 +IsBackgroundSessionClosedStartup() 1.231 +{ 1.232 + int argc; 1.233 + LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc); 1.234 + bool backgroundSessionClosed = argc > 1 && !wcsicmp(argv[1], L"-BackgroundSessionClosed"); 1.235 + LocalFree(argv); 1.236 + return backgroundSessionClosed; 1.237 +} 1.238 + 1.239 +bool 1.240 +XRE_MetroCoreApplicationRun() 1.241 +{ 1.242 + HRESULT hr; 1.243 + LogThread(); 1.244 + 1.245 + using namespace mozilla::widget::winrt; 1.246 + 1.247 + sMetroApp = Make<MetroApp>(); 1.248 + 1.249 + HStringReference className(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication); 1.250 + hr = GetActivationFactory(className.Get(), sCoreApp.GetAddressOf()); 1.251 + if (FAILED(hr)) { 1.252 + LogHRESULT(hr); 1.253 + return false; 1.254 + } 1.255 + 1.256 + // Perform any cleanup for unclean shutdowns here, such as when the background session 1.257 + // is closed via the appbar on the left when outside of Metro. Windows restarts the 1.258 + // process solely for cleanup reasons. 1.259 + if (IsBackgroundSessionClosedStartup() && SUCCEEDED(XRE_metroStartup(false))) { 1.260 + 1.261 + // Whether or not to use sessionstore depends on if the bak exists. Since host process 1.262 + // shutdown isn't a crash we shouldn't restore sessionstore. 1.263 + nsCOMPtr<nsIFile> sessionBAK; 1.264 + if (NS_FAILED(NS_GetSpecialDirectory("ProfDS", getter_AddRefs(sessionBAK)))) { 1.265 + return false; 1.266 + } 1.267 + 1.268 + sessionBAK->AppendNative(nsDependentCString("sessionstore.bak")); 1.269 + bool exists; 1.270 + if (NS_SUCCEEDED(sessionBAK->Exists(&exists)) && exists) { 1.271 + sessionBAK->Remove(false); 1.272 + } 1.273 + return false; 1.274 + } 1.275 + 1.276 + hr = sCoreApp->Run(sMetroApp.Get()); 1.277 + 1.278 + WinUtils::Log("Exiting CoreApplication::Run"); 1.279 + 1.280 + sCoreApp = nullptr; 1.281 + sMetroApp = nullptr; 1.282 + 1.283 + return true; 1.284 +} 1.285 +