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