Thu, 15 Jan 2015 15:59:08 +0100
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 }