Home | History | Annotate | Download | only in WinLauncher
      1 /*
      2  * Copyright (C) 2006, 2008 Apple Computer, Inc.  All rights reserved.
      3  * Copyright (C) 2009 Brent Fulgha.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include "stdafx.h"
     28 #include "WinLauncher.h"
     29 #include <WebKit/WebKitCOMAPI.h>
     30 
     31 #include <commctrl.h>
     32 #include <commdlg.h>
     33 #include <objbase.h>
     34 #include <shlwapi.h>
     35 #include <wininet.h>
     36 
     37 #include "PrintWebUIDelegate.h"
     38 
     39 #define MAX_LOADSTRING 100
     40 #define URLBAR_HEIGHT  24
     41 
     42 // Global Variables:
     43 HINSTANCE hInst;                                // current instance
     44 HWND hMainWnd;
     45 HWND hURLBarWnd;
     46 long DefEditProc;
     47 IWebView* gWebView = 0;
     48 HWND gViewWindow = 0;
     49 WinLauncherWebHost* gWebHost = 0;
     50 PrintWebUIDelegate* gPrintDelegate = 0;
     51 TCHAR szTitle[MAX_LOADSTRING];                    // The title bar text
     52 TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name
     53 
     54 // Forward declarations of functions included in this code module:
     55 ATOM                MyRegisterClass(HINSTANCE hInstance);
     56 BOOL                InitInstance(HINSTANCE, int);
     57 LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
     58 INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
     59 LRESULT CALLBACK    MyEditProc(HWND, UINT, WPARAM, LPARAM);
     60 
     61 static void loadURL(BSTR urlBStr);
     62 
     63 HRESULT WinLauncherWebHost::updateAddressBar(IWebView* webView)
     64 {
     65     IWebFrame* mainFrame = 0;
     66     IWebDataSource* dataSource = 0;
     67     IWebMutableURLRequest* request = 0;
     68     BSTR frameURL = 0;
     69 
     70     HRESULT hr = S_OK;
     71 
     72     hr = webView->mainFrame(&mainFrame);
     73     if (FAILED(hr))
     74         goto exit;
     75 
     76     hr = mainFrame->dataSource(&dataSource);
     77     if (FAILED(hr) || !dataSource)
     78         hr = mainFrame->provisionalDataSource(&dataSource);
     79     if (FAILED(hr) || !dataSource)
     80         goto exit;
     81 
     82     hr = dataSource->request(&request);
     83     if (FAILED(hr) || !request)
     84         goto exit;
     85 
     86     hr = request->mainDocumentURL(&frameURL);
     87     if (FAILED(hr))
     88         goto exit;
     89 
     90     SendMessage(hURLBarWnd, (UINT)WM_SETTEXT, 0, (LPARAM)frameURL);
     91 
     92 exit:
     93     if (mainFrame)
     94         mainFrame->Release();
     95     if (dataSource)
     96         dataSource->Release();
     97     if (request)
     98         request->Release();
     99     SysFreeString(frameURL);
    100     return 0;
    101 }
    102 
    103 HRESULT STDMETHODCALLTYPE WinLauncherWebHost::QueryInterface(REFIID riid, void** ppvObject)
    104 {
    105     *ppvObject = 0;
    106     if (IsEqualGUID(riid, IID_IUnknown))
    107         *ppvObject = static_cast<IWebFrameLoadDelegate*>(this);
    108     else if (IsEqualGUID(riid, IID_IWebFrameLoadDelegate))
    109         *ppvObject = static_cast<IWebFrameLoadDelegate*>(this);
    110     else
    111         return E_NOINTERFACE;
    112 
    113     AddRef();
    114     return S_OK;
    115 }
    116 
    117 ULONG STDMETHODCALLTYPE WinLauncherWebHost::AddRef(void)
    118 {
    119     return ++m_refCount;
    120 }
    121 
    122 ULONG STDMETHODCALLTYPE WinLauncherWebHost::Release(void)
    123 {
    124     ULONG newRef = --m_refCount;
    125     if (!newRef)
    126         delete(this);
    127 
    128     return newRef;
    129 }
    130 
    131 static void resizeSubViews()
    132 {
    133     RECT rcClient;
    134     GetClientRect(hMainWnd, &rcClient);
    135     MoveWindow(hURLBarWnd, 0, 0, rcClient.right, URLBAR_HEIGHT, TRUE);
    136     MoveWindow(gViewWindow, 0, URLBAR_HEIGHT, rcClient.right, rcClient.bottom - URLBAR_HEIGHT, TRUE);
    137 }
    138 
    139 int APIENTRY _tWinMain(HINSTANCE hInstance,
    140                      HINSTANCE hPrevInstance,
    141                      LPTSTR    lpCmdLine,
    142                      int       nCmdShow)
    143 {
    144 #ifdef _CRTDBG_MAP_ALLOC
    145     _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
    146     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
    147 #endif
    148 
    149     UNREFERENCED_PARAMETER(hPrevInstance);
    150     UNREFERENCED_PARAMETER(lpCmdLine);
    151 
    152      // TODO: Place code here.
    153     MSG msg = {0};
    154     HACCEL hAccelTable;
    155 
    156     INITCOMMONCONTROLSEX InitCtrlEx;
    157 
    158     InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
    159     InitCtrlEx.dwICC  = 0x00004000; //ICC_STANDARD_CLASSES;
    160     InitCommonControlsEx(&InitCtrlEx);
    161 
    162     // Initialize global strings
    163     LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    164     LoadString(hInstance, IDC_WINLAUNCHER, szWindowClass, MAX_LOADSTRING);
    165     MyRegisterClass(hInstance);
    166 
    167     // Perform application initialization:
    168     if (!InitInstance (hInstance, nCmdShow))
    169         return FALSE;
    170 
    171     // Init COM
    172     OleInitialize(NULL);
    173 
    174     hURLBarWnd = CreateWindow(L"EDIT", 0,
    175                         WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL,
    176                         0, 0, 0, 0,
    177                         hMainWnd,
    178                         0,
    179                         hInstance, 0);
    180 
    181     DefEditProc = GetWindowLong(hURLBarWnd, GWL_WNDPROC);
    182     SetWindowLong(hURLBarWnd, GWL_WNDPROC,(long)MyEditProc);
    183     SetFocus(hURLBarWnd);
    184 
    185     HRESULT hr = WebKitCreateInstance(CLSID_WebView, 0, IID_IWebView, (void**)&gWebView);
    186     if (FAILED(hr))
    187         goto exit;
    188 
    189     gWebHost = new WinLauncherWebHost();
    190     gWebHost->AddRef();
    191     hr = gWebView->setFrameLoadDelegate(gWebHost);
    192     if (FAILED(hr))
    193         goto exit;
    194 
    195     gPrintDelegate = new PrintWebUIDelegate;
    196     gPrintDelegate->AddRef();
    197     hr = gWebView->setUIDelegate(gPrintDelegate);
    198     if (FAILED (hr))
    199         goto exit;
    200 
    201     hr = gWebView->setHostWindow((OLE_HANDLE) hMainWnd);
    202     if (FAILED(hr))
    203         goto exit;
    204 
    205     RECT clientRect;
    206     GetClientRect(hMainWnd, &clientRect);
    207     hr = gWebView->initWithFrame(clientRect, 0, 0);
    208     if (FAILED(hr))
    209         goto exit;
    210 
    211     IWebFrame* frame;
    212     hr = gWebView->mainFrame(&frame);
    213     if (FAILED(hr))
    214         goto exit;
    215 
    216     static BSTR defaultHTML = SysAllocString(TEXT("<p style=\"background-color: #00FF00\">Testing</p><img src=\"http://webkit.org/images/icon-gold.png\" alt=\"Face\"><div style=\"border: solid blue\" contenteditable=\"true\">div with blue border</div><ul><li>foo<li>bar<li>baz</ul>"));
    217     frame->loadHTMLString(defaultHTML, 0);
    218     frame->Release();
    219 
    220     IWebViewPrivate* viewExt;
    221     hr = gWebView->QueryInterface(IID_IWebViewPrivate, (void**)&viewExt);
    222     if (FAILED(hr))
    223         goto exit;
    224 
    225     hr = viewExt->viewWindow((OLE_HANDLE*) &gViewWindow);
    226     viewExt->Release();
    227     if (FAILED(hr) || !gViewWindow)
    228         goto exit;
    229 
    230     resizeSubViews();
    231 
    232     ShowWindow(gViewWindow, nCmdShow);
    233     UpdateWindow(gViewWindow);
    234 
    235     hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINLAUNCHER));
    236 
    237     // Main message loop:
    238     while (GetMessage(&msg, NULL, 0, 0)) {
    239         if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
    240             TranslateMessage(&msg);
    241             DispatchMessage(&msg);
    242         }
    243     }
    244 
    245 exit:
    246     gPrintDelegate->Release();
    247     gWebView->Release();
    248     shutDownWebKit();
    249 #ifdef _CRTDBG_MAP_ALLOC
    250     _CrtDumpMemoryLeaks();
    251 #endif
    252 
    253     // Shut down COM.
    254     OleUninitialize();
    255 
    256     return static_cast<int>(msg.wParam);
    257 }
    258 
    259 ATOM MyRegisterClass(HINSTANCE hInstance)
    260 {
    261     WNDCLASSEX wcex;
    262 
    263     wcex.cbSize = sizeof(WNDCLASSEX);
    264 
    265     wcex.style          = CS_HREDRAW | CS_VREDRAW;
    266     wcex.lpfnWndProc    = WndProc;
    267     wcex.cbClsExtra     = 0;
    268     wcex.cbWndExtra     = 0;
    269     wcex.hInstance      = hInstance;
    270     wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINLAUNCHER));
    271     wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    272     wcex.hbrBackground  = 0;
    273     wcex.lpszMenuName   = MAKEINTRESOURCE(IDC_WINLAUNCHER);
    274     wcex.lpszClassName  = szWindowClass;
    275     wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    276 
    277     return RegisterClassEx(&wcex);
    278 }
    279 
    280 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    281 {
    282    hInst = hInstance; // Store instance handle in our global variable
    283 
    284    hMainWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
    285       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
    286 
    287    if (!hMainWnd)
    288       return FALSE;
    289 
    290    ShowWindow(hMainWnd, nCmdShow);
    291    UpdateWindow(hMainWnd);
    292 
    293    return TRUE;
    294 }
    295 
    296 static BOOL CALLBACK AbortProc(HDC hDC, int Error)
    297 {
    298     MSG msg;
    299     while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
    300         ::TranslateMessage(&msg);
    301         ::DispatchMessage(&msg);
    302     }
    303 
    304     return TRUE;
    305 }
    306 
    307 static HDC getPrinterDC()
    308 {
    309     PRINTDLG pdlg;
    310     memset(&pdlg, 0, sizeof(PRINTDLG));
    311     pdlg.lStructSize = sizeof(PRINTDLG);
    312     pdlg.Flags = PD_PRINTSETUP | PD_RETURNDC;
    313 
    314     ::PrintDlg(&pdlg);
    315 
    316     return pdlg.hDC;
    317 }
    318 
    319 static void initDocStruct(DOCINFO* di, TCHAR* docname)
    320 {
    321     memset(di, 0, sizeof(DOCINFO));
    322     di->cbSize = sizeof(DOCINFO);
    323     di->lpszDocName = docname;
    324 }
    325 
    326 void PrintView(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    327 {
    328     HDC printDC = getPrinterDC();
    329     if (!printDC) {
    330         ::MessageBoxW(0, L"Error creating printing DC", L"Error", MB_APPLMODAL | MB_OK);
    331         return;
    332     }
    333 
    334     if (::SetAbortProc(printDC, AbortProc) == SP_ERROR) {
    335         ::MessageBoxW(0, L"Error setting up AbortProc", L"Error", MB_APPLMODAL | MB_OK);
    336         return;
    337     }
    338 
    339     IWebFrame* frame = 0;
    340     IWebFramePrivate* framePrivate = 0;
    341     if (FAILED(gWebView->mainFrame(&frame)))
    342         goto exit;
    343 
    344     if (FAILED(frame->QueryInterface(&framePrivate)))
    345         goto exit;
    346 
    347     framePrivate->setInPrintingMode(TRUE, printDC);
    348 
    349     UINT pageCount = 0;
    350     framePrivate->getPrintedPageCount(printDC, &pageCount);
    351 
    352     DOCINFO di;
    353     initDocStruct(&di, L"WebKit Doc");
    354     ::StartDoc(printDC, &di);
    355 
    356     // FIXME: Need CoreGraphics implementation
    357     void* graphicsContext = 0;
    358     for (size_t page = 1; page <= pageCount; ++page) {
    359         ::StartPage(printDC);
    360         framePrivate->spoolPages(printDC, page, page, graphicsContext);
    361         ::EndPage(printDC);
    362     }
    363 
    364     framePrivate->setInPrintingMode(FALSE, printDC);
    365 
    366     ::EndDoc(printDC);
    367     ::DeleteDC(printDC);
    368 
    369 exit:
    370     if (frame)
    371         frame->Release();
    372     if (framePrivate)
    373         framePrivate->Release();
    374 }
    375 
    376 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    377 {
    378     int wmId, wmEvent;
    379 
    380     switch (message) {
    381     case WM_COMMAND:
    382         wmId    = LOWORD(wParam);
    383         wmEvent = HIWORD(wParam);
    384         // Parse the menu selections:
    385         switch (wmId) {
    386             case IDM_ABOUT:
    387                 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
    388                 break;
    389             case IDM_EXIT:
    390                 DestroyWindow(hWnd);
    391                 break;
    392             case IDM_PRINT:
    393                 PrintView(hWnd, message, wParam, lParam);
    394                 break;
    395             default:
    396                 return DefWindowProc(hWnd, message, wParam, lParam);
    397         }
    398         break;
    399     case WM_DESTROY:
    400         PostQuitMessage(0);
    401         break;
    402     case WM_SIZE:
    403         if (!gWebView)
    404             break;
    405         resizeSubViews();
    406         break;
    407     default:
    408         return DefWindowProc(hWnd, message, wParam, lParam);
    409     }
    410     return 0;
    411 }
    412 
    413 
    414 #define MAX_URL_LENGTH  1024
    415 
    416 LRESULT CALLBACK MyEditProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    417 {
    418     switch (message) {
    419         case WM_CHAR:
    420             if (wParam == 13) { // Enter Key
    421                 wchar_t strPtr[MAX_URL_LENGTH];
    422                 *((LPWORD)strPtr) = MAX_URL_LENGTH;
    423                 int strLen = SendMessage(hDlg, EM_GETLINE, 0, (LPARAM)strPtr);
    424 
    425                 BSTR bstr = SysAllocStringLen(strPtr, strLen);
    426                 loadURL(bstr);
    427                 SysFreeString(bstr);
    428 
    429                 return 0;
    430             } else
    431                 return (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hDlg,message,wParam,lParam);
    432             break;
    433         default:
    434              return (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hDlg,message,wParam,lParam);
    435         break;
    436     }
    437 }
    438 
    439 
    440 // Message handler for about box.
    441 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    442 {
    443     UNREFERENCED_PARAMETER(lParam);
    444     switch (message) {
    445     case WM_INITDIALOG:
    446         return (INT_PTR)TRUE;
    447 
    448     case WM_COMMAND:
    449         if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
    450             EndDialog(hDlg, LOWORD(wParam));
    451             return (INT_PTR)TRUE;
    452         }
    453         break;
    454     }
    455     return (INT_PTR)FALSE;
    456 }
    457 
    458 static void loadURL(BSTR urlBStr)
    459 {
    460     IWebFrame* frame = 0;
    461     IWebMutableURLRequest* request = 0;
    462 
    463     static BSTR methodBStr = SysAllocString(TEXT("GET"));
    464 
    465     if (urlBStr && urlBStr[0] && (PathFileExists(urlBStr) || PathIsUNC(urlBStr))) {
    466         TCHAR fileURL[INTERNET_MAX_URL_LENGTH];
    467         DWORD fileURLLength = sizeof(fileURL)/sizeof(fileURL[0]);
    468 
    469         if (SUCCEEDED(UrlCreateFromPath(urlBStr, fileURL, &fileURLLength, 0)))
    470             SysReAllocString(&urlBStr, fileURL);
    471     }
    472 
    473     HRESULT hr = gWebView->mainFrame(&frame);
    474     if (FAILED(hr))
    475         goto exit;
    476 
    477     hr = WebKitCreateInstance(CLSID_WebMutableURLRequest, 0, IID_IWebMutableURLRequest, (void**)&request);
    478     if (FAILED(hr))
    479         goto exit;
    480 
    481     hr = request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 60);
    482     if (FAILED(hr))
    483         goto exit;
    484 
    485     hr = request->setHTTPMethod(methodBStr);
    486     if (FAILED(hr))
    487         goto exit;
    488 
    489     hr = frame->loadRequest(request);
    490     if (FAILED(hr))
    491         goto exit;
    492 
    493     SetFocus(gViewWindow);
    494 
    495 exit:
    496     if (frame)
    497         frame->Release();
    498     if (request)
    499         request->Release();
    500 }
    501