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