1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/windows/WidgetTraceEvent.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,132 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * Windows widget support for event loop instrumentation. 1.10 + * See toolkit/xre/EventTracer.cpp for more details. 1.11 + */ 1.12 + 1.13 +#include <stdio.h> 1.14 +#include <windows.h> 1.15 + 1.16 +#include "mozilla/WidgetTraceEvent.h" 1.17 +#include "nsAppShellCID.h" 1.18 +#include "nsComponentManagerUtils.h" 1.19 +#include "nsCOMPtr.h" 1.20 +#include "nsIAppShellService.h" 1.21 +#include "nsIBaseWindow.h" 1.22 +#include "nsIDocShell.h" 1.23 +#include "nsISupportsImpl.h" 1.24 +#include "nsIWidget.h" 1.25 +#include "nsIXULWindow.h" 1.26 +#include "nsAutoPtr.h" 1.27 +#include "nsServiceManagerUtils.h" 1.28 +#include "nsThreadUtils.h" 1.29 +#include "nsWindowDefs.h" 1.30 + 1.31 +namespace { 1.32 + 1.33 +// Used for signaling the background thread from the main thread. 1.34 +HANDLE sEventHandle = nullptr; 1.35 + 1.36 +// We need a runnable in order to find the hidden window on the main 1.37 +// thread. 1.38 +class HWNDGetter : public nsRunnable { 1.39 +public: 1.40 + HWNDGetter() : hidden_window_hwnd(nullptr) { 1.41 + MOZ_COUNT_CTOR(HWNDGetter); 1.42 + } 1.43 + ~HWNDGetter() { 1.44 + MOZ_COUNT_DTOR(HWNDGetter); 1.45 + } 1.46 + 1.47 + HWND hidden_window_hwnd; 1.48 + 1.49 + NS_IMETHOD Run() { 1.50 + // Jump through some hoops to locate the hidden window. 1.51 + nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); 1.52 + nsCOMPtr<nsIXULWindow> hiddenWindow; 1.53 + 1.54 + nsresult rv = appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow)); 1.55 + if (NS_FAILED(rv)) { 1.56 + return rv; 1.57 + } 1.58 + 1.59 + nsCOMPtr<nsIDocShell> docShell; 1.60 + rv = hiddenWindow->GetDocShell(getter_AddRefs(docShell)); 1.61 + if (NS_FAILED(rv) || !docShell) { 1.62 + return rv; 1.63 + } 1.64 + 1.65 + nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(docShell)); 1.66 + 1.67 + if (!baseWindow) 1.68 + return NS_ERROR_FAILURE; 1.69 + 1.70 + nsCOMPtr<nsIWidget> widget; 1.71 + baseWindow->GetMainWidget(getter_AddRefs(widget)); 1.72 + 1.73 + if (!widget) 1.74 + return NS_ERROR_FAILURE; 1.75 + 1.76 + hidden_window_hwnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW); 1.77 + 1.78 + return NS_OK; 1.79 + } 1.80 +}; 1.81 + 1.82 +HWND GetHiddenWindowHWND() 1.83 +{ 1.84 + // Need to dispatch this to the main thread because plenty of 1.85 + // the things it wants to access are main-thread-only. 1.86 + nsRefPtr<HWNDGetter> getter = new HWNDGetter(); 1.87 + NS_DispatchToMainThread(getter, NS_DISPATCH_SYNC); 1.88 + return getter->hidden_window_hwnd; 1.89 +} 1.90 + 1.91 +} // namespace 1.92 + 1.93 +namespace mozilla { 1.94 + 1.95 +bool InitWidgetTracing() 1.96 +{ 1.97 + sEventHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr); 1.98 + return sEventHandle != nullptr; 1.99 +} 1.100 + 1.101 +void CleanUpWidgetTracing() 1.102 +{ 1.103 + CloseHandle(sEventHandle); 1.104 + sEventHandle = nullptr; 1.105 +} 1.106 + 1.107 +// This function is called from the main (UI) thread. 1.108 +void SignalTracerThread() 1.109 +{ 1.110 + if (sEventHandle != nullptr) 1.111 + SetEvent(sEventHandle); 1.112 +} 1.113 + 1.114 +// This function is called from the background tracer thread. 1.115 +bool FireAndWaitForTracerEvent() 1.116 +{ 1.117 + NS_ABORT_IF_FALSE(sEventHandle, "Tracing not initialized!"); 1.118 + 1.119 + // First, try to find the hidden window. 1.120 + static HWND hidden_window = nullptr; 1.121 + if (hidden_window == nullptr) { 1.122 + hidden_window = GetHiddenWindowHWND(); 1.123 + } 1.124 + 1.125 + if (hidden_window == nullptr) 1.126 + return false; 1.127 + 1.128 + // Post the tracer message into the hidden window's message queue, 1.129 + // and then block until it's processed. 1.130 + PostMessage(hidden_window, MOZ_WM_TRACE, 0, 0); 1.131 + WaitForSingleObject(sEventHandle, INFINITE); 1.132 + return true; 1.133 +} 1.134 + 1.135 +} // namespace mozilla