forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			127 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
/*
 | 
						|
 * Windows widget support for event loop instrumentation.
 | 
						|
 * See toolkit/xre/EventTracer.cpp for more details.
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <windows.h>
 | 
						|
 | 
						|
#include "mozilla/RefPtr.h"
 | 
						|
#include "mozilla/WidgetTraceEvent.h"
 | 
						|
#include "nsAppShellCID.h"
 | 
						|
#include "nsComponentManagerUtils.h"
 | 
						|
#include "nsCOMPtr.h"
 | 
						|
#include "nsIAppShellService.h"
 | 
						|
#include "nsIBaseWindow.h"
 | 
						|
#include "nsIDocShell.h"
 | 
						|
#include "nsISupportsImpl.h"
 | 
						|
#include "nsIWidget.h"
 | 
						|
#include "nsIXULWindow.h"
 | 
						|
#include "nsServiceManagerUtils.h"
 | 
						|
#include "nsThreadUtils.h"
 | 
						|
#include "nsWindowDefs.h"
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
// Used for signaling the background thread from the main thread.
 | 
						|
HANDLE sEventHandle = nullptr;
 | 
						|
 | 
						|
// We need a runnable in order to find the hidden window on the main
 | 
						|
// thread.
 | 
						|
class HWNDGetter : public mozilla::Runnable {
 | 
						|
public:
 | 
						|
  HWNDGetter() : Runnable("HWNDGetter"), hidden_window_hwnd(nullptr) {}
 | 
						|
 | 
						|
  HWND hidden_window_hwnd;
 | 
						|
 | 
						|
  NS_IMETHOD Run() override {
 | 
						|
    // Jump through some hoops to locate the hidden window.
 | 
						|
    nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
 | 
						|
    nsCOMPtr<nsIXULWindow> hiddenWindow;
 | 
						|
 | 
						|
    nsresult rv = appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
 | 
						|
    if (NS_FAILED(rv)) {
 | 
						|
      return rv;
 | 
						|
    }
 | 
						|
 | 
						|
    nsCOMPtr<nsIDocShell> docShell;
 | 
						|
    rv = hiddenWindow->GetDocShell(getter_AddRefs(docShell));
 | 
						|
    if (NS_FAILED(rv) || !docShell) {
 | 
						|
      return rv;
 | 
						|
    }
 | 
						|
 | 
						|
    nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(docShell));
 | 
						|
 | 
						|
    if (!baseWindow)
 | 
						|
      return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
    nsCOMPtr<nsIWidget> widget;
 | 
						|
    baseWindow->GetMainWidget(getter_AddRefs(widget));
 | 
						|
 | 
						|
    if (!widget)
 | 
						|
      return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
    hidden_window_hwnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW);
 | 
						|
 | 
						|
    return NS_OK;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
HWND GetHiddenWindowHWND()
 | 
						|
{
 | 
						|
  // Need to dispatch this to the main thread because plenty of
 | 
						|
  // the things it wants to access are main-thread-only.
 | 
						|
  RefPtr<HWNDGetter> getter = new HWNDGetter();
 | 
						|
  NS_DispatchToMainThread(getter, NS_DISPATCH_SYNC);
 | 
						|
  return getter->hidden_window_hwnd;
 | 
						|
}
 | 
						|
 | 
						|
} // namespace
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
 | 
						|
bool InitWidgetTracing()
 | 
						|
{
 | 
						|
  sEventHandle = CreateEventW(nullptr, FALSE, FALSE, nullptr);
 | 
						|
  return sEventHandle != nullptr;
 | 
						|
}
 | 
						|
 | 
						|
void CleanUpWidgetTracing()
 | 
						|
{
 | 
						|
  CloseHandle(sEventHandle);
 | 
						|
  sEventHandle = nullptr;
 | 
						|
}
 | 
						|
 | 
						|
// This function is called from the main (UI) thread.
 | 
						|
void SignalTracerThread()
 | 
						|
{
 | 
						|
  if (sEventHandle != nullptr)
 | 
						|
    SetEvent(sEventHandle);
 | 
						|
}
 | 
						|
 | 
						|
// This function is called from the background tracer thread.
 | 
						|
bool FireAndWaitForTracerEvent()
 | 
						|
{
 | 
						|
  MOZ_ASSERT(sEventHandle, "Tracing not initialized!");
 | 
						|
 | 
						|
  // First, try to find the hidden window.
 | 
						|
  static HWND hidden_window = nullptr;
 | 
						|
  if (hidden_window == nullptr) {
 | 
						|
    hidden_window = GetHiddenWindowHWND();
 | 
						|
  }
 | 
						|
 | 
						|
  if (hidden_window == nullptr)
 | 
						|
    return false;
 | 
						|
 | 
						|
  // Post the tracer message into the hidden window's message queue,
 | 
						|
  // and then block until it's processed.
 | 
						|
  PostMessage(hidden_window, MOZ_WM_TRACE, 0, 0);
 | 
						|
  WaitForSingleObject(sEventHandle, INFINITE);
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
} // namespace mozilla
 |