• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2007, 2008 Apple, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "WebKitDLL.h"
28 #include "WebView.h"
29 
30 #include "CFDictionaryPropertyBag.h"
31 #include "DOMCoreClasses.h"
32 #include "MarshallingHelpers.h"
33 #include "SoftLinking.h"
34 #include "WebDatabaseManager.h"
35 #include "WebDocumentLoader.h"
36 #include "WebDownload.h"
37 #include "WebEditorClient.h"
38 #include "WebElementPropertyBag.h"
39 #include "WebFrame.h"
40 #include "WebBackForwardList.h"
41 #include "WebChromeClient.h"
42 #include "WebContextMenuClient.h"
43 #include "WebCoreTextRenderer.h"
44 #include "WebDragClient.h"
45 #include "WebIconDatabase.h"
46 #include "WebInspector.h"
47 #include "WebInspectorClient.h"
48 #include "WebKit.h"
49 #include "WebKitStatisticsPrivate.h"
50 #include "WebKitSystemBits.h"
51 #include "WebMutableURLRequest.h"
52 #include "WebNotificationCenter.h"
53 #include "WebPreferences.h"
54 #include "WindowsTouch.h"
55 #pragma warning( push, 0 )
56 #include <WebCore/ApplicationCacheStorage.h>
57 #include <WebCore/AXObjectCache.h>
58 #include <WebCore/BitmapInfo.h>
59 #include <WebCore/BString.h>
60 #include <WebCore/Cache.h>
61 #include <WebCore/ContextMenu.h>
62 #include <WebCore/ContextMenuController.h>
63 #include <WebCore/CookieStorageWin.h>
64 #include <WebCore/CString.h>
65 #include <WebCore/Cursor.h>
66 #include <WebCore/Document.h>
67 #include <WebCore/DragController.h>
68 #include <WebCore/DragData.h>
69 #include <WebCore/Editor.h>
70 #include <WebCore/EventHandler.h>
71 #include <WebCore/EventNames.h>
72 #include <WebCore/FileSystem.h>
73 #include <WebCore/FocusController.h>
74 #include <WebCore/FloatQuad.h>
75 #include <WebCore/FrameLoader.h>
76 #include <WebCore/FrameTree.h>
77 #include <WebCore/FrameView.h>
78 #include <WebCore/FrameWin.h>
79 #include <WebCore/GDIObjectCounter.h>
80 #include <WebCore/GraphicsContext.h>
81 #include <WebCore/HistoryItem.h>
82 #include <WebCore/HitTestRequest.h>
83 #include <WebCore/HitTestResult.h>
84 #include <WebCore/IntRect.h>
85 #include <WebCore/KeyboardEvent.h>
86 #include <WebCore/Language.h>
87 #include <WebCore/Logging.h>
88 #include <WebCore/MIMETypeRegistry.h>
89 #include <WebCore/Page.h>
90 #include <WebCore/PageCache.h>
91 #include <WebCore/PlatformKeyboardEvent.h>
92 #include <WebCore/PlatformMouseEvent.h>
93 #include <WebCore/PlatformWheelEvent.h>
94 #include <WebCore/PluginDatabase.h>
95 #include <WebCore/PluginInfoStore.h>
96 #include <WebCore/PluginView.h>
97 #include <WebCore/ProgressTracker.h>
98 #include <WebCore/RenderTheme.h>
99 #include <WebCore/RenderView.h>
100 #include <WebCore/ResourceHandle.h>
101 #include <WebCore/ResourceHandleClient.h>
102 #include <WebCore/ScriptValue.h>
103 #include <WebCore/Scrollbar.h>
104 #include <WebCore/ScrollbarTheme.h>
105 #include <WebCore/SecurityOrigin.h>
106 #include <WebCore/SelectionController.h>
107 #include <WebCore/Settings.h>
108 #include <WebCore/SimpleFontData.h>
109 #include <WebCore/TypingCommand.h>
110 #include <WebCore/WindowMessageBroadcaster.h>
111 #pragma warning(pop)
112 #include <JavaScriptCore/InitializeThreading.h>
113 #include <JavaScriptCore/JSLock.h>
114 #include <JavaScriptCore/JSValue.h>
115 
116 #if PLATFORM(CG)
117 #include <CoreGraphics/CGContext.h>
118 #endif
119 
120 #if PLATFORM(CF)
121 #include <CoreFoundation/CoreFoundation.h>
122 #endif
123 
124 #if USE(CFNETWORK)
125 #include <CFNetwork/CFURLCachePriv.h>
126 #include <CFNetwork/CFURLProtocolPriv.h>
127 #include <WebKitSystemInterface/WebKitSystemInterface.h>
128 #endif
129 
130 #include <wtf/HashSet.h>
131 #include <dimm.h>
132 #include <oleacc.h>
133 #include <ShlObj.h>
134 #include <tchar.h>
135 #include <windowsx.h>
136 
137 // Soft link functions for gestures and panning feedback
138 SOFT_LINK_LIBRARY(USER32);
139 SOFT_LINK_OPTIONAL(USER32, GetGestureInfo, BOOL, WINAPI, (HGESTUREINFO, PGESTUREINFO));
140 SOFT_LINK_OPTIONAL(USER32, SetGestureConfig, BOOL, WINAPI, (HWND, DWORD, UINT, PGESTURECONFIG, UINT));
141 SOFT_LINK_OPTIONAL(USER32, CloseGestureInfoHandle, BOOL, WINAPI, (HGESTUREINFO));
142 SOFT_LINK_LIBRARY(Uxtheme);
143 SOFT_LINK_OPTIONAL(Uxtheme, BeginPanningFeedback, BOOL, WINAPI, (HWND));
144 SOFT_LINK_OPTIONAL(Uxtheme, EndPanningFeedback, BOOL, WINAPI, (HWND, BOOL));
145 SOFT_LINK_OPTIONAL(Uxtheme, UpdatePanningFeedback, BOOL, WINAPI, (HWND, LONG, LONG, BOOL));
146 
147 using namespace WebCore;
148 using JSC::JSLock;
149 using std::min;
150 using std::max;
151 
152 static HMODULE accessibilityLib;
153 static HashSet<WebView*> pendingDeleteBackingStoreSet;
154 
155 static String osVersion();
156 static String webKitVersion();
157 
kit(Page * page)158 WebView* kit(Page* page)
159 {
160     return page ? static_cast<WebChromeClient*>(page->chrome()->client())->webView() : 0;
161 }
162 
163 class PreferencesChangedOrRemovedObserver : public IWebNotificationObserver {
164 public:
165     static PreferencesChangedOrRemovedObserver* sharedInstance();
166 
167 private:
PreferencesChangedOrRemovedObserver()168     PreferencesChangedOrRemovedObserver() {}
~PreferencesChangedOrRemovedObserver()169     ~PreferencesChangedOrRemovedObserver() {}
170 
QueryInterface(REFIID,void **)171     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**) { return E_FAIL; }
AddRef(void)172     virtual ULONG STDMETHODCALLTYPE AddRef(void) { return 0; }
Release(void)173     virtual ULONG STDMETHODCALLTYPE Release(void) { return 0; }
174 
175 public:
176     // IWebNotificationObserver
177     virtual HRESULT STDMETHODCALLTYPE onNotify(
178         /* [in] */ IWebNotification* notification);
179 
180 private:
181     HRESULT notifyPreferencesChanged(WebCacheModel);
182     HRESULT notifyPreferencesRemoved(WebCacheModel);
183 };
184 
sharedInstance()185 PreferencesChangedOrRemovedObserver* PreferencesChangedOrRemovedObserver::sharedInstance()
186 {
187     static PreferencesChangedOrRemovedObserver* shared = new PreferencesChangedOrRemovedObserver;
188     return shared;
189 }
190 
onNotify(IWebNotification * notification)191 HRESULT PreferencesChangedOrRemovedObserver::onNotify(IWebNotification* notification)
192 {
193     HRESULT hr = S_OK;
194 
195     COMPtr<IUnknown> unkPrefs;
196     hr = notification->getObject(&unkPrefs);
197     if (FAILED(hr))
198         return hr;
199 
200     COMPtr<IWebPreferences> preferences(Query, unkPrefs);
201     if (!preferences)
202         return E_NOINTERFACE;
203 
204     WebCacheModel cacheModel;
205     hr = preferences->cacheModel(&cacheModel);
206     if (FAILED(hr))
207         return hr;
208 
209     BSTR nameBSTR;
210     hr = notification->name(&nameBSTR);
211     if (FAILED(hr))
212         return hr;
213     BString name;
214     name.adoptBSTR(nameBSTR);
215 
216     if (wcscmp(name, WebPreferences::webPreferencesChangedNotification()) == 0)
217         return notifyPreferencesChanged(cacheModel);
218 
219     if (wcscmp(name, WebPreferences::webPreferencesRemovedNotification()) == 0)
220         return notifyPreferencesRemoved(cacheModel);
221 
222     ASSERT_NOT_REACHED();
223     return E_FAIL;
224 }
225 
notifyPreferencesChanged(WebCacheModel cacheModel)226 HRESULT PreferencesChangedOrRemovedObserver::notifyPreferencesChanged(WebCacheModel cacheModel)
227 {
228     HRESULT hr = S_OK;
229 
230     if (!WebView::didSetCacheModel() || cacheModel > WebView::cacheModel())
231         WebView::setCacheModel(cacheModel);
232     else if (cacheModel < WebView::cacheModel()) {
233         WebCacheModel sharedPreferencesCacheModel;
234         hr = WebPreferences::sharedStandardPreferences()->cacheModel(&sharedPreferencesCacheModel);
235         if (FAILED(hr))
236             return hr;
237         WebView::setCacheModel(max(sharedPreferencesCacheModel, WebView::maxCacheModelInAnyInstance()));
238     }
239 
240     return hr;
241 }
242 
notifyPreferencesRemoved(WebCacheModel cacheModel)243 HRESULT PreferencesChangedOrRemovedObserver::notifyPreferencesRemoved(WebCacheModel cacheModel)
244 {
245     HRESULT hr = S_OK;
246 
247     if (cacheModel == WebView::cacheModel()) {
248         WebCacheModel sharedPreferencesCacheModel;
249         hr = WebPreferences::sharedStandardPreferences()->cacheModel(&sharedPreferencesCacheModel);
250         if (FAILED(hr))
251             return hr;
252         WebView::setCacheModel(max(sharedPreferencesCacheModel, WebView::maxCacheModelInAnyInstance()));
253     }
254 
255     return hr;
256 }
257 
258 
259 const LPCWSTR kWebViewWindowClassName = L"WebViewWindowClass";
260 
261 const int WM_XP_THEMECHANGED = 0x031A;
262 const int WM_VISTA_MOUSEHWHEEL = 0x020E;
263 
264 static const int maxToolTipWidth = 250;
265 
266 static const int delayBeforeDeletingBackingStoreMsec = 5000;
267 
268 static ATOM registerWebView();
269 static LRESULT CALLBACK WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
270 
271 static void initializeStaticObservers();
272 
273 static HRESULT updateSharedSettingsFromPreferencesIfNeeded(IWebPreferences*);
274 
275 HRESULT createMatchEnumerator(Vector<IntRect>* rects, IEnumTextMatches** matches);
276 
277 static bool continuousSpellCheckingEnabled;
278 static bool grammarCheckingEnabled;
279 
280 static bool s_didSetCacheModel;
281 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
282 
283 enum {
284     UpdateActiveStateTimer = 1,
285     DeleteBackingStoreTimer = 2,
286 };
287 
288 // WebView ----------------------------------------------------------------
289 
290 bool WebView::s_allowSiteSpecificHacks = false;
291 
WebView()292 WebView::WebView()
293 : m_refCount(0)
294 , m_hostWindow(0)
295 , m_viewWindow(0)
296 , m_mainFrame(0)
297 , m_page(0)
298 , m_hasCustomDropTarget(false)
299 , m_useBackForwardList(true)
300 , m_userAgentOverridden(false)
301 , m_zoomMultiplier(1.0f)
302 , m_mouseActivated(false)
303 , m_dragData(0)
304 , m_currentCharacterCode(0)
305 , m_isBeingDestroyed(false)
306 , m_paintCount(0)
307 , m_hasSpellCheckerDocumentTag(false)
308 , m_smartInsertDeleteEnabled(false)
309 , m_didClose(false)
310 , m_inIMEComposition(0)
311 , m_toolTipHwnd(0)
312 , m_closeWindowTimer(this, &WebView::closeWindowTimerFired)
313 , m_topLevelParent(0)
314 , m_deleteBackingStoreTimerActive(false)
315 , m_transparent(false)
316 , m_selectTrailingWhitespaceEnabled(false)
317 , m_lastPanX(0)
318 , m_lastPanY(0)
319 , m_xOverpan(0)
320 , m_yOverpan(0)
321 {
322     JSC::initializeThreading();
323 
324     m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
325 
326     CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, IID_IDropTargetHelper,(void**)&m_dropTargetHelper);
327 
328     initializeStaticObservers();
329 
330     WebPreferences* sharedPreferences = WebPreferences::sharedStandardPreferences();
331     BOOL enabled;
332     if (SUCCEEDED(sharedPreferences->continuousSpellCheckingEnabled(&enabled)))
333         continuousSpellCheckingEnabled = !!enabled;
334     if (SUCCEEDED(sharedPreferences->grammarCheckingEnabled(&enabled)))
335         grammarCheckingEnabled = !!enabled;
336 
337     WebViewCount++;
338     gClassCount++;
339     gClassNameCount.add("WebView");
340 }
341 
~WebView()342 WebView::~WebView()
343 {
344     deleteBackingStore();
345 
346     // <rdar://4958382> m_viewWindow will be destroyed when m_hostWindow is destroyed, but if
347     // setHostWindow was never called we will leak our HWND. If we still have a valid HWND at
348     // this point, we should just destroy it ourselves.
349     if (!isBeingDestroyed() && ::IsWindow(m_viewWindow))
350         ::DestroyWindow(m_viewWindow);
351 
352     // the tooltip window needs to be explicitly destroyed since it isn't a WS_CHILD
353     if (::IsWindow(m_toolTipHwnd))
354         ::DestroyWindow(m_toolTipHwnd);
355 
356     ASSERT(!m_page);
357     ASSERT(!m_preferences);
358 
359     WebViewCount--;
360     gClassCount--;
361     gClassNameCount.remove("WebView");
362 }
363 
createInstance()364 WebView* WebView::createInstance()
365 {
366     WebView* instance = new WebView();
367     instance->AddRef();
368     return instance;
369 }
370 
initializeStaticObservers()371 void initializeStaticObservers()
372 {
373     static bool initialized;
374     if (initialized)
375         return;
376     initialized = true;
377 
378     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
379     notifyCenter->addObserver(PreferencesChangedOrRemovedObserver::sharedInstance(), WebPreferences::webPreferencesChangedNotification(), 0);
380     notifyCenter->addObserver(PreferencesChangedOrRemovedObserver::sharedInstance(), WebPreferences::webPreferencesRemovedNotification(), 0);
381 }
382 
allWebViewsSet()383 static HashSet<WebView*>& allWebViewsSet()
384 {
385     static HashSet<WebView*> allWebViewsSet;
386     return allWebViewsSet;
387 }
388 
addToAllWebViewsSet()389 void WebView::addToAllWebViewsSet()
390 {
391     allWebViewsSet().add(this);
392 }
393 
removeFromAllWebViewsSet()394 void WebView::removeFromAllWebViewsSet()
395 {
396     allWebViewsSet().remove(this);
397 }
398 
setCacheModel(WebCacheModel cacheModel)399 void WebView::setCacheModel(WebCacheModel cacheModel)
400 {
401 #if USE(CFNETWORK)
402     if (s_didSetCacheModel && cacheModel == s_cacheModel)
403         return;
404 
405     RetainPtr<CFURLCacheRef> cfurlCache(AdoptCF, CFURLCacheCopySharedURLCache());
406     RetainPtr<CFStringRef> cfurlCacheDirectory(AdoptCF, wkCopyFoundationCacheDirectory());
407     if (!cfurlCacheDirectory)
408         cfurlCacheDirectory.adoptCF(WebCore::localUserSpecificStorageDirectory().createCFString());
409 
410     // As a fudge factor, use 1000 instead of 1024, in case the reported byte
411     // count doesn't align exactly to a megabyte boundary.
412     unsigned long long memSize = WebMemorySize() / 1024 / 1000;
413     unsigned long long diskFreeSize = WebVolumeFreeSize(cfurlCacheDirectory.get()) / 1024 / 1000;
414 
415     unsigned cacheTotalCapacity = 0;
416     unsigned cacheMinDeadCapacity = 0;
417     unsigned cacheMaxDeadCapacity = 0;
418     double deadDecodedDataDeletionInterval = 0;
419 
420     unsigned pageCacheCapacity = 0;
421 
422     CFIndex cfurlCacheMemoryCapacity = 0;
423     CFIndex cfurlCacheDiskCapacity = 0;
424 
425     switch (cacheModel) {
426     case WebCacheModelDocumentViewer: {
427         // Page cache capacity (in pages)
428         pageCacheCapacity = 0;
429 
430         // Object cache capacities (in bytes)
431         if (memSize >= 2048)
432             cacheTotalCapacity = 96 * 1024 * 1024;
433         else if (memSize >= 1536)
434             cacheTotalCapacity = 64 * 1024 * 1024;
435         else if (memSize >= 1024)
436             cacheTotalCapacity = 32 * 1024 * 1024;
437         else if (memSize >= 512)
438             cacheTotalCapacity = 16 * 1024 * 1024;
439 
440         cacheMinDeadCapacity = 0;
441         cacheMaxDeadCapacity = 0;
442 
443         // Foundation memory cache capacity (in bytes)
444         cfurlCacheMemoryCapacity = 0;
445 
446         // Foundation disk cache capacity (in bytes)
447         cfurlCacheDiskCapacity = CFURLCacheDiskCapacity(cfurlCache.get());
448 
449         break;
450     }
451     case WebCacheModelDocumentBrowser: {
452         // Page cache capacity (in pages)
453         if (memSize >= 1024)
454             pageCacheCapacity = 3;
455         else if (memSize >= 512)
456             pageCacheCapacity = 2;
457         else if (memSize >= 256)
458             pageCacheCapacity = 1;
459         else
460             pageCacheCapacity = 0;
461 
462         // Object cache capacities (in bytes)
463         if (memSize >= 2048)
464             cacheTotalCapacity = 96 * 1024 * 1024;
465         else if (memSize >= 1536)
466             cacheTotalCapacity = 64 * 1024 * 1024;
467         else if (memSize >= 1024)
468             cacheTotalCapacity = 32 * 1024 * 1024;
469         else if (memSize >= 512)
470             cacheTotalCapacity = 16 * 1024 * 1024;
471 
472         cacheMinDeadCapacity = cacheTotalCapacity / 8;
473         cacheMaxDeadCapacity = cacheTotalCapacity / 4;
474 
475         // Foundation memory cache capacity (in bytes)
476         if (memSize >= 2048)
477             cfurlCacheMemoryCapacity = 4 * 1024 * 1024;
478         else if (memSize >= 1024)
479             cfurlCacheMemoryCapacity = 2 * 1024 * 1024;
480         else if (memSize >= 512)
481             cfurlCacheMemoryCapacity = 1 * 1024 * 1024;
482         else
483             cfurlCacheMemoryCapacity =      512 * 1024;
484 
485         // Foundation disk cache capacity (in bytes)
486         if (diskFreeSize >= 16384)
487             cfurlCacheDiskCapacity = 50 * 1024 * 1024;
488         else if (diskFreeSize >= 8192)
489             cfurlCacheDiskCapacity = 40 * 1024 * 1024;
490         else if (diskFreeSize >= 4096)
491             cfurlCacheDiskCapacity = 30 * 1024 * 1024;
492         else
493             cfurlCacheDiskCapacity = 20 * 1024 * 1024;
494 
495         break;
496     }
497     case WebCacheModelPrimaryWebBrowser: {
498         // Page cache capacity (in pages)
499         // (Research indicates that value / page drops substantially after 3 pages.)
500         if (memSize >= 2048)
501             pageCacheCapacity = 5;
502         else if (memSize >= 1024)
503             pageCacheCapacity = 4;
504         else if (memSize >= 512)
505             pageCacheCapacity = 3;
506         else if (memSize >= 256)
507             pageCacheCapacity = 2;
508         else
509             pageCacheCapacity = 1;
510 
511         // Object cache capacities (in bytes)
512         // (Testing indicates that value / MB depends heavily on content and
513         // browsing pattern. Even growth above 128MB can have substantial
514         // value / MB for some content / browsing patterns.)
515         if (memSize >= 2048)
516             cacheTotalCapacity = 128 * 1024 * 1024;
517         else if (memSize >= 1536)
518             cacheTotalCapacity = 96 * 1024 * 1024;
519         else if (memSize >= 1024)
520             cacheTotalCapacity = 64 * 1024 * 1024;
521         else if (memSize >= 512)
522             cacheTotalCapacity = 32 * 1024 * 1024;
523 
524         cacheMinDeadCapacity = cacheTotalCapacity / 4;
525         cacheMaxDeadCapacity = cacheTotalCapacity / 2;
526 
527         // This code is here to avoid a PLT regression. We can remove it if we
528         // can prove that the overall system gain would justify the regression.
529         cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity);
530 
531         deadDecodedDataDeletionInterval = 60;
532 
533         // Foundation memory cache capacity (in bytes)
534         // (These values are small because WebCore does most caching itself.)
535         if (memSize >= 1024)
536             cfurlCacheMemoryCapacity = 4 * 1024 * 1024;
537         else if (memSize >= 512)
538             cfurlCacheMemoryCapacity = 2 * 1024 * 1024;
539         else if (memSize >= 256)
540             cfurlCacheMemoryCapacity = 1 * 1024 * 1024;
541         else
542             cfurlCacheMemoryCapacity =      512 * 1024;
543 
544         // Foundation disk cache capacity (in bytes)
545         if (diskFreeSize >= 16384)
546             cfurlCacheDiskCapacity = 175 * 1024 * 1024;
547         else if (diskFreeSize >= 8192)
548             cfurlCacheDiskCapacity = 150 * 1024 * 1024;
549         else if (diskFreeSize >= 4096)
550             cfurlCacheDiskCapacity = 125 * 1024 * 1024;
551         else if (diskFreeSize >= 2048)
552             cfurlCacheDiskCapacity = 100 * 1024 * 1024;
553         else if (diskFreeSize >= 1024)
554             cfurlCacheDiskCapacity = 75 * 1024 * 1024;
555         else
556             cfurlCacheDiskCapacity = 50 * 1024 * 1024;
557 
558         break;
559     }
560     default:
561         ASSERT_NOT_REACHED();
562     }
563 
564     // Don't shrink a big disk cache, since that would cause churn.
565     cfurlCacheDiskCapacity = max(cfurlCacheDiskCapacity, CFURLCacheDiskCapacity(cfurlCache.get()));
566 
567     cache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
568     cache()->setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
569     pageCache()->setCapacity(pageCacheCapacity);
570 
571     CFURLCacheSetMemoryCapacity(cfurlCache.get(), cfurlCacheMemoryCapacity);
572     CFURLCacheSetDiskCapacity(cfurlCache.get(), cfurlCacheDiskCapacity);
573 
574     s_didSetCacheModel = true;
575     s_cacheModel = cacheModel;
576     return;
577 #endif
578 }
579 
cacheModel()580 WebCacheModel WebView::cacheModel()
581 {
582     return s_cacheModel;
583 }
584 
didSetCacheModel()585 bool WebView::didSetCacheModel()
586 {
587     return s_didSetCacheModel;
588 }
589 
maxCacheModelInAnyInstance()590 WebCacheModel WebView::maxCacheModelInAnyInstance()
591 {
592     WebCacheModel cacheModel = WebCacheModelDocumentViewer;
593 
594     HashSet<WebView*>::iterator end = allWebViewsSet().end();
595     for (HashSet<WebView*>::iterator it = allWebViewsSet().begin(); it != end; ++it) {
596         COMPtr<IWebPreferences> pref;
597         if (FAILED((*it)->preferences(&pref)))
598             continue;
599         WebCacheModel prefCacheModel = WebCacheModelDocumentViewer;
600         if (FAILED(pref->cacheModel(&prefCacheModel)))
601             continue;
602 
603         cacheModel = max(cacheModel, prefCacheModel);
604     }
605 
606     return cacheModel;
607 }
608 
close()609 HRESULT STDMETHODCALLTYPE WebView::close()
610 {
611     if (m_didClose)
612         return S_OK;
613 
614     m_didClose = true;
615 
616     if (m_uiDelegatePrivate)
617         m_uiDelegatePrivate->webViewClosing(this);
618 
619     removeFromAllWebViewsSet();
620 
621     Frame* frame = m_page->mainFrame();
622     if (frame)
623         frame->loader()->detachFromParent();
624 
625     if (m_mouseOutTracker) {
626         m_mouseOutTracker->dwFlags = TME_CANCEL;
627         ::TrackMouseEvent(m_mouseOutTracker.get());
628         m_mouseOutTracker.set(0);
629     }
630 
631     setHostWindow(0);
632 
633     setDownloadDelegate(0);
634     setEditingDelegate(0);
635     setFrameLoadDelegate(0);
636     setFrameLoadDelegatePrivate(0);
637     setPolicyDelegate(0);
638     setResourceLoadDelegate(0);
639     setUIDelegate(0);
640     setFormDelegate(0);
641 
642     if (m_webInspector)
643         m_webInspector->webViewClosed();
644 
645     delete m_page;
646     m_page = 0;
647 
648     registerForIconNotification(false);
649     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
650     notifyCenter->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
651 
652     BSTR identifier = 0;
653     m_preferences->identifier(&identifier);
654 
655     COMPtr<WebPreferences> preferences = m_preferences;
656     m_preferences = 0;
657     preferences->didRemoveFromWebView();
658     // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
659     preferences = 0;
660     if (identifier) {
661         WebPreferences::removeReferenceForIdentifier(identifier);
662         SysFreeString(identifier);
663     }
664 
665     deleteBackingStore();
666     return S_OK;
667 }
668 
repaint(const WebCore::IntRect & windowRect,bool contentChanged,bool immediate,bool repaintContentOnly)669 void WebView::repaint(const WebCore::IntRect& windowRect, bool contentChanged, bool immediate, bool repaintContentOnly)
670 {
671     if (!repaintContentOnly) {
672         RECT rect = windowRect;
673         ::InvalidateRect(m_viewWindow, &rect, false);
674     }
675     if (contentChanged)
676         addToDirtyRegion(windowRect);
677     if (immediate) {
678         if (repaintContentOnly)
679             updateBackingStore(core(topLevelFrame())->view());
680         else
681             ::UpdateWindow(m_viewWindow);
682     }
683 }
684 
deleteBackingStore()685 void WebView::deleteBackingStore()
686 {
687     pendingDeleteBackingStoreSet.remove(this);
688 
689     if (m_deleteBackingStoreTimerActive) {
690         KillTimer(m_viewWindow, DeleteBackingStoreTimer);
691         m_deleteBackingStoreTimerActive = false;
692     }
693     m_backingStoreBitmap.clear();
694     m_backingStoreDirtyRegion.clear();
695 
696     m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
697 }
698 
ensureBackingStore()699 bool WebView::ensureBackingStore()
700 {
701     RECT windowRect;
702     ::GetClientRect(m_viewWindow, &windowRect);
703     LONG width = windowRect.right - windowRect.left;
704     LONG height = windowRect.bottom - windowRect.top;
705     if (width > 0 && height > 0 && (width != m_backingStoreSize.cx || height != m_backingStoreSize.cy)) {
706         deleteBackingStore();
707 
708         m_backingStoreSize.cx = width;
709         m_backingStoreSize.cy = height;
710         BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(IntSize(m_backingStoreSize));
711 
712         void* pixels = NULL;
713         m_backingStoreBitmap.set(::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, NULL, 0));
714         return true;
715     }
716 
717     return false;
718 }
719 
addToDirtyRegion(const IntRect & dirtyRect)720 void WebView::addToDirtyRegion(const IntRect& dirtyRect)
721 {
722     HRGN newRegion = ::CreateRectRgn(dirtyRect.x(), dirtyRect.y(),
723                                      dirtyRect.right(), dirtyRect.bottom());
724     addToDirtyRegion(newRegion);
725 }
726 
addToDirtyRegion(HRGN newRegion)727 void WebView::addToDirtyRegion(HRGN newRegion)
728 {
729     LOCAL_GDI_COUNTER(0, __FUNCTION__);
730 
731     if (m_backingStoreDirtyRegion) {
732         HRGN combinedRegion = ::CreateRectRgn(0,0,0,0);
733         ::CombineRgn(combinedRegion, m_backingStoreDirtyRegion.get(), newRegion, RGN_OR);
734         ::DeleteObject(newRegion);
735         m_backingStoreDirtyRegion.set(combinedRegion);
736     } else
737         m_backingStoreDirtyRegion.set(newRegion);
738 
739     if (m_uiDelegatePrivate)
740         m_uiDelegatePrivate->webViewDidInvalidate(this);
741 }
742 
scrollBackingStore(FrameView * frameView,int dx,int dy,const IntRect & scrollViewRect,const IntRect & clipRect)743 void WebView::scrollBackingStore(FrameView* frameView, int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect)
744 {
745     LOCAL_GDI_COUNTER(0, __FUNCTION__);
746 
747     // If there's no backing store we don't need to update it
748     if (!m_backingStoreBitmap) {
749         if (m_uiDelegatePrivate)
750             m_uiDelegatePrivate->webViewScrolled(this);
751 
752         return;
753     }
754 
755     // Make a region to hold the invalidated scroll area.
756     HRGN updateRegion = ::CreateRectRgn(0, 0, 0, 0);
757 
758     // Collect our device context info and select the bitmap to scroll.
759     HDC windowDC = ::GetDC(m_viewWindow);
760     HDC bitmapDC = ::CreateCompatibleDC(windowDC);
761     ::SelectObject(bitmapDC, m_backingStoreBitmap.get());
762 
763     // Scroll the bitmap.
764     RECT scrollRectWin(scrollViewRect);
765     RECT clipRectWin(clipRect);
766     ::ScrollDC(bitmapDC, dx, dy, &scrollRectWin, &clipRectWin, updateRegion, 0);
767     RECT regionBox;
768     ::GetRgnBox(updateRegion, &regionBox);
769 
770     // Flush.
771     GdiFlush();
772 
773     // Add the dirty region to the backing store's dirty region.
774     addToDirtyRegion(updateRegion);
775 
776     if (m_uiDelegatePrivate)
777         m_uiDelegatePrivate->webViewScrolled(this);
778 
779     // Update the backing store.
780     updateBackingStore(frameView, bitmapDC, false);
781 
782     // Clean up.
783     ::DeleteDC(bitmapDC);
784     ::ReleaseDC(m_viewWindow, windowDC);
785 
786 }
787 
788 // This emulates the Mac smarts for painting rects intelligently.  This is very
789 // important for us, since we double buffer based off dirty rects.
getUpdateRects(HRGN region,const IntRect & dirtyRect,Vector<IntRect> & rects)790 static void getUpdateRects(HRGN region, const IntRect& dirtyRect, Vector<IntRect>& rects)
791 {
792     ASSERT_ARG(region, region);
793 
794     const int cRectThreshold = 10;
795     const float cWastedSpaceThreshold = 0.75f;
796 
797     rects.clear();
798 
799     DWORD regionDataSize = GetRegionData(region, sizeof(RGNDATA), NULL);
800     if (!regionDataSize) {
801         rects.append(dirtyRect);
802         return;
803     }
804 
805     Vector<unsigned char> buffer(regionDataSize);
806     RGNDATA* regionData = reinterpret_cast<RGNDATA*>(buffer.data());
807     GetRegionData(region, regionDataSize, regionData);
808     if (regionData->rdh.nCount > cRectThreshold) {
809         rects.append(dirtyRect);
810         return;
811     }
812 
813     double singlePixels = 0.0;
814     unsigned i;
815     RECT* rect;
816     for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++)
817         singlePixels += (rect->right - rect->left) * (rect->bottom - rect->top);
818 
819     double unionPixels = dirtyRect.width() * dirtyRect.height();
820     double wastedSpace = 1.0 - (singlePixels / unionPixels);
821     if (wastedSpace <= cWastedSpaceThreshold) {
822         rects.append(dirtyRect);
823         return;
824     }
825 
826     for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++)
827         rects.append(*rect);
828 }
829 
updateBackingStore(FrameView * frameView,HDC dc,bool backingStoreCompletelyDirty,WindowsToPaint windowsToPaint)830 void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStoreCompletelyDirty, WindowsToPaint windowsToPaint)
831 {
832     LOCAL_GDI_COUNTER(0, __FUNCTION__);
833 
834     HDC windowDC = 0;
835     HDC bitmapDC = dc;
836     if (!dc) {
837         windowDC = ::GetDC(m_viewWindow);
838         bitmapDC = ::CreateCompatibleDC(windowDC);
839         ::SelectObject(bitmapDC, m_backingStoreBitmap.get());
840     }
841 
842     if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) {
843         // Do a layout first so that everything we render to the backing store is always current.
844         if (Frame* coreFrame = core(m_mainFrame))
845             if (FrameView* view = coreFrame->view())
846                 view->layoutIfNeededRecursive();
847 
848         Vector<IntRect> paintRects;
849         if (!backingStoreCompletelyDirty) {
850             RECT regionBox;
851             ::GetRgnBox(m_backingStoreDirtyRegion.get(), &regionBox);
852             getUpdateRects(m_backingStoreDirtyRegion.get(), regionBox, paintRects);
853         } else {
854             RECT clientRect;
855             ::GetClientRect(m_viewWindow, &clientRect);
856             paintRects.append(clientRect);
857         }
858 
859         for (unsigned i = 0; i < paintRects.size(); ++i)
860             paintIntoBackingStore(frameView, bitmapDC, paintRects[i], windowsToPaint);
861 
862         if (m_uiDelegatePrivate)
863             m_uiDelegatePrivate->webViewPainted(this);
864 
865         m_backingStoreDirtyRegion.clear();
866     }
867 
868     if (!dc) {
869         ::DeleteDC(bitmapDC);
870         ::ReleaseDC(m_viewWindow, windowDC);
871     }
872 
873     GdiFlush();
874 }
875 
paint(HDC dc,LPARAM options)876 void WebView::paint(HDC dc, LPARAM options)
877 {
878     LOCAL_GDI_COUNTER(0, __FUNCTION__);
879 
880     Frame* coreFrame = core(m_mainFrame);
881     if (!coreFrame)
882         return;
883     FrameView* frameView = coreFrame->view();
884 
885     m_paintCount++;
886 
887     RECT rcPaint;
888     HDC hdc;
889     OwnPtr<HRGN> region;
890     int regionType = NULLREGION;
891     PAINTSTRUCT ps;
892     WindowsToPaint windowsToPaint;
893     if (!dc) {
894         region.set(CreateRectRgn(0,0,0,0));
895         regionType = GetUpdateRgn(m_viewWindow, region.get(), false);
896         hdc = BeginPaint(m_viewWindow, &ps);
897         rcPaint = ps.rcPaint;
898         // We're painting to the screen, and our child windows can handle
899         // painting themselves to the screen.
900         windowsToPaint = PaintWebViewOnly;
901     } else {
902         hdc = dc;
903         ::GetClientRect(m_viewWindow, &rcPaint);
904         if (options & PRF_ERASEBKGND)
905             ::FillRect(hdc, &rcPaint, (HBRUSH)GetStockObject(WHITE_BRUSH));
906         // Since we aren't painting to the screen, we want to paint all our
907         // children into the HDC.
908         windowsToPaint = PaintWebViewAndChildren;
909     }
910 
911     HDC bitmapDC = ::CreateCompatibleDC(hdc);
912     bool backingStoreCompletelyDirty = ensureBackingStore();
913     ::SelectObject(bitmapDC, m_backingStoreBitmap.get());
914 
915     // Update our backing store if needed.
916     updateBackingStore(frameView, bitmapDC, backingStoreCompletelyDirty, windowsToPaint);
917 
918     // Now we blit the updated backing store
919     IntRect windowDirtyRect = rcPaint;
920 
921     // Apply the same heuristic for this update region too.
922     Vector<IntRect> blitRects;
923     if (region && regionType == COMPLEXREGION)
924         getUpdateRects(region.get(), windowDirtyRect, blitRects);
925     else
926         blitRects.append(windowDirtyRect);
927 
928     for (unsigned i = 0; i < blitRects.size(); ++i)
929         paintIntoWindow(bitmapDC, hdc, blitRects[i]);
930 
931     ::DeleteDC(bitmapDC);
932 
933     // Paint the gripper.
934     COMPtr<IWebUIDelegate> ui;
935     if (SUCCEEDED(uiDelegate(&ui))) {
936         COMPtr<IWebUIDelegatePrivate> uiPrivate;
937         if (SUCCEEDED(ui->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate))) {
938             RECT r;
939             if (SUCCEEDED(uiPrivate->webViewResizerRect(this, &r))) {
940                 LOCAL_GDI_COUNTER(2, __FUNCTION__" webViewDrawResizer delegate call");
941                 uiPrivate->webViewDrawResizer(this, hdc, (frameView->containsScrollbarsAvoidingResizer() ? true : false), &r);
942             }
943         }
944     }
945 
946     if (!dc)
947         EndPaint(m_viewWindow, &ps);
948 
949     m_paintCount--;
950 
951     if (active())
952         cancelDeleteBackingStoreSoon();
953     else
954         deleteBackingStoreSoon();
955 }
956 
paintIntoBackingStore(FrameView * frameView,HDC bitmapDC,const IntRect & dirtyRect,WindowsToPaint windowsToPaint)957 void WebView::paintIntoBackingStore(FrameView* frameView, HDC bitmapDC, const IntRect& dirtyRect, WindowsToPaint windowsToPaint)
958 {
959     LOCAL_GDI_COUNTER(0, __FUNCTION__);
960 
961     RECT rect = dirtyRect;
962 
963 #if FLASH_BACKING_STORE_REDRAW
964     HDC dc = ::GetDC(m_viewWindow);
965     OwnPtr<HBRUSH> yellowBrush = CreateSolidBrush(RGB(255, 255, 0));
966     FillRect(dc, &rect, yellowBrush.get());
967     GdiFlush();
968     Sleep(50);
969     paintIntoWindow(bitmapDC, dc, dirtyRect);
970     ::ReleaseDC(m_viewWindow, dc);
971 #endif
972 
973     GraphicsContext gc(bitmapDC, m_transparent);
974     gc.setShouldIncludeChildWindows(windowsToPaint == PaintWebViewAndChildren);
975     gc.save();
976     if (m_transparent)
977         gc.clearRect(dirtyRect);
978     else
979         FillRect(bitmapDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
980     if (frameView && frameView->frame() && frameView->frame()->contentRenderer()) {
981         gc.clip(dirtyRect);
982         frameView->paint(&gc, dirtyRect);
983     }
984     gc.restore();
985 }
986 
paintIntoWindow(HDC bitmapDC,HDC windowDC,const IntRect & dirtyRect)987 void WebView::paintIntoWindow(HDC bitmapDC, HDC windowDC, const IntRect& dirtyRect)
988 {
989     LOCAL_GDI_COUNTER(0, __FUNCTION__);
990 #if FLASH_WINDOW_REDRAW
991     OwnPtr<HBRUSH> greenBrush = CreateSolidBrush(RGB(0, 255, 0));
992     RECT rect = dirtyRect;
993     FillRect(windowDC, &rect, greenBrush.get());
994     GdiFlush();
995     Sleep(50);
996 #endif
997 
998     // Blit the dirty rect from the backing store into the same position
999     // in the destination DC.
1000     BitBlt(windowDC, dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(), bitmapDC,
1001            dirtyRect.x(), dirtyRect.y(), SRCCOPY);
1002 }
1003 
frameRect(RECT * rect)1004 void WebView::frameRect(RECT* rect)
1005 {
1006     ::GetWindowRect(m_viewWindow, rect);
1007 }
1008 
closeWindowSoon()1009 void WebView::closeWindowSoon()
1010 {
1011     m_closeWindowTimer.startOneShot(0);
1012     AddRef();
1013 }
1014 
closeWindowTimerFired(WebCore::Timer<WebView> *)1015 void WebView::closeWindowTimerFired(WebCore::Timer<WebView>*)
1016 {
1017     closeWindow();
1018     Release();
1019 }
1020 
closeWindow()1021 void WebView::closeWindow()
1022 {
1023     if (m_hasSpellCheckerDocumentTag) {
1024         if (m_editingDelegate)
1025             m_editingDelegate->closeSpellDocument(this);
1026         m_hasSpellCheckerDocumentTag = false;
1027     }
1028 
1029     COMPtr<IWebUIDelegate> ui;
1030     if (SUCCEEDED(uiDelegate(&ui)))
1031         ui->webViewClose(this);
1032 }
1033 
canHandleRequest(const WebCore::ResourceRequest & request)1034 bool WebView::canHandleRequest(const WebCore::ResourceRequest& request)
1035 {
1036     // On the mac there's an about url protocol implementation but CFNetwork doesn't have that.
1037     if (equalIgnoringCase(String(request.url().protocol()), "about"))
1038         return true;
1039 
1040 #if USE(CFNETWORK)
1041     if (CFURLProtocolCanHandleRequest(request.cfURLRequest()))
1042         return true;
1043 
1044     // FIXME: Mac WebKit calls _representationExistsForURLScheme here
1045     return false;
1046 #else
1047     return true;
1048 #endif
1049 }
1050 
standardUserAgentWithApplicationName(const String & applicationName)1051 String WebView::standardUserAgentWithApplicationName(const String& applicationName)
1052 {
1053     return String::format("Mozilla/5.0 (Windows; U; %s; %s) AppleWebKit/%s (KHTML, like Gecko)%s%s", osVersion().latin1().data(), defaultLanguage().latin1().data(), webKitVersion().latin1().data(), (applicationName.length() ? " " : ""), applicationName.latin1().data());
1054 }
1055 
page()1056 Page* WebView::page()
1057 {
1058     return m_page;
1059 }
1060 
handleContextMenuEvent(WPARAM wParam,LPARAM lParam)1061 bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam)
1062 {
1063     static const int contextMenuMargin = 1;
1064 
1065     // Translate the screen coordinates into window coordinates
1066     POINT coords = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1067     if (coords.x == -1 || coords.y == -1) {
1068         FrameView* view = m_page->mainFrame()->view();
1069         if (!view)
1070             return false;
1071 
1072         int rightAligned = ::GetSystemMetrics(SM_MENUDROPALIGNMENT);
1073         IntPoint location;
1074 
1075         // The context menu event was generated from the keyboard, so show the context menu by the current selection.
1076         Position start = m_page->mainFrame()->selection()->selection().start();
1077         Position end = m_page->mainFrame()->selection()->selection().end();
1078 
1079         if (!start.node() || !end.node())
1080             location = IntPoint(rightAligned ? view->contentsWidth() - contextMenuMargin : contextMenuMargin, contextMenuMargin);
1081         else {
1082             RenderObject* renderer = start.node()->renderer();
1083             if (!renderer)
1084                 return false;
1085 
1086             // Calculate the rect of the first line of the selection (cribbed from -[WebCoreFrameBridge firstRectForDOMRange:],
1087             // now Frame::firstRectForRange(), which perhaps this should call).
1088             int extraWidthToEndOfLine = 0;
1089 
1090             InlineBox* startInlineBox;
1091             int startCaretOffset;
1092             start.getInlineBoxAndOffset(DOWNSTREAM, startInlineBox, startCaretOffset);
1093             IntRect startCaretRect = renderer->localCaretRect(startInlineBox, startCaretOffset, &extraWidthToEndOfLine);
1094             if (startCaretRect != IntRect())
1095                 startCaretRect = renderer->localToAbsoluteQuad(FloatRect(startCaretRect)).enclosingBoundingBox();
1096 
1097             InlineBox* endInlineBox;
1098             int endCaretOffset;
1099             end.getInlineBoxAndOffset(UPSTREAM, endInlineBox, endCaretOffset);
1100             IntRect endCaretRect = renderer->localCaretRect(endInlineBox, endCaretOffset);
1101             if (endCaretRect != IntRect())
1102                 endCaretRect = renderer->localToAbsoluteQuad(FloatRect(endCaretRect)).enclosingBoundingBox();
1103 
1104             IntRect firstRect;
1105             if (startCaretRect.y() == endCaretRect.y())
1106                 firstRect = IntRect(min(startCaretRect.x(), endCaretRect.x()), startCaretRect.y(), abs(endCaretRect.x() - startCaretRect.x()), max(startCaretRect.height(), endCaretRect.height()));
1107             else
1108                 firstRect = IntRect(startCaretRect.x(), startCaretRect.y(), startCaretRect.width() + extraWidthToEndOfLine, startCaretRect.height());
1109 
1110             location = IntPoint(rightAligned ? firstRect.right() : firstRect.x(), firstRect.bottom());
1111         }
1112 
1113         location = view->contentsToWindow(location);
1114         // FIXME: The IntSize(0, -1) is a hack to get the hit-testing to result in the selected element.
1115         // Ideally we'd have the position of a context menu event be separate from its target node.
1116         coords = location + IntSize(0, -1);
1117     } else {
1118         if (!::ScreenToClient(m_viewWindow, &coords))
1119             return false;
1120     }
1121 
1122     lParam = MAKELPARAM(coords.x, coords.y);
1123 
1124     // The contextMenuController() holds onto the last context menu that was popped up on the
1125     // page until a new one is created. We need to clear this menu before propagating the event
1126     // through the DOM so that we can detect if we create a new menu for this event, since we
1127     // won't create a new menu if the DOM swallows the event and the defaultEventHandler does
1128     // not run.
1129     m_page->contextMenuController()->clearContextMenu();
1130 
1131     IntPoint documentPoint(m_page->mainFrame()->view()->windowToContents(coords));
1132     HitTestResult result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(documentPoint, false);
1133     Frame* targetFrame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : m_page->focusController()->focusedOrMainFrame();
1134 
1135     targetFrame->view()->setCursor(pointerCursor());
1136     PlatformMouseEvent mouseEvent(m_viewWindow, WM_RBUTTONUP, wParam, lParam);
1137     bool handledEvent = targetFrame->eventHandler()->sendContextMenuEvent(mouseEvent);
1138     if (!handledEvent)
1139         return false;
1140 
1141     // Show the menu
1142     ContextMenu* coreMenu = m_page->contextMenuController()->contextMenu();
1143     if (!coreMenu)
1144         return false;
1145 
1146     Node* node = coreMenu->hitTestResult().innerNonSharedNode();
1147     if (!node)
1148         return false;
1149 
1150     Frame* frame = node->document()->frame();
1151     if (!frame)
1152         return false;
1153 
1154     FrameView* view = frame->view();
1155     if (!view)
1156         return false;
1157 
1158     POINT point(view->contentsToWindow(coreMenu->hitTestResult().point()));
1159 
1160     // Translate the point to screen coordinates
1161     if (!::ClientToScreen(m_viewWindow, &point))
1162         return false;
1163 
1164     BOOL hasCustomMenus = false;
1165     if (m_uiDelegate)
1166         m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1167 
1168     if (hasCustomMenus)
1169         m_uiDelegate->trackCustomPopupMenu((IWebView*)this, (OLE_HANDLE)(ULONG64)coreMenu->platformDescription(), &point);
1170     else {
1171         // Surprisingly, TPM_RIGHTBUTTON means that items are selectable with either the right OR left mouse button
1172         UINT flags = TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_HORIZONTAL
1173             | TPM_LEFTALIGN | TPM_HORPOSANIMATION;
1174         ::TrackPopupMenuEx(coreMenu->platformDescription(), flags, point.x, point.y, m_viewWindow, 0);
1175     }
1176 
1177     return true;
1178 }
1179 
onMeasureItem(WPARAM,LPARAM lParam)1180 bool WebView::onMeasureItem(WPARAM /*wParam*/, LPARAM lParam)
1181 {
1182     if (!m_uiDelegate)
1183         return false;
1184 
1185     BOOL hasCustomMenus = false;
1186     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1187     if (!hasCustomMenus)
1188         return false;
1189 
1190     m_uiDelegate->measureCustomMenuItem((IWebView*)this, (void*)lParam);
1191     return true;
1192 }
1193 
onDrawItem(WPARAM,LPARAM lParam)1194 bool WebView::onDrawItem(WPARAM /*wParam*/, LPARAM lParam)
1195 {
1196     if (!m_uiDelegate)
1197         return false;
1198 
1199     BOOL hasCustomMenus = false;
1200     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1201     if (!hasCustomMenus)
1202         return false;
1203 
1204     m_uiDelegate->drawCustomMenuItem((IWebView*)this, (void*)lParam);
1205     return true;
1206 }
1207 
onInitMenuPopup(WPARAM wParam,LPARAM)1208 bool WebView::onInitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
1209 {
1210     if (!m_uiDelegate)
1211         return false;
1212 
1213     HMENU menu = (HMENU)wParam;
1214     if (!menu)
1215         return false;
1216 
1217     BOOL hasCustomMenus = false;
1218     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1219     if (!hasCustomMenus)
1220         return false;
1221 
1222     m_uiDelegate->addCustomMenuDrawingData((IWebView*)this, (OLE_HANDLE)(ULONG64)menu);
1223     return true;
1224 }
1225 
onUninitMenuPopup(WPARAM wParam,LPARAM)1226 bool WebView::onUninitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
1227 {
1228     if (!m_uiDelegate)
1229         return false;
1230 
1231     HMENU menu = (HMENU)wParam;
1232     if (!menu)
1233         return false;
1234 
1235     BOOL hasCustomMenus = false;
1236     m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1237     if (!hasCustomMenus)
1238         return false;
1239 
1240     m_uiDelegate->cleanUpCustomMenuDrawingData((IWebView*)this, (OLE_HANDLE)(ULONG64)menu);
1241     return true;
1242 }
1243 
performContextMenuAction(WPARAM wParam,LPARAM lParam,bool byPosition)1244 void WebView::performContextMenuAction(WPARAM wParam, LPARAM lParam, bool byPosition)
1245 {
1246     ContextMenu* menu = m_page->contextMenuController()->contextMenu();
1247     ASSERT(menu);
1248 
1249     ContextMenuItem* item = byPosition ? menu->itemAtIndex((unsigned)wParam, (HMENU)lParam) : menu->itemWithAction((ContextMenuAction)wParam);
1250     if (!item)
1251         return;
1252     m_page->contextMenuController()->contextMenuItemSelected(item);
1253     delete item;
1254 }
1255 
handleMouseEvent(UINT message,WPARAM wParam,LPARAM lParam)1256 bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam)
1257 {
1258     static LONG globalClickCount;
1259     static IntPoint globalPrevPoint;
1260     static MouseButton globalPrevButton;
1261     static LONG globalPrevMouseDownTime;
1262 
1263     // Create our event.
1264     // On WM_MOUSELEAVE we need to create a mouseout event, so we force the position
1265     // of the event to be at (MINSHORT, MINSHORT).
1266     LPARAM position = (message == WM_MOUSELEAVE) ? ((MINSHORT << 16) | MINSHORT) : lParam;
1267     PlatformMouseEvent mouseEvent(m_viewWindow, message, wParam, position, m_mouseActivated);
1268 
1269     bool insideThreshold = abs(globalPrevPoint.x() - mouseEvent.pos().x()) < ::GetSystemMetrics(SM_CXDOUBLECLK) &&
1270                            abs(globalPrevPoint.y() - mouseEvent.pos().y()) < ::GetSystemMetrics(SM_CYDOUBLECLK);
1271     LONG messageTime = ::GetMessageTime();
1272 
1273     if (inResizer(position)) {
1274         if (m_uiDelegatePrivate)
1275             m_uiDelegatePrivate->webViewSendResizeMessage(message, wParam, position);
1276         return true;
1277     }
1278 
1279     bool handled = false;
1280 
1281     if (message == WM_LBUTTONDOWN || message == WM_MBUTTONDOWN || message == WM_RBUTTONDOWN) {
1282         // FIXME: I'm not sure if this is the "right" way to do this
1283         // but without this call, we never become focused since we don't allow
1284         // the default handling of mouse events.
1285         SetFocus(m_viewWindow);
1286 
1287         // Always start capturing events when the mouse goes down in our HWND.
1288         ::SetCapture(m_viewWindow);
1289 
1290         if (((messageTime - globalPrevMouseDownTime) < (LONG)::GetDoubleClickTime()) &&
1291             insideThreshold &&
1292             mouseEvent.button() == globalPrevButton)
1293             globalClickCount++;
1294         else
1295             // Reset the click count.
1296             globalClickCount = 1;
1297         globalPrevMouseDownTime = messageTime;
1298         globalPrevButton = mouseEvent.button();
1299         globalPrevPoint = mouseEvent.pos();
1300 
1301         mouseEvent.setClickCount(globalClickCount);
1302         handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent);
1303     } else if (message == WM_LBUTTONDBLCLK || message == WM_MBUTTONDBLCLK || message == WM_RBUTTONDBLCLK) {
1304         globalClickCount++;
1305         mouseEvent.setClickCount(globalClickCount);
1306         handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent);
1307     } else if (message == WM_LBUTTONUP || message == WM_MBUTTONUP || message == WM_RBUTTONUP) {
1308         // Record the global position and the button of the up.
1309         globalPrevButton = mouseEvent.button();
1310         globalPrevPoint = mouseEvent.pos();
1311         mouseEvent.setClickCount(globalClickCount);
1312         m_page->mainFrame()->eventHandler()->handleMouseReleaseEvent(mouseEvent);
1313         ::ReleaseCapture();
1314     } else if (message == WM_MOUSELEAVE && m_mouseOutTracker) {
1315         // Once WM_MOUSELEAVE is fired windows clears this tracker
1316         // so there is no need to disable it ourselves.
1317         m_mouseOutTracker.set(0);
1318         m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent);
1319         handled = true;
1320     } else if (message == WM_MOUSEMOVE) {
1321         if (!insideThreshold)
1322             globalClickCount = 0;
1323         mouseEvent.setClickCount(globalClickCount);
1324         handled = m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent);
1325         if (!m_mouseOutTracker) {
1326             m_mouseOutTracker.set(new TRACKMOUSEEVENT);
1327             m_mouseOutTracker->cbSize = sizeof(TRACKMOUSEEVENT);
1328             m_mouseOutTracker->dwFlags = TME_LEAVE;
1329             m_mouseOutTracker->hwndTrack = m_viewWindow;
1330             ::TrackMouseEvent(m_mouseOutTracker.get());
1331         }
1332     }
1333     setMouseActivated(false);
1334     return handled;
1335 }
1336 
gestureNotify(WPARAM wParam,LPARAM lParam)1337 bool WebView::gestureNotify(WPARAM wParam, LPARAM lParam)
1338 {
1339     GESTURENOTIFYSTRUCT* gn = reinterpret_cast<GESTURENOTIFYSTRUCT*>(lParam);
1340 
1341     Frame* coreFrame = core(m_mainFrame);
1342     if (!coreFrame)
1343         return false;
1344 
1345     ScrollView* view = coreFrame->view();
1346     if (!view)
1347         return false;
1348 
1349     // If we don't have this function, we shouldn't be receiving this message
1350     ASSERT(SetGestureConfigPtr());
1351 
1352     DWORD dwPanWant;
1353     DWORD dwPanBlock;
1354 
1355     // Translate gesture location to client to hit test on scrollbars
1356     POINT gestureBeginPoint = {gn->ptsLocation.x, gn->ptsLocation.y};
1357     IntPoint eventHandlerPoint = m_page->mainFrame()->view()->screenToContents(gestureBeginPoint);
1358 
1359     HitTestResult scrollbarTest = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(eventHandlerPoint, true, false, ShouldHitTestScrollbars);
1360 
1361     if (eventHandlerPoint.x() > view->visibleWidth() || scrollbarTest.scrollbar()) {
1362         // We are in the scrollbar, turn off panning, need to be able to drag the scrollbar
1363         dwPanWant = GC_PAN  | GC_PAN_WITH_INERTIA | GC_PAN_WITH_GUTTER;
1364         dwPanBlock = GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY | GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
1365     } else {
1366         dwPanWant = GC_PAN  | GC_PAN_WITH_SINGLE_FINGER_VERTICALLY | GC_PAN_WITH_INERTIA | GC_PAN_WITH_GUTTER;
1367         dwPanBlock = GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
1368     }
1369 
1370     GESTURECONFIG gc = { GID_PAN, dwPanWant , dwPanBlock } ;
1371     return SetGestureConfigPtr()(m_viewWindow, 0, 1, &gc, sizeof(GESTURECONFIG));
1372 }
1373 
gesture(WPARAM wParam,LPARAM lParam)1374 bool WebView::gesture(WPARAM wParam, LPARAM lParam)
1375 {
1376     // We want to bail out if we don't have either of these functions
1377     if (!GetGestureInfoPtr() || !CloseGestureInfoHandlePtr())
1378         return false;
1379 
1380     HGESTUREINFO gestureHandle = reinterpret_cast<HGESTUREINFO>(lParam);
1381 
1382     GESTUREINFO gi = {0};
1383     gi.cbSize = sizeof(GESTUREINFO);
1384 
1385     if (!GetGestureInfoPtr()(gestureHandle, reinterpret_cast<PGESTUREINFO>(&gi)))
1386         return false;
1387 
1388     switch (gi.dwID) {
1389     case GID_BEGIN:
1390         m_lastPanX = gi.ptsLocation.x;
1391         m_lastPanY = gi.ptsLocation.y;
1392 
1393         CloseGestureInfoHandlePtr()(gestureHandle);
1394         break;
1395     case GID_PAN: {
1396         // Where are the fingers currently?
1397         long currentX = gi.ptsLocation.x;
1398         long currentY = gi.ptsLocation.y;
1399 
1400         // How far did we pan in each direction?
1401         long deltaX = currentX - m_lastPanX;
1402         long deltaY = currentY - m_lastPanY;
1403 
1404         // Calculate the overpan for window bounce
1405         m_yOverpan -= m_lastPanY - currentY;
1406         m_xOverpan -= m_lastPanX - currentX;
1407 
1408         // Update our class variables with updated values
1409         m_lastPanX = currentX;
1410         m_lastPanY = currentY;
1411 
1412         Frame* coreFrame = core(m_mainFrame);
1413         if (!coreFrame) {
1414             CloseGestureInfoHandlePtr()(gestureHandle);
1415             return false;
1416         }
1417         // Represent the pan gesture as a mouse wheel event
1418         PlatformWheelEvent wheelEvent(m_viewWindow, FloatSize(deltaX, deltaY), FloatPoint(currentX, currentY));
1419         coreFrame->eventHandler()->handleWheelEvent(wheelEvent);
1420 
1421         if (!(UpdatePanningFeedbackPtr() && BeginPanningFeedbackPtr() && EndPanningFeedbackPtr())) {
1422             CloseGestureInfoHandlePtr()(gestureHandle);
1423             return true;
1424         }
1425 
1426         if (gi.dwFlags & GF_BEGIN) {
1427             BeginPanningFeedbackPtr()(m_viewWindow);
1428             m_yOverpan = 0;
1429         } else if (gi.dwFlags & GF_END) {
1430             EndPanningFeedbackPtr()(m_viewWindow, true);
1431             m_yOverpan = 0;
1432         }
1433 
1434         ScrollView* view = coreFrame->view();
1435         if (!view) {
1436             CloseGestureInfoHandlePtr()(gestureHandle);
1437             return false;
1438         }
1439         Scrollbar* vertScrollbar = view->verticalScrollbar();
1440         if (!vertScrollbar) {
1441             CloseGestureInfoHandlePtr()(gestureHandle);
1442             return true;
1443         }
1444 
1445         // FIXME: Support Horizontal Window Bounce
1446         if (vertScrollbar->currentPos() == 0)
1447             UpdatePanningFeedbackPtr()(m_viewWindow, 0, m_yOverpan, gi.dwFlags & GF_INERTIA);
1448         else if (vertScrollbar->currentPos() >= vertScrollbar->maximum())
1449             UpdatePanningFeedbackPtr()(m_viewWindow, 0, m_yOverpan, gi.dwFlags & GF_INERTIA);
1450 
1451         CloseGestureInfoHandlePtr()(gestureHandle);
1452         break;
1453     }
1454     default:
1455         // We have encountered an unknown gesture - return false to pass it to DefWindowProc
1456         CloseGestureInfoHandlePtr()(gestureHandle);
1457         break;
1458     }
1459 
1460     return true;
1461 }
1462 
mouseWheel(WPARAM wParam,LPARAM lParam,bool isMouseHWheel)1463 bool WebView::mouseWheel(WPARAM wParam, LPARAM lParam, bool isMouseHWheel)
1464 {
1465     // Ctrl+Mouse wheel doesn't ever go into WebCore.  It is used to
1466     // zoom instead (Mac zooms the whole Desktop, but Windows browsers trigger their
1467     // own local zoom modes for Ctrl+wheel).
1468     if (wParam & MK_CONTROL) {
1469         short delta = short(HIWORD(wParam));
1470         if (delta < 0)
1471             makeTextSmaller(0);
1472         else
1473             makeTextLarger(0);
1474         return true;
1475     }
1476 
1477     PlatformWheelEvent wheelEvent(m_viewWindow, wParam, lParam, isMouseHWheel);
1478     Frame* coreFrame = core(m_mainFrame);
1479     if (!coreFrame)
1480         return false;
1481 
1482     return coreFrame->eventHandler()->handleWheelEvent(wheelEvent);
1483 }
1484 
execCommand(WPARAM wParam,LPARAM)1485 bool WebView::execCommand(WPARAM wParam, LPARAM /*lParam*/)
1486 {
1487     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1488     switch (LOWORD(wParam)) {
1489         case SelectAll:
1490             return frame->editor()->command("SelectAll").execute();
1491         case Undo:
1492             return frame->editor()->command("Undo").execute();
1493         case Redo:
1494             return frame->editor()->command("Redo").execute();
1495     }
1496     return false;
1497 }
1498 
keyUp(WPARAM virtualKeyCode,LPARAM keyData,bool systemKeyDown)1499 bool WebView::keyUp(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
1500 {
1501     PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, PlatformKeyboardEvent::KeyUp, systemKeyDown);
1502 
1503     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1504     m_currentCharacterCode = 0;
1505 
1506     return frame->eventHandler()->keyEvent(keyEvent);
1507 }
1508 
1509 static const unsigned CtrlKey = 1 << 0;
1510 static const unsigned AltKey = 1 << 1;
1511 static const unsigned ShiftKey = 1 << 2;
1512 
1513 
1514 struct KeyDownEntry {
1515     unsigned virtualKey;
1516     unsigned modifiers;
1517     const char* name;
1518 };
1519 
1520 struct KeyPressEntry {
1521     unsigned charCode;
1522     unsigned modifiers;
1523     const char* name;
1524 };
1525 
1526 static const KeyDownEntry keyDownEntries[] = {
1527     { VK_LEFT,   0,                  "MoveLeft"                                    },
1528     { VK_LEFT,   ShiftKey,           "MoveLeftAndModifySelection"                  },
1529     { VK_LEFT,   CtrlKey,            "MoveWordLeft"                                },
1530     { VK_LEFT,   CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection"              },
1531     { VK_RIGHT,  0,                  "MoveRight"                                   },
1532     { VK_RIGHT,  ShiftKey,           "MoveRightAndModifySelection"                 },
1533     { VK_RIGHT,  CtrlKey,            "MoveWordRight"                               },
1534     { VK_RIGHT,  CtrlKey | ShiftKey, "MoveWordRightAndModifySelection"             },
1535     { VK_UP,     0,                  "MoveUp"                                      },
1536     { VK_UP,     ShiftKey,           "MoveUpAndModifySelection"                    },
1537     { VK_PRIOR,  ShiftKey,           "MovePageUpAndModifySelection"                },
1538     { VK_DOWN,   0,                  "MoveDown"                                    },
1539     { VK_DOWN,   ShiftKey,           "MoveDownAndModifySelection"                  },
1540     { VK_NEXT,   ShiftKey,           "MovePageDownAndModifySelection"              },
1541     { VK_PRIOR,  0,                  "MovePageUp"                                  },
1542     { VK_NEXT,   0,                  "MovePageDown"                                },
1543     { VK_HOME,   0,                  "MoveToBeginningOfLine"                       },
1544     { VK_HOME,   ShiftKey,           "MoveToBeginningOfLineAndModifySelection"     },
1545     { VK_HOME,   CtrlKey,            "MoveToBeginningOfDocument"                   },
1546     { VK_HOME,   CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" },
1547 
1548     { VK_END,    0,                  "MoveToEndOfLine"                             },
1549     { VK_END,    ShiftKey,           "MoveToEndOfLineAndModifySelection"           },
1550     { VK_END,    CtrlKey,            "MoveToEndOfDocument"                         },
1551     { VK_END,    CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection"       },
1552 
1553     { VK_BACK,   0,                  "DeleteBackward"                              },
1554     { VK_BACK,   ShiftKey,           "DeleteBackward"                              },
1555     { VK_DELETE, 0,                  "DeleteForward"                               },
1556     { VK_BACK,   CtrlKey,            "DeleteWordBackward"                          },
1557     { VK_DELETE, CtrlKey,            "DeleteWordForward"                           },
1558 
1559     { 'B',       CtrlKey,            "ToggleBold"                                  },
1560     { 'I',       CtrlKey,            "ToggleItalic"                                },
1561 
1562     { VK_ESCAPE, 0,                  "Cancel"                                      },
1563     { VK_OEM_PERIOD, CtrlKey,        "Cancel"                                      },
1564     { VK_TAB,    0,                  "InsertTab"                                   },
1565     { VK_TAB,    ShiftKey,           "InsertBacktab"                               },
1566     { VK_RETURN, 0,                  "InsertNewline"                               },
1567     { VK_RETURN, CtrlKey,            "InsertNewline"                               },
1568     { VK_RETURN, AltKey,             "InsertNewline"                               },
1569     { VK_RETURN, ShiftKey,           "InsertNewline"                               },
1570     { VK_RETURN, AltKey | ShiftKey,  "InsertNewline"                               },
1571 
1572     // It's not quite clear whether clipboard shortcuts and Undo/Redo should be handled
1573     // in the application or in WebKit. We chose WebKit.
1574     { 'C',       CtrlKey,            "Copy"                                        },
1575     { 'V',       CtrlKey,            "Paste"                                       },
1576     { 'X',       CtrlKey,            "Cut"                                         },
1577     { 'A',       CtrlKey,            "SelectAll"                                   },
1578     { VK_INSERT, CtrlKey,            "Copy"                                        },
1579     { VK_DELETE, ShiftKey,           "Cut"                                         },
1580     { VK_INSERT, ShiftKey,           "Paste"                                       },
1581     { 'Z',       CtrlKey,            "Undo"                                        },
1582     { 'Z',       CtrlKey | ShiftKey, "Redo"                                        },
1583 };
1584 
1585 static const KeyPressEntry keyPressEntries[] = {
1586     { '\t',   0,                  "InsertTab"                                   },
1587     { '\t',   ShiftKey,           "InsertBacktab"                               },
1588     { '\r',   0,                  "InsertNewline"                               },
1589     { '\r',   CtrlKey,            "InsertNewline"                               },
1590     { '\r',   AltKey,             "InsertNewline"                               },
1591     { '\r',   ShiftKey,           "InsertNewline"                               },
1592     { '\r',   AltKey | ShiftKey,  "InsertNewline"                               },
1593 };
1594 
interpretKeyEvent(const KeyboardEvent * evt)1595 const char* WebView::interpretKeyEvent(const KeyboardEvent* evt)
1596 {
1597     ASSERT(evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
1598 
1599     static HashMap<int, const char*>* keyDownCommandsMap = 0;
1600     static HashMap<int, const char*>* keyPressCommandsMap = 0;
1601 
1602     if (!keyDownCommandsMap) {
1603         keyDownCommandsMap = new HashMap<int, const char*>;
1604         keyPressCommandsMap = new HashMap<int, const char*>;
1605 
1606         for (unsigned i = 0; i < _countof(keyDownEntries); i++)
1607             keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
1608 
1609         for (unsigned i = 0; i < _countof(keyPressEntries); i++)
1610             keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
1611     }
1612 
1613     unsigned modifiers = 0;
1614     if (evt->shiftKey())
1615         modifiers |= ShiftKey;
1616     if (evt->altKey())
1617         modifiers |= AltKey;
1618     if (evt->ctrlKey())
1619         modifiers |= CtrlKey;
1620 
1621     if (evt->type() == eventNames().keydownEvent) {
1622         int mapKey = modifiers << 16 | evt->keyCode();
1623         return mapKey ? keyDownCommandsMap->get(mapKey) : 0;
1624     }
1625 
1626     int mapKey = modifiers << 16 | evt->charCode();
1627     return mapKey ? keyPressCommandsMap->get(mapKey) : 0;
1628 }
1629 
handleEditingKeyboardEvent(KeyboardEvent * evt)1630 bool WebView::handleEditingKeyboardEvent(KeyboardEvent* evt)
1631 {
1632     Node* node = evt->target()->toNode();
1633     ASSERT(node);
1634     Frame* frame = node->document()->frame();
1635     ASSERT(frame);
1636 
1637     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
1638     if (!keyEvent || keyEvent->isSystemKey())  // do not treat this as text input if it's a system key event
1639         return false;
1640 
1641     Editor::Command command = frame->editor()->command(interpretKeyEvent(evt));
1642 
1643     if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
1644         // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
1645         // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
1646         // (e.g. Tab that inserts a Tab character, or Enter).
1647         return !command.isTextInsertion() && command.execute(evt);
1648     }
1649 
1650      if (command.execute(evt))
1651         return true;
1652 
1653     // Don't insert null or control characters as they can result in unexpected behaviour
1654     if (evt->charCode() < ' ')
1655         return false;
1656 
1657     return frame->editor()->insertText(evt->keyEvent()->text(), evt);
1658 }
1659 
keyDown(WPARAM virtualKeyCode,LPARAM keyData,bool systemKeyDown)1660 bool WebView::keyDown(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
1661 {
1662     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1663     if (virtualKeyCode == VK_CAPITAL)
1664         frame->eventHandler()->capsLockStateMayHaveChanged();
1665 
1666     PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, PlatformKeyboardEvent::RawKeyDown, systemKeyDown);
1667     bool handled = frame->eventHandler()->keyEvent(keyEvent);
1668 
1669     // These events cannot be canceled, and we have no default handling for them.
1670     // FIXME: match IE list more closely, see <http://msdn2.microsoft.com/en-us/library/ms536938.aspx>.
1671     if (systemKeyDown && virtualKeyCode != VK_RETURN)
1672         return false;
1673 
1674     if (handled) {
1675         // FIXME: remove WM_UNICHAR, too
1676         MSG msg;
1677         // WM_SYSCHAR events should not be removed, because access keys are implemented in WebCore in WM_SYSCHAR handler.
1678         if (!systemKeyDown)
1679             ::PeekMessage(&msg, m_viewWindow, WM_CHAR, WM_CHAR, PM_REMOVE);
1680         return true;
1681     }
1682 
1683     // We need to handle back/forward using either Backspace(+Shift) or Ctrl+Left/Right Arrow keys.
1684     if ((virtualKeyCode == VK_BACK && keyEvent.shiftKey()) || (virtualKeyCode == VK_RIGHT && keyEvent.ctrlKey()))
1685         m_page->goForward();
1686     else if (virtualKeyCode == VK_BACK || (virtualKeyCode == VK_LEFT && keyEvent.ctrlKey()))
1687         m_page->goBack();
1688 
1689     // Need to scroll the page if the arrow keys, pgup/dn, or home/end are hit.
1690     ScrollDirection direction;
1691     ScrollGranularity granularity;
1692     switch (virtualKeyCode) {
1693         case VK_LEFT:
1694             granularity = ScrollByLine;
1695             direction = ScrollLeft;
1696             break;
1697         case VK_RIGHT:
1698             granularity = ScrollByLine;
1699             direction = ScrollRight;
1700             break;
1701         case VK_UP:
1702             granularity = ScrollByLine;
1703             direction = ScrollUp;
1704             break;
1705         case VK_DOWN:
1706             granularity = ScrollByLine;
1707             direction = ScrollDown;
1708             break;
1709         case VK_HOME:
1710             granularity = ScrollByDocument;
1711             direction = ScrollUp;
1712             break;
1713         case VK_END:
1714             granularity = ScrollByDocument;
1715             direction = ScrollDown;
1716             break;
1717         case VK_PRIOR:
1718             granularity = ScrollByPage;
1719             direction = ScrollUp;
1720             break;
1721         case VK_NEXT:
1722             granularity = ScrollByPage;
1723             direction = ScrollDown;
1724             break;
1725         default:
1726             return false;
1727     }
1728 
1729     return frame->eventHandler()->scrollRecursively(direction, granularity);
1730 }
1731 
keyPress(WPARAM charCode,LPARAM keyData,bool systemKeyDown)1732 bool WebView::keyPress(WPARAM charCode, LPARAM keyData, bool systemKeyDown)
1733 {
1734     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1735 
1736     PlatformKeyboardEvent keyEvent(m_viewWindow, charCode, keyData, PlatformKeyboardEvent::Char, systemKeyDown);
1737     // IE does not dispatch keypress event for WM_SYSCHAR.
1738     if (systemKeyDown)
1739         return frame->eventHandler()->handleAccessKey(keyEvent);
1740     return frame->eventHandler()->keyEvent(keyEvent);
1741 }
1742 
inResizer(LPARAM lParam)1743 bool WebView::inResizer(LPARAM lParam)
1744 {
1745     if (!m_uiDelegatePrivate)
1746         return false;
1747 
1748     RECT r;
1749     if (FAILED(m_uiDelegatePrivate->webViewResizerRect(this, &r)))
1750         return false;
1751 
1752     POINT pt;
1753     pt.x = LOWORD(lParam);
1754     pt.y = HIWORD(lParam);
1755     return !!PtInRect(&r, pt);
1756 }
1757 
registerWebViewWindowClass()1758 static bool registerWebViewWindowClass()
1759 {
1760     static bool haveRegisteredWindowClass = false;
1761     if (haveRegisteredWindowClass)
1762         return true;
1763 
1764     haveRegisteredWindowClass = true;
1765 
1766     WNDCLASSEX wcex;
1767 
1768     wcex.cbSize = sizeof(WNDCLASSEX);
1769 
1770     wcex.style          = CS_DBLCLKS;
1771     wcex.lpfnWndProc    = WebViewWndProc;
1772     wcex.cbClsExtra     = 0;
1773     wcex.cbWndExtra     = 4; // 4 bytes for the IWebView pointer
1774     wcex.hInstance      = gInstance;
1775     wcex.hIcon          = 0;
1776     wcex.hCursor        = ::LoadCursor(0, IDC_ARROW);
1777     wcex.hbrBackground  = 0;
1778     wcex.lpszMenuName   = 0;
1779     wcex.lpszClassName  = kWebViewWindowClassName;
1780     wcex.hIconSm        = 0;
1781 
1782     return !!RegisterClassEx(&wcex);
1783 }
1784 
1785 namespace WebCore {
1786     extern HCURSOR lastSetCursor;
1787 }
1788 
findTopLevelParent(HWND window)1789 static HWND findTopLevelParent(HWND window)
1790 {
1791     if (!window)
1792         return 0;
1793 
1794     HWND current = window;
1795     for (HWND parent = GetParent(current); current; current = parent, parent = GetParent(parent))
1796         if (!parent || !(GetWindowLongPtr(current, GWL_STYLE) & (WS_POPUP | WS_CHILD)))
1797             return current;
1798     ASSERT_NOT_REACHED();
1799     return 0;
1800 }
1801 
WebViewWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)1802 static LRESULT CALLBACK WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1803 {
1804     LRESULT lResult = 0;
1805     LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0);
1806     WebView* webView = reinterpret_cast<WebView*>(longPtr);
1807     WebFrame* mainFrameImpl = webView ? webView->topLevelFrame() : 0;
1808     if (!mainFrameImpl || webView->isBeingDestroyed())
1809         return DefWindowProc(hWnd, message, wParam, lParam);
1810 
1811     // hold a ref, since the WebView could go away in an event handler.
1812     COMPtr<WebView> protector(webView);
1813     ASSERT(webView);
1814 
1815     // Windows Media Player has a modal message loop that will deliver messages
1816     // to us at inappropriate times and we will crash if we handle them when
1817     // they are delivered. We repost paint messages so that we eventually get
1818     // a chance to paint once the modal loop has exited, but other messages
1819     // aren't safe to repost, so we just drop them.
1820     if (PluginView::isCallingPlugin()) {
1821         if (message == WM_PAINT)
1822             PostMessage(hWnd, message, wParam, lParam);
1823         return 0;
1824     }
1825 
1826     bool handled = true;
1827 
1828     switch (message) {
1829         case WM_PAINT: {
1830             webView->paint(0, 0);
1831             break;
1832         }
1833         case WM_PRINTCLIENT:
1834             webView->paint((HDC)wParam, lParam);
1835             break;
1836         case WM_DESTROY:
1837             webView->close();
1838             webView->setIsBeingDestroyed();
1839             webView->revokeDragDrop();
1840             break;
1841         case WM_GESTURENOTIFY:
1842             handled = webView->gestureNotify(wParam, lParam);
1843             break;
1844         case WM_GESTURE:
1845             handled = webView->gesture(wParam, lParam);
1846             break;
1847         case WM_MOUSEMOVE:
1848         case WM_LBUTTONDOWN:
1849         case WM_MBUTTONDOWN:
1850         case WM_RBUTTONDOWN:
1851         case WM_LBUTTONDBLCLK:
1852         case WM_MBUTTONDBLCLK:
1853         case WM_RBUTTONDBLCLK:
1854         case WM_LBUTTONUP:
1855         case WM_MBUTTONUP:
1856         case WM_RBUTTONUP:
1857         case WM_MOUSELEAVE:
1858             if (Frame* coreFrame = core(mainFrameImpl))
1859                 if (coreFrame->view()->didFirstLayout())
1860                     handled = webView->handleMouseEvent(message, wParam, lParam);
1861             break;
1862         case WM_MOUSEWHEEL:
1863         case WM_VISTA_MOUSEHWHEEL:
1864             if (Frame* coreFrame = core(mainFrameImpl))
1865                 if (coreFrame->view()->didFirstLayout())
1866                     handled = webView->mouseWheel(wParam, lParam, message == WM_VISTA_MOUSEHWHEEL);
1867             break;
1868         case WM_SYSKEYDOWN:
1869             handled = webView->keyDown(wParam, lParam, true);
1870             break;
1871         case WM_KEYDOWN:
1872             handled = webView->keyDown(wParam, lParam);
1873             break;
1874         case WM_SYSKEYUP:
1875             handled = webView->keyUp(wParam, lParam, true);
1876             break;
1877         case WM_KEYUP:
1878             handled = webView->keyUp(wParam, lParam);
1879             break;
1880         case WM_SYSCHAR:
1881             handled = webView->keyPress(wParam, lParam, true);
1882             break;
1883         case WM_CHAR:
1884             handled = webView->keyPress(wParam, lParam);
1885             break;
1886         // FIXME: We need to check WM_UNICHAR to support supplementary characters (that don't fit in 16 bits).
1887         case WM_SIZE:
1888             if (webView->isBeingDestroyed())
1889                 // If someone has sent us this message while we're being destroyed, we should bail out so we don't crash.
1890                 break;
1891 
1892             if (lParam != 0) {
1893                 webView->deleteBackingStore();
1894                 if (Frame* coreFrame = core(mainFrameImpl))
1895                     coreFrame->view()->resize(LOWORD(lParam), HIWORD(lParam));
1896             }
1897             break;
1898         case WM_SHOWWINDOW:
1899             lResult = DefWindowProc(hWnd, message, wParam, lParam);
1900             if (wParam == 0)
1901                 // The window is being hidden (e.g., because we switched tabs).
1902                 // Null out our backing store.
1903                 webView->deleteBackingStore();
1904             break;
1905         case WM_SETFOCUS: {
1906             COMPtr<IWebUIDelegate> uiDelegate;
1907             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
1908             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate &&
1909                 SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)
1910                 uiDelegatePrivate->webViewReceivedFocus(webView);
1911 
1912             FocusController* focusController = webView->page()->focusController();
1913             if (Frame* frame = focusController->focusedFrame()) {
1914                 // Send focus events unless the previously focused window is a
1915                 // child of ours (for example a plugin).
1916                 if (!IsChild(hWnd, reinterpret_cast<HWND>(wParam)))
1917                     focusController->setFocused(true);
1918             } else {
1919                 focusController->setFocused(true);
1920                 focusController->setFocusedFrame(webView->page()->mainFrame());
1921             }
1922             break;
1923         }
1924         case WM_KILLFOCUS: {
1925             COMPtr<IWebUIDelegate> uiDelegate;
1926             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
1927             HWND newFocusWnd = reinterpret_cast<HWND>(wParam);
1928             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate &&
1929                 SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)
1930                 uiDelegatePrivate->webViewLostFocus(webView, (OLE_HANDLE)(ULONG64)newFocusWnd);
1931 
1932             FocusController* focusController = webView->page()->focusController();
1933             Frame* frame = focusController->focusedOrMainFrame();
1934             webView->resetIME(frame);
1935             // Send blur events unless we're losing focus to a child of ours.
1936             if (!IsChild(hWnd, newFocusWnd))
1937                 focusController->setFocused(false);
1938             break;
1939         }
1940         case WM_WINDOWPOSCHANGED:
1941             if (reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_SHOWWINDOW)
1942                 webView->updateActiveStateSoon();
1943             handled = false;
1944             break;
1945         case WM_CUT:
1946             webView->cut(0);
1947             break;
1948         case WM_COPY:
1949             webView->copy(0);
1950             break;
1951         case WM_PASTE:
1952             webView->paste(0);
1953             break;
1954         case WM_CLEAR:
1955             webView->delete_(0);
1956             break;
1957         case WM_COMMAND:
1958             if (HIWORD(wParam))
1959                 handled = webView->execCommand(wParam, lParam);
1960             else // If the high word of wParam is 0, the message is from a menu
1961                 webView->performContextMenuAction(wParam, lParam, false);
1962             break;
1963         case WM_MENUCOMMAND:
1964             webView->performContextMenuAction(wParam, lParam, true);
1965             break;
1966         case WM_CONTEXTMENU:
1967             handled = webView->handleContextMenuEvent(wParam, lParam);
1968             break;
1969         case WM_INITMENUPOPUP:
1970             handled = webView->onInitMenuPopup(wParam, lParam);
1971             break;
1972         case WM_MEASUREITEM:
1973             handled = webView->onMeasureItem(wParam, lParam);
1974             break;
1975         case WM_DRAWITEM:
1976             handled = webView->onDrawItem(wParam, lParam);
1977             break;
1978         case WM_UNINITMENUPOPUP:
1979             handled = webView->onUninitMenuPopup(wParam, lParam);
1980             break;
1981         case WM_XP_THEMECHANGED:
1982             if (Frame* coreFrame = core(mainFrameImpl)) {
1983                 webView->deleteBackingStore();
1984                 coreFrame->page()->theme()->themeChanged();
1985                 ScrollbarTheme::nativeTheme()->themeChanged();
1986                 RECT windowRect;
1987                 ::GetClientRect(hWnd, &windowRect);
1988                 ::InvalidateRect(hWnd, &windowRect, false);
1989             }
1990             break;
1991         case WM_MOUSEACTIVATE:
1992             webView->setMouseActivated(true);
1993             break;
1994         case WM_GETDLGCODE: {
1995             COMPtr<IWebUIDelegate> uiDelegate;
1996             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
1997             LONG_PTR dlgCode = 0;
1998             UINT keyCode = 0;
1999             if (lParam) {
2000                 LPMSG lpMsg = (LPMSG)lParam;
2001                 if (lpMsg->message == WM_KEYDOWN)
2002                     keyCode = (UINT) lpMsg->wParam;
2003             }
2004             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate &&
2005                 SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate &&
2006                 SUCCEEDED(uiDelegatePrivate->webViewGetDlgCode(webView, keyCode, &dlgCode)))
2007                 return dlgCode;
2008             handled = false;
2009             break;
2010         }
2011         case WM_GETOBJECT:
2012             handled = webView->onGetObject(wParam, lParam, lResult);
2013             break;
2014         case WM_IME_STARTCOMPOSITION:
2015             handled = webView->onIMEStartComposition();
2016             break;
2017         case WM_IME_REQUEST:
2018             webView->onIMERequest(wParam, lParam, &lResult);
2019             break;
2020         case WM_IME_COMPOSITION:
2021             handled = webView->onIMEComposition(lParam);
2022             break;
2023         case WM_IME_ENDCOMPOSITION:
2024             handled = webView->onIMEEndComposition();
2025             break;
2026         case WM_IME_CHAR:
2027             handled = webView->onIMEChar(wParam, lParam);
2028             break;
2029         case WM_IME_NOTIFY:
2030             handled = webView->onIMENotify(wParam, lParam, &lResult);
2031             break;
2032         case WM_IME_SELECT:
2033             handled = webView->onIMESelect(wParam, lParam);
2034             break;
2035         case WM_IME_SETCONTEXT:
2036             handled = webView->onIMESetContext(wParam, lParam);
2037             break;
2038         case WM_TIMER:
2039             switch (wParam) {
2040                 case UpdateActiveStateTimer:
2041                     KillTimer(hWnd, UpdateActiveStateTimer);
2042                     webView->updateActiveState();
2043                     break;
2044                 case DeleteBackingStoreTimer:
2045                     webView->deleteBackingStore();
2046                     break;
2047             }
2048             break;
2049         case WM_SETCURSOR:
2050             if (handled = webView->page()->chrome()->setCursor(lastSetCursor))
2051                 break;
2052 
2053             __fallthrough;
2054         default:
2055             handled = false;
2056             break;
2057     }
2058 
2059     if (!handled)
2060         lResult = DefWindowProc(hWnd, message, wParam, lParam);
2061 
2062     // Let the client know whether we consider this message handled.
2063     return (message == WM_KEYDOWN || message == WM_SYSKEYDOWN || message == WM_KEYUP || message == WM_SYSKEYUP) ? !handled : lResult;
2064 }
2065 
developerExtrasEnabled() const2066 bool WebView::developerExtrasEnabled() const
2067 {
2068     if (m_preferences->developerExtrasDisabledByOverride())
2069         return false;
2070 
2071 #ifdef NDEBUG
2072     BOOL enabled;
2073     return SUCCEEDED(m_preferences->developerExtrasEnabled(&enabled)) && enabled;
2074 #else
2075     return true;
2076 #endif
2077 }
2078 
osVersion()2079 static String osVersion()
2080 {
2081     String osVersion;
2082     OSVERSIONINFO versionInfo = {0};
2083     versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
2084     GetVersionEx(&versionInfo);
2085 
2086     if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
2087         if (versionInfo.dwMajorVersion == 4) {
2088             if (versionInfo.dwMinorVersion == 0)
2089                 osVersion = "Windows 95";
2090             else if (versionInfo.dwMinorVersion == 10)
2091                 osVersion = "Windows 98";
2092             else if (versionInfo.dwMinorVersion == 90)
2093                 osVersion = "Windows 98; Win 9x 4.90";
2094         }
2095     } else if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
2096         osVersion = String::format("Windows NT %d.%d", versionInfo.dwMajorVersion, versionInfo.dwMinorVersion);
2097 
2098     if (!osVersion.length())
2099         osVersion = String::format("Windows %d.%d", versionInfo.dwMajorVersion, versionInfo.dwMinorVersion);
2100 
2101     return osVersion;
2102 }
2103 
webKitVersion()2104 static String webKitVersion()
2105 {
2106     String versionStr = "420+";
2107     void* data = 0;
2108 
2109     struct LANGANDCODEPAGE {
2110         WORD wLanguage;
2111         WORD wCodePage;
2112     } *lpTranslate;
2113 
2114     TCHAR path[MAX_PATH];
2115     GetModuleFileName(gInstance, path, ARRAYSIZE(path));
2116     DWORD handle;
2117     DWORD versionSize = GetFileVersionInfoSize(path, &handle);
2118     if (!versionSize)
2119         goto exit;
2120     data = malloc(versionSize);
2121     if (!data)
2122         goto exit;
2123     if (!GetFileVersionInfo(path, 0, versionSize, data))
2124         goto exit;
2125     UINT cbTranslate;
2126     if (!VerQueryValue(data, TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &cbTranslate))
2127         goto exit;
2128     TCHAR key[256];
2129     _stprintf_s(key, ARRAYSIZE(key), TEXT("\\StringFileInfo\\%04x%04x\\ProductVersion"), lpTranslate[0].wLanguage, lpTranslate[0].wCodePage);
2130     LPCTSTR productVersion;
2131     UINT productVersionLength;
2132     if (!VerQueryValue(data, (LPTSTR)(LPCTSTR)key, (void**)&productVersion, &productVersionLength))
2133         goto exit;
2134     versionStr = String(productVersion, productVersionLength);
2135 
2136 exit:
2137     if (data)
2138         free(data);
2139     return versionStr;
2140 }
2141 
userAgentForKURL(const KURL &)2142 const String& WebView::userAgentForKURL(const KURL&)
2143 {
2144     if (m_userAgentOverridden)
2145         return m_userAgentCustom;
2146 
2147     if (!m_userAgentStandard.length())
2148         m_userAgentStandard = WebView::standardUserAgentWithApplicationName(m_applicationName);
2149     return m_userAgentStandard;
2150 }
2151 
2152 // IUnknown -------------------------------------------------------------------
2153 
QueryInterface(REFIID riid,void ** ppvObject)2154 HRESULT STDMETHODCALLTYPE WebView::QueryInterface(REFIID riid, void** ppvObject)
2155 {
2156     *ppvObject = 0;
2157     if (IsEqualGUID(riid, CLSID_WebView))
2158         *ppvObject = this;
2159     else if (IsEqualGUID(riid, IID_IUnknown))
2160         *ppvObject = static_cast<IWebView*>(this);
2161     else if (IsEqualGUID(riid, IID_IWebView))
2162         *ppvObject = static_cast<IWebView*>(this);
2163     else if (IsEqualGUID(riid, IID_IWebViewPrivate))
2164         *ppvObject = static_cast<IWebViewPrivate*>(this);
2165     else if (IsEqualGUID(riid, IID_IWebIBActions))
2166         *ppvObject = static_cast<IWebIBActions*>(this);
2167     else if (IsEqualGUID(riid, IID_IWebViewCSS))
2168         *ppvObject = static_cast<IWebViewCSS*>(this);
2169     else if (IsEqualGUID(riid, IID_IWebViewEditing))
2170         *ppvObject = static_cast<IWebViewEditing*>(this);
2171     else if (IsEqualGUID(riid, IID_IWebViewUndoableEditing))
2172         *ppvObject = static_cast<IWebViewUndoableEditing*>(this);
2173     else if (IsEqualGUID(riid, IID_IWebViewEditingActions))
2174         *ppvObject = static_cast<IWebViewEditingActions*>(this);
2175     else if (IsEqualGUID(riid, IID_IWebNotificationObserver))
2176         *ppvObject = static_cast<IWebNotificationObserver*>(this);
2177     else if (IsEqualGUID(riid, IID_IDropTarget))
2178         *ppvObject = static_cast<IDropTarget*>(this);
2179     else
2180         return E_NOINTERFACE;
2181 
2182     AddRef();
2183     return S_OK;
2184 }
2185 
AddRef(void)2186 ULONG STDMETHODCALLTYPE WebView::AddRef(void)
2187 {
2188     return ++m_refCount;
2189 }
2190 
Release(void)2191 ULONG STDMETHODCALLTYPE WebView::Release(void)
2192 {
2193     ULONG newRef = --m_refCount;
2194     if (!newRef)
2195         delete(this);
2196 
2197     return newRef;
2198 }
2199 
2200 // IWebView --------------------------------------------------------------------
2201 
canShowMIMEType(BSTR mimeType,BOOL * canShow)2202 HRESULT STDMETHODCALLTYPE WebView::canShowMIMEType(
2203     /* [in] */ BSTR mimeType,
2204     /* [retval][out] */ BOOL* canShow)
2205 {
2206     String mimeTypeStr(mimeType, SysStringLen(mimeType));
2207 
2208     if (!canShow)
2209         return E_POINTER;
2210 
2211     *canShow = MIMETypeRegistry::isSupportedImageMIMEType(mimeTypeStr) ||
2212         MIMETypeRegistry::isSupportedNonImageMIMEType(mimeTypeStr) ||
2213         PluginInfoStore::supportsMIMEType(mimeTypeStr) ||
2214         shouldUseEmbeddedView(mimeTypeStr);
2215 
2216     return S_OK;
2217 }
2218 
canShowMIMETypeAsHTML(BSTR,BOOL * canShow)2219 HRESULT STDMETHODCALLTYPE WebView::canShowMIMETypeAsHTML(
2220     /* [in] */ BSTR /*mimeType*/,
2221     /* [retval][out] */ BOOL* canShow)
2222 {
2223     // FIXME
2224     *canShow = TRUE;
2225     return S_OK;
2226 }
2227 
MIMETypesShownAsHTML(IEnumVARIANT **)2228 HRESULT STDMETHODCALLTYPE WebView::MIMETypesShownAsHTML(
2229     /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
2230 {
2231     ASSERT_NOT_REACHED();
2232     return E_NOTIMPL;
2233 }
2234 
setMIMETypesShownAsHTML(BSTR *,int)2235 HRESULT STDMETHODCALLTYPE WebView::setMIMETypesShownAsHTML(
2236         /* [size_is][in] */ BSTR* /*mimeTypes*/,
2237         /* [in] */ int /*cMimeTypes*/)
2238 {
2239     ASSERT_NOT_REACHED();
2240     return E_NOTIMPL;
2241 }
2242 
URLFromPasteboard(IDataObject *,BSTR *)2243 HRESULT STDMETHODCALLTYPE WebView::URLFromPasteboard(
2244     /* [in] */ IDataObject* /*pasteboard*/,
2245     /* [retval][out] */ BSTR* /*url*/)
2246 {
2247     ASSERT_NOT_REACHED();
2248     return E_NOTIMPL;
2249 }
2250 
URLTitleFromPasteboard(IDataObject *,BSTR *)2251 HRESULT STDMETHODCALLTYPE WebView::URLTitleFromPasteboard(
2252     /* [in] */ IDataObject* /*pasteboard*/,
2253     /* [retval][out] */ BSTR* /*urlTitle*/)
2254 {
2255     ASSERT_NOT_REACHED();
2256     return E_NOTIMPL;
2257 }
2258 
WebKitSetApplicationCachePathIfNecessary()2259 static void WebKitSetApplicationCachePathIfNecessary()
2260 {
2261     static bool initialized = false;
2262     if (initialized)
2263         return;
2264 
2265     String path = localUserSpecificStorageDirectory();
2266     if (!path.isNull())
2267         cacheStorage().setCacheDirectory(path);
2268 
2269     initialized = true;
2270 }
2271 
initWithFrame(RECT frame,BSTR frameName,BSTR groupName)2272 HRESULT STDMETHODCALLTYPE WebView::initWithFrame(
2273     /* [in] */ RECT frame,
2274     /* [in] */ BSTR frameName,
2275     /* [in] */ BSTR groupName)
2276 {
2277     HRESULT hr = S_OK;
2278 
2279     if (m_viewWindow)
2280         return E_FAIL;
2281 
2282     registerWebViewWindowClass();
2283 
2284     if (!::IsWindow(m_hostWindow)) {
2285         ASSERT_NOT_REACHED();
2286         return E_FAIL;
2287     }
2288 
2289     m_viewWindow = CreateWindowEx(0, kWebViewWindowClassName, 0, WS_CHILD | WS_CLIPCHILDREN,
2290         frame.left, frame.top, frame.right - frame.left, frame.bottom - frame.top, m_hostWindow, 0, gInstance, 0);
2291     ASSERT(::IsWindow(m_viewWindow));
2292 
2293     hr = registerDragDrop();
2294     if (FAILED(hr))
2295         return hr;
2296 
2297     WebPreferences* sharedPreferences = WebPreferences::sharedStandardPreferences();
2298     sharedPreferences->willAddToWebView();
2299     m_preferences = sharedPreferences;
2300 
2301     InitializeLoggingChannelsIfNecessary();
2302 #if ENABLE(DATABASE)
2303     WebKitSetWebDatabasesPathIfNecessary();
2304 #endif
2305     WebKitSetApplicationCachePathIfNecessary();
2306 
2307 #if USE(SAFARI_THEME)
2308     BOOL shouldPaintNativeControls;
2309     if (SUCCEEDED(m_preferences->shouldPaintNativeControls(&shouldPaintNativeControls)))
2310         Settings::setShouldPaintNativeControls(shouldPaintNativeControls);
2311 #endif
2312 
2313     m_page = new Page(new WebChromeClient(this), new WebContextMenuClient(this), new WebEditorClient(this), new WebDragClient(this), new WebInspectorClient(this));
2314 
2315     BSTR localStoragePath;
2316     if (SUCCEEDED(m_preferences->localStorageDatabasePath(&localStoragePath))) {
2317         m_page->settings()->setLocalStorageDatabasePath(String(localStoragePath, SysStringLen(localStoragePath)));
2318         SysFreeString(localStoragePath);
2319     }
2320 
2321     if (m_uiDelegate) {
2322         BSTR path;
2323         if (SUCCEEDED(m_uiDelegate->ftpDirectoryTemplatePath(this, &path))) {
2324             m_page->settings()->setFTPDirectoryTemplatePath(String(path, SysStringLen(path)));
2325             SysFreeString(path);
2326         }
2327     }
2328 
2329     WebFrame* webFrame = WebFrame::createInstance();
2330     RefPtr<Frame> coreFrame = webFrame->init(this, m_page, 0);
2331     m_mainFrame = webFrame;
2332     webFrame->Release(); // The WebFrame is owned by the Frame, so release our reference to it.
2333 
2334     coreFrame->tree()->setName(String(frameName, SysStringLen(frameName)));
2335     coreFrame->init();
2336     setGroupName(groupName);
2337 
2338     addToAllWebViewsSet();
2339 
2340     #pragma warning(suppress: 4244)
2341     SetWindowLongPtr(m_viewWindow, 0, (LONG_PTR)this);
2342     ShowWindow(m_viewWindow, SW_SHOW);
2343 
2344     initializeToolTipWindow();
2345     windowAncestryDidChange();
2346 
2347     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
2348     notifyCenter->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
2349     m_preferences->postPreferencesChangesNotification();
2350 
2351     setSmartInsertDeleteEnabled(TRUE);
2352     return hr;
2353 }
2354 
initCommonControls()2355 static bool initCommonControls()
2356 {
2357     static bool haveInitialized = false;
2358     if (haveInitialized)
2359         return true;
2360 
2361     INITCOMMONCONTROLSEX init;
2362     init.dwSize = sizeof(init);
2363     init.dwICC = ICC_TREEVIEW_CLASSES;
2364     haveInitialized = !!::InitCommonControlsEx(&init);
2365     return haveInitialized;
2366 }
2367 
initializeToolTipWindow()2368 void WebView::initializeToolTipWindow()
2369 {
2370     if (!initCommonControls())
2371         return;
2372 
2373     m_toolTipHwnd = CreateWindowEx(0, TOOLTIPS_CLASS, 0, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
2374                                    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
2375                                    m_viewWindow, 0, 0, 0);
2376     if (!m_toolTipHwnd)
2377         return;
2378 
2379     TOOLINFO info = {0};
2380     info.cbSize = sizeof(info);
2381     info.uFlags = TTF_IDISHWND | TTF_SUBCLASS ;
2382     info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
2383 
2384     ::SendMessage(m_toolTipHwnd, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&info));
2385     ::SendMessage(m_toolTipHwnd, TTM_SETMAXTIPWIDTH, 0, maxToolTipWidth);
2386 
2387     ::SetWindowPos(m_toolTipHwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
2388 }
2389 
setToolTip(const String & toolTip)2390 void WebView::setToolTip(const String& toolTip)
2391 {
2392     if (!m_toolTipHwnd)
2393         return;
2394 
2395     if (toolTip == m_toolTip)
2396         return;
2397 
2398     m_toolTip = toolTip;
2399 
2400     if (!m_toolTip.isEmpty()) {
2401         TOOLINFO info = {0};
2402         info.cbSize = sizeof(info);
2403         info.uFlags = TTF_IDISHWND;
2404         info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
2405         info.lpszText = const_cast<UChar*>(m_toolTip.charactersWithNullTermination());
2406         ::SendMessage(m_toolTipHwnd, TTM_UPDATETIPTEXT, 0, reinterpret_cast<LPARAM>(&info));
2407     }
2408 
2409     ::SendMessage(m_toolTipHwnd, TTM_ACTIVATE, !m_toolTip.isEmpty(), 0);
2410 }
2411 
notifyDidAddIcon(IWebNotification * notification)2412 HRESULT WebView::notifyDidAddIcon(IWebNotification* notification)
2413 {
2414     COMPtr<IPropertyBag> propertyBag;
2415     HRESULT hr = notification->userInfo(&propertyBag);
2416     if (FAILED(hr))
2417         return hr;
2418     if (!propertyBag)
2419         return E_FAIL;
2420 
2421     COMPtr<CFDictionaryPropertyBag> dictionaryPropertyBag;
2422     hr = propertyBag->QueryInterface(&dictionaryPropertyBag);
2423     if (FAILED(hr))
2424         return hr;
2425 
2426     CFDictionaryRef dictionary = dictionaryPropertyBag->dictionary();
2427     if (!dictionary)
2428         return E_FAIL;
2429 
2430     CFTypeRef value = CFDictionaryGetValue(dictionary, WebIconDatabase::iconDatabaseNotificationUserInfoURLKey());
2431     if (!value)
2432         return E_FAIL;
2433     if (CFGetTypeID(value) != CFStringGetTypeID())
2434         return E_FAIL;
2435 
2436     String mainFrameURL;
2437     if (m_mainFrame)
2438         mainFrameURL = m_mainFrame->url().string();
2439 
2440     if (!mainFrameURL.isEmpty() && mainFrameURL == String((CFStringRef)value))
2441         dispatchDidReceiveIconFromWebFrame(m_mainFrame);
2442 
2443     return hr;
2444 }
2445 
registerForIconNotification(bool listen)2446 void WebView::registerForIconNotification(bool listen)
2447 {
2448     IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
2449     if (listen)
2450         nc->addObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
2451     else
2452         nc->removeObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
2453 }
2454 
dispatchDidReceiveIconFromWebFrame(WebFrame * frame)2455 void WebView::dispatchDidReceiveIconFromWebFrame(WebFrame* frame)
2456 {
2457     registerForIconNotification(false);
2458 
2459     if (m_frameLoadDelegate)
2460         // FIXME: <rdar://problem/5491010> - Pass in the right HBITMAP.
2461         m_frameLoadDelegate->didReceiveIcon(this, 0, frame);
2462 }
2463 
setUIDelegate(IWebUIDelegate * d)2464 HRESULT STDMETHODCALLTYPE WebView::setUIDelegate(
2465     /* [in] */ IWebUIDelegate* d)
2466 {
2467     m_uiDelegate = d;
2468 
2469     if (m_uiDelegatePrivate)
2470         m_uiDelegatePrivate = 0;
2471 
2472     if (d) {
2473         if (FAILED(d->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&m_uiDelegatePrivate)))
2474             m_uiDelegatePrivate = 0;
2475     }
2476 
2477     return S_OK;
2478 }
2479 
uiDelegate(IWebUIDelegate ** d)2480 HRESULT STDMETHODCALLTYPE WebView::uiDelegate(
2481     /* [out][retval] */ IWebUIDelegate** d)
2482 {
2483     if (!m_uiDelegate)
2484         return E_FAIL;
2485 
2486     return m_uiDelegate.copyRefTo(d);
2487 }
2488 
setResourceLoadDelegate(IWebResourceLoadDelegate * d)2489 HRESULT STDMETHODCALLTYPE WebView::setResourceLoadDelegate(
2490     /* [in] */ IWebResourceLoadDelegate* d)
2491 {
2492     m_resourceLoadDelegate = d;
2493     return S_OK;
2494 }
2495 
resourceLoadDelegate(IWebResourceLoadDelegate ** d)2496 HRESULT STDMETHODCALLTYPE WebView::resourceLoadDelegate(
2497     /* [out][retval] */ IWebResourceLoadDelegate** d)
2498 {
2499     if (!m_resourceLoadDelegate)
2500         return E_FAIL;
2501 
2502     return m_resourceLoadDelegate.copyRefTo(d);
2503 }
2504 
setDownloadDelegate(IWebDownloadDelegate * d)2505 HRESULT STDMETHODCALLTYPE WebView::setDownloadDelegate(
2506     /* [in] */ IWebDownloadDelegate* d)
2507 {
2508     m_downloadDelegate = d;
2509     return S_OK;
2510 }
2511 
downloadDelegate(IWebDownloadDelegate ** d)2512 HRESULT STDMETHODCALLTYPE WebView::downloadDelegate(
2513     /* [out][retval] */ IWebDownloadDelegate** d)
2514 {
2515     if (!m_downloadDelegate)
2516         return E_FAIL;
2517 
2518     return m_downloadDelegate.copyRefTo(d);
2519 }
2520 
setFrameLoadDelegate(IWebFrameLoadDelegate * d)2521 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegate(
2522     /* [in] */ IWebFrameLoadDelegate* d)
2523 {
2524     m_frameLoadDelegate = d;
2525     return S_OK;
2526 }
2527 
frameLoadDelegate(IWebFrameLoadDelegate ** d)2528 HRESULT STDMETHODCALLTYPE WebView::frameLoadDelegate(
2529     /* [out][retval] */ IWebFrameLoadDelegate** d)
2530 {
2531     if (!m_frameLoadDelegate)
2532         return E_FAIL;
2533 
2534     return m_frameLoadDelegate.copyRefTo(d);
2535 }
2536 
setPolicyDelegate(IWebPolicyDelegate * d)2537 HRESULT STDMETHODCALLTYPE WebView::setPolicyDelegate(
2538     /* [in] */ IWebPolicyDelegate* d)
2539 {
2540     m_policyDelegate = d;
2541     return S_OK;
2542 }
2543 
policyDelegate(IWebPolicyDelegate ** d)2544 HRESULT STDMETHODCALLTYPE WebView::policyDelegate(
2545     /* [out][retval] */ IWebPolicyDelegate** d)
2546 {
2547     if (!m_policyDelegate)
2548         return E_FAIL;
2549     return m_policyDelegate.copyRefTo(d);
2550 }
2551 
mainFrame(IWebFrame ** frame)2552 HRESULT STDMETHODCALLTYPE WebView::mainFrame(
2553     /* [out][retval] */ IWebFrame** frame)
2554 {
2555     if (!frame) {
2556         ASSERT_NOT_REACHED();
2557         return E_POINTER;
2558     }
2559 
2560     *frame = m_mainFrame;
2561     if (!m_mainFrame)
2562         return E_FAIL;
2563 
2564     m_mainFrame->AddRef();
2565     return S_OK;
2566 }
2567 
focusedFrame(IWebFrame ** frame)2568 HRESULT STDMETHODCALLTYPE WebView::focusedFrame(
2569     /* [out][retval] */ IWebFrame** frame)
2570 {
2571     if (!frame) {
2572         ASSERT_NOT_REACHED();
2573         return E_POINTER;
2574     }
2575 
2576     *frame = 0;
2577     Frame* f = m_page->focusController()->focusedFrame();
2578     if (!f)
2579         return E_FAIL;
2580 
2581     WebFrame* webFrame = kit(f);
2582     if (!webFrame)
2583         return E_FAIL;
2584 
2585     return webFrame->QueryInterface(IID_IWebFrame, (void**) frame);
2586 }
backForwardList(IWebBackForwardList ** list)2587 HRESULT STDMETHODCALLTYPE WebView::backForwardList(
2588     /* [out][retval] */ IWebBackForwardList** list)
2589 {
2590     if (!m_useBackForwardList)
2591         return E_FAIL;
2592 
2593     *list = WebBackForwardList::createInstance(m_page->backForwardList());
2594 
2595     return S_OK;
2596 }
2597 
setMaintainsBackForwardList(BOOL flag)2598 HRESULT STDMETHODCALLTYPE WebView::setMaintainsBackForwardList(
2599     /* [in] */ BOOL flag)
2600 {
2601     m_useBackForwardList = !!flag;
2602     return S_OK;
2603 }
2604 
goBack(BOOL * succeeded)2605 HRESULT STDMETHODCALLTYPE WebView::goBack(
2606     /* [retval][out] */ BOOL* succeeded)
2607 {
2608     *succeeded = m_page->goBack();
2609     return S_OK;
2610 }
2611 
goForward(BOOL * succeeded)2612 HRESULT STDMETHODCALLTYPE WebView::goForward(
2613     /* [retval][out] */ BOOL* succeeded)
2614 {
2615     *succeeded = m_page->goForward();
2616     return S_OK;
2617 }
2618 
goToBackForwardItem(IWebHistoryItem * item,BOOL * succeeded)2619 HRESULT STDMETHODCALLTYPE WebView::goToBackForwardItem(
2620     /* [in] */ IWebHistoryItem* item,
2621     /* [retval][out] */ BOOL* succeeded)
2622 {
2623     *succeeded = FALSE;
2624 
2625     COMPtr<WebHistoryItem> webHistoryItem;
2626     HRESULT hr = item->QueryInterface(&webHistoryItem);
2627     if (FAILED(hr))
2628         return hr;
2629 
2630     m_page->goToItem(webHistoryItem->historyItem(), FrameLoadTypeIndexedBackForward);
2631     *succeeded = TRUE;
2632 
2633     return S_OK;
2634 }
2635 
setTextSizeMultiplier(float multiplier)2636 HRESULT STDMETHODCALLTYPE WebView::setTextSizeMultiplier(
2637     /* [in] */ float multiplier)
2638 {
2639     if (!m_mainFrame)
2640         return E_FAIL;
2641     setZoomMultiplier(multiplier, true);
2642     return S_OK;
2643 }
2644 
setPageSizeMultiplier(float multiplier)2645 HRESULT STDMETHODCALLTYPE WebView::setPageSizeMultiplier(
2646     /* [in] */ float multiplier)
2647 {
2648     if (!m_mainFrame)
2649         return E_FAIL;
2650     setZoomMultiplier(multiplier, false);
2651     return S_OK;
2652 }
2653 
setZoomMultiplier(float multiplier,bool isTextOnly)2654 void WebView::setZoomMultiplier(float multiplier, bool isTextOnly)
2655 {
2656     m_zoomMultiplier = multiplier;
2657     m_page->settings()->setZoomsTextOnly(isTextOnly);
2658     if (Frame* coreFrame = core(m_mainFrame))
2659         coreFrame->setZoomFactor(multiplier, isTextOnly);
2660 }
2661 
textSizeMultiplier(float * multiplier)2662 HRESULT STDMETHODCALLTYPE WebView::textSizeMultiplier(
2663     /* [retval][out] */ float* multiplier)
2664 {
2665     *multiplier = zoomMultiplier(true);
2666     return S_OK;
2667 }
2668 
pageSizeMultiplier(float * multiplier)2669 HRESULT STDMETHODCALLTYPE WebView::pageSizeMultiplier(
2670     /* [retval][out] */ float* multiplier)
2671 {
2672     *multiplier = zoomMultiplier(false);
2673     return S_OK;
2674 }
2675 
zoomMultiplier(bool isTextOnly)2676 float WebView::zoomMultiplier(bool isTextOnly)
2677 {
2678     if (isTextOnly != m_page->settings()->zoomsTextOnly())
2679         return 1.0f;
2680     return m_zoomMultiplier;
2681 }
2682 
setApplicationNameForUserAgent(BSTR applicationName)2683 HRESULT STDMETHODCALLTYPE WebView::setApplicationNameForUserAgent(
2684     /* [in] */ BSTR applicationName)
2685 {
2686     m_applicationName = String(applicationName, SysStringLen(applicationName));
2687     m_userAgentStandard = String();
2688     return S_OK;
2689 }
2690 
applicationNameForUserAgent(BSTR * applicationName)2691 HRESULT STDMETHODCALLTYPE WebView::applicationNameForUserAgent(
2692     /* [retval][out] */ BSTR* applicationName)
2693 {
2694     *applicationName = SysAllocStringLen(m_applicationName.characters(), m_applicationName.length());
2695     if (!*applicationName && m_applicationName.length())
2696         return E_OUTOFMEMORY;
2697     return S_OK;
2698 }
2699 
setCustomUserAgent(BSTR userAgentString)2700 HRESULT STDMETHODCALLTYPE WebView::setCustomUserAgent(
2701     /* [in] */ BSTR userAgentString)
2702 {
2703     m_userAgentOverridden = userAgentString;
2704     m_userAgentCustom = String(userAgentString, SysStringLen(userAgentString));
2705     return S_OK;
2706 }
2707 
customUserAgent(BSTR * userAgentString)2708 HRESULT STDMETHODCALLTYPE WebView::customUserAgent(
2709     /* [retval][out] */ BSTR* userAgentString)
2710 {
2711     *userAgentString = 0;
2712     if (!m_userAgentOverridden)
2713         return S_OK;
2714     *userAgentString = SysAllocStringLen(m_userAgentCustom.characters(), m_userAgentCustom.length());
2715     if (!*userAgentString && m_userAgentCustom.length())
2716         return E_OUTOFMEMORY;
2717     return S_OK;
2718 }
2719 
userAgentForURL(BSTR url,BSTR * userAgent)2720 HRESULT STDMETHODCALLTYPE WebView::userAgentForURL(
2721     /* [in] */ BSTR url,
2722     /* [retval][out] */ BSTR* userAgent)
2723 {
2724     String userAgentString = userAgentForKURL(MarshallingHelpers::BSTRToKURL(url));
2725     *userAgent = SysAllocStringLen(userAgentString.characters(), userAgentString.length());
2726     if (!*userAgent && userAgentString.length())
2727         return E_OUTOFMEMORY;
2728     return S_OK;
2729 }
2730 
supportsTextEncoding(BOOL * supports)2731 HRESULT STDMETHODCALLTYPE WebView::supportsTextEncoding(
2732     /* [retval][out] */ BOOL* supports)
2733 {
2734     *supports = TRUE;
2735     return S_OK;
2736 }
2737 
setCustomTextEncodingName(BSTR encodingName)2738 HRESULT STDMETHODCALLTYPE WebView::setCustomTextEncodingName(
2739     /* [in] */ BSTR encodingName)
2740 {
2741     if (!m_mainFrame)
2742         return E_FAIL;
2743 
2744     HRESULT hr;
2745     BSTR oldEncoding;
2746     hr = customTextEncodingName(&oldEncoding);
2747     if (FAILED(hr))
2748         return hr;
2749 
2750     if (oldEncoding != encodingName && (!oldEncoding || !encodingName || _tcscmp(oldEncoding, encodingName))) {
2751         if (Frame* coreFrame = core(m_mainFrame))
2752             coreFrame->loader()->reloadWithOverrideEncoding(String(encodingName, SysStringLen(encodingName)));
2753     }
2754 
2755     return S_OK;
2756 }
2757 
customTextEncodingName(BSTR * encodingName)2758 HRESULT STDMETHODCALLTYPE WebView::customTextEncodingName(
2759     /* [retval][out] */ BSTR* encodingName)
2760 {
2761     HRESULT hr = S_OK;
2762     COMPtr<IWebDataSource> dataSource;
2763     COMPtr<WebDataSource> dataSourceImpl;
2764     *encodingName = 0;
2765 
2766     if (!m_mainFrame)
2767         return E_FAIL;
2768 
2769     if (FAILED(m_mainFrame->provisionalDataSource(&dataSource)) || !dataSource) {
2770         hr = m_mainFrame->dataSource(&dataSource);
2771         if (FAILED(hr) || !dataSource)
2772             return hr;
2773     }
2774 
2775     hr = dataSource->QueryInterface(IID_WebDataSource, (void**)&dataSourceImpl);
2776     if (FAILED(hr))
2777         return hr;
2778 
2779     BString str = dataSourceImpl->documentLoader()->overrideEncoding();
2780     if (FAILED(hr))
2781         return hr;
2782 
2783     if (!*encodingName)
2784         *encodingName = SysAllocStringLen(m_overrideEncoding.characters(), m_overrideEncoding.length());
2785 
2786     if (!*encodingName && m_overrideEncoding.length())
2787         return E_OUTOFMEMORY;
2788 
2789     return S_OK;
2790 }
2791 
setMediaStyle(BSTR)2792 HRESULT STDMETHODCALLTYPE WebView::setMediaStyle(
2793     /* [in] */ BSTR /*media*/)
2794 {
2795     ASSERT_NOT_REACHED();
2796     return E_NOTIMPL;
2797 }
2798 
mediaStyle(BSTR *)2799 HRESULT STDMETHODCALLTYPE WebView::mediaStyle(
2800     /* [retval][out] */ BSTR* /*media*/)
2801 {
2802     ASSERT_NOT_REACHED();
2803     return E_NOTIMPL;
2804 }
2805 
stringByEvaluatingJavaScriptFromString(BSTR script,BSTR * result)2806 HRESULT STDMETHODCALLTYPE WebView::stringByEvaluatingJavaScriptFromString(
2807     /* [in] */ BSTR script, // assumes input does not have "JavaScript" at the begining.
2808     /* [retval][out] */ BSTR* result)
2809 {
2810     if (!result) {
2811         ASSERT_NOT_REACHED();
2812         return E_POINTER;
2813     }
2814 
2815     *result = 0;
2816 
2817     Frame* coreFrame = core(m_mainFrame);
2818     if (!coreFrame)
2819         return E_FAIL;
2820 
2821     JSC::JSValue scriptExecutionResult = coreFrame->loader()->executeScript(WebCore::String(script), true).jsValue();
2822     if (!scriptExecutionResult)
2823         return E_FAIL;
2824     else if (scriptExecutionResult.isString()) {
2825         JSLock lock(JSC::SilenceAssertionsOnly);
2826         *result = BString(String(scriptExecutionResult.getString()));
2827     }
2828 
2829     return S_OK;
2830 }
2831 
windowScriptObject(IWebScriptObject **)2832 HRESULT STDMETHODCALLTYPE WebView::windowScriptObject(
2833     /* [retval][out] */ IWebScriptObject** /*webScriptObject*/)
2834 {
2835     ASSERT_NOT_REACHED();
2836     return E_NOTIMPL;
2837 }
2838 
setPreferences(IWebPreferences * prefs)2839 HRESULT STDMETHODCALLTYPE WebView::setPreferences(
2840     /* [in] */ IWebPreferences* prefs)
2841 {
2842     if (!prefs)
2843         prefs = WebPreferences::sharedStandardPreferences();
2844 
2845     if (m_preferences == prefs)
2846         return S_OK;
2847 
2848     COMPtr<WebPreferences> webPrefs(Query, prefs);
2849     if (!webPrefs)
2850         return E_NOINTERFACE;
2851     webPrefs->willAddToWebView();
2852 
2853     COMPtr<WebPreferences> oldPrefs = m_preferences;
2854 
2855     IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
2856     nc->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
2857 
2858     BSTR identifier = 0;
2859     oldPrefs->identifier(&identifier);
2860     oldPrefs->didRemoveFromWebView();
2861     oldPrefs = 0; // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
2862 
2863     m_preferences = webPrefs;
2864 
2865     if (identifier) {
2866         WebPreferences::removeReferenceForIdentifier(identifier);
2867         SysFreeString(identifier);
2868     }
2869 
2870     nc->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
2871 
2872     m_preferences->postPreferencesChangesNotification();
2873 
2874     return S_OK;
2875 }
2876 
preferences(IWebPreferences ** prefs)2877 HRESULT STDMETHODCALLTYPE WebView::preferences(
2878     /* [retval][out] */ IWebPreferences** prefs)
2879 {
2880     if (!prefs)
2881         return E_POINTER;
2882     *prefs = m_preferences.get();
2883     if (m_preferences)
2884         m_preferences->AddRef();
2885     return S_OK;
2886 }
2887 
setPreferencesIdentifier(BSTR)2888 HRESULT STDMETHODCALLTYPE WebView::setPreferencesIdentifier(
2889     /* [in] */ BSTR /*anIdentifier*/)
2890 {
2891     ASSERT_NOT_REACHED();
2892     return E_NOTIMPL;
2893 }
2894 
preferencesIdentifier(BSTR *)2895 HRESULT STDMETHODCALLTYPE WebView::preferencesIdentifier(
2896     /* [retval][out] */ BSTR* /*anIdentifier*/)
2897 {
2898     ASSERT_NOT_REACHED();
2899     return E_NOTIMPL;
2900 }
2901 
windowReceivedMessage(HWND,UINT message,WPARAM wParam,LPARAM)2902 void WebView::windowReceivedMessage(HWND, UINT message, WPARAM wParam, LPARAM)
2903 {
2904     switch (message) {
2905     case WM_NCACTIVATE:
2906         updateActiveStateSoon();
2907         if (!wParam)
2908             deleteBackingStoreSoon();
2909         break;
2910     }
2911 }
2912 
updateActiveStateSoon() const2913 void WebView::updateActiveStateSoon() const
2914 {
2915     // This function is called while processing the WM_NCACTIVATE message.
2916     // While processing WM_NCACTIVATE when we are being deactivated, GetActiveWindow() will
2917     // still return our window. If we were to call updateActiveState() in that case, we would
2918     // wrongly think that we are still the active window. To work around this, we update our
2919     // active state after a 0-delay timer fires, at which point GetActiveWindow() will return
2920     // the newly-activated window.
2921 
2922     SetTimer(m_viewWindow, UpdateActiveStateTimer, 0, 0);
2923 }
2924 
deleteBackingStoreSoon()2925 void WebView::deleteBackingStoreSoon()
2926 {
2927     if (pendingDeleteBackingStoreSet.size() > 2) {
2928         Vector<WebView*> views;
2929         HashSet<WebView*>::iterator end = pendingDeleteBackingStoreSet.end();
2930         for (HashSet<WebView*>::iterator it = pendingDeleteBackingStoreSet.begin(); it != end; ++it)
2931             views.append(*it);
2932         for (int i = 0; i < views.size(); ++i)
2933             views[i]->deleteBackingStore();
2934         ASSERT(pendingDeleteBackingStoreSet.isEmpty());
2935     }
2936 
2937     pendingDeleteBackingStoreSet.add(this);
2938     m_deleteBackingStoreTimerActive = true;
2939     SetTimer(m_viewWindow, DeleteBackingStoreTimer, delayBeforeDeletingBackingStoreMsec, 0);
2940 }
2941 
cancelDeleteBackingStoreSoon()2942 void WebView::cancelDeleteBackingStoreSoon()
2943 {
2944     if (!m_deleteBackingStoreTimerActive)
2945         return;
2946     pendingDeleteBackingStoreSet.remove(this);
2947     m_deleteBackingStoreTimerActive = false;
2948     KillTimer(m_viewWindow, DeleteBackingStoreTimer);
2949 }
2950 
setHostWindow(OLE_HANDLE oleWindow)2951 HRESULT STDMETHODCALLTYPE WebView::setHostWindow(
2952     /* [in] */ OLE_HANDLE oleWindow)
2953 {
2954     HWND window = (HWND)(ULONG64)oleWindow;
2955     if (m_viewWindow && window)
2956         SetParent(m_viewWindow, window);
2957 
2958     m_hostWindow = window;
2959 
2960     if (m_viewWindow)
2961         windowAncestryDidChange();
2962 
2963     return S_OK;
2964 }
2965 
hostWindow(OLE_HANDLE * window)2966 HRESULT STDMETHODCALLTYPE WebView::hostWindow(
2967     /* [retval][out] */ OLE_HANDLE* window)
2968 {
2969     *window = (OLE_HANDLE)(ULONG64)m_hostWindow;
2970     return S_OK;
2971 }
2972 
2973 
incrementFrame(Frame * curr,bool forward,bool wrapFlag)2974 static Frame *incrementFrame(Frame *curr, bool forward, bool wrapFlag)
2975 {
2976     return forward
2977         ? curr->tree()->traverseNextWithWrap(wrapFlag)
2978         : curr->tree()->traversePreviousWithWrap(wrapFlag);
2979 }
2980 
searchFor(BSTR str,BOOL forward,BOOL caseFlag,BOOL wrapFlag,BOOL * found)2981 HRESULT STDMETHODCALLTYPE WebView::searchFor(
2982     /* [in] */ BSTR str,
2983     /* [in] */ BOOL forward,
2984     /* [in] */ BOOL caseFlag,
2985     /* [in] */ BOOL wrapFlag,
2986     /* [retval][out] */ BOOL* found)
2987 {
2988     if (!found)
2989         return E_INVALIDARG;
2990 
2991     if (!m_page || !m_page->mainFrame())
2992         return E_UNEXPECTED;
2993 
2994     if (!str || !SysStringLen(str))
2995         return E_INVALIDARG;
2996 
2997     *found = m_page->findString(String(str, SysStringLen(str)), caseFlag ? TextCaseSensitive : TextCaseInsensitive, forward ? FindDirectionForward : FindDirectionBackward, wrapFlag);
2998     return S_OK;
2999 }
3000 
active()3001 bool WebView::active()
3002 {
3003     HWND activeWindow = GetActiveWindow();
3004     return (activeWindow && m_topLevelParent == findTopLevelParent(activeWindow));
3005 }
3006 
updateActiveState()3007 void WebView::updateActiveState()
3008 {
3009     m_page->focusController()->setActive(active());
3010 }
3011 
updateFocusedAndActiveState()3012 HRESULT STDMETHODCALLTYPE WebView::updateFocusedAndActiveState()
3013 {
3014     updateActiveState();
3015 
3016     bool active = m_page->focusController()->isActive();
3017     Frame* mainFrame = m_page->mainFrame();
3018     Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
3019     mainFrame->selection()->setFocused(active && mainFrame == focusedFrame);
3020 
3021     return S_OK;
3022 }
3023 
executeCoreCommandByName(BSTR bName,BSTR bValue)3024 HRESULT STDMETHODCALLTYPE WebView::executeCoreCommandByName(BSTR bName, BSTR bValue)
3025 {
3026     String name(bName, SysStringLen(bName));
3027     String value(bValue, SysStringLen(bValue));
3028 
3029     m_page->focusController()->focusedOrMainFrame()->editor()->command(name).execute(value);
3030 
3031     return S_OK;
3032 }
3033 
clearMainFrameName()3034 HRESULT STDMETHODCALLTYPE WebView::clearMainFrameName()
3035 {
3036     m_page->mainFrame()->tree()->clearName();
3037 
3038     return S_OK;
3039 }
3040 
markAllMatchesForText(BSTR str,BOOL caseSensitive,BOOL highlight,UINT limit,UINT * matches)3041 HRESULT STDMETHODCALLTYPE WebView::markAllMatchesForText(
3042     BSTR str, BOOL caseSensitive, BOOL highlight, UINT limit, UINT* matches)
3043 {
3044     if (!matches)
3045         return E_INVALIDARG;
3046 
3047     if (!m_page || !m_page->mainFrame())
3048         return E_UNEXPECTED;
3049 
3050     if (!str || !SysStringLen(str))
3051         return E_INVALIDARG;
3052 
3053     *matches = m_page->markAllMatchesForText(String(str, SysStringLen(str)), caseSensitive ? TextCaseSensitive : TextCaseInsensitive, highlight, limit);
3054     return S_OK;
3055 }
3056 
unmarkAllTextMatches()3057 HRESULT STDMETHODCALLTYPE WebView::unmarkAllTextMatches()
3058 {
3059     if (!m_page || !m_page->mainFrame())
3060         return E_UNEXPECTED;
3061 
3062     m_page->unmarkAllTextMatches();
3063     return S_OK;
3064 }
3065 
rectsForTextMatches(IEnumTextMatches ** pmatches)3066 HRESULT STDMETHODCALLTYPE WebView::rectsForTextMatches(
3067     IEnumTextMatches** pmatches)
3068 {
3069     Vector<IntRect> allRects;
3070     WebCore::Frame* frame = m_page->mainFrame();
3071     do {
3072         if (Document* document = frame->document()) {
3073             IntRect visibleRect = frame->view()->visibleContentRect();
3074             Vector<IntRect> frameRects = document->renderedRectsForMarkers(DocumentMarker::TextMatch);
3075             IntPoint frameOffset(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height());
3076             frameOffset = frame->view()->convertToContainingWindow(frameOffset);
3077 
3078             Vector<IntRect>::iterator end = frameRects.end();
3079             for (Vector<IntRect>::iterator it = frameRects.begin(); it < end; it++) {
3080                 it->intersect(visibleRect);
3081                 it->move(frameOffset.x(), frameOffset.y());
3082                 allRects.append(*it);
3083             }
3084         }
3085         frame = incrementFrame(frame, true, false);
3086     } while (frame);
3087 
3088     return createMatchEnumerator(&allRects, pmatches);
3089 }
3090 
generateSelectionImage(BOOL forceWhiteText,OLE_HANDLE * hBitmap)3091 HRESULT STDMETHODCALLTYPE WebView::generateSelectionImage(BOOL forceWhiteText, OLE_HANDLE* hBitmap)
3092 {
3093     *hBitmap = 0;
3094 
3095     WebCore::Frame* frame = m_page->focusController()->focusedOrMainFrame();
3096 
3097     if (frame) {
3098         HBITMAP bitmap = imageFromSelection(frame, forceWhiteText ? TRUE : FALSE);
3099         *hBitmap = (OLE_HANDLE)(ULONG64)bitmap;
3100     }
3101 
3102     return S_OK;
3103 }
3104 
selectionRect(RECT * rc)3105 HRESULT STDMETHODCALLTYPE WebView::selectionRect(RECT* rc)
3106 {
3107     WebCore::Frame* frame = m_page->focusController()->focusedOrMainFrame();
3108 
3109     if (frame) {
3110         IntRect ir = enclosingIntRect(frame->selectionBounds());
3111         ir = frame->view()->convertToContainingWindow(ir);
3112         ir.move(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height());
3113         rc->left = ir.x();
3114         rc->top = ir.y();
3115         rc->bottom = rc->top + ir.height();
3116         rc->right = rc->left + ir.width();
3117     }
3118 
3119     return S_OK;
3120 }
3121 
registerViewClass(IWebDocumentView *,IWebDocumentRepresentation *,BSTR)3122 HRESULT STDMETHODCALLTYPE WebView::registerViewClass(
3123     /* [in] */ IWebDocumentView* /*view*/,
3124     /* [in] */ IWebDocumentRepresentation* /*representation*/,
3125     /* [in] */ BSTR /*forMIMEType*/)
3126 {
3127     ASSERT_NOT_REACHED();
3128     return E_NOTIMPL;
3129 }
3130 
setGroupName(BSTR groupName)3131 HRESULT STDMETHODCALLTYPE WebView::setGroupName(
3132         /* [in] */ BSTR groupName)
3133 {
3134     if (!m_page)
3135         return S_OK;
3136     m_page->setGroupName(String(groupName, SysStringLen(groupName)));
3137     return S_OK;
3138 }
3139 
groupName(BSTR * groupName)3140 HRESULT STDMETHODCALLTYPE WebView::groupName(
3141         /* [retval][out] */ BSTR* groupName)
3142 {
3143     *groupName = 0;
3144     if (!m_page)
3145         return S_OK;
3146     String groupNameString = m_page->groupName();
3147     *groupName = SysAllocStringLen(groupNameString.characters(), groupNameString.length());
3148     if (!*groupName && groupNameString.length())
3149         return E_OUTOFMEMORY;
3150     return S_OK;
3151 }
3152 
estimatedProgress(double * estimatedProgress)3153 HRESULT STDMETHODCALLTYPE WebView::estimatedProgress(
3154         /* [retval][out] */ double* estimatedProgress)
3155 {
3156     *estimatedProgress = m_page->progress()->estimatedProgress();
3157     return S_OK;
3158 }
3159 
isLoading(BOOL * isLoading)3160 HRESULT STDMETHODCALLTYPE WebView::isLoading(
3161         /* [retval][out] */ BOOL* isLoading)
3162 {
3163     COMPtr<IWebDataSource> dataSource;
3164     COMPtr<IWebDataSource> provisionalDataSource;
3165 
3166     if (!isLoading)
3167         return E_POINTER;
3168 
3169     *isLoading = FALSE;
3170 
3171     if (SUCCEEDED(m_mainFrame->dataSource(&dataSource)))
3172         dataSource->isLoading(isLoading);
3173 
3174     if (*isLoading)
3175         return S_OK;
3176 
3177     if (SUCCEEDED(m_mainFrame->provisionalDataSource(&provisionalDataSource)))
3178         provisionalDataSource->isLoading(isLoading);
3179     return S_OK;
3180 }
3181 
elementAtPoint(LPPOINT point,IPropertyBag ** elementDictionary)3182 HRESULT STDMETHODCALLTYPE WebView::elementAtPoint(
3183         /* [in] */ LPPOINT point,
3184         /* [retval][out] */ IPropertyBag** elementDictionary)
3185 {
3186     if (!elementDictionary) {
3187         ASSERT_NOT_REACHED();
3188         return E_POINTER;
3189     }
3190 
3191     *elementDictionary = 0;
3192 
3193     Frame* frame = core(m_mainFrame);
3194     if (!frame)
3195         return E_FAIL;
3196 
3197     IntPoint webCorePoint = IntPoint(point->x, point->y);
3198     HitTestResult result = HitTestResult(webCorePoint);
3199     if (frame->contentRenderer())
3200         result = frame->eventHandler()->hitTestResultAtPoint(webCorePoint, false);
3201     *elementDictionary = WebElementPropertyBag::createInstance(result);
3202     return S_OK;
3203 }
3204 
pasteboardTypesForSelection(IEnumVARIANT **)3205 HRESULT STDMETHODCALLTYPE WebView::pasteboardTypesForSelection(
3206     /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
3207 {
3208     ASSERT_NOT_REACHED();
3209     return E_NOTIMPL;
3210 }
3211 
writeSelectionWithPasteboardTypes(BSTR *,int,IDataObject *)3212 HRESULT STDMETHODCALLTYPE WebView::writeSelectionWithPasteboardTypes(
3213         /* [size_is][in] */ BSTR* /*types*/,
3214         /* [in] */ int /*cTypes*/,
3215         /* [in] */ IDataObject* /*pasteboard*/)
3216 {
3217     ASSERT_NOT_REACHED();
3218     return E_NOTIMPL;
3219 }
3220 
pasteboardTypesForElement(IPropertyBag *,IEnumVARIANT **)3221 HRESULT STDMETHODCALLTYPE WebView::pasteboardTypesForElement(
3222     /* [in] */ IPropertyBag* /*elementDictionary*/,
3223     /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
3224 {
3225     ASSERT_NOT_REACHED();
3226     return E_NOTIMPL;
3227 }
3228 
writeElement(IPropertyBag *,BSTR *,int,IDataObject *)3229 HRESULT STDMETHODCALLTYPE WebView::writeElement(
3230         /* [in] */ IPropertyBag* /*elementDictionary*/,
3231         /* [size_is][in] */ BSTR* /*withPasteboardTypes*/,
3232         /* [in] */ int /*cWithPasteboardTypes*/,
3233         /* [in] */ IDataObject* /*pasteboard*/)
3234 {
3235     ASSERT_NOT_REACHED();
3236     return E_NOTIMPL;
3237 }
3238 
selectedText(BSTR * text)3239 HRESULT STDMETHODCALLTYPE WebView::selectedText(
3240         /* [out, retval] */ BSTR* text)
3241 {
3242     if (!text) {
3243         ASSERT_NOT_REACHED();
3244         return E_POINTER;
3245     }
3246 
3247     *text = 0;
3248 
3249     Frame* focusedFrame = (m_page && m_page->focusController()) ? m_page->focusController()->focusedOrMainFrame() : 0;
3250     if (!focusedFrame)
3251         return E_FAIL;
3252 
3253     String frameSelectedText = focusedFrame->selectedText();
3254     *text = SysAllocStringLen(frameSelectedText.characters(), frameSelectedText.length());
3255     if (!*text && frameSelectedText.length())
3256         return E_OUTOFMEMORY;
3257     return S_OK;
3258 }
3259 
centerSelectionInVisibleArea(IUnknown *)3260 HRESULT STDMETHODCALLTYPE WebView::centerSelectionInVisibleArea(
3261         /* [in] */ IUnknown* /* sender */)
3262 {
3263     Frame* coreFrame = core(m_mainFrame);
3264     if (!coreFrame)
3265         return E_FAIL;
3266 
3267     coreFrame->revealSelection(ScrollAlignment::alignCenterAlways);
3268     return S_OK;
3269 }
3270 
3271 
moveDragCaretToPoint(LPPOINT)3272 HRESULT STDMETHODCALLTYPE WebView::moveDragCaretToPoint(
3273         /* [in] */ LPPOINT /*point*/)
3274 {
3275     ASSERT_NOT_REACHED();
3276     return E_NOTIMPL;
3277 }
3278 
removeDragCaret(void)3279 HRESULT STDMETHODCALLTYPE WebView::removeDragCaret( void)
3280 {
3281     ASSERT_NOT_REACHED();
3282     return E_NOTIMPL;
3283 }
3284 
setDrawsBackground(BOOL)3285 HRESULT STDMETHODCALLTYPE WebView::setDrawsBackground(
3286         /* [in] */ BOOL /*drawsBackground*/)
3287 {
3288     ASSERT_NOT_REACHED();
3289     return E_NOTIMPL;
3290 }
3291 
drawsBackground(BOOL *)3292 HRESULT STDMETHODCALLTYPE WebView::drawsBackground(
3293         /* [retval][out] */ BOOL* /*drawsBackground*/)
3294 {
3295     ASSERT_NOT_REACHED();
3296     return E_NOTIMPL;
3297 }
3298 
setMainFrameURL(BSTR)3299 HRESULT STDMETHODCALLTYPE WebView::setMainFrameURL(
3300         /* [in] */ BSTR /*urlString*/)
3301 {
3302     ASSERT_NOT_REACHED();
3303     return E_NOTIMPL;
3304 }
3305 
mainFrameURL(BSTR *)3306 HRESULT STDMETHODCALLTYPE WebView::mainFrameURL(
3307         /* [retval][out] */ BSTR* /*urlString*/)
3308 {
3309     ASSERT_NOT_REACHED();
3310     return E_NOTIMPL;
3311 }
3312 
mainFrameDocument(IDOMDocument ** document)3313 HRESULT STDMETHODCALLTYPE WebView::mainFrameDocument(
3314         /* [retval][out] */ IDOMDocument** document)
3315 {
3316     if (document)
3317         *document = 0;
3318     if (!m_mainFrame)
3319         return E_FAIL;
3320     return m_mainFrame->DOMDocument(document);
3321 }
3322 
mainFrameTitle(BSTR *)3323 HRESULT STDMETHODCALLTYPE WebView::mainFrameTitle(
3324         /* [retval][out] */ BSTR* /*title*/)
3325 {
3326     ASSERT_NOT_REACHED();
3327     return E_NOTIMPL;
3328 }
3329 
mainFrameIcon(OLE_HANDLE *)3330 HRESULT STDMETHODCALLTYPE WebView::mainFrameIcon(
3331         /* [retval][out] */ OLE_HANDLE* /*hBitmap*/)
3332 {
3333     ASSERT_NOT_REACHED();
3334     return E_NOTIMPL;
3335 }
3336 
registerURLSchemeAsLocal(BSTR scheme)3337 HRESULT STDMETHODCALLTYPE WebView::registerURLSchemeAsLocal(
3338         /* [in] */ BSTR scheme)
3339 {
3340     if (!scheme)
3341         return E_POINTER;
3342 
3343     SecurityOrigin::registerURLSchemeAsLocal(String(scheme, ::SysStringLen(scheme)));
3344 
3345     return S_OK;
3346 }
3347 
3348 // IWebIBActions ---------------------------------------------------------------
3349 
takeStringURLFrom(IUnknown *)3350 HRESULT STDMETHODCALLTYPE WebView::takeStringURLFrom(
3351         /* [in] */ IUnknown* /*sender*/)
3352 {
3353     ASSERT_NOT_REACHED();
3354     return E_NOTIMPL;
3355 }
3356 
stopLoading(IUnknown *)3357 HRESULT STDMETHODCALLTYPE WebView::stopLoading(
3358         /* [in] */ IUnknown* /*sender*/)
3359 {
3360     if (!m_mainFrame)
3361         return E_FAIL;
3362 
3363     return m_mainFrame->stopLoading();
3364 }
3365 
reload(IUnknown *)3366 HRESULT STDMETHODCALLTYPE WebView::reload(
3367         /* [in] */ IUnknown* /*sender*/)
3368 {
3369     if (!m_mainFrame)
3370         return E_FAIL;
3371 
3372     return m_mainFrame->reload();
3373 }
3374 
canGoBack(IUnknown *,BOOL * result)3375 HRESULT STDMETHODCALLTYPE WebView::canGoBack(
3376         /* [in] */ IUnknown* /*sender*/,
3377         /* [retval][out] */ BOOL* result)
3378 {
3379     *result = !!m_page->backForwardList()->backItem();
3380     return S_OK;
3381 }
3382 
goBack(IUnknown *)3383 HRESULT STDMETHODCALLTYPE WebView::goBack(
3384         /* [in] */ IUnknown* /*sender*/)
3385 {
3386     ASSERT_NOT_REACHED();
3387     return E_NOTIMPL;
3388 }
3389 
canGoForward(IUnknown *,BOOL * result)3390 HRESULT STDMETHODCALLTYPE WebView::canGoForward(
3391         /* [in] */ IUnknown* /*sender*/,
3392         /* [retval][out] */ BOOL* result)
3393 {
3394     *result = !!m_page->backForwardList()->forwardItem();
3395     return S_OK;
3396 }
3397 
goForward(IUnknown *)3398 HRESULT STDMETHODCALLTYPE WebView::goForward(
3399         /* [in] */ IUnknown* /*sender*/)
3400 {
3401     ASSERT_NOT_REACHED();
3402     return E_NOTIMPL;
3403 }
3404 
3405 // FIXME: This code should move into WebCore so it can be shared by all the WebKits.
3406 #define MinimumZoomMultiplier   0.5f
3407 #define MaximumZoomMultiplier   3.0f
3408 #define ZoomMultiplierRatio     1.2f
3409 
canMakeTextLarger(IUnknown *,BOOL * result)3410 HRESULT STDMETHODCALLTYPE WebView::canMakeTextLarger(
3411         /* [in] */ IUnknown* /*sender*/,
3412         /* [retval][out] */ BOOL* result)
3413 {
3414     bool canGrowMore = canZoomIn(m_page->settings()->zoomsTextOnly());
3415     *result = canGrowMore ? TRUE : FALSE;
3416     return S_OK;
3417 }
3418 
canZoomPageIn(IUnknown *,BOOL * result)3419 HRESULT STDMETHODCALLTYPE WebView::canZoomPageIn(
3420         /* [in] */ IUnknown* /*sender*/,
3421         /* [retval][out] */ BOOL* result)
3422 {
3423     bool canGrowMore = canZoomIn(false);
3424     *result = canGrowMore ? TRUE : FALSE;
3425     return S_OK;
3426 }
3427 
canZoomIn(bool isTextOnly)3428 bool WebView::canZoomIn(bool isTextOnly)
3429 {
3430     return zoomMultiplier(isTextOnly) * ZoomMultiplierRatio < MaximumZoomMultiplier;
3431 }
3432 
makeTextLarger(IUnknown *)3433 HRESULT STDMETHODCALLTYPE WebView::makeTextLarger(
3434         /* [in] */ IUnknown* /*sender*/)
3435 {
3436     return zoomIn(m_page->settings()->zoomsTextOnly());
3437 }
3438 
zoomPageIn(IUnknown *)3439 HRESULT STDMETHODCALLTYPE WebView::zoomPageIn(
3440         /* [in] */ IUnknown* /*sender*/)
3441 {
3442     return zoomIn(false);
3443 }
3444 
zoomIn(bool isTextOnly)3445 HRESULT WebView::zoomIn(bool isTextOnly)
3446 {
3447     if (!canZoomIn(isTextOnly))
3448         return E_FAIL;
3449     setZoomMultiplier(zoomMultiplier(isTextOnly) * ZoomMultiplierRatio, isTextOnly);
3450     return S_OK;
3451 }
3452 
canMakeTextSmaller(IUnknown *,BOOL * result)3453 HRESULT STDMETHODCALLTYPE WebView::canMakeTextSmaller(
3454         /* [in] */ IUnknown* /*sender*/,
3455         /* [retval][out] */ BOOL* result)
3456 {
3457     bool canShrinkMore = canZoomOut(m_page->settings()->zoomsTextOnly());
3458     *result = canShrinkMore ? TRUE : FALSE;
3459     return S_OK;
3460 }
3461 
canZoomPageOut(IUnknown *,BOOL * result)3462 HRESULT STDMETHODCALLTYPE WebView::canZoomPageOut(
3463         /* [in] */ IUnknown* /*sender*/,
3464         /* [retval][out] */ BOOL* result)
3465 {
3466     bool canShrinkMore = canZoomOut(false);
3467     *result = canShrinkMore ? TRUE : FALSE;
3468     return S_OK;
3469 }
3470 
canZoomOut(bool isTextOnly)3471 bool WebView::canZoomOut(bool isTextOnly)
3472 {
3473     return zoomMultiplier(isTextOnly) / ZoomMultiplierRatio > MinimumZoomMultiplier;
3474 }
3475 
makeTextSmaller(IUnknown *)3476 HRESULT STDMETHODCALLTYPE WebView::makeTextSmaller(
3477         /* [in] */ IUnknown* /*sender*/)
3478 {
3479     return zoomOut(m_page->settings()->zoomsTextOnly());
3480 }
3481 
zoomPageOut(IUnknown *)3482 HRESULT STDMETHODCALLTYPE WebView::zoomPageOut(
3483         /* [in] */ IUnknown* /*sender*/)
3484 {
3485     return zoomOut(false);
3486 }
3487 
zoomOut(bool isTextOnly)3488 HRESULT WebView::zoomOut(bool isTextOnly)
3489 {
3490     if (!canZoomOut(isTextOnly))
3491         return E_FAIL;
3492     setZoomMultiplier(zoomMultiplier(isTextOnly) / ZoomMultiplierRatio, isTextOnly);
3493     return S_OK;
3494 }
3495 
canMakeTextStandardSize(IUnknown *,BOOL * result)3496 HRESULT STDMETHODCALLTYPE WebView::canMakeTextStandardSize(
3497     /* [in] */ IUnknown* /*sender*/,
3498     /* [retval][out] */ BOOL* result)
3499 {
3500     // Since we always reset text zoom and page zoom together, this should continue to return an answer about text zoom even if its not enabled.
3501     bool notAlreadyStandard = canResetZoom(true);
3502     *result = notAlreadyStandard ? TRUE : FALSE;
3503     return S_OK;
3504 }
3505 
canResetPageZoom(IUnknown *,BOOL * result)3506 HRESULT STDMETHODCALLTYPE WebView::canResetPageZoom(
3507     /* [in] */ IUnknown* /*sender*/,
3508     /* [retval][out] */ BOOL* result)
3509 {
3510     bool notAlreadyStandard = canResetZoom(false);
3511     *result = notAlreadyStandard ? TRUE : FALSE;
3512     return S_OK;
3513 }
3514 
canResetZoom(bool isTextOnly)3515 bool WebView::canResetZoom(bool isTextOnly)
3516 {
3517     return zoomMultiplier(isTextOnly) != 1.0f;
3518 }
3519 
makeTextStandardSize(IUnknown *)3520 HRESULT STDMETHODCALLTYPE WebView::makeTextStandardSize(
3521     /* [in] */ IUnknown* /*sender*/)
3522 {
3523     return resetZoom(true);
3524 }
3525 
resetPageZoom(IUnknown *)3526 HRESULT STDMETHODCALLTYPE WebView::resetPageZoom(
3527     /* [in] */ IUnknown* /*sender*/)
3528 {
3529     return resetZoom(false);
3530 }
3531 
resetZoom(bool isTextOnly)3532 HRESULT WebView::resetZoom(bool isTextOnly)
3533 {
3534     if (!canResetZoom(isTextOnly))
3535         return E_FAIL;
3536     setZoomMultiplier(1.0f, isTextOnly);
3537     return S_OK;
3538 }
3539 
toggleContinuousSpellChecking(IUnknown *)3540 HRESULT STDMETHODCALLTYPE WebView::toggleContinuousSpellChecking(
3541     /* [in] */ IUnknown* /*sender*/)
3542 {
3543     HRESULT hr;
3544     BOOL enabled;
3545     if (FAILED(hr = isContinuousSpellCheckingEnabled(&enabled)))
3546         return hr;
3547     return setContinuousSpellCheckingEnabled(enabled ? FALSE : TRUE);
3548 }
3549 
toggleSmartInsertDelete(IUnknown *)3550 HRESULT STDMETHODCALLTYPE WebView::toggleSmartInsertDelete(
3551     /* [in] */ IUnknown* /*sender*/)
3552 {
3553     BOOL enabled = FALSE;
3554     HRESULT hr = smartInsertDeleteEnabled(&enabled);
3555     if (FAILED(hr))
3556         return hr;
3557 
3558     return setSmartInsertDeleteEnabled(enabled ? FALSE : TRUE);
3559 }
3560 
toggleGrammarChecking(IUnknown *)3561 HRESULT STDMETHODCALLTYPE WebView::toggleGrammarChecking(
3562     /* [in] */ IUnknown* /*sender*/)
3563 {
3564     BOOL enabled;
3565     HRESULT hr = isGrammarCheckingEnabled(&enabled);
3566     if (FAILED(hr))
3567         return hr;
3568 
3569     return setGrammarCheckingEnabled(enabled ? FALSE : TRUE);
3570 }
3571 
3572 // IWebViewCSS -----------------------------------------------------------------
3573 
computedStyleForElement(IDOMElement *,BSTR,IDOMCSSStyleDeclaration **)3574 HRESULT STDMETHODCALLTYPE WebView::computedStyleForElement(
3575         /* [in] */ IDOMElement* /*element*/,
3576         /* [in] */ BSTR /*pseudoElement*/,
3577         /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
3578 {
3579     ASSERT_NOT_REACHED();
3580     return E_NOTIMPL;
3581 }
3582 
3583 // IWebViewEditing -------------------------------------------------------------
3584 
editableDOMRangeForPoint(LPPOINT,IDOMRange **)3585 HRESULT STDMETHODCALLTYPE WebView::editableDOMRangeForPoint(
3586         /* [in] */ LPPOINT /*point*/,
3587         /* [retval][out] */ IDOMRange** /*range*/)
3588 {
3589     ASSERT_NOT_REACHED();
3590     return E_NOTIMPL;
3591 }
3592 
setSelectedDOMRange(IDOMRange *,WebSelectionAffinity)3593 HRESULT STDMETHODCALLTYPE WebView::setSelectedDOMRange(
3594         /* [in] */ IDOMRange* /*range*/,
3595         /* [in] */ WebSelectionAffinity /*affinity*/)
3596 {
3597     ASSERT_NOT_REACHED();
3598     return E_NOTIMPL;
3599 }
3600 
selectedDOMRange(IDOMRange **)3601 HRESULT STDMETHODCALLTYPE WebView::selectedDOMRange(
3602         /* [retval][out] */ IDOMRange** /*range*/)
3603 {
3604     ASSERT_NOT_REACHED();
3605     return E_NOTIMPL;
3606 }
3607 
selectionAffinity(WebSelectionAffinity *)3608 HRESULT STDMETHODCALLTYPE WebView::selectionAffinity(
3609         /* [retval][out][retval][out] */ WebSelectionAffinity* /*affinity*/)
3610 {
3611     ASSERT_NOT_REACHED();
3612     return E_NOTIMPL;
3613 }
3614 
setEditable(BOOL)3615 HRESULT STDMETHODCALLTYPE WebView::setEditable(
3616         /* [in] */ BOOL /*flag*/)
3617 {
3618     ASSERT_NOT_REACHED();
3619     return E_NOTIMPL;
3620 }
3621 
isEditable(BOOL *)3622 HRESULT STDMETHODCALLTYPE WebView::isEditable(
3623         /* [retval][out] */ BOOL* /*isEditable*/)
3624 {
3625     ASSERT_NOT_REACHED();
3626     return E_NOTIMPL;
3627 }
3628 
setTypingStyle(IDOMCSSStyleDeclaration *)3629 HRESULT STDMETHODCALLTYPE WebView::setTypingStyle(
3630         /* [in] */ IDOMCSSStyleDeclaration* /*style*/)
3631 {
3632     ASSERT_NOT_REACHED();
3633     return E_NOTIMPL;
3634 }
3635 
typingStyle(IDOMCSSStyleDeclaration **)3636 HRESULT STDMETHODCALLTYPE WebView::typingStyle(
3637         /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
3638 {
3639     ASSERT_NOT_REACHED();
3640     return E_NOTIMPL;
3641 }
3642 
setSmartInsertDeleteEnabled(BOOL flag)3643 HRESULT STDMETHODCALLTYPE WebView::setSmartInsertDeleteEnabled(
3644         /* [in] */ BOOL flag)
3645 {
3646     m_smartInsertDeleteEnabled = !!flag;
3647     if (m_smartInsertDeleteEnabled)
3648         setSelectTrailingWhitespaceEnabled(false);
3649     return S_OK;
3650 }
3651 
smartInsertDeleteEnabled(BOOL * enabled)3652 HRESULT STDMETHODCALLTYPE WebView::smartInsertDeleteEnabled(
3653         /* [retval][out] */ BOOL* enabled)
3654 {
3655     *enabled = m_smartInsertDeleteEnabled ? TRUE : FALSE;
3656     return S_OK;
3657 }
3658 
setSelectTrailingWhitespaceEnabled(BOOL flag)3659 HRESULT STDMETHODCALLTYPE WebView::setSelectTrailingWhitespaceEnabled(
3660         /* [in] */ BOOL flag)
3661 {
3662     m_selectTrailingWhitespaceEnabled = !!flag;
3663     if (m_selectTrailingWhitespaceEnabled)
3664         setSmartInsertDeleteEnabled(false);
3665     return S_OK;
3666 }
3667 
isSelectTrailingWhitespaceEnabled(BOOL * enabled)3668 HRESULT STDMETHODCALLTYPE WebView::isSelectTrailingWhitespaceEnabled(
3669         /* [retval][out] */ BOOL* enabled)
3670 {
3671     *enabled = m_selectTrailingWhitespaceEnabled ? TRUE : FALSE;
3672     return S_OK;
3673 }
3674 
setContinuousSpellCheckingEnabled(BOOL flag)3675 HRESULT STDMETHODCALLTYPE WebView::setContinuousSpellCheckingEnabled(
3676         /* [in] */ BOOL flag)
3677 {
3678     if (continuousSpellCheckingEnabled != !!flag) {
3679         continuousSpellCheckingEnabled = !!flag;
3680         COMPtr<IWebPreferences> prefs;
3681         if (SUCCEEDED(preferences(&prefs)))
3682             prefs->setContinuousSpellCheckingEnabled(flag);
3683     }
3684 
3685     BOOL spellCheckingEnabled;
3686     if (SUCCEEDED(isContinuousSpellCheckingEnabled(&spellCheckingEnabled)) && spellCheckingEnabled)
3687         preflightSpellChecker();
3688     else
3689         m_mainFrame->unmarkAllMisspellings();
3690 
3691     return S_OK;
3692 }
3693 
isContinuousSpellCheckingEnabled(BOOL * enabled)3694 HRESULT STDMETHODCALLTYPE WebView::isContinuousSpellCheckingEnabled(
3695         /* [retval][out] */ BOOL* enabled)
3696 {
3697     *enabled = (continuousSpellCheckingEnabled && continuousCheckingAllowed()) ? TRUE : FALSE;
3698     return S_OK;
3699 }
3700 
spellCheckerDocumentTag(int * tag)3701 HRESULT STDMETHODCALLTYPE WebView::spellCheckerDocumentTag(
3702         /* [retval][out] */ int* tag)
3703 {
3704     // we just use this as a flag to indicate that we've spell checked the document
3705     // and need to close the spell checker out when the view closes.
3706     *tag = 0;
3707     m_hasSpellCheckerDocumentTag = true;
3708     return S_OK;
3709 }
3710 
3711 static COMPtr<IWebEditingDelegate> spellingDelegateForTimer;
3712 
preflightSpellCheckerNow()3713 static void preflightSpellCheckerNow()
3714 {
3715     spellingDelegateForTimer->preflightChosenSpellServer();
3716     spellingDelegateForTimer = 0;
3717 }
3718 
preflightSpellCheckerTimerCallback(HWND,UINT,UINT_PTR id,DWORD)3719 static void CALLBACK preflightSpellCheckerTimerCallback(HWND, UINT, UINT_PTR id, DWORD)
3720 {
3721     ::KillTimer(0, id);
3722     preflightSpellCheckerNow();
3723 }
3724 
preflightSpellChecker()3725 void WebView::preflightSpellChecker()
3726 {
3727     // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch.
3728     if (!m_editingDelegate)
3729         return;
3730 
3731     BOOL exists;
3732     spellingDelegateForTimer = m_editingDelegate;
3733     if (SUCCEEDED(m_editingDelegate->sharedSpellCheckerExists(&exists)) && exists)
3734         preflightSpellCheckerNow();
3735     else
3736         ::SetTimer(0, 0, 2000, preflightSpellCheckerTimerCallback);
3737 }
3738 
continuousCheckingAllowed()3739 bool WebView::continuousCheckingAllowed()
3740 {
3741     static bool allowContinuousSpellChecking = true;
3742     static bool readAllowContinuousSpellCheckingDefault = false;
3743     if (!readAllowContinuousSpellCheckingDefault) {
3744         COMPtr<IWebPreferences> prefs;
3745         if (SUCCEEDED(preferences(&prefs))) {
3746             BOOL allowed;
3747             prefs->allowContinuousSpellChecking(&allowed);
3748             allowContinuousSpellChecking = !!allowed;
3749         }
3750         readAllowContinuousSpellCheckingDefault = true;
3751     }
3752     return allowContinuousSpellChecking;
3753 }
3754 
undoManager(IWebUndoManager **)3755 HRESULT STDMETHODCALLTYPE WebView::undoManager(
3756         /* [retval][out] */ IWebUndoManager** /*manager*/)
3757 {
3758     ASSERT_NOT_REACHED();
3759     return E_NOTIMPL;
3760 }
3761 
setEditingDelegate(IWebEditingDelegate * d)3762 HRESULT STDMETHODCALLTYPE WebView::setEditingDelegate(
3763         /* [in] */ IWebEditingDelegate* d)
3764 {
3765     m_editingDelegate = d;
3766     return S_OK;
3767 }
3768 
editingDelegate(IWebEditingDelegate ** d)3769 HRESULT STDMETHODCALLTYPE WebView::editingDelegate(
3770         /* [retval][out] */ IWebEditingDelegate** d)
3771 {
3772     if (!d) {
3773         ASSERT_NOT_REACHED();
3774         return E_POINTER;
3775     }
3776 
3777     *d = m_editingDelegate.get();
3778     if (!*d)
3779         return E_FAIL;
3780 
3781     (*d)->AddRef();
3782     return S_OK;
3783 }
3784 
styleDeclarationWithText(BSTR,IDOMCSSStyleDeclaration **)3785 HRESULT STDMETHODCALLTYPE WebView::styleDeclarationWithText(
3786         /* [in] */ BSTR /*text*/,
3787         /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
3788 {
3789     ASSERT_NOT_REACHED();
3790     return E_NOTIMPL;
3791 }
3792 
hasSelectedRange(BOOL * hasSelectedRange)3793 HRESULT STDMETHODCALLTYPE WebView::hasSelectedRange(
3794         /* [retval][out] */ BOOL* hasSelectedRange)
3795 {
3796     *hasSelectedRange = m_page->mainFrame()->selection()->isRange();
3797     return S_OK;
3798 }
3799 
cutEnabled(BOOL * enabled)3800 HRESULT STDMETHODCALLTYPE WebView::cutEnabled(
3801         /* [retval][out] */ BOOL* enabled)
3802 {
3803     Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
3804     *enabled = editor->canCut() || editor->canDHTMLCut();
3805     return S_OK;
3806 }
3807 
copyEnabled(BOOL * enabled)3808 HRESULT STDMETHODCALLTYPE WebView::copyEnabled(
3809         /* [retval][out] */ BOOL* enabled)
3810 {
3811     Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
3812     *enabled = editor->canCopy() || editor->canDHTMLCopy();
3813     return S_OK;
3814 }
3815 
pasteEnabled(BOOL * enabled)3816 HRESULT STDMETHODCALLTYPE WebView::pasteEnabled(
3817         /* [retval][out] */ BOOL* enabled)
3818 {
3819     Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
3820     *enabled = editor->canPaste() || editor->canDHTMLPaste();
3821     return S_OK;
3822 }
3823 
deleteEnabled(BOOL * enabled)3824 HRESULT STDMETHODCALLTYPE WebView::deleteEnabled(
3825         /* [retval][out] */ BOOL* enabled)
3826 {
3827     *enabled = m_page->focusController()->focusedOrMainFrame()->editor()->canDelete();
3828     return S_OK;
3829 }
3830 
editingEnabled(BOOL * enabled)3831 HRESULT STDMETHODCALLTYPE WebView::editingEnabled(
3832         /* [retval][out] */ BOOL* enabled)
3833 {
3834     *enabled = m_page->focusController()->focusedOrMainFrame()->editor()->canEdit();
3835     return S_OK;
3836 }
3837 
isGrammarCheckingEnabled(BOOL * enabled)3838 HRESULT STDMETHODCALLTYPE WebView::isGrammarCheckingEnabled(
3839     /* [retval][out] */ BOOL* enabled)
3840 {
3841     *enabled = grammarCheckingEnabled ? TRUE : FALSE;
3842     return S_OK;
3843 }
3844 
setGrammarCheckingEnabled(BOOL enabled)3845 HRESULT STDMETHODCALLTYPE WebView::setGrammarCheckingEnabled(
3846     BOOL enabled)
3847 {
3848     if (!m_editingDelegate) {
3849         LOG_ERROR("No NSSpellChecker");
3850         return E_FAIL;
3851     }
3852 
3853     if (grammarCheckingEnabled == !!enabled)
3854         return S_OK;
3855 
3856     grammarCheckingEnabled = !!enabled;
3857     COMPtr<IWebPreferences> prefs;
3858     if (SUCCEEDED(preferences(&prefs)))
3859         prefs->setGrammarCheckingEnabled(enabled);
3860 
3861     m_editingDelegate->updateGrammar();
3862 
3863     // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here
3864     // because grammar checking only occurs on code paths that already preflight spell checking appropriately.
3865 
3866     BOOL grammarEnabled;
3867     if (SUCCEEDED(isGrammarCheckingEnabled(&grammarEnabled)) && !grammarEnabled)
3868         m_mainFrame->unmarkAllBadGrammar();
3869 
3870     return S_OK;
3871 }
3872 
3873 // IWebViewUndoableEditing -----------------------------------------------------
3874 
replaceSelectionWithNode(IDOMNode *)3875 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithNode(
3876         /* [in] */ IDOMNode* /*node*/)
3877 {
3878     ASSERT_NOT_REACHED();
3879     return E_NOTIMPL;
3880 }
3881 
replaceSelectionWithText(BSTR text)3882 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithText(
3883         /* [in] */ BSTR text)
3884 {
3885     String textString(text, ::SysStringLen(text));
3886     Position start = m_page->mainFrame()->selection()->selection().start();
3887     m_page->focusController()->focusedOrMainFrame()->editor()->insertText(textString, 0);
3888     m_page->mainFrame()->selection()->setBase(start);
3889     return S_OK;
3890 }
3891 
replaceSelectionWithMarkupString(BSTR)3892 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithMarkupString(
3893         /* [in] */ BSTR /*markupString*/)
3894 {
3895     ASSERT_NOT_REACHED();
3896     return E_NOTIMPL;
3897 }
3898 
replaceSelectionWithArchive(IWebArchive *)3899 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithArchive(
3900         /* [in] */ IWebArchive* /*archive*/)
3901 {
3902     ASSERT_NOT_REACHED();
3903     return E_NOTIMPL;
3904 }
3905 
deleteSelection(void)3906 HRESULT STDMETHODCALLTYPE WebView::deleteSelection( void)
3907 {
3908     Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
3909     editor->deleteSelectionWithSmartDelete(editor->canSmartCopyOrDelete());
3910     return S_OK;
3911 }
3912 
clearSelection(void)3913 HRESULT STDMETHODCALLTYPE WebView::clearSelection( void)
3914 {
3915     m_page->focusController()->focusedOrMainFrame()->selection()->clear();
3916     return S_OK;
3917 }
3918 
applyStyle(IDOMCSSStyleDeclaration *)3919 HRESULT STDMETHODCALLTYPE WebView::applyStyle(
3920         /* [in] */ IDOMCSSStyleDeclaration* /*style*/)
3921 {
3922     ASSERT_NOT_REACHED();
3923     return E_NOTIMPL;
3924 }
3925 
3926 // IWebViewEditingActions ------------------------------------------------------
3927 
copy(IUnknown *)3928 HRESULT STDMETHODCALLTYPE WebView::copy(
3929         /* [in] */ IUnknown* /*sender*/)
3930 {
3931     m_page->focusController()->focusedOrMainFrame()->editor()->command("Copy").execute();
3932     return S_OK;
3933 }
3934 
cut(IUnknown *)3935 HRESULT STDMETHODCALLTYPE WebView::cut(
3936         /* [in] */ IUnknown* /*sender*/)
3937 {
3938     m_page->focusController()->focusedOrMainFrame()->editor()->command("Cut").execute();
3939     return S_OK;
3940 }
3941 
paste(IUnknown *)3942 HRESULT STDMETHODCALLTYPE WebView::paste(
3943         /* [in] */ IUnknown* /*sender*/)
3944 {
3945     m_page->focusController()->focusedOrMainFrame()->editor()->command("Paste").execute();
3946     return S_OK;
3947 }
3948 
copyURL(BSTR url)3949 HRESULT STDMETHODCALLTYPE WebView::copyURL(
3950         /* [in] */ BSTR url)
3951 {
3952     m_page->focusController()->focusedOrMainFrame()->editor()->copyURL(MarshallingHelpers::BSTRToKURL(url), "");
3953     return S_OK;
3954 }
3955 
3956 
copyFont(IUnknown *)3957 HRESULT STDMETHODCALLTYPE WebView::copyFont(
3958         /* [in] */ IUnknown* /*sender*/)
3959 {
3960     ASSERT_NOT_REACHED();
3961     return E_NOTIMPL;
3962 }
3963 
pasteFont(IUnknown *)3964 HRESULT STDMETHODCALLTYPE WebView::pasteFont(
3965         /* [in] */ IUnknown* /*sender*/)
3966 {
3967     ASSERT_NOT_REACHED();
3968     return E_NOTIMPL;
3969 }
3970 
delete_(IUnknown *)3971 HRESULT STDMETHODCALLTYPE WebView::delete_(
3972         /* [in] */ IUnknown* /*sender*/)
3973 {
3974     m_page->focusController()->focusedOrMainFrame()->editor()->command("Delete").execute();
3975     return S_OK;
3976 }
3977 
pasteAsPlainText(IUnknown *)3978 HRESULT STDMETHODCALLTYPE WebView::pasteAsPlainText(
3979         /* [in] */ IUnknown* /*sender*/)
3980 {
3981     ASSERT_NOT_REACHED();
3982     return E_NOTIMPL;
3983 }
3984 
pasteAsRichText(IUnknown *)3985 HRESULT STDMETHODCALLTYPE WebView::pasteAsRichText(
3986         /* [in] */ IUnknown* /*sender*/)
3987 {
3988     ASSERT_NOT_REACHED();
3989     return E_NOTIMPL;
3990 }
3991 
changeFont(IUnknown *)3992 HRESULT STDMETHODCALLTYPE WebView::changeFont(
3993         /* [in] */ IUnknown* /*sender*/)
3994 {
3995     ASSERT_NOT_REACHED();
3996     return E_NOTIMPL;
3997 }
3998 
changeAttributes(IUnknown *)3999 HRESULT STDMETHODCALLTYPE WebView::changeAttributes(
4000         /* [in] */ IUnknown* /*sender*/)
4001 {
4002     ASSERT_NOT_REACHED();
4003     return E_NOTIMPL;
4004 }
4005 
changeDocumentBackgroundColor(IUnknown *)4006 HRESULT STDMETHODCALLTYPE WebView::changeDocumentBackgroundColor(
4007         /* [in] */ IUnknown* /*sender*/)
4008 {
4009     ASSERT_NOT_REACHED();
4010     return E_NOTIMPL;
4011 }
4012 
changeColor(IUnknown *)4013 HRESULT STDMETHODCALLTYPE WebView::changeColor(
4014         /* [in] */ IUnknown* /*sender*/)
4015 {
4016     ASSERT_NOT_REACHED();
4017     return E_NOTIMPL;
4018 }
4019 
alignCenter(IUnknown *)4020 HRESULT STDMETHODCALLTYPE WebView::alignCenter(
4021         /* [in] */ IUnknown* /*sender*/)
4022 {
4023     ASSERT_NOT_REACHED();
4024     return E_NOTIMPL;
4025 }
4026 
alignJustified(IUnknown *)4027 HRESULT STDMETHODCALLTYPE WebView::alignJustified(
4028         /* [in] */ IUnknown* /*sender*/)
4029 {
4030     ASSERT_NOT_REACHED();
4031     return E_NOTIMPL;
4032 }
4033 
alignLeft(IUnknown *)4034 HRESULT STDMETHODCALLTYPE WebView::alignLeft(
4035         /* [in] */ IUnknown* /*sender*/)
4036 {
4037     ASSERT_NOT_REACHED();
4038     return E_NOTIMPL;
4039 }
4040 
alignRight(IUnknown *)4041 HRESULT STDMETHODCALLTYPE WebView::alignRight(
4042         /* [in] */ IUnknown* /*sender*/)
4043 {
4044     ASSERT_NOT_REACHED();
4045     return E_NOTIMPL;
4046 }
4047 
checkSpelling(IUnknown *)4048 HRESULT STDMETHODCALLTYPE WebView::checkSpelling(
4049         /* [in] */ IUnknown* /*sender*/)
4050 {
4051     if (!m_editingDelegate) {
4052         LOG_ERROR("No NSSpellChecker");
4053         return E_FAIL;
4054     }
4055 
4056     core(m_mainFrame)->editor()->advanceToNextMisspelling();
4057     return S_OK;
4058 }
4059 
showGuessPanel(IUnknown *)4060 HRESULT STDMETHODCALLTYPE WebView::showGuessPanel(
4061         /* [in] */ IUnknown* /*sender*/)
4062 {
4063     if (!m_editingDelegate) {
4064         LOG_ERROR("No NSSpellChecker");
4065         return E_FAIL;
4066     }
4067 
4068     // Post-Tiger, this menu item is a show/hide toggle, to match AppKit. Leave Tiger behavior alone
4069     // to match rest of OS X.
4070     BOOL showing;
4071     if (SUCCEEDED(m_editingDelegate->spellingUIIsShowing(&showing)) && showing) {
4072         m_editingDelegate->showSpellingUI(FALSE);
4073     }
4074 
4075     core(m_mainFrame)->editor()->advanceToNextMisspelling(true);
4076     m_editingDelegate->showSpellingUI(TRUE);
4077     return S_OK;
4078 }
4079 
performFindPanelAction(IUnknown *)4080 HRESULT STDMETHODCALLTYPE WebView::performFindPanelAction(
4081         /* [in] */ IUnknown* /*sender*/)
4082 {
4083     ASSERT_NOT_REACHED();
4084     return E_NOTIMPL;
4085 }
4086 
startSpeaking(IUnknown *)4087 HRESULT STDMETHODCALLTYPE WebView::startSpeaking(
4088         /* [in] */ IUnknown* /*sender*/)
4089 {
4090     ASSERT_NOT_REACHED();
4091     return E_NOTIMPL;
4092 }
4093 
stopSpeaking(IUnknown *)4094 HRESULT STDMETHODCALLTYPE WebView::stopSpeaking(
4095         /* [in] */ IUnknown* /*sender*/)
4096 {
4097     ASSERT_NOT_REACHED();
4098     return E_NOTIMPL;
4099 }
4100 
4101 // IWebNotificationObserver -----------------------------------------------------------------
4102 
onNotify(IWebNotification * notification)4103 HRESULT STDMETHODCALLTYPE WebView::onNotify(
4104     /* [in] */ IWebNotification* notification)
4105 {
4106     BSTR nameBSTR;
4107     HRESULT hr = notification->name(&nameBSTR);
4108     if (FAILED(hr))
4109         return hr;
4110 
4111     BString name;
4112     name.adoptBSTR(nameBSTR);
4113 
4114     if (!wcscmp(name, WebIconDatabase::iconDatabaseDidAddIconNotification()))
4115         return notifyDidAddIcon(notification);
4116 
4117     if (!wcscmp(name, WebPreferences::webPreferencesChangedNotification()))
4118         return notifyPreferencesChanged(notification);
4119 
4120     return hr;
4121 }
4122 
notifyPreferencesChanged(IWebNotification * notification)4123 HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification)
4124 {
4125     HRESULT hr;
4126 
4127     COMPtr<IUnknown> unkPrefs;
4128     hr = notification->getObject(&unkPrefs);
4129     if (FAILED(hr))
4130         return hr;
4131 
4132     COMPtr<IWebPreferences> preferences(Query, unkPrefs);
4133     if (!preferences)
4134         return E_NOINTERFACE;
4135 
4136     ASSERT(preferences == m_preferences);
4137 
4138     BSTR str;
4139     int size;
4140     BOOL enabled;
4141 
4142     Settings* settings = m_page->settings();
4143 
4144     hr = preferences->cursiveFontFamily(&str);
4145     if (FAILED(hr))
4146         return hr;
4147     settings->setCursiveFontFamily(AtomicString(str, SysStringLen(str)));
4148     SysFreeString(str);
4149 
4150     hr = preferences->defaultFixedFontSize(&size);
4151     if (FAILED(hr))
4152         return hr;
4153     settings->setDefaultFixedFontSize(size);
4154 
4155     hr = preferences->defaultFontSize(&size);
4156     if (FAILED(hr))
4157         return hr;
4158     settings->setDefaultFontSize(size);
4159 
4160     hr = preferences->defaultTextEncodingName(&str);
4161     if (FAILED(hr))
4162         return hr;
4163     settings->setDefaultTextEncodingName(String(str, SysStringLen(str)));
4164     SysFreeString(str);
4165 
4166     hr = preferences->fantasyFontFamily(&str);
4167     if (FAILED(hr))
4168         return hr;
4169     settings->setFantasyFontFamily(AtomicString(str, SysStringLen(str)));
4170     SysFreeString(str);
4171 
4172     hr = preferences->fixedFontFamily(&str);
4173     if (FAILED(hr))
4174         return hr;
4175     settings->setFixedFontFamily(AtomicString(str, SysStringLen(str)));
4176     SysFreeString(str);
4177 
4178     hr = preferences->isJavaEnabled(&enabled);
4179     if (FAILED(hr))
4180         return hr;
4181     settings->setJavaEnabled(!!enabled);
4182 
4183     hr = preferences->isJavaScriptEnabled(&enabled);
4184     if (FAILED(hr))
4185         return hr;
4186     settings->setJavaScriptEnabled(!!enabled);
4187 
4188     hr = preferences->javaScriptCanOpenWindowsAutomatically(&enabled);
4189     if (FAILED(hr))
4190         return hr;
4191     settings->setJavaScriptCanOpenWindowsAutomatically(!!enabled);
4192 
4193     hr = preferences->minimumFontSize(&size);
4194     if (FAILED(hr))
4195         return hr;
4196     settings->setMinimumFontSize(size);
4197 
4198     hr = preferences->minimumLogicalFontSize(&size);
4199     if (FAILED(hr))
4200         return hr;
4201     settings->setMinimumLogicalFontSize(size);
4202 
4203     hr = preferences->arePlugInsEnabled(&enabled);
4204     if (FAILED(hr))
4205         return hr;
4206     settings->setPluginsEnabled(!!enabled);
4207 
4208     hr = preferences->privateBrowsingEnabled(&enabled);
4209     if (FAILED(hr))
4210         return hr;
4211     settings->setPrivateBrowsingEnabled(!!enabled);
4212 
4213     hr = preferences->sansSerifFontFamily(&str);
4214     if (FAILED(hr))
4215         return hr;
4216     settings->setSansSerifFontFamily(AtomicString(str, SysStringLen(str)));
4217     SysFreeString(str);
4218 
4219     hr = preferences->serifFontFamily(&str);
4220     if (FAILED(hr))
4221         return hr;
4222     settings->setSerifFontFamily(AtomicString(str, SysStringLen(str)));
4223     SysFreeString(str);
4224 
4225     hr = preferences->standardFontFamily(&str);
4226     if (FAILED(hr))
4227         return hr;
4228     settings->setStandardFontFamily(AtomicString(str, SysStringLen(str)));
4229     SysFreeString(str);
4230 
4231     hr = preferences->loadsImagesAutomatically(&enabled);
4232     if (FAILED(hr))
4233         return hr;
4234     settings->setLoadsImagesAutomatically(!!enabled);
4235 
4236     hr = preferences->userStyleSheetEnabled(&enabled);
4237     if (FAILED(hr))
4238         return hr;
4239     if (enabled) {
4240         hr = preferences->userStyleSheetLocation(&str);
4241         if (FAILED(hr))
4242             return hr;
4243 
4244         RetainPtr<CFStringRef> urlString(AdoptCF, String(str, SysStringLen(str)).createCFString());
4245         RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateWithString(kCFAllocatorDefault, urlString.get(), 0));
4246 
4247         // Check if the passed in string is a path and convert it to a URL.
4248         // FIXME: This is a workaround for nightly builds until we can get Safari to pass
4249         // in an URL here. See <rdar://problem/5478378>
4250         if (!url) {
4251             DWORD len = SysStringLen(str) + 1;
4252 
4253             int result = WideCharToMultiByte(CP_UTF8, 0, str, len, 0, 0, 0, 0);
4254             Vector<UInt8> utf8Path(result);
4255             if (!WideCharToMultiByte(CP_UTF8, 0, str, len, (LPSTR)utf8Path.data(), result, 0, 0))
4256                 return E_FAIL;
4257 
4258             url.adoptCF(CFURLCreateFromFileSystemRepresentation(0, utf8Path.data(), result - 1, false));
4259         }
4260 
4261         settings->setUserStyleSheetLocation(url.get());
4262         SysFreeString(str);
4263     } else {
4264         settings->setUserStyleSheetLocation(KURL());
4265     }
4266 
4267     hr = preferences->shouldPrintBackgrounds(&enabled);
4268     if (FAILED(hr))
4269         return hr;
4270     settings->setShouldPrintBackgrounds(!!enabled);
4271 
4272     hr = preferences->textAreasAreResizable(&enabled);
4273     if (FAILED(hr))
4274         return hr;
4275     settings->setTextAreasAreResizable(!!enabled);
4276 
4277     WebKitEditableLinkBehavior behavior;
4278     hr = preferences->editableLinkBehavior(&behavior);
4279     if (FAILED(hr))
4280         return hr;
4281     settings->setEditableLinkBehavior((EditableLinkBehavior)behavior);
4282 
4283     hr = preferences->usesPageCache(&enabled);
4284     if (FAILED(hr))
4285         return hr;
4286     settings->setUsesPageCache(!!enabled);
4287 
4288     hr = preferences->isDOMPasteAllowed(&enabled);
4289     if (FAILED(hr))
4290         return hr;
4291     settings->setDOMPasteAllowed(!!enabled);
4292 
4293     hr = preferences->shouldPaintCustomScrollbars(&enabled);
4294     if (FAILED(hr))
4295         return hr;
4296     settings->setShouldPaintCustomScrollbars(!!enabled);
4297 
4298     hr = preferences->zoomsTextOnly(&enabled);
4299     if (FAILED(hr))
4300         return hr;
4301     settings->setZoomsTextOnly(!!enabled);
4302 
4303     settings->setShowsURLsInToolTips(false);
4304     settings->setForceFTPDirectoryListings(true);
4305     settings->setDeveloperExtrasEnabled(developerExtrasEnabled());
4306     settings->setNeedsSiteSpecificQuirks(s_allowSiteSpecificHacks);
4307 
4308     FontSmoothingType smoothingType;
4309     hr = preferences->fontSmoothing(&smoothingType);
4310     if (FAILED(hr))
4311         return hr;
4312     settings->setFontRenderingMode(smoothingType != FontSmoothingTypeWindows ? NormalRenderingMode : AlternateRenderingMode);
4313 
4314     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
4315     if (prefsPrivate) {
4316         hr = prefsPrivate->authorAndUserStylesEnabled(&enabled);
4317         if (FAILED(hr))
4318             return hr;
4319         settings->setAuthorAndUserStylesEnabled(enabled);
4320     }
4321 
4322     hr = prefsPrivate->inApplicationChromeMode(&enabled);
4323     if (FAILED(hr))
4324         return hr;
4325     settings->setApplicationChromeMode(enabled);
4326 
4327     hr = prefsPrivate->offlineWebApplicationCacheEnabled(&enabled);
4328     if (FAILED(hr))
4329         return hr;
4330     settings->setOfflineWebApplicationCacheEnabled(enabled);
4331 
4332     hr = prefsPrivate->databasesEnabled(&enabled);
4333     if (FAILED(hr))
4334         return hr;
4335     settings->setDatabasesEnabled(enabled);
4336 
4337     hr = prefsPrivate->localStorageEnabled(&enabled);
4338     if (FAILED(hr))
4339         return hr;
4340     settings->setLocalStorageEnabled(enabled);
4341 
4342     hr = prefsPrivate->isWebSecurityEnabled(&enabled);
4343     if (FAILED(hr))
4344         return hr;
4345     settings->setWebSecurityEnabled(!!enabled);
4346 
4347     hr = prefsPrivate->allowUniversalAccessFromFileURLs(&enabled);
4348     if (FAILED(hr))
4349         return hr;
4350     settings->setAllowUniversalAccessFromFileURLs(!!enabled);
4351 
4352     hr = prefsPrivate->isXSSAuditorEnabled(&enabled);
4353     if (FAILED(hr))
4354         return hr;
4355     settings->setXSSAuditorEnabled(!!enabled);
4356 
4357 #if USE(SAFARI_THEME)
4358     hr = prefsPrivate->shouldPaintNativeControls(&enabled);
4359     if (FAILED(hr))
4360         return hr;
4361     settings->setShouldPaintNativeControls(!!enabled);
4362 #endif
4363 
4364     if (!m_closeWindowTimer.isActive())
4365         m_mainFrame->invalidate(); // FIXME
4366 
4367     hr = updateSharedSettingsFromPreferencesIfNeeded(preferences.get());
4368     if (FAILED(hr))
4369         return hr;
4370 
4371     return S_OK;
4372 }
4373 
updateSharedSettingsFromPreferencesIfNeeded(IWebPreferences * preferences)4374 HRESULT updateSharedSettingsFromPreferencesIfNeeded(IWebPreferences* preferences)
4375 {
4376     if (preferences != WebPreferences::sharedStandardPreferences())
4377         return S_OK;
4378 
4379     WebKitCookieStorageAcceptPolicy acceptPolicy;
4380     HRESULT hr = preferences->cookieStorageAcceptPolicy(&acceptPolicy);
4381     if (FAILED(hr))
4382         return hr;
4383 
4384 #if USE(CFNETWORK)
4385     // Set cookie storage accept policy
4386     if (CFHTTPCookieStorageRef cookieStorage = currentCookieStorage())
4387         CFHTTPCookieStorageSetCookieAcceptPolicy(cookieStorage, acceptPolicy);
4388 #endif
4389 
4390     return S_OK;
4391 }
4392 
4393 // IWebViewPrivate ------------------------------------------------------------
4394 
setCustomDropTarget(IDropTarget * dt)4395 HRESULT STDMETHODCALLTYPE WebView::setCustomDropTarget(
4396     /* [in] */ IDropTarget* dt)
4397 {
4398     ASSERT(::IsWindow(m_viewWindow));
4399     if (!dt)
4400         return E_POINTER;
4401     m_hasCustomDropTarget = true;
4402     revokeDragDrop();
4403     return ::RegisterDragDrop(m_viewWindow,dt);
4404 }
4405 
removeCustomDropTarget()4406 HRESULT STDMETHODCALLTYPE WebView::removeCustomDropTarget()
4407 {
4408     if (!m_hasCustomDropTarget)
4409         return S_OK;
4410     m_hasCustomDropTarget = false;
4411     revokeDragDrop();
4412     return registerDragDrop();
4413 }
4414 
setInViewSourceMode(BOOL flag)4415 HRESULT STDMETHODCALLTYPE WebView::setInViewSourceMode(
4416         /* [in] */ BOOL flag)
4417 {
4418     if (!m_mainFrame)
4419         return E_FAIL;
4420 
4421     return m_mainFrame->setInViewSourceMode(flag);
4422 }
4423 
inViewSourceMode(BOOL * flag)4424 HRESULT STDMETHODCALLTYPE WebView::inViewSourceMode(
4425         /* [retval][out] */ BOOL* flag)
4426 {
4427     if (!m_mainFrame)
4428         return E_FAIL;
4429 
4430     return m_mainFrame->inViewSourceMode(flag);
4431 }
4432 
viewWindow(OLE_HANDLE * window)4433 HRESULT STDMETHODCALLTYPE WebView::viewWindow(
4434         /* [retval][out] */ OLE_HANDLE *window)
4435 {
4436     *window = (OLE_HANDLE)(ULONG64)m_viewWindow;
4437     return S_OK;
4438 }
4439 
setFormDelegate(IWebFormDelegate * formDelegate)4440 HRESULT STDMETHODCALLTYPE WebView::setFormDelegate(
4441     /* [in] */ IWebFormDelegate *formDelegate)
4442 {
4443     m_formDelegate = formDelegate;
4444     return S_OK;
4445 }
4446 
formDelegate(IWebFormDelegate ** formDelegate)4447 HRESULT STDMETHODCALLTYPE WebView::formDelegate(
4448     /* [retval][out] */ IWebFormDelegate **formDelegate)
4449 {
4450     if (!m_formDelegate)
4451         return E_FAIL;
4452 
4453     return m_formDelegate.copyRefTo(formDelegate);
4454 }
4455 
setFrameLoadDelegatePrivate(IWebFrameLoadDelegatePrivate * d)4456 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegatePrivate(
4457     /* [in] */ IWebFrameLoadDelegatePrivate* d)
4458 {
4459     m_frameLoadDelegatePrivate = d;
4460     return S_OK;
4461 }
4462 
frameLoadDelegatePrivate(IWebFrameLoadDelegatePrivate ** d)4463 HRESULT STDMETHODCALLTYPE WebView::frameLoadDelegatePrivate(
4464     /* [out][retval] */ IWebFrameLoadDelegatePrivate** d)
4465 {
4466     if (!m_frameLoadDelegatePrivate)
4467         return E_FAIL;
4468 
4469     return m_frameLoadDelegatePrivate.copyRefTo(d);
4470 }
4471 
scrollOffset(LPPOINT offset)4472 HRESULT STDMETHODCALLTYPE WebView::scrollOffset(
4473     /* [retval][out] */ LPPOINT offset)
4474 {
4475     if (!offset)
4476         return E_POINTER;
4477     IntSize offsetIntSize = m_page->mainFrame()->view()->scrollOffset();
4478     offset->x = offsetIntSize.width();
4479     offset->y = offsetIntSize.height();
4480     return S_OK;
4481 }
4482 
scrollBy(LPPOINT offset)4483 HRESULT STDMETHODCALLTYPE WebView::scrollBy(
4484     /* [in] */ LPPOINT offset)
4485 {
4486     if (!offset)
4487         return E_POINTER;
4488     m_page->mainFrame()->view()->scrollBy(IntSize(offset->x, offset->y));
4489     return S_OK;
4490 }
4491 
visibleContentRect(LPRECT rect)4492 HRESULT STDMETHODCALLTYPE WebView::visibleContentRect(
4493     /* [retval][out] */ LPRECT rect)
4494 {
4495     if (!rect)
4496         return E_POINTER;
4497     FloatRect visibleContent = m_page->mainFrame()->view()->visibleContentRect();
4498     rect->left = (LONG) visibleContent.x();
4499     rect->top = (LONG) visibleContent.y();
4500     rect->right = (LONG) visibleContent.right();
4501     rect->bottom = (LONG) visibleContent.bottom();
4502     return S_OK;
4503 }
4504 
dragOperationToDragCursor(DragOperation op)4505 static DWORD dragOperationToDragCursor(DragOperation op) {
4506     DWORD res = DROPEFFECT_NONE;
4507     if (op & DragOperationCopy)
4508         res = DROPEFFECT_COPY;
4509     else if (op & DragOperationLink)
4510         res = DROPEFFECT_LINK;
4511     else if (op & DragOperationMove)
4512         res = DROPEFFECT_MOVE;
4513     else if (op & DragOperationGeneric)
4514         res = DROPEFFECT_MOVE; //This appears to be the Firefox behaviour
4515     return res;
4516 }
4517 
keyStateToDragOperation(DWORD)4518 static DragOperation keyStateToDragOperation(DWORD) {
4519     //FIXME: This is currently very simple, it may need to actually
4520     //work out an appropriate DragOperation in future -- however this
4521     //behaviour appears to match FireFox
4522     return (DragOperation)(DragOperationCopy | DragOperationLink);
4523 }
4524 
DragEnter(IDataObject * pDataObject,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)4525 HRESULT STDMETHODCALLTYPE WebView::DragEnter(
4526         IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
4527 {
4528     m_dragData = 0;
4529 
4530     if (m_dropTargetHelper)
4531         m_dropTargetHelper->DragEnter(m_viewWindow, pDataObject, (POINT*)&pt, *pdwEffect);
4532 
4533     POINTL localpt = pt;
4534     ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
4535     DragData data(pDataObject, IntPoint(localpt.x, localpt.y),
4536         IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
4537     *pdwEffect = dragOperationToDragCursor(m_page->dragController()->dragEntered(&data));
4538 
4539     m_dragData = pDataObject;
4540 
4541     return S_OK;
4542 }
4543 
DragOver(DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)4544 HRESULT STDMETHODCALLTYPE WebView::DragOver(
4545         DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
4546 {
4547     if (m_dropTargetHelper)
4548         m_dropTargetHelper->DragOver((POINT*)&pt, *pdwEffect);
4549 
4550     if (m_dragData) {
4551         POINTL localpt = pt;
4552         ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
4553         DragData data(m_dragData.get(), IntPoint(localpt.x, localpt.y),
4554             IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
4555         *pdwEffect = dragOperationToDragCursor(m_page->dragController()->dragUpdated(&data));
4556     } else
4557         *pdwEffect = DROPEFFECT_NONE;
4558 
4559     return S_OK;
4560 }
4561 
DragLeave()4562 HRESULT STDMETHODCALLTYPE WebView::DragLeave()
4563 {
4564     if (m_dropTargetHelper)
4565         m_dropTargetHelper->DragLeave();
4566 
4567     if (m_dragData) {
4568         DragData data(m_dragData.get(), IntPoint(), IntPoint(),
4569             DragOperationNone);
4570         m_page->dragController()->dragExited(&data);
4571         m_dragData = 0;
4572     }
4573     return S_OK;
4574 }
4575 
Drop(IDataObject * pDataObject,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)4576 HRESULT STDMETHODCALLTYPE WebView::Drop(
4577         IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
4578 {
4579     if (m_dropTargetHelper)
4580         m_dropTargetHelper->Drop(pDataObject, (POINT*)&pt, *pdwEffect);
4581 
4582     m_dragData = 0;
4583     *pdwEffect = DROPEFFECT_NONE;
4584     POINTL localpt = pt;
4585     ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
4586     DragData data(pDataObject, IntPoint(localpt.x, localpt.y),
4587         IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
4588     m_page->dragController()->performDrag(&data);
4589     return S_OK;
4590 }
4591 
canHandleRequest(IWebURLRequest * request,BOOL * result)4592 HRESULT STDMETHODCALLTYPE WebView::canHandleRequest(
4593     IWebURLRequest *request,
4594     BOOL *result)
4595 {
4596     COMPtr<WebMutableURLRequest> requestImpl;
4597 
4598     HRESULT hr = request->QueryInterface(&requestImpl);
4599     if (FAILED(hr))
4600         return hr;
4601 
4602     *result = !!canHandleRequest(requestImpl->resourceRequest());
4603     return S_OK;
4604 }
4605 
standardUserAgentWithApplicationName(BSTR applicationName,BSTR * groupName)4606 HRESULT STDMETHODCALLTYPE WebView::standardUserAgentWithApplicationName(
4607     BSTR applicationName,
4608     BSTR* groupName)
4609 {
4610     if (!groupName) {
4611         ASSERT_NOT_REACHED();
4612         return E_POINTER;
4613     }
4614 
4615     *groupName;
4616 
4617     if (!applicationName) {
4618         ASSERT_NOT_REACHED();
4619         return E_POINTER;
4620     }
4621 
4622     BString applicationNameBString(applicationName);
4623     *groupName = BString(standardUserAgentWithApplicationName(String(applicationNameBString, SysStringLen(applicationNameBString)))).release();
4624     return S_OK;
4625 }
4626 
clearFocusNode()4627 HRESULT STDMETHODCALLTYPE WebView::clearFocusNode()
4628 {
4629     if (m_page && m_page->focusController())
4630         m_page->focusController()->setFocusedNode(0, 0);
4631     return S_OK;
4632 }
4633 
setInitialFocus(BOOL forward)4634 HRESULT STDMETHODCALLTYPE WebView::setInitialFocus(
4635     /* [in] */ BOOL forward)
4636 {
4637     if (m_page && m_page->focusController()) {
4638         Frame* frame = m_page->focusController()->focusedOrMainFrame();
4639         frame->document()->setFocusedNode(0);
4640         m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0);
4641     }
4642     return S_OK;
4643 }
4644 
setTabKeyCyclesThroughElements(BOOL cycles)4645 HRESULT STDMETHODCALLTYPE WebView::setTabKeyCyclesThroughElements(
4646     /* [in] */ BOOL cycles)
4647 {
4648     if (m_page)
4649         m_page->setTabKeyCyclesThroughElements(!!cycles);
4650 
4651     return S_OK;
4652 }
4653 
tabKeyCyclesThroughElements(BOOL * result)4654 HRESULT STDMETHODCALLTYPE WebView::tabKeyCyclesThroughElements(
4655     /* [retval][out] */ BOOL* result)
4656 {
4657     if (!result) {
4658         ASSERT_NOT_REACHED();
4659         return E_POINTER;
4660     }
4661 
4662     *result = m_page && m_page->tabKeyCyclesThroughElements() ? TRUE : FALSE;
4663     return S_OK;
4664 }
4665 
setAllowSiteSpecificHacks(BOOL allow)4666 HRESULT STDMETHODCALLTYPE WebView::setAllowSiteSpecificHacks(
4667     /* [in] */ BOOL allow)
4668 {
4669     s_allowSiteSpecificHacks = !!allow;
4670     // FIXME: This sets a global so it needs to call notifyPreferencesChanged
4671     // on all WebView objects (not just itself).
4672     return S_OK;
4673 }
4674 
addAdditionalPluginDirectory(BSTR directory)4675 HRESULT STDMETHODCALLTYPE WebView::addAdditionalPluginDirectory(
4676         /* [in] */ BSTR directory)
4677 {
4678     PluginDatabase::installedPlugins()->addExtraPluginDirectory(String(directory, SysStringLen(directory)));
4679     return S_OK;
4680 }
4681 
loadBackForwardListFromOtherView(IWebView * otherView)4682 HRESULT STDMETHODCALLTYPE WebView::loadBackForwardListFromOtherView(
4683     /* [in] */ IWebView* otherView)
4684 {
4685     if (!m_page)
4686         return E_FAIL;
4687 
4688     // It turns out the right combination of behavior is done with the back/forward load
4689     // type.  (See behavior matrix at the top of WebFramePrivate.)  So we copy all the items
4690     // in the back forward list, and go to the current one.
4691     BackForwardList* backForwardList = m_page->backForwardList();
4692     ASSERT(!backForwardList->currentItem()); // destination list should be empty
4693 
4694     COMPtr<WebView> otherWebView;
4695     if (FAILED(otherView->QueryInterface(&otherWebView)))
4696         return E_FAIL;
4697     BackForwardList* otherBackForwardList = otherWebView->m_page->backForwardList();
4698     if (!otherBackForwardList->currentItem())
4699         return S_OK; // empty back forward list, bail
4700 
4701     HistoryItem* newItemToGoTo = 0;
4702 
4703     int lastItemIndex = otherBackForwardList->forwardListCount();
4704     for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
4705         if (!i) {
4706             // If this item is showing , save away its current scroll and form state,
4707             // since that might have changed since loading and it is normally not saved
4708             // until we leave that page.
4709             otherWebView->m_page->mainFrame()->loader()->saveDocumentAndScrollState();
4710         }
4711         RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
4712         if (!i)
4713             newItemToGoTo = newItem.get();
4714         backForwardList->addItem(newItem.release());
4715     }
4716 
4717     ASSERT(newItemToGoTo);
4718     m_page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
4719     return S_OK;
4720 }
4721 
clearUndoRedoOperations()4722 HRESULT STDMETHODCALLTYPE WebView::clearUndoRedoOperations()
4723 {
4724     if (Frame* frame = m_page->focusController()->focusedOrMainFrame())
4725         frame->editor()->clearUndoRedoOperations();
4726     return S_OK;
4727 }
4728 
shouldClose(BOOL * result)4729 HRESULT STDMETHODCALLTYPE WebView::shouldClose(
4730     /* [retval][out] */ BOOL* result)
4731 {
4732     if (!result) {
4733         ASSERT_NOT_REACHED();
4734         return E_POINTER;
4735     }
4736 
4737     *result = TRUE;
4738     if (Frame* frame = m_page->focusController()->focusedOrMainFrame())
4739         *result = frame->shouldClose() ? TRUE : FALSE;
4740     return S_OK;
4741 }
4742 
registerDragDrop()4743 HRESULT WebView::registerDragDrop()
4744 {
4745     ASSERT(::IsWindow(m_viewWindow));
4746     return ::RegisterDragDrop(m_viewWindow, this);
4747 }
4748 
revokeDragDrop()4749 HRESULT WebView::revokeDragDrop()
4750 {
4751     ASSERT(::IsWindow(m_viewWindow));
4752     return ::RevokeDragDrop(m_viewWindow);
4753 }
4754 
setProhibitsMainFrameScrolling(BOOL b)4755 HRESULT WebView::setProhibitsMainFrameScrolling(BOOL b)
4756 {
4757     if (!m_page)
4758         return E_FAIL;
4759 
4760     m_page->mainFrame()->view()->setProhibitsScrolling(b);
4761     return S_OK;
4762 }
4763 
setShouldApplyMacFontAscentHack(BOOL b)4764 HRESULT WebView::setShouldApplyMacFontAscentHack(BOOL b)
4765 {
4766     SimpleFontData::setShouldApplyMacAscentHack(b);
4767     return S_OK;
4768 }
4769 
4770 class IMMDict {
4771     typedef HIMC (CALLBACK *getContextPtr)(HWND);
4772     typedef BOOL (CALLBACK *releaseContextPtr)(HWND, HIMC);
4773     typedef LONG (CALLBACK *getCompositionStringPtr)(HIMC, DWORD, LPVOID, DWORD);
4774     typedef BOOL (CALLBACK *setCandidateWindowPtr)(HIMC, LPCANDIDATEFORM);
4775     typedef BOOL (CALLBACK *setOpenStatusPtr)(HIMC, BOOL);
4776     typedef BOOL (CALLBACK *notifyIMEPtr)(HIMC, DWORD, DWORD, DWORD);
4777     typedef BOOL (CALLBACK *associateContextExPtr)(HWND, HIMC, DWORD);
4778 
4779 public:
4780     getContextPtr getContext;
4781     releaseContextPtr releaseContext;
4782     getCompositionStringPtr getCompositionString;
4783     setCandidateWindowPtr setCandidateWindow;
4784     setOpenStatusPtr setOpenStatus;
4785     notifyIMEPtr notifyIME;
4786     associateContextExPtr associateContextEx;
4787 
4788     static const IMMDict& dict();
4789 private:
4790     IMMDict();
4791     HMODULE m_instance;
4792 };
4793 
dict()4794 const IMMDict& IMMDict::dict()
4795 {
4796     static IMMDict instance;
4797     return instance;
4798 }
4799 
IMMDict()4800 IMMDict::IMMDict()
4801 {
4802     m_instance = ::LoadLibrary(TEXT("IMM32.DLL"));
4803     getContext = reinterpret_cast<getContextPtr>(::GetProcAddress(m_instance, "ImmGetContext"));
4804     ASSERT(getContext);
4805     releaseContext = reinterpret_cast<releaseContextPtr>(::GetProcAddress(m_instance, "ImmReleaseContext"));
4806     ASSERT(releaseContext);
4807     getCompositionString = reinterpret_cast<getCompositionStringPtr>(::GetProcAddress(m_instance, "ImmGetCompositionStringW"));
4808     ASSERT(getCompositionString);
4809     setCandidateWindow = reinterpret_cast<setCandidateWindowPtr>(::GetProcAddress(m_instance, "ImmSetCandidateWindow"));
4810     ASSERT(setCandidateWindow);
4811     setOpenStatus = reinterpret_cast<setOpenStatusPtr>(::GetProcAddress(m_instance, "ImmSetOpenStatus"));
4812     ASSERT(setOpenStatus);
4813     notifyIME = reinterpret_cast<notifyIMEPtr>(::GetProcAddress(m_instance, "ImmNotifyIME"));
4814     ASSERT(notifyIME);
4815     associateContextEx = reinterpret_cast<associateContextExPtr>(::GetProcAddress(m_instance, "ImmAssociateContextEx"));
4816     ASSERT(associateContextEx);
4817 }
4818 
getIMMContext()4819 HIMC WebView::getIMMContext()
4820 {
4821     HIMC context = IMMDict::dict().getContext(m_viewWindow);
4822     return context;
4823 }
4824 
releaseIMMContext(HIMC hIMC)4825 void WebView::releaseIMMContext(HIMC hIMC)
4826 {
4827     if (!hIMC)
4828         return;
4829     IMMDict::dict().releaseContext(m_viewWindow, hIMC);
4830 }
4831 
prepareCandidateWindow(Frame * targetFrame,HIMC hInputContext)4832 void WebView::prepareCandidateWindow(Frame* targetFrame, HIMC hInputContext)
4833 {
4834     IntRect caret;
4835     if (RefPtr<Range> range = targetFrame->selection()->selection().toNormalizedRange()) {
4836         ExceptionCode ec = 0;
4837         RefPtr<Range> tempRange = range->cloneRange(ec);
4838         caret = targetFrame->firstRectForRange(tempRange.get());
4839     }
4840     caret = targetFrame->view()->contentsToWindow(caret);
4841     CANDIDATEFORM form;
4842     form.dwIndex = 0;
4843     form.dwStyle = CFS_EXCLUDE;
4844     form.ptCurrentPos.x = caret.x();
4845     form.ptCurrentPos.y = caret.y() + caret.height();
4846     form.rcArea.top = caret.y();
4847     form.rcArea.bottom = caret.bottom();
4848     form.rcArea.left = caret.x();
4849     form.rcArea.right = caret.right();
4850     IMMDict::dict().setCandidateWindow(hInputContext, &form);
4851 }
4852 
resetIME(Frame * targetFrame)4853 void WebView::resetIME(Frame* targetFrame)
4854 {
4855     if (targetFrame)
4856         targetFrame->editor()->confirmCompositionWithoutDisturbingSelection();
4857 
4858     if (HIMC hInputContext = getIMMContext()) {
4859         IMMDict::dict().notifyIME(hInputContext, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
4860         releaseIMMContext(hInputContext);
4861     }
4862 }
4863 
updateSelectionForIME()4864 void WebView::updateSelectionForIME()
4865 {
4866     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
4867     if (!targetFrame || !targetFrame->editor()->hasComposition())
4868         return;
4869 
4870     if (targetFrame->editor()->ignoreCompositionSelectionChange())
4871         return;
4872 
4873     unsigned start;
4874     unsigned end;
4875     if (!targetFrame->editor()->getCompositionSelection(start, end))
4876         resetIME(targetFrame);
4877 }
4878 
setInputMethodState(bool enabled)4879 void WebView::setInputMethodState(bool enabled)
4880 {
4881     IMMDict::dict().associateContextEx(m_viewWindow, 0, enabled ? IACE_DEFAULT : 0);
4882 }
4883 
selectionChanged()4884 void WebView::selectionChanged()
4885 {
4886     updateSelectionForIME();
4887 }
4888 
onIMEStartComposition()4889 bool WebView::onIMEStartComposition()
4890 {
4891     m_inIMEComposition++;
4892     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
4893     if (!targetFrame)
4894         return true;
4895 
4896     HIMC hInputContext = getIMMContext();
4897     prepareCandidateWindow(targetFrame, hInputContext);
4898     releaseIMMContext(hInputContext);
4899     return true;
4900 }
4901 
getCompositionString(HIMC hInputContext,DWORD type,String & result)4902 static bool getCompositionString(HIMC hInputContext, DWORD type, String& result)
4903 {
4904     int compositionLength = IMMDict::dict().getCompositionString(hInputContext, type, 0, 0);
4905     if (compositionLength <= 0)
4906         return false;
4907     Vector<UChar> compositionBuffer(compositionLength / 2);
4908     compositionLength = IMMDict::dict().getCompositionString(hInputContext, type, (LPVOID)compositionBuffer.data(), compositionLength);
4909     result = String(compositionBuffer.data(), compositionLength / 2);
4910     ASSERT(!compositionLength || compositionBuffer[0]);
4911     ASSERT(!compositionLength || compositionBuffer[compositionLength / 2 - 1]);
4912     return true;
4913 }
4914 
compositionToUnderlines(const Vector<DWORD> & clauses,const Vector<BYTE> & attributes,Vector<CompositionUnderline> & underlines)4915 static void compositionToUnderlines(const Vector<DWORD>& clauses, const Vector<BYTE>& attributes, Vector<CompositionUnderline>& underlines)
4916 {
4917     if (clauses.isEmpty()) {
4918         underlines.clear();
4919         return;
4920     }
4921 
4922     const size_t numBoundaries = clauses.size() - 1;
4923     underlines.resize(numBoundaries);
4924     for (unsigned i = 0; i < numBoundaries; i++) {
4925         underlines[i].startOffset = clauses[i];
4926         underlines[i].endOffset = clauses[i + 1];
4927         BYTE attribute = attributes[clauses[i]];
4928         underlines[i].thick = attribute == ATTR_TARGET_CONVERTED || attribute == ATTR_TARGET_NOTCONVERTED;
4929         underlines[i].color = Color(0,0,0);
4930     }
4931 }
4932 
onIMEComposition(LPARAM lparam)4933 bool WebView::onIMEComposition(LPARAM lparam)
4934 {
4935     HIMC hInputContext = getIMMContext();
4936     if (!hInputContext)
4937         return true;
4938 
4939     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
4940     if (!targetFrame || !targetFrame->editor()->canEdit())
4941         return true;
4942 
4943     prepareCandidateWindow(targetFrame, hInputContext);
4944 
4945     if (lparam & GCS_RESULTSTR || !lparam) {
4946         String compositionString;
4947         if (!getCompositionString(hInputContext, GCS_RESULTSTR, compositionString) && lparam)
4948             return true;
4949 
4950         targetFrame->editor()->confirmComposition(compositionString);
4951     } else {
4952         String compositionString;
4953         if (!getCompositionString(hInputContext, GCS_COMPSTR, compositionString))
4954             return true;
4955 
4956         // Composition string attributes
4957         int numAttributes = IMMDict::dict().getCompositionString(hInputContext, GCS_COMPATTR, 0, 0);
4958         Vector<BYTE> attributes(numAttributes);
4959         IMMDict::dict().getCompositionString(hInputContext, GCS_COMPATTR, attributes.data(), numAttributes);
4960 
4961         // Get clauses
4962         int numClauses = IMMDict::dict().getCompositionString(hInputContext, GCS_COMPCLAUSE, 0, 0);
4963         Vector<DWORD> clauses(numClauses / sizeof(DWORD));
4964         IMMDict::dict().getCompositionString(hInputContext, GCS_COMPCLAUSE, clauses.data(), numClauses);
4965 
4966         Vector<CompositionUnderline> underlines;
4967         compositionToUnderlines(clauses, attributes, underlines);
4968 
4969         int cursorPosition = LOWORD(IMMDict::dict().getCompositionString(hInputContext, GCS_CURSORPOS, 0, 0));
4970 
4971         targetFrame->editor()->setComposition(compositionString, underlines, cursorPosition, 0);
4972     }
4973 
4974     return true;
4975 }
4976 
onIMEEndComposition()4977 bool WebView::onIMEEndComposition()
4978 {
4979     if (m_inIMEComposition)
4980         m_inIMEComposition--;
4981     return true;
4982 }
4983 
onIMEChar(WPARAM,LPARAM)4984 bool WebView::onIMEChar(WPARAM, LPARAM)
4985 {
4986     return true;
4987 }
4988 
onIMENotify(WPARAM,LPARAM,LRESULT *)4989 bool WebView::onIMENotify(WPARAM, LPARAM, LRESULT*)
4990 {
4991     return false;
4992 }
4993 
onIMERequestCharPosition(Frame * targetFrame,IMECHARPOSITION * charPos,LRESULT * result)4994 bool WebView::onIMERequestCharPosition(Frame* targetFrame, IMECHARPOSITION* charPos, LRESULT* result)
4995 {
4996     IntRect caret;
4997     ASSERT(charPos->dwCharPos == 0 || targetFrame->editor()->hasComposition());
4998     if (RefPtr<Range> range = targetFrame->editor()->hasComposition() ? targetFrame->editor()->compositionRange() : targetFrame->selection()->selection().toNormalizedRange()) {
4999         ExceptionCode ec = 0;
5000         RefPtr<Range> tempRange = range->cloneRange(ec);
5001         tempRange->setStart(tempRange->startContainer(ec), tempRange->startOffset(ec) + charPos->dwCharPos, ec);
5002         caret = targetFrame->firstRectForRange(tempRange.get());
5003     }
5004     caret = targetFrame->view()->contentsToWindow(caret);
5005     charPos->pt.x = caret.x();
5006     charPos->pt.y = caret.y();
5007     ::ClientToScreen(m_viewWindow, &charPos->pt);
5008     charPos->cLineHeight = caret.height();
5009     ::GetWindowRect(m_viewWindow, &charPos->rcDocument);
5010     *result = TRUE;
5011     return true;
5012 }
5013 
onIMERequestReconvertString(Frame * targetFrame,RECONVERTSTRING * reconvertString,LRESULT * result)5014 bool WebView::onIMERequestReconvertString(Frame* targetFrame, RECONVERTSTRING* reconvertString, LRESULT* result)
5015 {
5016     RefPtr<Range> selectedRange = targetFrame->selection()->toNormalizedRange();
5017     String text = selectedRange->text();
5018     if (!reconvertString) {
5019         *result = sizeof(RECONVERTSTRING) + text.length() * sizeof(UChar);
5020         return true;
5021     }
5022 
5023     unsigned totalSize = sizeof(RECONVERTSTRING) + text.length() * sizeof(UChar);
5024     *result = totalSize;
5025     if (totalSize > reconvertString->dwSize) {
5026         *result = 0;
5027         return false;
5028     }
5029     reconvertString->dwCompStrLen = text.length();
5030     reconvertString->dwStrLen = text.length();
5031     reconvertString->dwTargetStrLen = text.length();
5032     reconvertString->dwStrOffset = sizeof(RECONVERTSTRING);
5033     memcpy(reconvertString + 1, text.characters(), text.length() * sizeof(UChar));
5034     return true;
5035 }
5036 
onIMERequest(WPARAM request,LPARAM data,LRESULT * result)5037 bool WebView::onIMERequest(WPARAM request, LPARAM data, LRESULT* result)
5038 {
5039     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
5040     if (!targetFrame || !targetFrame->editor()->canEdit())
5041         return true;
5042 
5043     switch (request) {
5044         case IMR_RECONVERTSTRING:
5045             return onIMERequestReconvertString(targetFrame, (RECONVERTSTRING*)data, result);
5046 
5047         case IMR_QUERYCHARPOSITION:
5048             return onIMERequestCharPosition(targetFrame, (IMECHARPOSITION*)data, result);
5049     }
5050     return false;
5051 }
5052 
onIMESelect(WPARAM,LPARAM)5053 bool WebView::onIMESelect(WPARAM, LPARAM)
5054 {
5055     return false;
5056 }
5057 
onIMESetContext(WPARAM,LPARAM)5058 bool WebView::onIMESetContext(WPARAM, LPARAM)
5059 {
5060     return false;
5061 }
5062 
inspector(IWebInspector ** inspector)5063 HRESULT STDMETHODCALLTYPE WebView::inspector(IWebInspector** inspector)
5064 {
5065     if (!m_webInspector)
5066         m_webInspector.adoptRef(WebInspector::createInstance(this));
5067 
5068     return m_webInspector.copyRefTo(inspector);
5069 }
5070 
windowAncestryDidChange()5071 HRESULT STDMETHODCALLTYPE WebView::windowAncestryDidChange()
5072 {
5073     HWND newParent = findTopLevelParent(m_hostWindow);
5074     if (newParent == m_topLevelParent)
5075         return S_OK;
5076 
5077     if (m_topLevelParent)
5078         WindowMessageBroadcaster::removeListener(m_topLevelParent, this);
5079 
5080     m_topLevelParent = newParent;
5081 
5082     if (m_topLevelParent)
5083         WindowMessageBroadcaster::addListener(m_topLevelParent, this);
5084 
5085     updateActiveState();
5086 
5087     return S_OK;
5088 }
5089 
paintDocumentRectToContext(RECT rect,OLE_HANDLE deviceContext)5090 HRESULT STDMETHODCALLTYPE WebView::paintDocumentRectToContext(
5091     /* [in] */ RECT rect,
5092     /* [in] */ OLE_HANDLE deviceContext)
5093 {
5094     if (!deviceContext)
5095         return E_POINTER;
5096 
5097     if (!m_mainFrame)
5098         return E_FAIL;
5099 
5100     return m_mainFrame->paintDocumentRectToContext(rect, deviceContext);
5101 }
5102 
setCustomHTMLTokenizerTimeDelay(double timeDelay)5103 HRESULT STDMETHODCALLTYPE WebView::setCustomHTMLTokenizerTimeDelay(
5104     /* [in] */ double timeDelay)
5105 {
5106     if (!m_page)
5107         return E_FAIL;
5108 
5109     m_page->setCustomHTMLTokenizerTimeDelay(timeDelay);
5110     return S_OK;
5111 }
5112 
setCustomHTMLTokenizerChunkSize(int chunkSize)5113 HRESULT STDMETHODCALLTYPE WebView::setCustomHTMLTokenizerChunkSize(
5114     /* [in] */ int chunkSize)
5115 {
5116     if (!m_page)
5117         return E_FAIL;
5118 
5119     m_page->setCustomHTMLTokenizerChunkSize(chunkSize);
5120     return S_OK;
5121 }
5122 
backingStore(OLE_HANDLE * hBitmap)5123 HRESULT STDMETHODCALLTYPE WebView::backingStore(
5124     /* [out, retval] */ OLE_HANDLE* hBitmap)
5125 {
5126     if (!hBitmap)
5127         return E_POINTER;
5128     *hBitmap = reinterpret_cast<OLE_HANDLE>(m_backingStoreBitmap.get());
5129     return S_OK;
5130 }
5131 
setTransparent(BOOL transparent)5132 HRESULT STDMETHODCALLTYPE WebView::setTransparent(BOOL transparent)
5133 {
5134     if (m_transparent == !!transparent)
5135         return S_OK;
5136 
5137     m_transparent = transparent;
5138     m_mainFrame->updateBackground();
5139     return S_OK;
5140 }
5141 
transparent(BOOL * transparent)5142 HRESULT STDMETHODCALLTYPE WebView::transparent(BOOL* transparent)
5143 {
5144     if (!transparent)
5145         return E_POINTER;
5146 
5147     *transparent = this->transparent() ? TRUE : FALSE;
5148     return S_OK;
5149 }
5150 
setCookieEnabled(BOOL enable)5151 HRESULT STDMETHODCALLTYPE WebView::setCookieEnabled(BOOL enable)
5152 {
5153     if (!m_page)
5154         return E_FAIL;
5155 
5156     m_page->setCookieEnabled(enable);
5157     return S_OK;
5158 }
5159 
cookieEnabled(BOOL * enabled)5160 HRESULT STDMETHODCALLTYPE WebView::cookieEnabled(BOOL* enabled)
5161 {
5162     if (!enabled)
5163         return E_POINTER;
5164 
5165     if (!m_page)
5166         return E_FAIL;
5167 
5168     *enabled = m_page->cookieEnabled();
5169     return S_OK;
5170 }
5171 
setMediaVolume(float volume)5172 HRESULT STDMETHODCALLTYPE WebView::setMediaVolume(float volume)
5173 {
5174     if (!m_page)
5175         return E_FAIL;
5176 
5177     m_page->setMediaVolume(volume);
5178     return S_OK;
5179 }
5180 
mediaVolume(float * volume)5181 HRESULT STDMETHODCALLTYPE WebView::mediaVolume(float* volume)
5182 {
5183     if (!volume)
5184         return E_POINTER;
5185 
5186     if (!m_page)
5187         return E_FAIL;
5188 
5189     *volume = m_page->mediaVolume();
5190     return S_OK;
5191 }
5192 
setDefersCallbacks(BOOL defersCallbacks)5193 HRESULT STDMETHODCALLTYPE WebView::setDefersCallbacks(BOOL defersCallbacks)
5194 {
5195     if (!m_page)
5196         return E_FAIL;
5197 
5198     m_page->setDefersLoading(defersCallbacks);
5199     return S_OK;
5200 }
5201 
defersCallbacks(BOOL * defersCallbacks)5202 HRESULT STDMETHODCALLTYPE WebView::defersCallbacks(BOOL* defersCallbacks)
5203 {
5204     if (!defersCallbacks)
5205         return E_POINTER;
5206 
5207     if (!m_page)
5208         return E_FAIL;
5209 
5210     *defersCallbacks = m_page->defersLoading();
5211     return S_OK;
5212 }
5213 
globalHistoryItem(IWebHistoryItem ** item)5214 HRESULT STDMETHODCALLTYPE WebView::globalHistoryItem(IWebHistoryItem** item)
5215 {
5216     if (!item)
5217         return E_POINTER;
5218 
5219     if (!m_page)
5220         return E_FAIL;
5221 
5222     if (!m_page->globalHistoryItem()) {
5223         *item = 0;
5224         return S_OK;
5225     }
5226 
5227     *item = WebHistoryItem::createInstance(m_page->globalHistoryItem());
5228     return S_OK;
5229 }
5230 
setAlwaysUsesComplexTextCodePath(BOOL complex)5231 HRESULT STDMETHODCALLTYPE WebView::setAlwaysUsesComplexTextCodePath(BOOL complex)
5232 {
5233     WebCoreSetAlwaysUsesComplexTextCodePath(complex);
5234 
5235     return S_OK;
5236 }
5237 
alwaysUsesComplexTextCodePath(BOOL * complex)5238 HRESULT STDMETHODCALLTYPE WebView::alwaysUsesComplexTextCodePath(BOOL* complex)
5239 {
5240     if (!complex)
5241         return E_POINTER;
5242 
5243     *complex = WebCoreAlwaysUsesComplexTextCodePath();
5244     return S_OK;
5245 }
5246 
registerEmbeddedViewMIMEType(BSTR mimeType)5247 HRESULT STDMETHODCALLTYPE WebView::registerEmbeddedViewMIMEType(BSTR mimeType)
5248 {
5249     if (!mimeType)
5250         return E_POINTER;
5251 
5252     if (!m_embeddedViewMIMETypes)
5253         m_embeddedViewMIMETypes.set(new HashSet<String>);
5254 
5255     m_embeddedViewMIMETypes->add(String(mimeType, ::SysStringLen(mimeType)));
5256     return S_OK;
5257 }
5258 
shouldUseEmbeddedView(const WebCore::String & mimeType) const5259 bool WebView::shouldUseEmbeddedView(const WebCore::String& mimeType) const
5260 {
5261     if (!m_embeddedViewMIMETypes)
5262         return false;
5263 
5264     return m_embeddedViewMIMETypes->contains(mimeType);
5265 }
5266 
onGetObject(WPARAM wParam,LPARAM lParam,LRESULT & lResult) const5267 bool WebView::onGetObject(WPARAM wParam, LPARAM lParam, LRESULT& lResult) const
5268 {
5269     lResult = 0;
5270 
5271     if (lParam != OBJID_CLIENT)
5272         return false;
5273 
5274     AXObjectCache::enableAccessibility();
5275 
5276     // Get the accessible object for the top-level frame.
5277     WebFrame* mainFrameImpl = topLevelFrame();
5278     if (!mainFrameImpl)
5279         return false;
5280 
5281     COMPtr<IAccessible> accessible = mainFrameImpl->accessible();
5282     if (!accessible)
5283         return false;
5284 
5285     if (!accessibilityLib) {
5286         if (!(accessibilityLib = ::LoadLibrary(TEXT("oleacc.dll"))))
5287             return false;
5288     }
5289 
5290     static LPFNLRESULTFROMOBJECT procPtr = reinterpret_cast<LPFNLRESULTFROMOBJECT>(::GetProcAddress(accessibilityLib, "LresultFromObject"));
5291     if (!procPtr)
5292         return false;
5293 
5294     // LresultFromObject returns a reference to the accessible object, stored
5295     // in an LRESULT. If this call is not successful, Windows will handle the
5296     // request through DefWindowProc.
5297     return SUCCEEDED(lResult = procPtr(__uuidof(IAccessible), wParam, accessible.get()));
5298 }
5299 
AccessibleObjectFromWindow(HWND hwnd,DWORD objectID,REFIID riid,void ** ppObject)5300 STDMETHODIMP WebView::AccessibleObjectFromWindow(HWND hwnd, DWORD objectID, REFIID riid, void** ppObject)
5301 {
5302     ASSERT(accessibilityLib);
5303     static LPFNACCESSIBLEOBJECTFROMWINDOW procPtr = reinterpret_cast<LPFNACCESSIBLEOBJECTFROMWINDOW>(::GetProcAddress(accessibilityLib, "AccessibleObjectFromWindow"));
5304     if (!procPtr)
5305         return E_FAIL;
5306     return procPtr(hwnd, objectID, riid, ppObject);
5307 }
5308 
setMemoryCacheDelegateCallsEnabled(BOOL enabled)5309 HRESULT WebView::setMemoryCacheDelegateCallsEnabled(BOOL enabled)
5310 {
5311     m_page->setMemoryCacheClientCallsEnabled(enabled);
5312     return S_OK;
5313 }
5314 
setJavaScriptURLsAreAllowed(BOOL areAllowed)5315 HRESULT WebView::setJavaScriptURLsAreAllowed(BOOL areAllowed)
5316 {
5317     m_page->setJavaScriptURLsAreAllowed(areAllowed);
5318     return S_OK;
5319 }
5320 
setCanStartPlugins(BOOL canStartPlugins)5321 HRESULT WebView::setCanStartPlugins(BOOL canStartPlugins)
5322 {
5323     m_page->setCanStartPlugins(canStartPlugins);
5324     return S_OK;
5325 }
5326 
downloadURL(const KURL & url)5327 void WebView::downloadURL(const KURL& url)
5328 {
5329     // It's the delegate's job to ref the WebDownload to keep it alive - otherwise it will be
5330     // destroyed when this function returns.
5331     COMPtr<WebDownload> download(AdoptCOM, WebDownload::createInstance(url, m_downloadDelegate.get()));
5332     download->start();
5333 }
5334 
5335 class EnumTextMatches : public IEnumTextMatches
5336 {
5337     long m_ref;
5338     UINT m_index;
5339     Vector<IntRect> m_rects;
5340 public:
EnumTextMatches(Vector<IntRect> * rects)5341     EnumTextMatches(Vector<IntRect>* rects) : m_index(0), m_ref(1)
5342     {
5343         m_rects = *rects;
5344     }
5345 
QueryInterface(REFIID riid,void ** ppv)5346     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv)
5347     {
5348         if (IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IEnumTextMatches)) {
5349             *ppv = this;
5350             AddRef();
5351         }
5352 
5353         return *ppv?S_OK:E_NOINTERFACE;
5354     }
5355 
AddRef()5356     virtual ULONG STDMETHODCALLTYPE AddRef()
5357     {
5358         return m_ref++;
5359     }
5360 
Release()5361     virtual ULONG STDMETHODCALLTYPE Release()
5362     {
5363         if (m_ref == 1) {
5364             delete this;
5365             return 0;
5366         }
5367         else
5368             return m_ref--;
5369     }
5370 
Next(ULONG,RECT * rect,ULONG * pceltFetched)5371     virtual HRESULT STDMETHODCALLTYPE Next(ULONG, RECT* rect, ULONG* pceltFetched)
5372     {
5373         if (m_index < m_rects.size()) {
5374             if (pceltFetched)
5375                 *pceltFetched = 1;
5376             *rect = m_rects[m_index];
5377             m_index++;
5378             return S_OK;
5379         }
5380 
5381         if (pceltFetched)
5382             *pceltFetched = 0;
5383 
5384         return S_FALSE;
5385     }
Skip(ULONG celt)5386     virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
5387     {
5388         m_index += celt;
5389         return S_OK;
5390     }
Reset(void)5391     virtual HRESULT STDMETHODCALLTYPE Reset(void)
5392     {
5393         m_index = 0;
5394         return S_OK;
5395     }
Clone(IEnumTextMatches **)5396     virtual HRESULT STDMETHODCALLTYPE Clone(IEnumTextMatches**)
5397     {
5398         return E_NOTIMPL;
5399     }
5400 };
5401 
createMatchEnumerator(Vector<IntRect> * rects,IEnumTextMatches ** matches)5402 HRESULT createMatchEnumerator(Vector<IntRect>* rects, IEnumTextMatches** matches)
5403 {
5404     *matches = new EnumTextMatches(rects);
5405     return (*matches)?S_OK:E_OUTOFMEMORY;
5406 }
5407 
core(IWebView * iWebView)5408 Page* core(IWebView* iWebView)
5409 {
5410     Page* page = 0;
5411 
5412     COMPtr<WebView> webView;
5413     if (SUCCEEDED(iWebView->QueryInterface(&webView)) && webView)
5414         page = webView->page();
5415 
5416     return page;
5417 }
5418 
5419