diff -r 000000000000 -r dd21522fd290 webengine/osswebengine/WebKitTools/Drosera/win/Drosera.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webengine/osswebengine/WebKitTools/Drosera/win/Drosera.cpp Mon Mar 30 12:54:55 2009 +0300 @@ -0,0 +1,445 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Drosera.h" + +#include "DebuggerClient.h" +#include "DebuggerDocument.h" +#include "HelperFunctions.h" +#include "resource.h" + +#include +#include +#include +#include +#include +#include + +const unsigned MAX_LOADSTRING = 100; + +TCHAR szTitle[MAX_LOADSTRING]; // The title bar text +TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name + +static const LRESULT kNotHandledResult = -1; +static LPCTSTR kDroseraPointerProp = TEXT("DroseraPointer"); +HINSTANCE Drosera::m_hInst(0); + +extern "C" BOOL InitializeCoreGraphics(); + +ATOM registerDroseraClass(HINSTANCE hInstance); +LRESULT CALLBACK droseraWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK attachWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK aboutWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +int APIENTRY _tWinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) +{ + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + MSG msg; + + InitializeCoreGraphics(); + + Drosera drosera; + + HRESULT ret = drosera.initUI(hInstance, nCmdShow); + if (FAILED(ret)) + return ret; + + HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DROSERA)); + + // Main message loop: + while (GetMessage(&msg, 0, 0, 0)) { + if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return static_cast(msg.wParam); +} + +////////////////// Setup Windows Specific Interface ////////////////// + +ATOM registerDroseraClass(HINSTANCE hInstance) +{ + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = ::droseraWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = sizeof(Drosera*); + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DROSERA)); + wcex.hCursor = LoadCursor(0, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = MAKEINTRESOURCE(IDC_DROSERA); + wcex.lpszClassName = szWindowClass; + wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); + + return RegisterClassEx(&wcex); +} + +//Processes messages for the main window. +LRESULT CALLBACK droseraWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int wmId, wmEvent; + PAINTSTRUCT ps; + HDC hdc; + + LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0); + Drosera* drosera = reinterpret_cast(longPtr); + + switch (message) { + case WM_COMMAND: + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + switch (wmId) { + case ID_HELP_ABOUT: + DialogBox(Drosera::getInst(), MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, ::aboutWndProc); + break; + case ID_FILE_ATTACH: + DialogBox(Drosera::getInst(), MAKEINTRESOURCE(IDD_ATTACH), hWnd, ::attachWndProc); + break; + case ID_FILE_EXIT: + DestroyWindow(hWnd); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + break; + case WM_SIZE: + if (!drosera) + return 0; + return drosera->webViewLoaded() ? drosera->onSize(wParam, lParam) : 0; + case WM_PAINT: + hdc = BeginPaint(hWnd, &ps); + // TODO: Add any drawing code here... + EndPaint(hWnd, &ps); + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +// Message handler for about box. +INT_PTR CALLBACK aboutWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + UNREFERENCED_PARAMETER(lParam); + switch (message) { + case WM_INITDIALOG: + return (INT_PTR)TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, LOWORD(wParam)); + return (INT_PTR)TRUE; + } + break; + } + return (INT_PTR)FALSE; +} + +// Message handler for Attach box. +INT_PTR CALLBACK attachWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + UNREFERENCED_PARAMETER(lParam); + switch (message) { + case WM_INITDIALOG: + return (INT_PTR)TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, LOWORD(wParam)); + return (INT_PTR)TRUE; + } + break; + } + return (INT_PTR)FALSE; +} + +////////////////// End Setup Windows Specific Interface ////////////////// + +Drosera::Drosera() + : m_hWnd(0) + , m_webViewLoaded(false) + , m_debuggerDocument(new DebuggerClient()) +{ +} + +HRESULT Drosera::initUI(HINSTANCE hInstance, int nCmdShow) +{ + // Initialize global strings + LoadString(hInstance, IDS_APP_TITLE, szTitle, ARRAYSIZE(szTitle)); + LoadString(hInstance, IDC_DROSERA, szWindowClass, ARRAYSIZE(szWindowClass)); + registerDroseraClass(hInstance); + + Drosera::setInst(hInstance); // Store instance handle in our local variable + + m_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hInstance, 0); + + if (!m_hWnd) + return HRESULT_FROM_WIN32(GetLastError()); + + SetLastError(0); + SetWindowLongPtr(m_hWnd, 0, reinterpret_cast(this)); + HRESULT ret = HRESULT_FROM_WIN32(GetLastError()); + if (FAILED(ret)) + return ret; + + ret = OleInitialize(0); + if (FAILED(ret)) + return ret; + + ret = CoCreateInstance(CLSID_WebView, 0, CLSCTX_ALL, IID_IWebView, (void**)&m_webView); + if (FAILED(ret)) + return ret; + + ret = m_webView->QueryInterface(IID_IWebViewPrivate, reinterpret_cast(&m_webViewPrivate)); + if (FAILED(ret)) + return ret; + + ret = m_webView->setHostWindow(reinterpret_cast(m_hWnd)); + if (FAILED(ret)) + return ret; + + ret = m_webView->setFrameLoadDelegate(this); + if (FAILED(ret)) + return ret; + + ret = m_webView->setUIDelegate(this); + if (FAILED(ret)) + return ret; + + RECT rect = {0}; + ret = m_webView->initWithFrame(rect, 0, 0); + if (FAILED(ret)) + return ret; + + HWND viewWindow; + ret = m_webViewPrivate->viewWindow(reinterpret_cast(&viewWindow)); + if (FAILED(ret)) + return ret; + + ::SetProp(viewWindow, kDroseraPointerProp, (HANDLE)this); + + COMPtr mainFrame; + ret = m_webView->mainFrame(&mainFrame); + if (FAILED(ret)) + return ret; + + COMPtr request; + ret = CoCreateInstance(CLSID_WebMutableURLRequest, 0, CLSCTX_ALL, IID_IWebMutableURLRequest, (void**)&request); + if (FAILED(ret)) + return ret; + + RetainPtr htmlURLRef(AdoptCF, ::CFBundleCopyResourceURL(::CFBundleGetBundleWithIdentifier(CFSTR("org.webkit.drosera")), CFSTR("debugger"), CFSTR("html"), CFSTR("Drosera"))); + if (!htmlURLRef) + return E_FAIL; + + CFStringRef urlStringRef = ::CFURLGetString(htmlURLRef.get()); + BSTR tempStr = cfStringToBSTR(urlStringRef); // Both initWithRUL and SysFreeString can handle 0. + ret = request->initWithURL(tempStr, WebURLRequestUseProtocolCachePolicy, 60); + SysFreeString(tempStr); + if (FAILED(ret)) + return ret; + + ret = mainFrame->loadRequest(request.get()); + if (FAILED(ret)) + return ret; + + m_webViewLoaded = true; + + // FIXME: Implement window size/position save/restore + + RECT frame; + frame.left = 60; + frame.top = 200; + frame.right = 750; + frame.bottom = 550; + ::SetWindowPos(m_hWnd, HWND_TOPMOST, frame.left, frame.top, frame.right - frame.left, frame.bottom - frame.top, 0); + ShowWindow(m_hWnd, nCmdShow); + UpdateWindow(m_hWnd); + + return 0; +} + +// IUnknown ------------------------------ +HRESULT STDMETHODCALLTYPE Drosera::QueryInterface(REFIID riid, void** ppvObject) // how to cast between implemented interfaces +{ + *ppvObject = 0; + if (IsEqualGUID(riid, IID_IUnknown)) + *ppvObject = this; + else if (IsEqualGUID(riid, IID_IWebFrameLoadDelegate)) + *ppvObject = static_cast(this); + else if (IsEqualGUID(riid, IID_IWebUIDelegate)) + *ppvObject = static_cast(this); + else + return E_NOINTERFACE; + + AddRef(); + return S_OK; +} + +ULONG STDMETHODCALLTYPE Drosera::AddRef(void) +{ // COM ref-counting isn't useful to us because we're in charge of the lifetime of the WebView. + // We use the number 2 because of some idiosycracy with COM that expects us to be referenced twice. + return 2; +} + +ULONG STDMETHODCALLTYPE Drosera::Release(void) +{ // COM ref-counting isn't useful to us because we're in charge of the lifetime of the WebView. + // We use the number 2 because of some idiosycracy with COM that expects us to be referenced twice. + return 2; +} + +// IWebFrameLoadDelegate ------------------------------ +HRESULT STDMETHODCALLTYPE Drosera::didFinishLoadForFrame( + /* [in] */ IWebView* m_webView, + /* [in] */ IWebFrame* frame) +{ + // note: this is Drosera's own WebView, not the one in the app that we are attached to. + m_webViewLoaded = true; + + COMPtr mainFrame; + HRESULT hr = m_webView->mainFrame(&mainFrame); + if (FAILED(hr)) + return hr; + + if (mainFrame != frame) // FIXME Replace below with X Drosera + return S_OK; + + COMPtr document; + hr = mainFrame->DOMDocument(&document); + if (FAILED(hr)) + return hr; + + COMPtr htmlDocument; + hr = document->QueryInterface(IID_IDOMHTMLDocument, reinterpret_cast(&htmlDocument)); + if (FAILED(hr)) + return hr; + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE Drosera::windowScriptObjectAvailable( + /* [in] */ IWebView*, + /* [in] */ JSContextRef context, + /* [in] */ JSObjectRef windowObject) +{ + + JSValueRef exception = 0; + m_debuggerDocument.windowScriptObjectAvailable(context, windowObject, &exception); + if (exception) + return S_FALSE; + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE Drosera::runJavaScriptAlertPanelWithMessage( // For debugging purposes + /* [in] */ IWebView*, + /* [in] */ BSTR message) +{ +#ifndef NDEBUG + fwprintf(stderr, L"%s\n", message ? message : L""); +#else + (void)message; +#endif + return S_OK; +} + +LRESULT Drosera::onSize(WPARAM, LPARAM) +{ + if (!m_webViewPrivate) + return 0; + + RECT clientRect = {0}; + ::GetClientRect(m_hWnd, &clientRect); + + HWND viewWindow; + if (FAILED(m_webViewPrivate->viewWindow(reinterpret_cast(&viewWindow)))) + return 0; + + // FIXME should this be the height-command bars height? + ::SetWindowPos(viewWindow, 0, clientRect.left, clientRect.top, clientRect.right - clientRect.left, clientRect.bottom - clientRect.top, SWP_NOZORDER); + return 0; +} + +void Drosera::initWithServerName(std::wstring* /*serverName*/) +{ +// m_debuggerDocument = new DebuggerDocument(m_debuggerClient); + + //if ((self = [super init])) + // [self switchToServerNamed:serverName]; + //return self; +} + +void Drosera::switchToServerNamed(std::wstring* /*server*/) +{ + //if (server) { + // [[NSNotificationCenter defaultCenter] removeObserver:self name:NSConnectionDidDieNotification object:[(NSDistantObject *)server connectionForProxy]]; + // if ([[(NSDistantObject *)server connectionForProxy] isValid]) { + // [server removeListener:self]; + // [self resume]; + // } + //} + + //id old = server; + //server = ([name length] ? [[NSConnection rootProxyForConnectionWithRegisteredName:name host:nil] retain] : nil); + //[old release]; + + //old = currentServerName; + //currentServerName = [name copy]; + //[old release]; + + //if (server) { + // @try { + // [(NSDistantObject *)server setProtocolForProxy:@protocol(WebScriptDebugServer)]; + // [server addListener:self]; + // } @catch (NSException *exception) { + // [currentServerName release]; + // currentServerName = nil; + // [server release]; + // server = nil; + // } + + // if (server) + // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(serverConnectionDidDie:) name:NSConnectionDidDieNotification object:[(NSDistantObject *)server connectionForProxy]]; + //} +} \ No newline at end of file