c32ab9026e70958feffba4520b71fed252b52f17
[WebKit-https.git] / Tools / WinLauncher / WinLauncher.cpp
1 /*
2  * Copyright (C) 2006, 2008, 2013, 2014 Apple Inc.  All rights reserved.
3  * Copyright (C) 2009, 2011 Brent Fulgham.  All rights reserved.
4  * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
5  * Copyright (C) 2013 Alex Christensen. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
27  */
28
29 #include "stdafx.h"
30 #include "WinLauncher.h"
31
32 #include "DOMDefaultImpl.h"
33 #include "WinLauncherLibResource.h"
34 #include "WinLauncherReplace.h"
35 #include <WebKit/WebKitCOMAPI.h>
36 #include <wtf/ExportMacros.h>
37 #include <wtf/Platform.h>
38
39 #if USE(CF)
40 #include <CoreFoundation/CFRunLoop.h>
41 #endif
42
43 #include <algorithm>
44 #include <cassert>
45 #include <functional>
46 #include <memory>
47 #include <string>
48 #include <vector>
49
50 static const int maxHistorySize = 10;
51
52 typedef _com_ptr_t<_com_IIID<IWebMutableURLRequest, &__uuidof(IWebMutableURLRequest)>> IWebMutableURLRequestPtr;
53
54 WinLauncher::WinLauncher(HWND mainWnd, HWND urlBarWnd, bool useLayeredWebView, bool pageLoadTesting)
55     : m_hMainWnd(mainWnd)
56     , m_hURLBarWnd(urlBarWnd)
57     , m_useLayeredWebView(useLayeredWebView)
58     , m_pageLoadTestClient(std::make_unique<PageLoadTestClient>(this, pageLoadTesting))
59 {
60 }
61
62 HRESULT WinLauncher::init()
63 {
64     HRESULT hr = WebKitCreateInstance(CLSID_WebView, 0, IID_IWebView, reinterpret_cast<void**>(&m_webView.GetInterfacePtr()));
65     if (FAILED(hr))
66         return hr;
67
68     hr = m_webView->QueryInterface(IID_IWebViewPrivate, reinterpret_cast<void**>(&m_webViewPrivate.GetInterfacePtr()));
69     if (FAILED(hr))
70         return hr;
71
72     hr = WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(m_webHistory), reinterpret_cast<void**>(&m_webHistory.GetInterfacePtr()));
73     if (FAILED(hr))
74         return hr;
75
76     hr = WebKitCreateInstance(CLSID_WebCoreStatistics, 0, __uuidof(m_statistics), reinterpret_cast<void**>(&m_statistics.GetInterfacePtr()));
77     if (FAILED(hr))
78         return hr;
79
80     hr = WebKitCreateInstance(CLSID_WebCache, 0, __uuidof(m_webCache), reinterpret_cast<void**>(&m_webCache.GetInterfacePtr()));
81
82     return hr;
83 }
84
85 HRESULT WinLauncher::prepareViews(HWND mainWnd, const RECT& clientRect, const BSTR& requestedURL, HWND& viewHwnd)
86 {
87     if (!m_webView)
88         return E_FAIL;
89
90     HRESULT hr = m_webView->setHostWindow(mainWnd);
91     if (FAILED(hr))
92         return hr;
93
94     hr = m_webView->initWithFrame(clientRect, 0, 0);
95     if (FAILED(hr))
96         return hr;
97
98     if (!requestedURL) {
99         IWebFramePtr frame;
100         hr = m_webView->mainFrame(&frame.GetInterfacePtr());
101         if (FAILED(hr))
102             return hr;
103
104         frame->loadHTMLString(_bstr_t(defaultHTML).GetBSTR(), 0);
105     }
106
107     hr = m_webViewPrivate->setTransparent(m_useLayeredWebView);
108     if (FAILED(hr))
109         return hr;
110
111     hr = m_webViewPrivate->setUsesLayeredWindow(m_useLayeredWebView);
112     if (FAILED(hr))
113         return hr;
114
115     hr = m_webViewPrivate->viewWindow(&viewHwnd);
116
117     return hr;
118 }
119
120 HRESULT WinLauncher::setFrameLoadDelegate(IWebFrameLoadDelegate* frameLoadDelegate)
121 {
122     m_frameLoadDelegate = frameLoadDelegate;
123     return m_webView->setFrameLoadDelegate(frameLoadDelegate);
124 }
125
126 HRESULT WinLauncher::setFrameLoadDelegatePrivate(IWebFrameLoadDelegatePrivate* frameLoadDelegatePrivate)
127 {
128     return m_webViewPrivate->setFrameLoadDelegatePrivate(frameLoadDelegatePrivate);
129 }
130
131 HRESULT WinLauncher::setUIDelegate(IWebUIDelegate* uiDelegate)
132 {
133     m_uiDelegate = uiDelegate;
134     return m_webView->setUIDelegate(uiDelegate);
135 }
136
137 HRESULT WinLauncher::setAccessibilityDelegate(IAccessibilityDelegate* accessibilityDelegate)
138 {
139     m_accessibilityDelegate = accessibilityDelegate;
140     return m_webView->setAccessibilityDelegate(accessibilityDelegate);
141 }
142
143
144 HRESULT WinLauncher::setResourceLoadDelegate(IWebResourceLoadDelegate* resourceLoadDelegate)
145 {
146     m_resourceLoadDelegate = resourceLoadDelegate;
147     return m_webView->setResourceLoadDelegate(resourceLoadDelegate);
148 }
149
150 IWebFramePtr WinLauncher::mainFrame()
151 {
152     IWebFramePtr framePtr;
153     m_webView->mainFrame(&framePtr.GetInterfacePtr());
154     return framePtr;
155 }
156
157 bool WinLauncher::seedInitialDefaultPreferences()
158 {
159     IWebPreferencesPtr tmpPreferences;
160     if (FAILED(WebKitCreateInstance(CLSID_WebPreferences, 0, IID_IWebPreferences, reinterpret_cast<void**>(&tmpPreferences.GetInterfacePtr()))))
161         return false;
162
163     if (FAILED(tmpPreferences->standardPreferences(&m_standardPreferences.GetInterfacePtr())))
164         return false;
165
166     return true;
167 }
168
169 bool WinLauncher::setToDefaultPreferences()
170 {
171     HRESULT hr = m_standardPreferences->QueryInterface(IID_IWebPreferencesPrivate, reinterpret_cast<void**>(&m_prefsPrivate.GetInterfacePtr()));
172     if (!SUCCEEDED(hr))
173         return false;
174
175 #if USE(CG)
176     m_standardPreferences->setAVFoundationEnabled(TRUE);
177     m_prefsPrivate->setAcceleratedCompositingEnabled(TRUE);
178 #endif
179
180     m_prefsPrivate->setFullScreenEnabled(TRUE);
181     m_prefsPrivate->setShowDebugBorders(FALSE);
182     m_prefsPrivate->setShowRepaintCounter(FALSE);
183
184     m_standardPreferences->setLoadsImagesAutomatically(TRUE);
185     m_prefsPrivate->setAuthorAndUserStylesEnabled(TRUE);
186     m_standardPreferences->setJavaScriptEnabled(TRUE);
187     m_prefsPrivate->setAllowUniversalAccessFromFileURLs(FALSE);
188     m_prefsPrivate->setAllowFileAccessFromFileURLs(TRUE);
189
190     m_prefsPrivate->setDeveloperExtrasEnabled(TRUE);
191
192     return true;
193 }
194
195 static void updateMenuItemForHistoryItem(HMENU menu, IWebHistoryItem& historyItem, int currentHistoryItem)
196 {
197     UINT menuID = IDM_HISTORY_LINK0 + currentHistoryItem;
198
199     MENUITEMINFO menuItemInfo = { 0 };
200     menuItemInfo.cbSize = sizeof(MENUITEMINFO);
201     menuItemInfo.fMask = MIIM_TYPE;
202     menuItemInfo.fType = MFT_STRING;
203
204     _bstr_t title;
205     historyItem.title(title.GetAddress());
206     menuItemInfo.dwTypeData = static_cast<LPWSTR>(title);
207
208     ::SetMenuItemInfo(menu, menuID, FALSE, &menuItemInfo);
209     ::EnableMenuItem(menu, menuID, MF_BYCOMMAND | MF_ENABLED);
210 }
211
212 void WinLauncher::showLastVisitedSites(IWebView& webView)
213 {
214     HMENU menu = ::GetMenu(m_hMainWnd);
215
216     _com_ptr_t<_com_IIID<IWebBackForwardList, &__uuidof(IWebBackForwardList)>> backForwardList;
217     HRESULT hr = webView.backForwardList(&backForwardList.GetInterfacePtr());
218     if (FAILED(hr))
219         return;
220
221     int capacity = 0;
222     hr = backForwardList->capacity(&capacity);
223     if (FAILED(hr))
224         return;
225
226     int backCount = 0;
227     hr = backForwardList->backListCount(&backCount);
228     if (FAILED(hr))
229         return;
230
231     UINT backSetting = MF_BYCOMMAND | ((backCount) ? MF_ENABLED : MF_DISABLED);
232     ::EnableMenuItem(menu, IDM_HISTORY_BACKWARD, backSetting);
233
234     int forwardCount = 0;
235     hr = backForwardList->forwardListCount(&forwardCount);
236     if (FAILED(hr))
237         return;
238
239     UINT forwardSetting = MF_BYCOMMAND | ((forwardCount) ? MF_ENABLED : MF_DISABLED);
240     ::EnableMenuItem(menu, IDM_HISTORY_FORWARD, forwardSetting);
241
242     IWebHistoryItemPtr currentItem;
243     hr = backForwardList->currentItem(&currentItem.GetInterfacePtr());
244     if (FAILED(hr))
245         return;
246
247     hr = m_webHistory->addItems(1, &currentItem.GetInterfacePtr());
248     if (FAILED(hr))
249         return;
250
251     _com_ptr_t<_com_IIID<IWebHistoryPrivate, &__uuidof(IWebHistoryPrivate)>> webHistory;
252     hr = m_webHistory->QueryInterface(IID_IWebHistoryPrivate, reinterpret_cast<void**>(&webHistory.GetInterfacePtr()));
253     if (FAILED(hr))
254         return;
255
256     int totalListCount = 0;
257     hr = webHistory->allItems(&totalListCount, 0);
258     if (FAILED(hr))
259         return;
260
261     m_historyItems.resize(totalListCount);
262
263     std::vector<IWebHistoryItem*> historyToLoad(totalListCount);
264     hr = webHistory->allItems(&totalListCount, historyToLoad.data());
265     if (FAILED(hr))
266         return;
267
268     size_t i = 0;
269     for (auto& cur : historyToLoad) {
270         m_historyItems[i].Attach(cur);
271         ++i;
272     }
273
274     int allItemsOffset = 0;
275     if (totalListCount > maxHistorySize)
276         allItemsOffset = totalListCount - maxHistorySize;
277
278     int currentHistoryItem = 0;
279     for (int i = 0; i < m_historyItems.size() && (allItemsOffset + currentHistoryItem) < m_historyItems.size(); ++i) {
280         updateMenuItemForHistoryItem(menu, *(m_historyItems[allItemsOffset + currentHistoryItem]), currentHistoryItem);
281         ++currentHistoryItem;
282     }
283
284     // Hide any history we aren't using yet.
285     for (int i = currentHistoryItem; i < maxHistorySize; ++i)
286         ::EnableMenuItem(menu, IDM_HISTORY_LINK0 + i, MF_BYCOMMAND | MF_DISABLED);
287 }
288
289 void WinLauncher::launchInspector()
290 {
291     if (!m_webViewPrivate)
292         return;
293
294     if (!SUCCEEDED(m_webViewPrivate->inspector(&m_inspector.GetInterfacePtr())))
295         return;
296
297     m_inspector->show();
298 }
299
300 void WinLauncher::navigateForwardOrBackward(HWND hWnd, UINT menuID)
301 {
302     if (!m_webView)
303         return;
304
305     BOOL wentBackOrForward = FALSE;
306     if (IDM_HISTORY_FORWARD == menuID)
307         m_webView->goForward(&wentBackOrForward);
308     else
309         m_webView->goBack(&wentBackOrForward);
310 }
311
312 void WinLauncher::navigateToHistory(HWND hWnd, UINT menuID)
313 {
314     if (!m_webView)
315         return;
316
317     int historyEntry = menuID - IDM_HISTORY_LINK0;
318     if (historyEntry > m_historyItems.size())
319         return;
320
321     IWebHistoryItemPtr desiredHistoryItem = m_historyItems[historyEntry];
322     if (!desiredHistoryItem)
323         return;
324
325     BOOL succeeded = FALSE;
326     m_webView->goToBackForwardItem(desiredHistoryItem, &succeeded);
327
328     _bstr_t frameURL;
329     desiredHistoryItem->URLString(frameURL.GetAddress());
330
331     ::SendMessage(m_hURLBarWnd, (UINT)WM_SETTEXT, 0, (LPARAM)frameURL.GetBSTR());
332 }
333
334 bool WinLauncher::goBack()
335 {
336     BOOL wentBack = FALSE;
337     m_webView->goBack(&wentBack);
338     return wentBack;
339 }
340
341 bool WinLauncher::goForward()
342 {
343     BOOL wentForward = FALSE;
344     m_webView->goForward(&wentForward);
345     return wentForward;
346 }
347
348 HRESULT WinLauncher::loadURL(const BSTR& passedURL)
349 {
350     _bstr_t urlBStr(passedURL);
351     if (!!urlBStr && (::PathFileExists(urlBStr) || ::PathIsUNC(urlBStr))) {
352         TCHAR fileURL[INTERNET_MAX_URL_LENGTH];
353         DWORD fileURLLength = sizeof(fileURL) / sizeof(fileURL[0]);
354
355         if (SUCCEEDED(::UrlCreateFromPath(urlBStr, fileURL, &fileURLLength, 0)))
356             urlBStr = fileURL;
357     }
358
359     IWebFramePtr frame;
360     HRESULT hr = m_webView->mainFrame(&frame.GetInterfacePtr());
361     if (FAILED(hr))
362         return hr;
363
364     if (!passedURL)
365         return frame->loadHTMLString(_bstr_t(defaultHTML).GetBSTR(), 0);
366
367     IWebMutableURLRequestPtr request;
368     hr = WebKitCreateInstance(CLSID_WebMutableURLRequest, 0, IID_IWebMutableURLRequest, (void**)&request);
369     if (FAILED(hr))
370         return hr;
371
372     hr = request->initWithURL(wcsstr(static_cast<wchar_t*>(urlBStr), L"://") ? urlBStr : _bstr_t(L"http://") + urlBStr, WebURLRequestUseProtocolCachePolicy, 60);
373     if (FAILED(hr))
374         return hr;
375
376     _bstr_t methodBStr(L"GET");
377     hr = request->setHTTPMethod(methodBStr);
378     if (FAILED(hr))
379         return hr;
380
381     hr = frame->loadRequest(request);
382
383     return hr;
384 }
385
386 void WinLauncher::exitProgram()
387 {
388     ::PostMessage(m_hMainWnd, static_cast<UINT>(WM_COMMAND), MAKELPARAM(IDM_EXIT, 0), 0);
389 }
390
391 void WinLauncher::setUserAgent(UINT menuID)
392 {
393     if (!webView())
394         return;
395
396     _bstr_t customUserAgent;
397     switch (menuID) {
398     case IDM_UA_DEFAULT:
399         // Set to null user agent
400         break;
401     case IDM_UA_SAFARI_8_0:
402         customUserAgent = L"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/600.1.25 (KHTML, like Gecko) Version/8.0 Safari/600.1.25";
403         break;
404     case IDM_UA_SAFARI_IOS_8_IPHONE:
405         customUserAgent = L"Mozilla/5.0 (iPhone; CPU OS 8_1 like Mac OS X) AppleWebKit/601.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B403 Safari/600.1.4";
406         break;
407     case IDM_UA_SAFARI_IOS_8_IPAD:
408         customUserAgent = L"Mozilla/5.0 (iPad; CPU OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B403 Safari/600.1.4";
409         break;
410     case IDM_UA_IE_11:
411         customUserAgent = L"Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko";
412         break;
413     case IDM_UA_CHROME_MAC:
414         customUserAgent = L"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31";
415         break;
416     case IDM_UA_CHROME_WIN:
417         customUserAgent = L"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31";
418         break;
419     case IDM_UA_FIREFOX_MAC:
420         customUserAgent = L"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:20.0) Gecko/20100101 Firefox/20.0";
421         break;
422     case IDM_UA_FIREFOX_WIN:
423         customUserAgent = L"Mozilla/5.0 (Windows NT 6.2; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0";
424         break;
425     case IDM_UA_OTHER:
426     default:
427         ASSERT(0); // We should never hit this case
428         return;
429     }
430
431     setUserAgent(customUserAgent);
432 }
433
434 void WinLauncher::setUserAgent(_bstr_t& customUserAgent)
435 {
436     webView()->setCustomUserAgent(customUserAgent.GetBSTR());
437 }
438
439 _bstr_t WinLauncher::userAgent()
440 {
441     _bstr_t userAgent;
442     if (FAILED(webView()->customUserAgent(&userAgent.GetBSTR())))
443         return _bstr_t(L"- Unknown -: Call failed.");
444
445     return userAgent;
446 }
447
448 typedef _com_ptr_t<_com_IIID<IWebIBActions, &__uuidof(IWebIBActions)>> IWebIBActionsPtr;
449
450 void WinLauncher::resetZoom()
451 {
452     IWebIBActionsPtr webActions;
453     if (FAILED(m_webView->QueryInterface(IID_IWebIBActions, reinterpret_cast<void**>(&webActions.GetInterfacePtr()))))
454         return;
455
456     webActions->resetPageZoom(nullptr);
457 }
458
459 void WinLauncher::zoomIn()
460 {
461     IWebIBActionsPtr webActions;
462     if (FAILED(m_webView->QueryInterface(IID_IWebIBActions, reinterpret_cast<void**>(&webActions.GetInterfacePtr()))))
463         return;
464
465     webActions->zoomPageIn(nullptr);
466 }
467
468 void WinLauncher::zoomOut()
469 {
470     IWebIBActionsPtr webActions;
471     if (FAILED(m_webView->QueryInterface(IID_IWebIBActions, reinterpret_cast<void**>(&webActions.GetInterfacePtr()))))
472         return;
473
474     webActions->zoomPageOut(nullptr);
475 }