2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple, Inc. All rights reserved.
3 * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
4 * Copyright (C) 2011 Brent Fulgham. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "CFDictionaryPropertyBag.h"
32 #include "DOMCoreClasses.h"
33 #include "FullscreenVideoController.h"
34 #include "MarshallingHelpers.h"
35 #include "SoftLinking.h"
36 #include "TextIterator.h"
37 #include "WebBackForwardList.h"
38 #include "WebChromeClient.h"
39 #include "WebContextMenuClient.h"
40 #include "WebCoreTextRenderer.h"
41 #include "WebDatabaseManager.h"
42 #include "WebDocumentLoader.h"
43 #include "WebDownload.h"
44 #include "WebDragClient.h"
45 #include "WebEditorClient.h"
46 #include "WebElementPropertyBag.h"
48 #include "WebGeolocationClient.h"
49 #include "WebGeolocationPosition.h"
50 #include "WebIconDatabase.h"
51 #include "WebInspector.h"
52 #include "WebInspectorClient.h"
54 #include "WebKitDLL.h"
55 #include "WebKitLogging.h"
56 #include "WebKitStatisticsPrivate.h"
57 #include "WebKitSystemBits.h"
58 #include "WebMutableURLRequest.h"
59 #include "WebNotificationCenter.h"
60 #include "WebPlatformStrategies.h"
61 #include "WebPreferences.h"
62 #include "WebScriptWorld.h"
64 #include <JavaScriptCore/APICast.h>
65 #include <JavaScriptCore/InitializeThreading.h>
66 #include <JavaScriptCore/JSLock.h>
67 #include <JavaScriptCore/JSValue.h>
68 #include <WebCore/AXObjectCache.h>
69 #include <WebCore/AbstractDatabase.h>
70 #include <WebCore/ApplicationCacheStorage.h>
71 #include <WebCore/BString.h>
72 #include <WebCore/BackForwardListImpl.h>
73 #include <WebCore/BitmapInfo.h>
74 #include <WebCore/Chrome.h>
75 #include <WebCore/ContextMenu.h>
76 #include <WebCore/ContextMenuController.h>
77 #include <WebCore/Cursor.h>
78 #include <WebCore/Document.h>
79 #include <WebCore/DocumentMarkerController.h>
80 #include <WebCore/DragController.h>
81 #include <WebCore/DragData.h>
82 #include <WebCore/DragSession.h>
83 #include <WebCore/Editor.h>
84 #include <WebCore/EventHandler.h>
85 #include <WebCore/EventNames.h>
86 #include <WebCore/FileSystem.h>
87 #include <WebCore/FloatQuad.h>
88 #include <WebCore/FocusController.h>
89 #include <WebCore/Frame.h>
90 #include <WebCore/FrameLoader.h>
91 #include <WebCore/FrameSelection.h>
92 #include <WebCore/FrameTree.h>
93 #include <WebCore/FrameView.h>
94 #include <WebCore/FrameWin.h>
95 #include <WebCore/GDIObjectCounter.h>
96 #include <WebCore/GeolocationController.h>
97 #include <WebCore/GeolocationError.h>
98 #include <WebCore/GraphicsContext.h>
99 #include <WebCore/HTMLMediaElement.h>
100 #include <WebCore/HTMLNames.h>
101 #include <WebCore/HWndDC.h>
102 #include <WebCore/HistoryItem.h>
103 #include <WebCore/HitTestRequest.h>
104 #include <WebCore/HitTestResult.h>
105 #include <WebCore/IntRect.h>
106 #include <WebCore/JSElement.h>
107 #include <WebCore/KeyboardEvent.h>
108 #include <WebCore/Logging.h>
109 #include <WebCore/MIMETypeRegistry.h>
110 #include <WebCore/MemoryCache.h>
111 #include <WebCore/Page.h>
112 #include <WebCore/PageCache.h>
113 #include <WebCore/PageGroup.h>
114 #include <WebCore/PlatformKeyboardEvent.h>
115 #include <WebCore/PlatformMouseEvent.h>
116 #include <WebCore/PlatformWheelEvent.h>
117 #include <WebCore/PluginData.h>
118 #include <WebCore/PluginDatabase.h>
119 #include <WebCore/PluginView.h>
120 #include <WebCore/PopupMenu.h>
121 #include <WebCore/PopupMenuWin.h>
122 #include <WebCore/ProgressTracker.h>
123 #include <WebCore/RenderLayer.h>
124 #include <WebCore/RenderTheme.h>
125 #include <WebCore/RenderTreeAsText.h>
126 #include <WebCore/RenderView.h>
127 #include <WebCore/RenderWidget.h>
128 #include <WebCore/ResourceHandle.h>
129 #include <WebCore/ResourceHandleClient.h>
130 #include <WebCore/ResourceRequest.h>
131 #include <WebCore/SchemeRegistry.h>
132 #include <WebCore/ScriptValue.h>
133 #include <WebCore/Scrollbar.h>
134 #include <WebCore/ScrollbarTheme.h>
135 #include <WebCore/SecurityOrigin.h>
136 #include <WebCore/SecurityPolicy.h>
137 #include <WebCore/Settings.h>
138 #include <WebCore/SimpleFontData.h>
139 #include <WebCore/SystemInfo.h>
140 #include <WebCore/WindowMessageBroadcaster.h>
141 #include <WebCore/WindowsTouch.h>
142 #include <wtf/MainThread.h>
145 #include <CoreGraphics/CGContext.h>
149 #include <CoreFoundation/CoreFoundation.h>
153 #include <CFNetwork/CFURLCachePriv.h>
154 #include <CFNetwork/CFURLProtocolPriv.h>
155 #include <WebCore/CookieStorageCFNet.h>
156 #include <WebKitSystemInterface/WebKitSystemInterface.h>
159 #if USE(ACCELERATED_COMPOSITING)
160 #include <WebCore/CACFLayerTreeHost.h>
161 #include <WebCore/PlatformCALayer.h>
164 #if ENABLE(FULLSCREEN_API)
165 #include <WebCore/FullScreenController.h>
173 #include <windowsx.h>
174 #include <wtf/HashSet.h>
175 #include <wtf/text/CString.h>
176 #include <wtf/text/StringConcatenate.h>
178 // Soft link functions for gestures and panning feedback
179 SOFT_LINK_LIBRARY(USER32);
180 SOFT_LINK_OPTIONAL(USER32, GetGestureInfo, BOOL, WINAPI, (HGESTUREINFO, PGESTUREINFO));
181 SOFT_LINK_OPTIONAL(USER32, SetGestureConfig, BOOL, WINAPI, (HWND, DWORD, UINT, PGESTURECONFIG, UINT));
182 SOFT_LINK_OPTIONAL(USER32, CloseGestureInfoHandle, BOOL, WINAPI, (HGESTUREINFO));
183 SOFT_LINK_LIBRARY(Uxtheme);
184 SOFT_LINK_OPTIONAL(Uxtheme, BeginPanningFeedback, BOOL, WINAPI, (HWND));
185 SOFT_LINK_OPTIONAL(Uxtheme, EndPanningFeedback, BOOL, WINAPI, (HWND, BOOL));
186 SOFT_LINK_OPTIONAL(Uxtheme, UpdatePanningFeedback, BOOL, WINAPI, (HWND, LONG, LONG, BOOL));
188 using namespace WebCore;
192 static HMODULE accessibilityLib;
193 static HashSet<WebView*> pendingDeleteBackingStoreSet;
195 static String webKitVersionString();
197 WebView* kit(Page* page)
199 return page ? static_cast<WebView*>(static_cast<WebChromeClient*>(page->chrome()->client())->webView()) : 0;
202 class PreferencesChangedOrRemovedObserver : public IWebNotificationObserver {
204 static PreferencesChangedOrRemovedObserver* sharedInstance();
207 PreferencesChangedOrRemovedObserver() {}
208 ~PreferencesChangedOrRemovedObserver() {}
210 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**) { return E_FAIL; }
211 virtual ULONG STDMETHODCALLTYPE AddRef(void) { return 0; }
212 virtual ULONG STDMETHODCALLTYPE Release(void) { return 0; }
215 // IWebNotificationObserver
216 virtual HRESULT STDMETHODCALLTYPE onNotify(
217 /* [in] */ IWebNotification* notification);
220 HRESULT notifyPreferencesChanged(WebCacheModel);
221 HRESULT notifyPreferencesRemoved(WebCacheModel);
224 PreferencesChangedOrRemovedObserver* PreferencesChangedOrRemovedObserver::sharedInstance()
226 static PreferencesChangedOrRemovedObserver* shared = new PreferencesChangedOrRemovedObserver;
230 HRESULT PreferencesChangedOrRemovedObserver::onNotify(IWebNotification* notification)
234 COMPtr<IUnknown> unkPrefs;
235 hr = notification->getObject(&unkPrefs);
239 COMPtr<IWebPreferences> preferences(Query, unkPrefs);
241 return E_NOINTERFACE;
243 WebCacheModel cacheModel;
244 hr = preferences->cacheModel(&cacheModel);
249 hr = notification->name(&nameBSTR);
253 name.adoptBSTR(nameBSTR);
255 if (wcscmp(name, WebPreferences::webPreferencesChangedNotification()) == 0)
256 return notifyPreferencesChanged(cacheModel);
258 if (wcscmp(name, WebPreferences::webPreferencesRemovedNotification()) == 0)
259 return notifyPreferencesRemoved(cacheModel);
261 ASSERT_NOT_REACHED();
265 HRESULT PreferencesChangedOrRemovedObserver::notifyPreferencesChanged(WebCacheModel cacheModel)
269 if (!WebView::didSetCacheModel() || cacheModel > WebView::cacheModel())
270 WebView::setCacheModel(cacheModel);
271 else if (cacheModel < WebView::cacheModel()) {
272 WebCacheModel sharedPreferencesCacheModel;
273 hr = WebPreferences::sharedStandardPreferences()->cacheModel(&sharedPreferencesCacheModel);
276 WebView::setCacheModel(max(sharedPreferencesCacheModel, WebView::maxCacheModelInAnyInstance()));
282 HRESULT PreferencesChangedOrRemovedObserver::notifyPreferencesRemoved(WebCacheModel cacheModel)
286 if (cacheModel == WebView::cacheModel()) {
287 WebCacheModel sharedPreferencesCacheModel;
288 hr = WebPreferences::sharedStandardPreferences()->cacheModel(&sharedPreferencesCacheModel);
291 WebView::setCacheModel(max(sharedPreferencesCacheModel, WebView::maxCacheModelInAnyInstance()));
298 const LPCWSTR kWebViewWindowClassName = L"WebViewWindowClass";
300 const int WM_XP_THEMECHANGED = 0x031A;
301 const int WM_VISTA_MOUSEHWHEEL = 0x020E;
303 static const int maxToolTipWidth = 250;
305 static const int delayBeforeDeletingBackingStoreMsec = 5000;
307 static ATOM registerWebView();
309 static void initializeStaticObservers();
311 static HRESULT updateSharedSettingsFromPreferencesIfNeeded(IWebPreferences*);
313 HRESULT createMatchEnumerator(Vector<IntRect>* rects, IEnumTextMatches** matches);
315 static bool continuousSpellCheckingEnabled;
316 static bool grammarCheckingEnabled;
318 static bool s_didSetCacheModel;
319 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
322 UpdateActiveStateTimer = 1,
323 DeleteBackingStoreTimer = 2,
326 // WebView ----------------------------------------------------------------
328 bool WebView::s_allowSiteSpecificHacks = false;
332 , m_shouldInvertColors(false)
334 , m_deletionHasBegun(false)
340 #if ENABLE(INSPECTOR)
341 , m_inspectorClient(0)
342 #endif // ENABLE(INSPECTOR)
343 , m_hasCustomDropTarget(false)
344 , m_useBackForwardList(true)
345 , m_userAgentOverridden(false)
346 , m_zoomMultiplier(1.0f)
347 , m_zoomsTextOnly(false)
348 , m_mouseActivated(false)
350 , m_currentCharacterCode(0)
351 , m_isBeingDestroyed(false)
353 , m_hasSpellCheckerDocumentTag(false)
354 , m_smartInsertDeleteEnabled(false)
356 , m_inIMEComposition(0)
358 , m_closeWindowTimer(0)
359 , m_topLevelParent(0)
360 , m_deleteBackingStoreTimerActive(false)
361 , m_transparent(false)
362 , m_selectTrailingWhitespaceEnabled(false)
367 #if USE(ACCELERATED_COMPOSITING)
368 , m_isAcceleratedCompositing(false)
370 , m_nextDisplayIsSynchronous(false)
372 , m_usesLayeredWindow(false)
374 JSC::initializeThreading();
375 WTF::initializeMainThread();
377 m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
379 CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, IID_IDropTargetHelper,(void**)&m_dropTargetHelper);
381 initializeStaticObservers();
383 WebPreferences* sharedPreferences = WebPreferences::sharedStandardPreferences();
385 if (SUCCEEDED(sharedPreferences->continuousSpellCheckingEnabled(&enabled)))
386 continuousSpellCheckingEnabled = !!enabled;
387 if (SUCCEEDED(sharedPreferences->grammarCheckingEnabled(&enabled)))
388 grammarCheckingEnabled = !!enabled;
392 gClassNameCount.add("WebView");
397 deleteBackingStore();
399 // the tooltip window needs to be explicitly destroyed since it isn't a WS_CHILD
400 if (::IsWindow(m_toolTipHwnd))
401 ::DestroyWindow(m_toolTipHwnd);
404 ASSERT(!m_preferences);
405 ASSERT(!m_viewWindow);
407 #if USE(ACCELERATED_COMPOSITING)
408 ASSERT(!m_layerTreeHost);
409 ASSERT(!m_backingLayer);
414 gClassNameCount.remove("WebView");
417 WebView* WebView::createInstance()
419 WebView* instance = new WebView();
424 void initializeStaticObservers()
426 static bool initialized;
431 IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
432 notifyCenter->addObserver(PreferencesChangedOrRemovedObserver::sharedInstance(), WebPreferences::webPreferencesChangedNotification(), 0);
433 notifyCenter->addObserver(PreferencesChangedOrRemovedObserver::sharedInstance(), WebPreferences::webPreferencesRemovedNotification(), 0);
436 static HashSet<WebView*>& allWebViewsSet()
438 static HashSet<WebView*> allWebViewsSet;
439 return allWebViewsSet;
442 void WebView::addToAllWebViewsSet()
444 allWebViewsSet().add(this);
447 void WebView::removeFromAllWebViewsSet()
449 allWebViewsSet().remove(this);
452 void WebView::setCacheModel(WebCacheModel cacheModel)
455 if (s_didSetCacheModel && cacheModel == s_cacheModel)
458 RetainPtr<CFURLCacheRef> cfurlCache(AdoptCF, CFURLCacheCopySharedURLCache());
459 RetainPtr<CFStringRef> cfurlCacheDirectory(AdoptCF, wkCopyFoundationCacheDirectory(0));
460 if (!cfurlCacheDirectory)
461 cfurlCacheDirectory.adoptCF(WebCore::localUserSpecificStorageDirectory().createCFString());
463 // As a fudge factor, use 1000 instead of 1024, in case the reported byte
464 // count doesn't align exactly to a megabyte boundary.
465 unsigned long long memSize = WebMemorySize() / 1024 / 1000;
466 unsigned long long diskFreeSize = WebVolumeFreeSize(cfurlCacheDirectory.get()) / 1024 / 1000;
468 unsigned cacheTotalCapacity = 0;
469 unsigned cacheMinDeadCapacity = 0;
470 unsigned cacheMaxDeadCapacity = 0;
471 double deadDecodedDataDeletionInterval = 0;
473 unsigned pageCacheCapacity = 0;
475 CFIndex cfurlCacheMemoryCapacity = 0;
476 CFIndex cfurlCacheDiskCapacity = 0;
478 switch (cacheModel) {
479 case WebCacheModelDocumentViewer: {
480 // Page cache capacity (in pages)
481 pageCacheCapacity = 0;
483 // Object cache capacities (in bytes)
485 cacheTotalCapacity = 96 * 1024 * 1024;
486 else if (memSize >= 1536)
487 cacheTotalCapacity = 64 * 1024 * 1024;
488 else if (memSize >= 1024)
489 cacheTotalCapacity = 32 * 1024 * 1024;
490 else if (memSize >= 512)
491 cacheTotalCapacity = 16 * 1024 * 1024;
493 cacheMinDeadCapacity = 0;
494 cacheMaxDeadCapacity = 0;
496 // Foundation memory cache capacity (in bytes)
497 cfurlCacheMemoryCapacity = 0;
499 // Foundation disk cache capacity (in bytes)
500 cfurlCacheDiskCapacity = CFURLCacheDiskCapacity(cfurlCache.get());
504 case WebCacheModelDocumentBrowser: {
505 // Page cache capacity (in pages)
507 pageCacheCapacity = 3;
508 else if (memSize >= 512)
509 pageCacheCapacity = 2;
510 else if (memSize >= 256)
511 pageCacheCapacity = 1;
513 pageCacheCapacity = 0;
515 // Object cache capacities (in bytes)
517 cacheTotalCapacity = 96 * 1024 * 1024;
518 else if (memSize >= 1536)
519 cacheTotalCapacity = 64 * 1024 * 1024;
520 else if (memSize >= 1024)
521 cacheTotalCapacity = 32 * 1024 * 1024;
522 else if (memSize >= 512)
523 cacheTotalCapacity = 16 * 1024 * 1024;
525 cacheMinDeadCapacity = cacheTotalCapacity / 8;
526 cacheMaxDeadCapacity = cacheTotalCapacity / 4;
528 // Foundation memory cache capacity (in bytes)
530 cfurlCacheMemoryCapacity = 4 * 1024 * 1024;
531 else if (memSize >= 1024)
532 cfurlCacheMemoryCapacity = 2 * 1024 * 1024;
533 else if (memSize >= 512)
534 cfurlCacheMemoryCapacity = 1 * 1024 * 1024;
536 cfurlCacheMemoryCapacity = 512 * 1024;
538 // Foundation disk cache capacity (in bytes)
539 if (diskFreeSize >= 16384)
540 cfurlCacheDiskCapacity = 50 * 1024 * 1024;
541 else if (diskFreeSize >= 8192)
542 cfurlCacheDiskCapacity = 40 * 1024 * 1024;
543 else if (diskFreeSize >= 4096)
544 cfurlCacheDiskCapacity = 30 * 1024 * 1024;
546 cfurlCacheDiskCapacity = 20 * 1024 * 1024;
550 case WebCacheModelPrimaryWebBrowser: {
551 // Page cache capacity (in pages)
552 // (Research indicates that value / page drops substantially after 3 pages.)
554 pageCacheCapacity = 5;
555 else if (memSize >= 1024)
556 pageCacheCapacity = 4;
557 else if (memSize >= 512)
558 pageCacheCapacity = 3;
559 else if (memSize >= 256)
560 pageCacheCapacity = 2;
562 pageCacheCapacity = 1;
564 // Object cache capacities (in bytes)
565 // (Testing indicates that value / MB depends heavily on content and
566 // browsing pattern. Even growth above 128MB can have substantial
567 // value / MB for some content / browsing patterns.)
569 cacheTotalCapacity = 128 * 1024 * 1024;
570 else if (memSize >= 1536)
571 cacheTotalCapacity = 96 * 1024 * 1024;
572 else if (memSize >= 1024)
573 cacheTotalCapacity = 64 * 1024 * 1024;
574 else if (memSize >= 512)
575 cacheTotalCapacity = 32 * 1024 * 1024;
577 cacheMinDeadCapacity = cacheTotalCapacity / 4;
578 cacheMaxDeadCapacity = cacheTotalCapacity / 2;
580 // This code is here to avoid a PLT regression. We can remove it if we
581 // can prove that the overall system gain would justify the regression.
582 cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity);
584 deadDecodedDataDeletionInterval = 60;
586 // Foundation memory cache capacity (in bytes)
587 // (These values are small because WebCore does most caching itself.)
589 cfurlCacheMemoryCapacity = 4 * 1024 * 1024;
590 else if (memSize >= 512)
591 cfurlCacheMemoryCapacity = 2 * 1024 * 1024;
592 else if (memSize >= 256)
593 cfurlCacheMemoryCapacity = 1 * 1024 * 1024;
595 cfurlCacheMemoryCapacity = 512 * 1024;
597 // Foundation disk cache capacity (in bytes)
598 if (diskFreeSize >= 16384)
599 cfurlCacheDiskCapacity = 175 * 1024 * 1024;
600 else if (diskFreeSize >= 8192)
601 cfurlCacheDiskCapacity = 150 * 1024 * 1024;
602 else if (diskFreeSize >= 4096)
603 cfurlCacheDiskCapacity = 125 * 1024 * 1024;
604 else if (diskFreeSize >= 2048)
605 cfurlCacheDiskCapacity = 100 * 1024 * 1024;
606 else if (diskFreeSize >= 1024)
607 cfurlCacheDiskCapacity = 75 * 1024 * 1024;
609 cfurlCacheDiskCapacity = 50 * 1024 * 1024;
614 ASSERT_NOT_REACHED();
617 // Don't shrink a big disk cache, since that would cause churn.
618 cfurlCacheDiskCapacity = max(cfurlCacheDiskCapacity, CFURLCacheDiskCapacity(cfurlCache.get()));
620 memoryCache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
621 memoryCache()->setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
622 pageCache()->setCapacity(pageCacheCapacity);
624 CFURLCacheSetMemoryCapacity(cfurlCache.get(), cfurlCacheMemoryCapacity);
625 CFURLCacheSetDiskCapacity(cfurlCache.get(), cfurlCacheDiskCapacity);
627 s_didSetCacheModel = true;
628 s_cacheModel = cacheModel;
633 WebCacheModel WebView::cacheModel()
638 bool WebView::didSetCacheModel()
640 return s_didSetCacheModel;
643 WebCacheModel WebView::maxCacheModelInAnyInstance()
645 WebCacheModel cacheModel = WebCacheModelDocumentViewer;
647 HashSet<WebView*>::iterator end = allWebViewsSet().end();
648 for (HashSet<WebView*>::iterator it = allWebViewsSet().begin(); it != end; ++it) {
649 COMPtr<IWebPreferences> pref;
650 if (FAILED((*it)->preferences(&pref)))
652 WebCacheModel prefCacheModel = WebCacheModelDocumentViewer;
653 if (FAILED(pref->cacheModel(&prefCacheModel)))
656 cacheModel = max(cacheModel, prefCacheModel);
662 HRESULT STDMETHODCALLTYPE WebView::close()
669 #if USE(ACCELERATED_COMPOSITING)
670 setAcceleratedCompositing(false);
673 WebNotificationCenter::defaultCenterInternal()->postNotificationName(_bstr_t(WebViewWillCloseNotification).GetBSTR(), static_cast<IWebView*>(this), 0);
675 if (m_uiDelegatePrivate)
676 m_uiDelegatePrivate->webViewClosing(this);
678 removeFromAllWebViewsSet();
681 if (Frame* frame = m_page->mainFrame())
682 frame->loader()->detachFromParent();
685 if (m_mouseOutTracker) {
686 m_mouseOutTracker->dwFlags = TME_CANCEL;
687 ::TrackMouseEvent(m_mouseOutTracker.get());
688 m_mouseOutTracker.clear();
694 // We can't check IsWindow(m_viewWindow) here, because that will return true even while
695 // we're already handling WM_DESTROY. So we check !isBeingDestroyed() instead.
696 if (!isBeingDestroyed())
697 DestroyWindow(m_viewWindow);
698 // Either we just destroyed m_viewWindow, or it's in the process of being destroyed. Either
699 // way, we clear it out to make sure we don't try to use it later.
705 setDownloadDelegate(0);
706 setEditingDelegate(0);
707 setFrameLoadDelegate(0);
708 setFrameLoadDelegatePrivate(0);
709 setHistoryDelegate(0);
710 setPolicyDelegate(0);
711 setResourceLoadDelegate(0);
715 #if ENABLE(INSPECTOR)
716 m_inspectorClient = 0;
718 m_webInspector->webViewClosed();
719 #endif // ENABLE(INSPECTOR)
724 registerForIconNotification(false);
725 IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
726 notifyCenter->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
728 if (COMPtr<WebPreferences> preferences = m_preferences) {
730 preferences->identifier(&identifier);
733 preferences->didRemoveFromWebView();
734 // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
737 WebPreferences::removeReferenceForIdentifier(identifier);
738 SysFreeString(identifier);
742 deleteBackingStore();
746 void WebView::repaint(const WebCore::IntRect& windowRect, bool contentChanged, bool immediate, bool repaintContentOnly)
748 #if USE(ACCELERATED_COMPOSITING)
749 if (isAcceleratedCompositing()) {
750 // The contentChanged, immediate, and repaintContentOnly parameters are all based on a non-
751 // compositing painting/scrolling model.
752 addToDirtyRegion(windowRect);
757 if (!repaintContentOnly) {
758 RECT rect = windowRect;
759 ::InvalidateRect(m_viewWindow, &rect, false);
762 addToDirtyRegion(windowRect);
764 if (repaintContentOnly)
765 updateBackingStore(core(topLevelFrame())->view());
767 ::UpdateWindow(m_viewWindow);
771 void WebView::deleteBackingStore()
773 pendingDeleteBackingStoreSet.remove(this);
775 if (m_deleteBackingStoreTimerActive) {
776 KillTimer(m_viewWindow, DeleteBackingStoreTimer);
777 m_deleteBackingStoreTimerActive = false;
779 m_backingStoreBitmap.clear();
780 m_backingStoreDirtyRegion.clear();
781 m_backingStoreSize.cx = m_backingStoreSize.cy = 0;
784 bool WebView::ensureBackingStore()
787 ::GetClientRect(m_viewWindow, &windowRect);
788 LONG width = windowRect.right - windowRect.left;
789 LONG height = windowRect.bottom - windowRect.top;
790 if (width > 0 && height > 0 && (width != m_backingStoreSize.cx || height != m_backingStoreSize.cy)) {
791 deleteBackingStore();
793 m_backingStoreSize.cx = width;
794 m_backingStoreSize.cy = height;
795 BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(IntSize(m_backingStoreSize));
798 m_backingStoreBitmap = RefCountedHBITMAP::create(::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0));
805 void WebView::addToDirtyRegion(const IntRect& dirtyRect)
807 // FIXME: We want an assert here saying that the dirtyRect is inside the clienRect,
808 // but it was being hit during our layout tests, and is being investigated in
809 // http://webkit.org/b/29350.
811 #if USE(ACCELERATED_COMPOSITING)
812 if (isAcceleratedCompositing()) {
813 m_backingLayer->setNeedsDisplayInRect(dirtyRect);
818 HRGN newRegion = ::CreateRectRgn(dirtyRect.x(), dirtyRect.y(),
819 dirtyRect.maxX(), dirtyRect.maxY());
820 addToDirtyRegion(newRegion);
823 void WebView::addToDirtyRegion(HRGN newRegion)
825 #if USE(ACCELERATED_COMPOSITING)
826 ASSERT(!isAcceleratedCompositing());
829 LOCAL_GDI_COUNTER(0, __FUNCTION__);
831 if (m_backingStoreDirtyRegion) {
832 HRGN combinedRegion = ::CreateRectRgn(0,0,0,0);
833 ::CombineRgn(combinedRegion, m_backingStoreDirtyRegion->handle(), newRegion, RGN_OR);
834 ::DeleteObject(newRegion);
835 m_backingStoreDirtyRegion = RefCountedHRGN::create(combinedRegion);
837 m_backingStoreDirtyRegion = RefCountedHRGN::create(newRegion);
839 if (m_uiDelegatePrivate)
840 m_uiDelegatePrivate->webViewDidInvalidate(this);
843 void WebView::scrollBackingStore(FrameView* frameView, int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect)
845 #if USE(ACCELERATED_COMPOSITING)
846 if (isAcceleratedCompositing()) {
847 // FIXME: We should be doing something smarter here, like moving tiles around and painting
848 // any newly-exposed tiles. <http://webkit.org/b/52714>
849 m_backingLayer->setNeedsDisplayInRect(scrollViewRect);
854 LOCAL_GDI_COUNTER(0, __FUNCTION__);
856 // If there's no backing store we don't need to update it
857 if (!m_backingStoreBitmap) {
858 if (m_uiDelegatePrivate)
859 m_uiDelegatePrivate->webViewScrolled(this);
864 // Make a region to hold the invalidated scroll area.
865 HRGN updateRegion = ::CreateRectRgn(0, 0, 0, 0);
867 // Collect our device context info and select the bitmap to scroll.
868 HWndDC windowDC(m_viewWindow);
869 HDC bitmapDC = ::CreateCompatibleDC(windowDC);
870 HGDIOBJ oldBitmap = ::SelectObject(bitmapDC, m_backingStoreBitmap->handle());
872 // Scroll the bitmap.
873 RECT scrollRectWin(scrollViewRect);
874 RECT clipRectWin(clipRect);
875 ::ScrollDC(bitmapDC, dx, dy, &scrollRectWin, &clipRectWin, updateRegion, 0);
877 ::GetRgnBox(updateRegion, ®ionBox);
882 // Add the dirty region to the backing store's dirty region.
883 addToDirtyRegion(updateRegion);
885 if (m_uiDelegatePrivate)
886 m_uiDelegatePrivate->webViewScrolled(this);
888 // Update the backing store.
889 updateBackingStore(frameView, bitmapDC, false);
892 ::SelectObject(bitmapDC, oldBitmap);
893 ::DeleteDC(bitmapDC);
896 void WebView::sizeChanged(const IntSize& newSize)
898 deleteBackingStore();
900 if (Frame* coreFrame = core(topLevelFrame()))
901 coreFrame->view()->resize(newSize);
903 #if USE(ACCELERATED_COMPOSITING)
905 m_layerTreeHost->resize();
906 if (m_backingLayer) {
907 m_backingLayer->setSize(newSize);
908 m_backingLayer->setNeedsDisplay();
913 // This emulates the Mac smarts for painting rects intelligently. This is very
914 // important for us, since we double buffer based off dirty rects.
915 static void getUpdateRects(HRGN region, const IntRect& dirtyRect, Vector<IntRect>& rects)
917 ASSERT_ARG(region, region);
919 const int cRectThreshold = 10;
920 const float cWastedSpaceThreshold = 0.75f;
924 DWORD regionDataSize = GetRegionData(region, sizeof(RGNDATA), NULL);
925 if (!regionDataSize) {
926 rects.append(dirtyRect);
930 Vector<unsigned char> buffer(regionDataSize);
931 RGNDATA* regionData = reinterpret_cast<RGNDATA*>(buffer.data());
932 GetRegionData(region, regionDataSize, regionData);
933 if (regionData->rdh.nCount > cRectThreshold) {
934 rects.append(dirtyRect);
938 double singlePixels = 0.0;
941 for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++)
942 singlePixels += (rect->right - rect->left) * (rect->bottom - rect->top);
944 double unionPixels = dirtyRect.width() * dirtyRect.height();
945 double wastedSpace = 1.0 - (singlePixels / unionPixels);
946 if (wastedSpace <= cWastedSpaceThreshold) {
947 rects.append(dirtyRect);
951 for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++)
955 void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStoreCompletelyDirty, WindowsToPaint windowsToPaint)
957 #if USE(ACCELERATED_COMPOSITING)
958 ASSERT(!isAcceleratedCompositing());
961 LOCAL_GDI_COUNTER(0, __FUNCTION__);
964 HGDIOBJ oldBitmap = 0;
966 HWndDC windowDC(m_viewWindow);
967 bitmapDC = ::CreateCompatibleDC(windowDC);
968 oldBitmap = ::SelectObject(bitmapDC, m_backingStoreBitmap->handle());
971 if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) {
972 // Do a layout first so that everything we render to the backing store is always current.
973 if (Frame* coreFrame = core(m_mainFrame))
974 if (FrameView* view = coreFrame->view())
975 view->updateLayoutAndStyleIfNeededRecursive();
977 Vector<IntRect> paintRects;
978 if (!backingStoreCompletelyDirty && m_backingStoreDirtyRegion) {
980 ::GetRgnBox(m_backingStoreDirtyRegion->handle(), ®ionBox);
981 getUpdateRects(m_backingStoreDirtyRegion->handle(), regionBox, paintRects);
984 ::GetClientRect(m_viewWindow, &clientRect);
985 paintRects.append(clientRect);
988 for (unsigned i = 0; i < paintRects.size(); ++i)
989 paintIntoBackingStore(frameView, bitmapDC, paintRects[i], windowsToPaint);
991 if (m_uiDelegatePrivate)
992 m_uiDelegatePrivate->webViewPainted(this);
994 m_backingStoreDirtyRegion.clear();
998 ::SelectObject(bitmapDC, oldBitmap);
999 ::DeleteDC(bitmapDC);
1005 void WebView::performLayeredWindowUpdate()
1007 // The backing store may have been destroyed if the window rect was set to zero height or zero width.
1008 if (!m_backingStoreBitmap)
1011 HWndDC hdcScreen(m_viewWindow);
1012 OwnPtr<HDC> hdcMem = adoptPtr(::CreateCompatibleDC(hdcScreen));
1013 HBITMAP hbmOld = static_cast<HBITMAP>(::SelectObject(hdcMem.get(), m_backingStoreBitmap->handle()));
1016 ::GetObject(m_backingStoreBitmap->handle(), sizeof(bmpInfo), &bmpInfo);
1017 SIZE windowSize = { bmpInfo.bmWidth, bmpInfo.bmHeight };
1019 BLENDFUNCTION blendFunction;
1020 blendFunction.BlendOp = AC_SRC_OVER;
1021 blendFunction.BlendFlags = 0;
1022 blendFunction.SourceConstantAlpha = 0xFF;
1023 blendFunction.AlphaFormat = AC_SRC_ALPHA;
1025 POINT layerPos = { 0, 0 };
1026 ::UpdateLayeredWindow(m_viewWindow, hdcScreen, 0, &windowSize, hdcMem.get(), &layerPos, 0, &blendFunction, ULW_ALPHA);
1028 ::SelectObject(hdcMem.get(), hbmOld);
1031 void WebView::paint(HDC dc, LPARAM options)
1033 LOCAL_GDI_COUNTER(0, __FUNCTION__);
1035 #if USE(ACCELERATED_COMPOSITING)
1036 if (isAcceleratedCompositing() && !usesLayeredWindow()) {
1037 m_layerTreeHost->flushPendingLayerChangesNow();
1038 // Flushing might have taken us out of compositing mode.
1039 if (isAcceleratedCompositing()) {
1040 // FIXME: We need to paint into dc (if provided). <http://webkit.org/b/52578>
1041 m_layerTreeHost->paint();
1042 ::ValidateRect(m_viewWindow, 0);
1048 Frame* coreFrame = core(m_mainFrame);
1051 FrameView* frameView = coreFrame->view();
1055 OwnPtr<HRGN> region;
1056 int regionType = NULLREGION;
1058 WindowsToPaint windowsToPaint;
1060 region = adoptPtr(CreateRectRgn(0,0,0,0));
1061 regionType = GetUpdateRgn(m_viewWindow, region.get(), false);
1062 hdc = BeginPaint(m_viewWindow, &ps);
1063 rcPaint = ps.rcPaint;
1064 // We're painting to the screen, and our child windows can handle
1065 // painting themselves to the screen.
1066 windowsToPaint = PaintWebViewOnly;
1069 ::GetClientRect(m_viewWindow, &rcPaint);
1070 if (options & PRF_ERASEBKGND)
1071 ::FillRect(hdc, &rcPaint, (HBRUSH)GetStockObject(WHITE_BRUSH));
1072 // Since we aren't painting to the screen, we want to paint all our
1073 // children into the HDC.
1074 windowsToPaint = PaintWebViewAndChildren;
1077 bool backingStoreCompletelyDirty = ensureBackingStore();
1078 if (!m_backingStoreBitmap) {
1080 EndPaint(m_viewWindow, &ps);
1086 HDC bitmapDC = ::CreateCompatibleDC(hdc);
1087 HGDIOBJ oldBitmap = ::SelectObject(bitmapDC, m_backingStoreBitmap->handle());
1089 // Update our backing store if needed.
1090 updateBackingStore(frameView, bitmapDC, backingStoreCompletelyDirty, windowsToPaint);
1092 // Now we blit the updated backing store
1093 IntRect windowDirtyRect = rcPaint;
1095 // Apply the same heuristic for this update region too.
1096 Vector<IntRect> blitRects;
1097 if (region && regionType == COMPLEXREGION)
1098 getUpdateRects(region.get(), windowDirtyRect, blitRects);
1100 blitRects.append(windowDirtyRect);
1102 for (unsigned i = 0; i < blitRects.size(); ++i)
1103 paintIntoWindow(bitmapDC, hdc, blitRects[i]);
1105 ::SelectObject(bitmapDC, oldBitmap);
1106 ::DeleteDC(bitmapDC);
1109 EndPaint(m_viewWindow, &ps);
1114 cancelDeleteBackingStoreSoon();
1116 deleteBackingStoreSoon();
1119 void WebView::paintIntoBackingStore(FrameView* frameView, HDC bitmapDC, const IntRect& dirtyRect, WindowsToPaint windowsToPaint)
1121 // FIXME: This function should never be called in accelerated compositing mode, and we should
1122 // assert as such. But currently it *is* sometimes called, so we can't assert yet. See
1123 // <http://webkit.org/b/58539>.
1125 LOCAL_GDI_COUNTER(0, __FUNCTION__);
1127 // FIXME: We want an assert here saying that the dirtyRect is inside the clienRect,
1128 // but it was being hit during our layout tests, and is being investigated in
1129 // http://webkit.org/b/29350.
1131 RECT rect = dirtyRect;
1133 #if FLASH_BACKING_STORE_REDRAW
1135 HWndDC dc(m_viewWindow);
1136 OwnPtr<HBRUSH> yellowBrush(CreateSolidBrush(RGB(255, 255, 0)));
1137 FillRect(dc, &rect, yellowBrush.get());
1140 paintIntoWindow(bitmapDC, dc, dirtyRect);
1144 GraphicsContext gc(bitmapDC, m_transparent);
1145 gc.setShouldIncludeChildWindows(windowsToPaint == PaintWebViewAndChildren);
1148 gc.clearRect(dirtyRect);
1150 FillRect(bitmapDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
1152 COMPtr<IWebUIDelegatePrivate2> uiPrivate(Query, m_uiDelegate);
1154 uiPrivate->drawBackground(this, reinterpret_cast<OLE_HANDLE>(bitmapDC), &rect);
1156 if (frameView && frameView->frame() && frameView->frame()->contentRenderer()) {
1158 frameView->paint(&gc, dirtyRect);
1159 if (m_shouldInvertColors)
1160 gc.fillRect(dirtyRect, Color::white, ColorSpaceDeviceRGB, CompositeDifference);
1165 void WebView::paintIntoWindow(HDC bitmapDC, HDC windowDC, const IntRect& dirtyRect)
1167 // FIXME: This function should never be called in accelerated compositing mode, and we should
1168 // assert as such. But currently it *is* sometimes called, so we can't assert yet. See
1169 // <http://webkit.org/b/58539>.
1171 LOCAL_GDI_COUNTER(0, __FUNCTION__);
1172 #if FLASH_WINDOW_REDRAW
1173 OwnPtr<HBRUSH> greenBrush = CreateSolidBrush(RGB(0, 255, 0));
1174 RECT rect = dirtyRect;
1175 FillRect(windowDC, &rect, greenBrush.get());
1180 // Blit the dirty rect from the backing store into the same position
1181 // in the destination DC.
1182 BitBlt(windowDC, dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(), bitmapDC,
1183 dirtyRect.x(), dirtyRect.y(), SRCCOPY);
1186 void WebView::frameRect(RECT* rect)
1188 ::GetWindowRect(m_viewWindow, rect);
1191 class WindowCloseTimer : public WebCore::SuspendableTimer {
1193 static WindowCloseTimer* create(WebView*);
1196 WindowCloseTimer(ScriptExecutionContext*, WebView*);
1197 virtual void contextDestroyed();
1198 virtual void fired();
1203 WindowCloseTimer* WindowCloseTimer::create(WebView* webView)
1205 ASSERT_ARG(webView, webView);
1206 Frame* frame = core(webView->topLevelFrame());
1211 Document* document = frame->document();
1216 return new WindowCloseTimer(document, webView);
1219 WindowCloseTimer::WindowCloseTimer(ScriptExecutionContext* context, WebView* webView)
1220 : SuspendableTimer(context)
1221 , m_webView(webView)
1223 ASSERT_ARG(context, context);
1224 ASSERT_ARG(webView, webView);
1227 void WindowCloseTimer::contextDestroyed()
1229 SuspendableTimer::contextDestroyed();
1233 void WindowCloseTimer::fired()
1235 m_webView->closeWindowTimerFired();
1238 void WebView::closeWindowSoon()
1240 if (m_closeWindowTimer)
1243 m_closeWindowTimer = WindowCloseTimer::create(this);
1244 if (!m_closeWindowTimer)
1246 m_closeWindowTimer->startOneShot(0);
1251 void WebView::closeWindowTimerFired()
1257 void WebView::closeWindow()
1259 if (m_hasSpellCheckerDocumentTag) {
1260 if (m_editingDelegate)
1261 m_editingDelegate->closeSpellDocument(this);
1262 m_hasSpellCheckerDocumentTag = false;
1265 COMPtr<IWebUIDelegate> ui;
1266 if (SUCCEEDED(uiDelegate(&ui)))
1267 ui->webViewClose(this);
1270 bool WebView::canHandleRequest(const WebCore::ResourceRequest& request)
1272 // On the mac there's an about url protocol implementation but CFNetwork doesn't have that.
1273 if (equalIgnoringCase(String(request.url().protocol()), "about"))
1277 if (CFURLProtocolCanHandleRequest(request.cfURLRequest()))
1280 // FIXME: Mac WebKit calls _representationExistsForURLScheme here
1287 String WebView::standardUserAgentWithApplicationName(const String& applicationName)
1289 DEFINE_STATIC_LOCAL(String, osVersion, (windowsVersionForUAString()));
1290 DEFINE_STATIC_LOCAL(String, webKitVersion, (webKitVersionString()));
1292 return makeString("Mozilla/5.0 (", osVersion, ") AppleWebKit/", webKitVersion, " (KHTML, like Gecko)", applicationName.isEmpty() ? "" : " ", applicationName);
1295 Page* WebView::page()
1300 bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam)
1302 // Translate the screen coordinates into window coordinates
1303 POINT coords = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1304 if (coords.x == -1 || coords.y == -1) {
1305 // The contextMenuController() holds onto the last context menu that was popped up on the
1306 // page until a new one is created. We need to clear this menu before propagating the event
1307 // through the DOM so that we can detect if we create a new menu for this event, since we
1308 // won't create a new menu if the DOM swallows the event and the defaultEventHandler does
1310 m_page->contextMenuController()->clearContextMenu();
1312 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1313 return focusedFrame->eventHandler()->sendContextMenuEventForKey();
1316 if (!::ScreenToClient(m_viewWindow, &coords))
1320 lParam = MAKELPARAM(coords.x, coords.y);
1322 m_page->contextMenuController()->clearContextMenu();
1324 IntPoint documentPoint(m_page->mainFrame()->view()->windowToContents(coords));
1325 HitTestResult result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(documentPoint, false);
1326 Frame* targetFrame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : m_page->focusController()->focusedOrMainFrame();
1328 targetFrame->view()->setCursor(pointerCursor());
1329 PlatformMouseEvent mouseEvent(m_viewWindow, WM_RBUTTONUP, wParam, lParam);
1330 bool handledEvent = targetFrame->eventHandler()->sendContextMenuEvent(mouseEvent);
1334 ContextMenuController* contextMenuController = m_page->contextMenuController();
1337 ContextMenu* coreMenu = contextMenuController->contextMenu();
1341 Node* node = contextMenuController->hitTestResult().innerNonSharedNode();
1345 Frame* frame = node->document()->frame();
1349 FrameView* view = frame->view();
1353 POINT point(view->contentsToWindow(contextMenuController->hitTestResult().roundedPoint()));
1355 // Translate the point to screen coordinates
1356 if (!::ClientToScreen(m_viewWindow, &point))
1359 BOOL hasCustomMenus = false;
1361 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1364 m_uiDelegate->trackCustomPopupMenu((IWebView*)this, (OLE_HANDLE)(ULONG64)coreMenu->nativeMenu(), &point);
1366 // Surprisingly, TPM_RIGHTBUTTON means that items are selectable with either the right OR left mouse button
1367 UINT flags = TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_HORIZONTAL
1368 | TPM_LEFTALIGN | TPM_HORPOSANIMATION;
1369 ::TrackPopupMenuEx(coreMenu->nativeMenu(), flags, point.x, point.y, m_viewWindow, 0);
1375 bool WebView::onMeasureItem(WPARAM /*wParam*/, LPARAM lParam)
1380 BOOL hasCustomMenus = false;
1381 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1382 if (!hasCustomMenus)
1385 m_uiDelegate->measureCustomMenuItem((IWebView*)this, (void*)lParam);
1389 bool WebView::onDrawItem(WPARAM /*wParam*/, LPARAM lParam)
1394 BOOL hasCustomMenus = false;
1395 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1396 if (!hasCustomMenus)
1399 m_uiDelegate->drawCustomMenuItem((IWebView*)this, (void*)lParam);
1403 bool WebView::onInitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
1408 HMENU menu = (HMENU)wParam;
1412 BOOL hasCustomMenus = false;
1413 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1414 if (!hasCustomMenus)
1417 m_uiDelegate->addCustomMenuDrawingData((IWebView*)this, (OLE_HANDLE)(ULONG64)menu);
1421 bool WebView::onUninitMenuPopup(WPARAM wParam, LPARAM /*lParam*/)
1426 HMENU menu = (HMENU)wParam;
1430 BOOL hasCustomMenus = false;
1431 m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
1432 if (!hasCustomMenus)
1435 m_uiDelegate->cleanUpCustomMenuDrawingData((IWebView*)this, (OLE_HANDLE)(ULONG64)menu);
1439 void WebView::performContextMenuAction(WPARAM wParam, LPARAM lParam, bool byPosition)
1441 ContextMenu* menu = m_page->contextMenuController()->contextMenu();
1444 ContextMenuItem* item = byPosition ? menu->itemAtIndex((unsigned)wParam) : menu->itemWithAction((ContextMenuAction)wParam);
1447 m_page->contextMenuController()->contextMenuItemSelected(item);
1450 bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam)
1452 static LONG globalClickCount;
1453 static IntPoint globalPrevPoint;
1454 static MouseButton globalPrevButton;
1455 static LONG globalPrevMouseDownTime;
1457 if (message == WM_CANCELMODE) {
1458 m_page->mainFrame()->eventHandler()->lostMouseCapture();
1462 // Create our event.
1463 // On WM_MOUSELEAVE we need to create a mouseout event, so we force the position
1464 // of the event to be at (MINSHORT, MINSHORT).
1465 LPARAM position = (message == WM_MOUSELEAVE) ? ((MINSHORT << 16) | MINSHORT) : lParam;
1466 PlatformMouseEvent mouseEvent(m_viewWindow, message, wParam, position, m_mouseActivated);
1468 setMouseActivated(false);
1470 bool insideThreshold = abs(globalPrevPoint.x() - mouseEvent.position().x()) < ::GetSystemMetrics(SM_CXDOUBLECLK) &&
1471 abs(globalPrevPoint.y() - mouseEvent.position().y()) < ::GetSystemMetrics(SM_CYDOUBLECLK);
1472 LONG messageTime = ::GetMessageTime();
1474 bool handled = false;
1476 if (message == WM_LBUTTONDOWN || message == WM_MBUTTONDOWN || message == WM_RBUTTONDOWN) {
1477 // FIXME: I'm not sure if this is the "right" way to do this
1478 // but without this call, we never become focused since we don't allow
1479 // the default handling of mouse events.
1480 SetFocus(m_viewWindow);
1482 // Always start capturing events when the mouse goes down in our HWND.
1483 ::SetCapture(m_viewWindow);
1485 if (((messageTime - globalPrevMouseDownTime) < (LONG)::GetDoubleClickTime()) &&
1487 mouseEvent.button() == globalPrevButton)
1490 // Reset the click count.
1491 globalClickCount = 1;
1492 globalPrevMouseDownTime = messageTime;
1493 globalPrevButton = mouseEvent.button();
1494 globalPrevPoint = mouseEvent.position();
1496 mouseEvent.setClickCount(globalClickCount);
1497 handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent);
1498 } else if (message == WM_LBUTTONDBLCLK || message == WM_MBUTTONDBLCLK || message == WM_RBUTTONDBLCLK) {
1500 mouseEvent.setClickCount(globalClickCount);
1501 handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent);
1502 } else if (message == WM_LBUTTONUP || message == WM_MBUTTONUP || message == WM_RBUTTONUP) {
1503 // Record the global position and the button of the up.
1504 globalPrevButton = mouseEvent.button();
1505 globalPrevPoint = mouseEvent.position();
1506 mouseEvent.setClickCount(globalClickCount);
1507 m_page->mainFrame()->eventHandler()->handleMouseReleaseEvent(mouseEvent);
1509 } else if (message == WM_MOUSELEAVE && m_mouseOutTracker) {
1510 // Once WM_MOUSELEAVE is fired windows clears this tracker
1511 // so there is no need to disable it ourselves.
1512 m_mouseOutTracker.clear();
1513 m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent);
1515 } else if (message == WM_MOUSEMOVE) {
1516 if (!insideThreshold)
1517 globalClickCount = 0;
1518 mouseEvent.setClickCount(globalClickCount);
1519 handled = m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent);
1520 if (!m_mouseOutTracker) {
1521 m_mouseOutTracker = adoptPtr(new TRACKMOUSEEVENT);
1522 m_mouseOutTracker->cbSize = sizeof(TRACKMOUSEEVENT);
1523 m_mouseOutTracker->dwFlags = TME_LEAVE;
1524 m_mouseOutTracker->hwndTrack = m_viewWindow;
1525 ::TrackMouseEvent(m_mouseOutTracker.get());
1531 bool WebView::gestureNotify(WPARAM wParam, LPARAM lParam)
1533 GESTURENOTIFYSTRUCT* gn = reinterpret_cast<GESTURENOTIFYSTRUCT*>(lParam);
1535 Frame* coreFrame = core(m_mainFrame);
1539 ScrollView* view = coreFrame->view();
1543 // If we don't have this function, we shouldn't be receiving this message
1544 ASSERT(SetGestureConfigPtr());
1546 bool hitScrollbar = false;
1547 POINT gestureBeginPoint = {gn->ptsLocation.x, gn->ptsLocation.y};
1548 HitTestRequest request(HitTestRequest::ReadOnly);
1549 for (Frame* childFrame = m_page->mainFrame(); childFrame; childFrame = EventHandler::subframeForTargetNode(m_gestureTargetNode.get())) {
1550 FrameView* frameView = childFrame->view();
1553 RenderView* renderView = childFrame->document()->renderView();
1556 RenderLayer* layer = renderView->layer();
1560 HitTestResult result(frameView->screenToContents(gestureBeginPoint));
1561 layer->hitTest(request, result);
1562 m_gestureTargetNode = result.innerNode();
1565 hitScrollbar = result.scrollbar();
1568 if (!hitScrollbar) {
1569 // The hit testing above won't detect if we've hit the main frame's vertical scrollbar. Check that manually now.
1571 GetWindowRect(m_viewWindow, &webViewRect);
1572 hitScrollbar = view->verticalScrollbar() && (gestureBeginPoint.x > (webViewRect.right - view->verticalScrollbar()->theme()->scrollbarThickness()));
1575 bool canBeScrolled = false;
1576 if (m_gestureTargetNode) {
1577 for (RenderObject* renderer = m_gestureTargetNode->renderer(); renderer; renderer = renderer->parent()) {
1578 if (renderer->isBox() && toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()) {
1579 canBeScrolled = true;
1585 // We always allow two-fingered panning with inertia and a gutter (which limits movement to one
1586 // direction in most cases).
1587 DWORD dwPanWant = GC_PAN | GC_PAN_WITH_INERTIA | GC_PAN_WITH_GUTTER;
1588 // We never allow single-fingered horizontal panning. That gesture is reserved for creating text
1589 // selections. This matches IE.
1590 DWORD dwPanBlock = GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
1592 if (hitScrollbar || !canBeScrolled) {
1593 // The part of the page under the gesture can't be scrolled, or the gesture is on a scrollbar.
1594 // Disallow single-fingered vertical panning in this case, too, so we'll fall back to the default
1595 // behavior (which allows the scrollbar thumb to be dragged, text selections to be made, etc.).
1596 dwPanBlock |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
1598 // The part of the page the gesture is under can be scrolled, and we're not under a scrollbar.
1599 // Allow single-fingered vertical panning in this case, so the user will be able to pan the page
1600 // with one or two fingers.
1601 dwPanWant |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
1604 GESTURECONFIG gc = { GID_PAN, dwPanWant, dwPanBlock };
1605 return SetGestureConfigPtr()(m_viewWindow, 0, 1, &gc, sizeof(GESTURECONFIG));
1608 bool WebView::gesture(WPARAM wParam, LPARAM lParam)
1610 // We want to bail out if we don't have either of these functions
1611 if (!GetGestureInfoPtr() || !CloseGestureInfoHandlePtr())
1614 HGESTUREINFO gestureHandle = reinterpret_cast<HGESTUREINFO>(lParam);
1616 GESTUREINFO gi = {0};
1617 gi.cbSize = sizeof(GESTUREINFO);
1619 if (!GetGestureInfoPtr()(gestureHandle, reinterpret_cast<PGESTUREINFO>(&gi)))
1624 m_lastPanX = gi.ptsLocation.x;
1625 m_lastPanY = gi.ptsLocation.y;
1629 m_gestureTargetNode = 0;
1632 // Where are the fingers currently?
1633 long currentX = gi.ptsLocation.x;
1634 long currentY = gi.ptsLocation.y;
1635 // How far did we pan in each direction?
1636 long deltaX = currentX - m_lastPanX;
1637 long deltaY = currentY - m_lastPanY;
1638 // Calculate the overpan for window bounce
1639 m_yOverpan -= m_lastPanY - currentY;
1640 m_xOverpan -= m_lastPanX - currentX;
1641 // Update our class variables with updated values
1642 m_lastPanX = currentX;
1643 m_lastPanY = currentY;
1645 Frame* coreFrame = core(m_mainFrame);
1647 CloseGestureInfoHandlePtr()(gestureHandle);
1651 if (!m_gestureTargetNode || !m_gestureTargetNode->renderer())
1654 // We negate here since panning up moves the content up, but moves the scrollbar down.
1655 m_gestureTargetNode->renderer()->enclosingLayer()->scrollByRecursively(IntSize(-deltaX, -deltaY));
1657 if (!(UpdatePanningFeedbackPtr() && BeginPanningFeedbackPtr() && EndPanningFeedbackPtr())) {
1658 CloseGestureInfoHandlePtr()(gestureHandle);
1662 if (gi.dwFlags & GF_BEGIN) {
1663 BeginPanningFeedbackPtr()(m_viewWindow);
1665 } else if (gi.dwFlags & GF_END) {
1666 EndPanningFeedbackPtr()(m_viewWindow, true);
1670 ScrollView* view = coreFrame->view();
1672 CloseGestureInfoHandlePtr()(gestureHandle);
1675 Scrollbar* vertScrollbar = view->verticalScrollbar();
1676 if (!vertScrollbar) {
1677 CloseGestureInfoHandlePtr()(gestureHandle);
1681 // FIXME: Support Horizontal Window Bounce. <https://webkit.org/b/28500>.
1682 // FIXME: If the user starts panning down after a window bounce has started, the window doesn't bounce back
1683 // until they release their finger. <https://webkit.org/b/28501>.
1684 if (vertScrollbar->currentPos() == 0)
1685 UpdatePanningFeedbackPtr()(m_viewWindow, 0, m_yOverpan, gi.dwFlags & GF_INERTIA);
1686 else if (vertScrollbar->currentPos() >= vertScrollbar->maximum())
1687 UpdatePanningFeedbackPtr()(m_viewWindow, 0, m_yOverpan, gi.dwFlags & GF_INERTIA);
1689 CloseGestureInfoHandlePtr()(gestureHandle);
1696 // If we get to this point, the gesture has not been handled. We forward
1697 // the call to DefWindowProc by returning false, and we don't need to
1698 // to call CloseGestureInfoHandle.
1699 // http://msdn.microsoft.com/en-us/library/dd353228(VS.85).aspx
1703 bool WebView::mouseWheel(WPARAM wParam, LPARAM lParam, bool isMouseHWheel)
1705 // Ctrl+Mouse wheel doesn't ever go into WebCore. It is used to
1706 // zoom instead (Mac zooms the whole Desktop, but Windows browsers trigger their
1707 // own local zoom modes for Ctrl+wheel).
1708 if (wParam & MK_CONTROL) {
1709 short delta = short(HIWORD(wParam));
1717 // 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.
1718 HWND focusedWindow = GetFocus();
1719 if (focusedWindow && focusedWindow != m_viewWindow) {
1720 // 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).
1721 WCHAR className[256];
1723 // Make sure truncation won't affect the comparison.
1724 ASSERT(WTF_ARRAY_LENGTH(className) > wcslen(PopupMenuWin::popupClassName()));
1726 if (GetClassNameW(focusedWindow, className, WTF_ARRAY_LENGTH(className)) && !wcscmp(className, PopupMenuWin::popupClassName())) {
1727 // We don't let the WebView scroll here for two reasons - 1) To match Firefox behavior, 2) If we do scroll, we lose the
1728 // focus ring around the select menu.
1729 SetFocus(m_viewWindow);
1734 PlatformWheelEvent wheelEvent(m_viewWindow, wParam, lParam, isMouseHWheel);
1735 Frame* coreFrame = core(m_mainFrame);
1739 return coreFrame->eventHandler()->handleWheelEvent(wheelEvent);
1742 bool WebView::verticalScroll(WPARAM wParam, LPARAM /*lParam*/)
1744 ScrollDirection direction;
1745 ScrollGranularity granularity;
1746 switch (LOWORD(wParam)) {
1748 granularity = ScrollByLine;
1749 direction = ScrollDown;
1752 granularity = ScrollByLine;
1753 direction = ScrollUp;
1756 granularity = ScrollByDocument;
1757 direction = ScrollDown;
1760 granularity = ScrollByDocument;
1761 direction = ScrollUp;
1768 Frame* frame = m_page->focusController()->focusedOrMainFrame();
1769 return frame->eventHandler()->scrollRecursively(direction, granularity);
1772 bool WebView::horizontalScroll(WPARAM wParam, LPARAM /*lParam*/)
1774 ScrollDirection direction;
1775 ScrollGranularity granularity;
1776 switch (LOWORD(wParam)) {
1778 granularity = ScrollByLine;
1779 direction = ScrollLeft;
1782 granularity = ScrollByLine;
1783 direction = ScrollRight;
1786 granularity = ScrollByDocument;
1787 direction = ScrollLeft;
1790 granularity = ScrollByDocument;
1791 direction = ScrollRight;
1797 Frame* frame = m_page->focusController()->focusedOrMainFrame();
1798 return frame->eventHandler()->scrollRecursively(direction, granularity);
1802 bool WebView::execCommand(WPARAM wParam, LPARAM /*lParam*/)
1804 Frame* frame = m_page->focusController()->focusedOrMainFrame();
1805 switch (LOWORD(wParam)) {
1807 return frame->editor()->command("SelectAll").execute();
1809 return frame->editor()->command("Undo").execute();
1811 return frame->editor()->command("Redo").execute();
1816 bool WebView::keyUp(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
1818 PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, PlatformEvent::KeyUp, systemKeyDown);
1820 Frame* frame = m_page->focusController()->focusedOrMainFrame();
1821 m_currentCharacterCode = 0;
1823 return frame->eventHandler()->keyEvent(keyEvent);
1826 static const unsigned CtrlKey = 1 << 0;
1827 static const unsigned AltKey = 1 << 1;
1828 static const unsigned ShiftKey = 1 << 2;
1831 struct KeyDownEntry {
1832 unsigned virtualKey;
1837 struct KeyPressEntry {
1843 static const KeyDownEntry keyDownEntries[] = {
1844 { VK_LEFT, 0, "MoveLeft" },
1845 { VK_LEFT, ShiftKey, "MoveLeftAndModifySelection" },
1846 { VK_LEFT, CtrlKey, "MoveWordLeft" },
1847 { VK_LEFT, CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection" },
1848 { VK_RIGHT, 0, "MoveRight" },
1849 { VK_RIGHT, ShiftKey, "MoveRightAndModifySelection" },
1850 { VK_RIGHT, CtrlKey, "MoveWordRight" },
1851 { VK_RIGHT, CtrlKey | ShiftKey, "MoveWordRightAndModifySelection" },
1852 { VK_UP, 0, "MoveUp" },
1853 { VK_UP, ShiftKey, "MoveUpAndModifySelection" },
1854 { VK_PRIOR, ShiftKey, "MovePageUpAndModifySelection" },
1855 { VK_DOWN, 0, "MoveDown" },
1856 { VK_DOWN, ShiftKey, "MoveDownAndModifySelection" },
1857 { VK_NEXT, ShiftKey, "MovePageDownAndModifySelection" },
1858 { VK_PRIOR, 0, "MovePageUp" },
1859 { VK_NEXT, 0, "MovePageDown" },
1860 { VK_HOME, 0, "MoveToBeginningOfLine" },
1861 { VK_HOME, ShiftKey, "MoveToBeginningOfLineAndModifySelection" },
1862 { VK_HOME, CtrlKey, "MoveToBeginningOfDocument" },
1863 { VK_HOME, CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" },
1865 { VK_END, 0, "MoveToEndOfLine" },
1866 { VK_END, ShiftKey, "MoveToEndOfLineAndModifySelection" },
1867 { VK_END, CtrlKey, "MoveToEndOfDocument" },
1868 { VK_END, CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection" },
1870 { VK_BACK, 0, "DeleteBackward" },
1871 { VK_BACK, ShiftKey, "DeleteBackward" },
1872 { VK_DELETE, 0, "DeleteForward" },
1873 { VK_BACK, CtrlKey, "DeleteWordBackward" },
1874 { VK_DELETE, CtrlKey, "DeleteWordForward" },
1876 { 'B', CtrlKey, "ToggleBold" },
1877 { 'I', CtrlKey, "ToggleItalic" },
1879 { VK_ESCAPE, 0, "Cancel" },
1880 { VK_OEM_PERIOD, CtrlKey, "Cancel" },
1881 { VK_TAB, 0, "InsertTab" },
1882 { VK_TAB, ShiftKey, "InsertBacktab" },
1883 { VK_RETURN, 0, "InsertNewline" },
1884 { VK_RETURN, CtrlKey, "InsertNewline" },
1885 { VK_RETURN, AltKey, "InsertNewline" },
1886 { VK_RETURN, ShiftKey, "InsertNewline" },
1887 { VK_RETURN, AltKey | ShiftKey, "InsertNewline" },
1889 // It's not quite clear whether clipboard shortcuts and Undo/Redo should be handled
1890 // in the application or in WebKit. We chose WebKit.
1891 { 'C', CtrlKey, "Copy" },
1892 { 'V', CtrlKey, "Paste" },
1893 { 'X', CtrlKey, "Cut" },
1894 { 'A', CtrlKey, "SelectAll" },
1895 { VK_INSERT, CtrlKey, "Copy" },
1896 { VK_DELETE, ShiftKey, "Cut" },
1897 { VK_INSERT, ShiftKey, "Paste" },
1898 { 'Z', CtrlKey, "Undo" },
1899 { 'Z', CtrlKey | ShiftKey, "Redo" },
1902 static const KeyPressEntry keyPressEntries[] = {
1903 { '\t', 0, "InsertTab" },
1904 { '\t', ShiftKey, "InsertBacktab" },
1905 { '\r', 0, "InsertNewline" },
1906 { '\r', CtrlKey, "InsertNewline" },
1907 { '\r', AltKey, "InsertNewline" },
1908 { '\r', ShiftKey, "InsertNewline" },
1909 { '\r', AltKey | ShiftKey, "InsertNewline" },
1912 const char* WebView::interpretKeyEvent(const KeyboardEvent* evt)
1914 ASSERT(evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
1916 static HashMap<int, const char*>* keyDownCommandsMap = 0;
1917 static HashMap<int, const char*>* keyPressCommandsMap = 0;
1919 if (!keyDownCommandsMap) {
1920 keyDownCommandsMap = new HashMap<int, const char*>;
1921 keyPressCommandsMap = new HashMap<int, const char*>;
1923 for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyDownEntries); ++i)
1924 keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
1926 for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyPressEntries); ++i)
1927 keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
1930 unsigned modifiers = 0;
1931 if (evt->shiftKey())
1932 modifiers |= ShiftKey;
1934 modifiers |= AltKey;
1936 modifiers |= CtrlKey;
1938 if (evt->type() == eventNames().keydownEvent) {
1939 int mapKey = modifiers << 16 | evt->keyCode();
1940 return mapKey ? keyDownCommandsMap->get(mapKey) : 0;
1943 int mapKey = modifiers << 16 | evt->charCode();
1944 return mapKey ? keyPressCommandsMap->get(mapKey) : 0;
1947 bool WebView::handleEditingKeyboardEvent(KeyboardEvent* evt)
1949 Node* node = evt->target()->toNode();
1951 Frame* frame = node->document()->frame();
1954 const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
1955 if (!keyEvent || keyEvent->isSystemKey()) // do not treat this as text input if it's a system key event
1958 Editor::Command command = frame->editor()->command(interpretKeyEvent(evt));
1960 if (keyEvent->type() == PlatformEvent::RawKeyDown) {
1961 // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
1962 // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
1963 // (e.g. Tab that inserts a Tab character, or Enter).
1964 return !command.isTextInsertion() && command.execute(evt);
1967 if (command.execute(evt))
1970 // Don't insert null or control characters as they can result in unexpected behaviour
1971 if (evt->charCode() < ' ')
1974 return frame->editor()->insertText(evt->keyEvent()->text(), evt);
1977 bool WebView::keyDown(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
1979 #if ENABLE(FULLSCREEN_API)
1980 // Trap the ESC key when in full screen mode.
1981 if (virtualKeyCode == VK_ESCAPE && isFullScreen()) {
1982 m_fullscreenController->exitFullScreen();
1986 Frame* frame = m_page->focusController()->focusedOrMainFrame();
1988 PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, PlatformEvent::RawKeyDown, systemKeyDown);
1989 bool handled = frame->eventHandler()->keyEvent(keyEvent);
1991 // These events cannot be canceled, and we have no default handling for them.
1992 // FIXME: match IE list more closely, see <http://msdn2.microsoft.com/en-us/library/ms536938.aspx>.
1993 if (systemKeyDown && virtualKeyCode != VK_RETURN)
1997 // FIXME: remove WM_UNICHAR, too
1999 // WM_SYSCHAR events should not be removed, because access keys are implemented in WebCore in WM_SYSCHAR handler.
2001 ::PeekMessage(&msg, m_viewWindow, WM_CHAR, WM_CHAR, PM_REMOVE);
2005 // We need to handle back/forward using either Ctrl+Left/Right Arrow keys.
2006 // FIXME: This logic should probably be in EventHandler::defaultArrowEventHandler().
2007 // FIXME: Should check that other modifiers aren't pressed.
2008 if (virtualKeyCode == VK_RIGHT && keyEvent.ctrlKey())
2009 return m_page->goForward();
2010 if (virtualKeyCode == VK_LEFT && keyEvent.ctrlKey())
2011 return m_page->goBack();
2013 // Need to scroll the page if the arrow keys, pgup/dn, or home/end are hit.
2014 ScrollDirection direction;
2015 ScrollGranularity granularity;
2016 switch (virtualKeyCode) {
2018 granularity = ScrollByLine;
2019 direction = ScrollLeft;
2022 granularity = ScrollByLine;
2023 direction = ScrollRight;
2026 granularity = ScrollByLine;
2027 direction = ScrollUp;
2030 granularity = ScrollByLine;
2031 direction = ScrollDown;
2034 granularity = ScrollByDocument;
2035 direction = ScrollUp;
2038 granularity = ScrollByDocument;
2039 direction = ScrollDown;
2042 granularity = ScrollByPage;
2043 direction = ScrollUp;
2046 granularity = ScrollByPage;
2047 direction = ScrollDown;
2053 return frame->eventHandler()->scrollRecursively(direction, granularity);
2056 bool WebView::keyPress(WPARAM charCode, LPARAM keyData, bool systemKeyDown)
2058 Frame* frame = m_page->focusController()->focusedOrMainFrame();
2060 PlatformKeyboardEvent keyEvent(m_viewWindow, charCode, keyData, PlatformEvent::Char, systemKeyDown);
2061 // IE does not dispatch keypress event for WM_SYSCHAR.
2063 return frame->eventHandler()->handleAccessKey(keyEvent);
2064 return frame->eventHandler()->keyEvent(keyEvent);
2067 void WebView::setIsBeingDestroyed()
2069 m_isBeingDestroyed = true;
2071 // Remove our this pointer from the window so we won't try to handle any more window messages.
2072 // See <http://webkit.org/b/55054>.
2073 ::SetWindowLongPtrW(m_viewWindow, 0, 0);
2076 void WebView::setShouldInvertColors(bool shouldInvertColors)
2078 if (m_shouldInvertColors == shouldInvertColors)
2081 m_shouldInvertColors = shouldInvertColors;
2083 #if USE(ACCELERATED_COMPOSITING)
2084 if (m_layerTreeHost)
2085 m_layerTreeHost->setShouldInvertColors(shouldInvertColors);
2088 RECT windowRect = {0};
2089 frameRect(&windowRect);
2090 repaint(windowRect, true, true);
2093 bool WebView::registerWebViewWindowClass()
2095 static bool haveRegisteredWindowClass = false;
2096 if (haveRegisteredWindowClass)
2099 haveRegisteredWindowClass = true;
2103 wcex.cbSize = sizeof(WNDCLASSEX);
2105 wcex.style = CS_DBLCLKS;
2106 wcex.lpfnWndProc = WebViewWndProc;
2107 wcex.cbClsExtra = 0;
2108 wcex.cbWndExtra = 4; // 4 bytes for the IWebView pointer
2109 wcex.hInstance = gInstance;
2111 wcex.hCursor = ::LoadCursor(0, IDC_ARROW);
2112 wcex.hbrBackground = 0;
2113 wcex.lpszMenuName = 0;
2114 wcex.lpszClassName = kWebViewWindowClassName;
2117 return !!RegisterClassEx(&wcex);
2120 static HWND findTopLevelParent(HWND window)
2125 HWND current = window;
2126 for (HWND parent = GetParent(current); current; current = parent, parent = GetParent(parent))
2127 if (!parent || !(GetWindowLongPtr(current, GWL_STYLE) & (WS_POPUP | WS_CHILD)))
2129 ASSERT_NOT_REACHED();
2133 LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
2135 LRESULT lResult = 0;
2136 LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0);
2137 WebView* webView = reinterpret_cast<WebView*>(longPtr);
2138 WebFrame* mainFrameImpl = webView ? webView->topLevelFrame() : 0;
2140 return DefWindowProc(hWnd, message, wParam, lParam);
2142 // We shouldn't be trying to handle any window messages after WM_DESTROY.
2143 // See <http://webkit.org/b/55054>.
2144 ASSERT(!webView->isBeingDestroyed());
2146 // hold a ref, since the WebView could go away in an event handler.
2147 COMPtr<WebView> protector(webView);
2150 // Windows Media Player has a modal message loop that will deliver messages
2151 // to us at inappropriate times and we will crash if we handle them when
2152 // they are delivered. We repost paint messages so that we eventually get
2153 // a chance to paint once the modal loop has exited, but other messages
2154 // aren't safe to repost, so we just drop them.
2155 if (PluginView::isCallingPlugin()) {
2156 if (message == WM_PAINT)
2157 PostMessage(hWnd, message, wParam, lParam);
2161 bool handled = true;
2165 webView->paint(0, 0);
2166 if (webView->usesLayeredWindow())
2167 webView->performLayeredWindowUpdate();
2171 if (webView->usesLayeredWindow()) {
2172 // Don't perform a background erase for transparent views.
2177 case WM_PRINTCLIENT:
2178 webView->paint((HDC)wParam, lParam);
2181 webView->setIsBeingDestroyed();
2184 case WM_GESTURENOTIFY:
2185 handled = webView->gestureNotify(wParam, lParam);
2188 handled = webView->gesture(wParam, lParam);
2191 case WM_LBUTTONDOWN:
2192 case WM_MBUTTONDOWN:
2193 case WM_RBUTTONDOWN:
2194 case WM_LBUTTONDBLCLK:
2195 case WM_MBUTTONDBLCLK:
2196 case WM_RBUTTONDBLCLK:
2202 if (Frame* coreFrame = core(mainFrameImpl))
2203 if (coreFrame->view()->didFirstLayout())
2204 handled = webView->handleMouseEvent(message, wParam, lParam);
2207 case WM_VISTA_MOUSEHWHEEL:
2208 if (Frame* coreFrame = core(mainFrameImpl))
2209 if (coreFrame->view()->didFirstLayout())
2210 handled = webView->mouseWheel(wParam, lParam, message == WM_VISTA_MOUSEHWHEEL);
2213 handled = webView->keyDown(wParam, lParam, true);
2216 handled = webView->keyDown(wParam, lParam);
2219 handled = webView->keyUp(wParam, lParam, true);
2222 handled = webView->keyUp(wParam, lParam);
2225 handled = webView->keyPress(wParam, lParam, true);
2228 handled = webView->keyPress(wParam, lParam);
2230 // FIXME: We need to check WM_UNICHAR to support supplementary characters (that don't fit in 16 bits).
2233 webView->sizeChanged(IntSize(LOWORD(lParam), HIWORD(lParam)));
2236 lResult = DefWindowProc(hWnd, message, wParam, lParam);
2238 // The window is being hidden (e.g., because we switched tabs).
2239 // Null out our backing store.
2240 webView->deleteBackingStore();
2244 COMPtr<IWebUIDelegate> uiDelegate;
2245 COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
2246 if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate
2247 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)
2248 uiDelegatePrivate->webViewReceivedFocus(webView);
2250 FocusController* focusController = webView->page()->focusController();
2251 if (Frame* frame = focusController->focusedFrame()) {
2252 // Send focus events unless the previously focused window is a
2253 // child of ours (for example a plugin).
2254 if (!IsChild(hWnd, reinterpret_cast<HWND>(wParam)))
2255 focusController->setFocused(true);
2257 focusController->setFocused(true);
2260 case WM_KILLFOCUS: {
2261 COMPtr<IWebUIDelegate> uiDelegate;
2262 COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
2263 HWND newFocusWnd = reinterpret_cast<HWND>(wParam);
2264 if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate
2265 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)
2266 uiDelegatePrivate->webViewLostFocus(webView, (OLE_HANDLE)(ULONG64)newFocusWnd);
2268 FocusController* focusController = webView->page()->focusController();
2269 Frame* frame = focusController->focusedOrMainFrame();
2270 webView->resetIME(frame);
2271 // Send blur events unless we're losing focus to a child of ours.
2272 if (!IsChild(hWnd, newFocusWnd))
2273 focusController->setFocused(false);
2275 // If we are pan-scrolling when we lose focus, stop the pan scrolling.
2276 frame->eventHandler()->stopAutoscrollTimer();
2280 case WM_WINDOWPOSCHANGED:
2281 if (reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_SHOWWINDOW)
2282 webView->updateActiveStateSoon();
2295 webView->delete_(0);
2299 handled = webView->execCommand(wParam, lParam);
2300 else // If the high word of wParam is 0, the message is from a menu
2301 webView->performContextMenuAction(wParam, lParam, false);
2303 case WM_MENUCOMMAND:
2304 webView->performContextMenuAction(wParam, lParam, true);
2306 case WM_CONTEXTMENU:
2307 handled = webView->handleContextMenuEvent(wParam, lParam);
2309 case WM_INITMENUPOPUP:
2310 handled = webView->onInitMenuPopup(wParam, lParam);
2312 case WM_MEASUREITEM:
2313 handled = webView->onMeasureItem(wParam, lParam);
2316 handled = webView->onDrawItem(wParam, lParam);
2318 case WM_UNINITMENUPOPUP:
2319 handled = webView->onUninitMenuPopup(wParam, lParam);
2321 case WM_XP_THEMECHANGED:
2322 if (Frame* coreFrame = core(mainFrameImpl)) {
2323 webView->deleteBackingStore();
2324 coreFrame->page()->theme()->themeChanged();
2325 ScrollbarTheme::theme()->themeChanged();
2327 ::GetClientRect(hWnd, &windowRect);
2328 ::InvalidateRect(hWnd, &windowRect, false);
2329 #if USE(ACCELERATED_COMPOSITING)
2330 if (webView->isAcceleratedCompositing())
2331 webView->m_backingLayer->setNeedsDisplay();
2335 case WM_MOUSEACTIVATE:
2336 webView->setMouseActivated(true);
2339 case WM_GETDLGCODE: {
2340 COMPtr<IWebUIDelegate> uiDelegate;
2341 COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;
2342 LONG_PTR dlgCode = 0;
2345 LPMSG lpMsg = (LPMSG)lParam;
2346 if (lpMsg->message == WM_KEYDOWN)
2347 keyCode = (UINT) lpMsg->wParam;
2349 if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate
2350 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate
2351 && SUCCEEDED(uiDelegatePrivate->webViewGetDlgCode(webView, keyCode, &dlgCode)))
2357 handled = webView->onGetObject(wParam, lParam, lResult);
2359 case WM_IME_STARTCOMPOSITION:
2360 handled = webView->onIMEStartComposition();
2362 case WM_IME_REQUEST:
2363 lResult = webView->onIMERequest(wParam, lParam);
2365 case WM_IME_COMPOSITION:
2366 handled = webView->onIMEComposition(lParam);
2368 case WM_IME_ENDCOMPOSITION:
2369 handled = webView->onIMEEndComposition();
2372 handled = webView->onIMEChar(wParam, lParam);
2375 handled = webView->onIMENotify(wParam, lParam, &lResult);
2378 handled = webView->onIMESelect(wParam, lParam);
2380 case WM_IME_SETCONTEXT:
2381 handled = webView->onIMESetContext(wParam, lParam);
2385 case UpdateActiveStateTimer:
2386 KillTimer(hWnd, UpdateActiveStateTimer);
2387 webView->updateActiveState();
2389 case DeleteBackingStoreTimer:
2390 webView->deleteBackingStore();
2395 handled = ::SetCursor(webView->m_lastSetCursor);
2398 handled = webView->verticalScroll(wParam, lParam);
2401 handled = webView->horizontalScroll(wParam, lParam);
2409 lResult = DefWindowProc(hWnd, message, wParam, lParam);
2411 // Let the client know whether we consider this message handled.
2412 return (message == WM_KEYDOWN || message == WM_SYSKEYDOWN || message == WM_KEYUP || message == WM_SYSKEYUP) ? !handled : lResult;
2415 bool WebView::developerExtrasEnabled() const
2417 if (m_preferences->developerExtrasDisabledByOverride())
2422 return SUCCEEDED(m_preferences->developerExtrasEnabled(&enabled)) && enabled;
2428 static String webKitVersionString()
2430 LPWSTR buildNumberStringPtr;
2431 if (!::LoadStringW(gInstance, BUILD_NUMBER, reinterpret_cast<LPWSTR>(&buildNumberStringPtr), 0) || !buildNumberStringPtr)
2434 return buildNumberStringPtr;
2437 const String& WebView::userAgentForKURL(const KURL&)
2439 if (m_userAgentOverridden)
2440 return m_userAgentCustom;
2442 if (!m_userAgentStandard.length())
2443 m_userAgentStandard = WebView::standardUserAgentWithApplicationName(m_applicationName);
2444 return m_userAgentStandard;
2447 // IUnknown -------------------------------------------------------------------
2449 HRESULT STDMETHODCALLTYPE WebView::QueryInterface(REFIID riid, void** ppvObject)
2452 if (IsEqualGUID(riid, CLSID_WebView))
2454 else if (IsEqualGUID(riid, IID_IUnknown))
2455 *ppvObject = static_cast<IWebView*>(this);
2456 else if (IsEqualGUID(riid, IID_IWebView))
2457 *ppvObject = static_cast<IWebView*>(this);
2458 else if (IsEqualGUID(riid, IID_IWebViewPrivate))
2459 *ppvObject = static_cast<IWebViewPrivate*>(this);
2460 else if (IsEqualGUID(riid, IID_IWebIBActions))
2461 *ppvObject = static_cast<IWebIBActions*>(this);
2462 else if (IsEqualGUID(riid, IID_IWebViewCSS))
2463 *ppvObject = static_cast<IWebViewCSS*>(this);
2464 else if (IsEqualGUID(riid, IID_IWebViewEditing))
2465 *ppvObject = static_cast<IWebViewEditing*>(this);
2466 else if (IsEqualGUID(riid, IID_IWebViewUndoableEditing))
2467 *ppvObject = static_cast<IWebViewUndoableEditing*>(this);
2468 else if (IsEqualGUID(riid, IID_IWebViewEditingActions))
2469 *ppvObject = static_cast<IWebViewEditingActions*>(this);
2470 else if (IsEqualGUID(riid, IID_IWebNotificationObserver))
2471 *ppvObject = static_cast<IWebNotificationObserver*>(this);
2472 else if (IsEqualGUID(riid, IID_IDropTarget))
2473 *ppvObject = static_cast<IDropTarget*>(this);
2475 return E_NOINTERFACE;
2481 ULONG STDMETHODCALLTYPE WebView::AddRef(void)
2483 ASSERT(!m_deletionHasBegun);
2484 return ++m_refCount;
2487 ULONG STDMETHODCALLTYPE WebView::Release(void)
2489 ASSERT(!m_deletionHasBegun);
2491 if (m_refCount == 1) {
2492 // Call close() now so that clients don't have to. (It's harmless to call close() multiple
2493 // times.) We do this here instead of in our destructor because close() can cause AddRef()
2494 // and Release() to be called, and if that happened in our destructor we would be destroyed
2499 ULONG newRef = --m_refCount;
2501 #if !ASSERT_DISABLED
2502 m_deletionHasBegun = true;
2510 // IWebView --------------------------------------------------------------------
2512 HRESULT STDMETHODCALLTYPE WebView::canShowMIMEType(
2513 /* [in] */ BSTR mimeType,
2514 /* [retval][out] */ BOOL* canShow)
2516 String mimeTypeStr(mimeType, SysStringLen(mimeType));
2521 *canShow = MIMETypeRegistry::isSupportedImageMIMEType(mimeTypeStr) ||
2522 MIMETypeRegistry::isSupportedNonImageMIMEType(mimeTypeStr) ||
2523 (m_page && m_page->pluginData() && m_page->pluginData()->supportsMimeType(mimeTypeStr)) ||
2524 shouldUseEmbeddedView(mimeTypeStr);
2529 HRESULT STDMETHODCALLTYPE WebView::canShowMIMETypeAsHTML(
2530 /* [in] */ BSTR /*mimeType*/,
2531 /* [retval][out] */ BOOL* canShow)
2538 HRESULT STDMETHODCALLTYPE WebView::MIMETypesShownAsHTML(
2539 /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
2541 ASSERT_NOT_REACHED();
2545 HRESULT STDMETHODCALLTYPE WebView::setMIMETypesShownAsHTML(
2546 /* [size_is][in] */ BSTR* /*mimeTypes*/,
2547 /* [in] */ int /*cMimeTypes*/)
2549 ASSERT_NOT_REACHED();
2553 HRESULT STDMETHODCALLTYPE WebView::URLFromPasteboard(
2554 /* [in] */ IDataObject* /*pasteboard*/,
2555 /* [retval][out] */ BSTR* /*url*/)
2557 ASSERT_NOT_REACHED();
2561 HRESULT STDMETHODCALLTYPE WebView::URLTitleFromPasteboard(
2562 /* [in] */ IDataObject* /*pasteboard*/,
2563 /* [retval][out] */ BSTR* /*urlTitle*/)
2565 ASSERT_NOT_REACHED();
2569 static void WebKitSetApplicationCachePathIfNecessary()
2571 static bool initialized = false;
2575 String path = localUserSpecificStorageDirectory();
2577 cacheStorage().setCacheDirectory(path);
2582 bool WebView::shouldInitializeTrackPointHack()
2584 static bool shouldCreateScrollbars;
2585 static bool hasRunTrackPointCheck;
2587 if (hasRunTrackPointCheck)
2588 return shouldCreateScrollbars;
2590 hasRunTrackPointCheck = true;
2591 const WCHAR trackPointKeys[][50] = { L"Software\\Lenovo\\TrackPoint",
2592 L"Software\\Lenovo\\UltraNav",
2593 L"Software\\Alps\\Apoint\\TrackPoint",
2594 L"Software\\Synaptics\\SynTPEnh\\UltraNavUSB",
2595 L"Software\\Synaptics\\SynTPEnh\\UltraNavPS2" };
2597 for (int i = 0; i < 5; ++i) {
2599 int readKeyResult = ::RegOpenKeyExW(HKEY_CURRENT_USER, trackPointKeys[i], 0, KEY_READ, &trackPointKey);
2600 ::RegCloseKey(trackPointKey);
2601 if (readKeyResult == ERROR_SUCCESS) {
2602 shouldCreateScrollbars = true;
2603 return shouldCreateScrollbars;
2607 return shouldCreateScrollbars;
2610 HRESULT STDMETHODCALLTYPE WebView::initWithFrame(
2611 /* [in] */ RECT frame,
2612 /* [in] */ BSTR frameName,
2613 /* [in] */ BSTR groupName)
2620 registerWebViewWindowClass();
2622 m_viewWindow = CreateWindowEx(0, kWebViewWindowClassName, 0, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
2623 frame.left, frame.top, frame.right - frame.left, frame.bottom - frame.top, m_hostWindow ? m_hostWindow : HWND_MESSAGE, 0, gInstance, 0);
2624 ASSERT(::IsWindow(m_viewWindow));
2626 if (shouldInitializeTrackPointHack()) {
2627 // If we detected a registry key belonging to a TrackPoint driver, then create fake trackpoint
2628 // scrollbars, so the WebView will receive WM_VSCROLL and WM_HSCROLL messages. We create one
2629 // vertical scrollbar and one horizontal to allow for receiving both types of messages.
2630 ::CreateWindowW(L"SCROLLBAR", L"FAKETRACKPOINTHSCROLLBAR", WS_CHILD | WS_VISIBLE | SBS_HORZ, 0, 0, 0, 0, m_viewWindow, 0, gInstance, 0);
2631 ::CreateWindowW(L"SCROLLBAR", L"FAKETRACKPOINTVSCROLLBAR", WS_CHILD | WS_VISIBLE | SBS_VERT, 0, 0, 0, 0, m_viewWindow, 0, gInstance, 0);
2634 hr = registerDragDrop();
2638 WebPreferences* sharedPreferences = WebPreferences::sharedStandardPreferences();
2639 sharedPreferences->willAddToWebView();
2640 m_preferences = sharedPreferences;
2642 static bool didOneTimeInitialization;
2643 if (!didOneTimeInitialization) {
2645 initializeLoggingChannelsIfNecessary();
2646 #endif // !LOG_DISABLED
2647 #if ENABLE(SQL_DATABASE)
2648 WebKitInitializeWebDatabasesIfNecessary();
2650 WebKitSetApplicationCachePathIfNecessary();
2651 WebPlatformStrategies::initialize();
2652 Settings::setDefaultMinDOMTimerInterval(0.004);
2654 didOneTimeInitialization = true;
2657 #if USE(SAFARI_THEME)
2658 BOOL shouldPaintNativeControls;
2659 if (SUCCEEDED(m_preferences->shouldPaintNativeControls(&shouldPaintNativeControls)))
2660 Settings::setShouldPaintNativeControls(shouldPaintNativeControls);
2663 BOOL useHighResolutionTimer;
2664 if (SUCCEEDED(m_preferences->shouldUseHighResolutionTimers(&useHighResolutionTimer)))
2665 Settings::setShouldUseHighResolutionTimers(useHighResolutionTimer);
2667 #if ENABLE(INSPECTOR)
2668 m_inspectorClient = new WebInspectorClient(this);
2669 #endif // ENABLE(INSPECTOR)
2671 Page::PageClients pageClients;
2672 pageClients.chromeClient = new WebChromeClient(this);
2673 pageClients.contextMenuClient = new WebContextMenuClient(this);
2674 pageClients.editorClient = new WebEditorClient(this);
2675 pageClients.dragClient = new WebDragClient(this);
2676 #if ENABLE(INSPECTOR)
2677 pageClients.inspectorClient = m_inspectorClient;
2678 #endif // ENABLE(INSPECTOR)
2680 m_page = new Page(pageClients);
2681 provideGeolocationTo(m_page, new WebGeolocationClient(this));
2683 BSTR localStoragePath;
2684 if (SUCCEEDED(m_preferences->localStorageDatabasePath(&localStoragePath))) {
2685 m_page->settings()->setLocalStorageDatabasePath(String(localStoragePath, SysStringLen(localStoragePath)));
2686 SysFreeString(localStoragePath);
2691 if (SUCCEEDED(m_uiDelegate->ftpDirectoryTemplatePath(this, &path))) {
2692 m_page->settings()->setFTPDirectoryTemplatePath(String(path, SysStringLen(path)));
2693 SysFreeString(path);
2697 WebFrame* webFrame = WebFrame::createInstance();
2698 RefPtr<Frame> coreFrame = webFrame->init(this, m_page, 0);
2699 m_mainFrame = webFrame;
2700 webFrame->Release(); // The WebFrame is owned by the Frame, so release our reference to it.
2702 coreFrame->tree()->setName(String(frameName, SysStringLen(frameName)));
2704 setGroupName(groupName);
2706 addToAllWebViewsSet();
2708 #pragma warning(suppress: 4244)
2709 SetWindowLongPtr(m_viewWindow, 0, (LONG_PTR)this);
2710 ShowWindow(m_viewWindow, SW_SHOW);
2712 initializeToolTipWindow();
2713 windowAncestryDidChange();
2715 IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
2716 notifyCenter->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
2717 m_preferences->postPreferencesChangesNotification();
2719 setSmartInsertDeleteEnabled(TRUE);
2723 static bool initCommonControls()
2725 static bool haveInitialized = false;
2726 if (haveInitialized)
2729 INITCOMMONCONTROLSEX init;
2730 init.dwSize = sizeof(init);
2731 init.dwICC = ICC_TREEVIEW_CLASSES;
2732 haveInitialized = !!::InitCommonControlsEx(&init);
2733 return haveInitialized;
2736 void WebView::initializeToolTipWindow()
2738 if (!initCommonControls())
2741 m_toolTipHwnd = CreateWindowEx(WS_EX_TRANSPARENT, TOOLTIPS_CLASS, 0, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
2742 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
2743 m_viewWindow, 0, 0, 0);
2747 TOOLINFO info = {0};
2748 info.cbSize = sizeof(info);
2749 info.uFlags = TTF_IDISHWND | TTF_SUBCLASS ;
2750 info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
2752 ::SendMessage(m_toolTipHwnd, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&info));
2753 ::SendMessage(m_toolTipHwnd, TTM_SETMAXTIPWIDTH, 0, maxToolTipWidth);
2755 ::SetWindowPos(m_toolTipHwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
2758 void WebView::setToolTip(const String& toolTip)
2763 if (toolTip == m_toolTip)
2766 m_toolTip = toolTip;
2768 if (!m_toolTip.isEmpty()) {
2769 TOOLINFO info = {0};
2770 info.cbSize = sizeof(info);
2771 info.uFlags = TTF_IDISHWND;
2772 info.uId = reinterpret_cast<UINT_PTR>(m_viewWindow);
2773 info.lpszText = const_cast<UChar*>(m_toolTip.charactersWithNullTermination());
2774 ::SendMessage(m_toolTipHwnd, TTM_UPDATETIPTEXT, 0, reinterpret_cast<LPARAM>(&info));
2777 ::SendMessage(m_toolTipHwnd, TTM_ACTIVATE, !m_toolTip.isEmpty(), 0);
2780 HRESULT WebView::notifyDidAddIcon(IWebNotification* notification)
2782 COMPtr<IPropertyBag> propertyBag;
2783 HRESULT hr = notification->userInfo(&propertyBag);
2789 COMPtr<CFDictionaryPropertyBag> dictionaryPropertyBag;
2790 hr = propertyBag->QueryInterface(&dictionaryPropertyBag);
2794 CFDictionaryRef dictionary = dictionaryPropertyBag->dictionary();
2798 CFTypeRef value = CFDictionaryGetValue(dictionary, WebIconDatabase::iconDatabaseNotificationUserInfoURLKey());
2801 if (CFGetTypeID(value) != CFStringGetTypeID())
2804 String mainFrameURL;
2806 mainFrameURL = m_mainFrame->url().string();
2808 if (!mainFrameURL.isEmpty() && mainFrameURL == String((CFStringRef)value))
2809 dispatchDidReceiveIconFromWebFrame(m_mainFrame);
2814 void WebView::registerForIconNotification(bool listen)
2816 IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
2818 nc->addObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
2820 nc->removeObserver(this, WebIconDatabase::iconDatabaseDidAddIconNotification(), 0);
2823 void WebView::dispatchDidReceiveIconFromWebFrame(WebFrame* frame)
2825 registerForIconNotification(false);
2827 if (m_frameLoadDelegate)
2828 // FIXME: <rdar://problem/5491010> - Pass in the right HBITMAP.
2829 m_frameLoadDelegate->didReceiveIcon(this, 0, frame);
2832 HRESULT STDMETHODCALLTYPE WebView::setUIDelegate(
2833 /* [in] */ IWebUIDelegate* d)
2837 if (m_uiDelegatePrivate)
2838 m_uiDelegatePrivate = 0;
2841 if (FAILED(d->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&m_uiDelegatePrivate)))
2842 m_uiDelegatePrivate = 0;
2848 HRESULT STDMETHODCALLTYPE WebView::uiDelegate(
2849 /* [out][retval] */ IWebUIDelegate** d)
2854 return m_uiDelegate.copyRefTo(d);
2857 HRESULT STDMETHODCALLTYPE WebView::setResourceLoadDelegate(
2858 /* [in] */ IWebResourceLoadDelegate* d)
2860 m_resourceLoadDelegate = d;
2864 HRESULT STDMETHODCALLTYPE WebView::resourceLoadDelegate(
2865 /* [out][retval] */ IWebResourceLoadDelegate** d)
2867 if (!m_resourceLoadDelegate)
2870 return m_resourceLoadDelegate.copyRefTo(d);
2873 HRESULT STDMETHODCALLTYPE WebView::setDownloadDelegate(
2874 /* [in] */ IWebDownloadDelegate* d)
2876 m_downloadDelegate = d;
2880 HRESULT STDMETHODCALLTYPE WebView::downloadDelegate(
2881 /* [out][retval] */ IWebDownloadDelegate** d)
2883 if (!m_downloadDelegate)
2886 return m_downloadDelegate.copyRefTo(d);
2889 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegate(
2890 /* [in] */ IWebFrameLoadDelegate* d)
2892 m_frameLoadDelegate = d;
2896 HRESULT STDMETHODCALLTYPE WebView::frameLoadDelegate(
2897 /* [out][retval] */ IWebFrameLoadDelegate** d)
2899 if (!m_frameLoadDelegate)
2902 return m_frameLoadDelegate.copyRefTo(d);
2905 HRESULT STDMETHODCALLTYPE WebView::setPolicyDelegate(
2906 /* [in] */ IWebPolicyDelegate* d)
2908 m_policyDelegate = d;
2912 HRESULT STDMETHODCALLTYPE WebView::policyDelegate(
2913 /* [out][retval] */ IWebPolicyDelegate** d)
2915 if (!m_policyDelegate)
2917 return m_policyDelegate.copyRefTo(d);
2920 HRESULT STDMETHODCALLTYPE WebView::mainFrame(
2921 /* [out][retval] */ IWebFrame** frame)
2924 ASSERT_NOT_REACHED();
2928 *frame = m_mainFrame;
2932 m_mainFrame->AddRef();
2936 HRESULT STDMETHODCALLTYPE WebView::focusedFrame(
2937 /* [out][retval] */ IWebFrame** frame)
2940 ASSERT_NOT_REACHED();
2945 Frame* f = m_page->focusController()->focusedFrame();
2949 WebFrame* webFrame = kit(f);
2953 return webFrame->QueryInterface(IID_IWebFrame, (void**) frame);
2956 HRESULT STDMETHODCALLTYPE WebView::backForwardList(
2957 /* [out][retval] */ IWebBackForwardList** list)
2959 if (!m_useBackForwardList)
2962 *list = WebBackForwardList::createInstance(static_cast<WebCore::BackForwardListImpl*>(m_page->backForwardList()));
2967 HRESULT STDMETHODCALLTYPE WebView::setMaintainsBackForwardList(
2968 /* [in] */ BOOL flag)
2970 m_useBackForwardList = !!flag;
2974 HRESULT STDMETHODCALLTYPE WebView::goBack(
2975 /* [retval][out] */ BOOL* succeeded)
2977 *succeeded = m_page->goBack();
2981 HRESULT STDMETHODCALLTYPE WebView::goForward(
2982 /* [retval][out] */ BOOL* succeeded)
2984 *succeeded = m_page->goForward();
2988 HRESULT STDMETHODCALLTYPE WebView::goToBackForwardItem(
2989 /* [in] */ IWebHistoryItem* item,
2990 /* [retval][out] */ BOOL* succeeded)
2994 COMPtr<WebHistoryItem> webHistoryItem;
2995 HRESULT hr = item->QueryInterface(&webHistoryItem);
2999 m_page->goToItem(webHistoryItem->historyItem(), FrameLoadTypeIndexedBackForward);
3005 HRESULT STDMETHODCALLTYPE WebView::setTextSizeMultiplier(
3006 /* [in] */ float multiplier)
3010 setZoomMultiplier(multiplier, true);
3014 HRESULT STDMETHODCALLTYPE WebView::setPageSizeMultiplier(
3015 /* [in] */ float multiplier)
3019 setZoomMultiplier(multiplier, false);
3023 void WebView::setZoomMultiplier(float multiplier, bool isTextOnly)
3025 m_zoomMultiplier = multiplier;
3026 m_zoomsTextOnly = isTextOnly;
3028 if (Frame* coreFrame = core(m_mainFrame)) {
3029 if (m_zoomsTextOnly)
3030 coreFrame->setPageAndTextZoomFactors(1, multiplier);
3032 coreFrame->setPageAndTextZoomFactors(multiplier, 1);
3036 HRESULT STDMETHODCALLTYPE WebView::textSizeMultiplier(
3037 /* [retval][out] */ float* multiplier)
3039 *multiplier = zoomMultiplier(true);
3043 HRESULT STDMETHODCALLTYPE WebView::pageSizeMultiplier(
3044 /* [retval][out] */ float* multiplier)
3046 *multiplier = zoomMultiplier(false);
3050 float WebView::zoomMultiplier(bool isTextOnly)
3052 if (isTextOnly != m_zoomsTextOnly)
3054 return m_zoomMultiplier;
3057 HRESULT STDMETHODCALLTYPE WebView::setApplicationNameForUserAgent(
3058 /* [in] */ BSTR applicationName)
3060 m_applicationName = String(applicationName, SysStringLen(applicationName));
3061 m_userAgentStandard = String();
3065 HRESULT STDMETHODCALLTYPE WebView::applicationNameForUserAgent(
3066 /* [retval][out] */ BSTR* applicationName)
3068 *applicationName = SysAllocStringLen(m_applicationName.characters(), m_applicationName.length());
3069 if (!*applicationName && m_applicationName.length())
3070 return E_OUTOFMEMORY;
3074 HRESULT STDMETHODCALLTYPE WebView::setCustomUserAgent(
3075 /* [in] */ BSTR userAgentString)
3077 m_userAgentOverridden = userAgentString;
3078 m_userAgentCustom = String(userAgentString, SysStringLen(userAgentString));
3082 HRESULT STDMETHODCALLTYPE WebView::customUserAgent(
3083 /* [retval][out] */ BSTR* userAgentString)
3085 *userAgentString = 0;
3086 if (!m_userAgentOverridden)
3088 *userAgentString = SysAllocStringLen(m_userAgentCustom.characters(), m_userAgentCustom.length());
3089 if (!*userAgentString && m_userAgentCustom.length())
3090 return E_OUTOFMEMORY;
3094 HRESULT STDMETHODCALLTYPE WebView::userAgentForURL(
3095 /* [in] */ BSTR url,
3096 /* [retval][out] */ BSTR* userAgent)
3098 String userAgentString = userAgentForKURL(MarshallingHelpers::BSTRToKURL(url));
3099 *userAgent = SysAllocStringLen(userAgentString.characters(), userAgentString.length());
3100 if (!*userAgent && userAgentString.length())
3101 return E_OUTOFMEMORY;
3105 HRESULT STDMETHODCALLTYPE WebView::supportsTextEncoding(
3106 /* [retval][out] */ BOOL* supports)
3112 HRESULT STDMETHODCALLTYPE WebView::setCustomTextEncodingName(
3113 /* [in] */ BSTR encodingName)
3120 hr = customTextEncodingName(&oldEncoding);
3124 if (oldEncoding != encodingName && (!oldEncoding || !encodingName || wcscmp(oldEncoding, encodingName))) {
3125 if (Frame* coreFrame = core(m_mainFrame))
3126 coreFrame->loader()->reloadWithOverrideEncoding(String(encodingName, SysStringLen(encodingName)));
3132 HRESULT STDMETHODCALLTYPE WebView::customTextEncodingName(
3133 /* [retval][out] */ BSTR* encodingName)
3136 COMPtr<IWebDataSource> dataSource;
3137 COMPtr<WebDataSource> dataSourceImpl;
3143 if (FAILED(m_mainFrame->provisionalDataSource(&dataSource)) || !dataSource) {
3144 hr = m_mainFrame->dataSource(&dataSource);
3145 if (FAILED(hr) || !dataSource)
3149 hr = dataSource->QueryInterface(IID_WebDataSource, (void**)&dataSourceImpl);
3153 BString str = dataSourceImpl->documentLoader()->overrideEncoding();
3158 *encodingName = SysAllocStringLen(m_overrideEncoding.characters(), m_overrideEncoding.length());
3160 if (!*encodingName && m_overrideEncoding.length())
3161 return E_OUTOFMEMORY;
3166 HRESULT STDMETHODCALLTYPE WebView::setMediaStyle(
3167 /* [in] */ BSTR /*media*/)
3169 ASSERT_NOT_REACHED();
3173 HRESULT STDMETHODCALLTYPE WebView::mediaStyle(
3174 /* [retval][out] */ BSTR* /*media*/)
3176 ASSERT_NOT_REACHED();
3180 HRESULT STDMETHODCALLTYPE WebView::stringByEvaluatingJavaScriptFromString(
3181 /* [in] */ BSTR script, // assumes input does not have "JavaScript" at the begining.
3182 /* [retval][out] */ BSTR* result)
3185 ASSERT_NOT_REACHED();
3191 Frame* coreFrame = core(m_mainFrame);
3195 JSC::JSValue scriptExecutionResult = coreFrame->script()->executeScript(WTF::String(script), true).jsValue();
3196 if (!scriptExecutionResult)
3198 else if (scriptExecutionResult.isString()) {
3199 JSC::ExecState* exec = coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec();
3200 JSC::JSLockHolder lock(exec);
3201 *result = BString(ustringToString(scriptExecutionResult.getString(exec)));
3207 HRESULT STDMETHODCALLTYPE WebView::windowScriptObject(
3208 /* [retval][out] */ IWebScriptObject** /*webScriptObject*/)
3210 ASSERT_NOT_REACHED();
3214 HRESULT STDMETHODCALLTYPE WebView::setPreferences(
3215 /* [in] */ IWebPreferences* prefs)
3218 prefs = WebPreferences::sharedStandardPreferences();
3220 if (m_preferences == prefs)
3223 COMPtr<WebPreferences> webPrefs(Query, prefs);
3225 return E_NOINTERFACE;
3226 webPrefs->willAddToWebView();
3228 COMPtr<WebPreferences> oldPrefs = m_preferences;
3230 IWebNotificationCenter* nc = WebNotificationCenter::defaultCenterInternal();
3231 nc->removeObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
3233 BSTR identifier = 0;
3234 oldPrefs->identifier(&identifier);
3235 oldPrefs->didRemoveFromWebView();
3236 oldPrefs = 0; // Make sure we release the reference, since WebPreferences::removeReferenceForIdentifier will check for last reference to WebPreferences
3238 m_preferences = webPrefs;
3241 WebPreferences::removeReferenceForIdentifier(identifier);
3242 SysFreeString(identifier);
3245 nc->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
3247 m_preferences->postPreferencesChangesNotification();
3252 HRESULT STDMETHODCALLTYPE WebView::preferences(
3253 /* [retval][out] */ IWebPreferences** prefs)
3257 *prefs = m_preferences.get();
3259 m_preferences->AddRef();
3263 HRESULT STDMETHODCALLTYPE WebView::setPreferencesIdentifier(
3264 /* [in] */ BSTR /*anIdentifier*/)
3266 ASSERT_NOT_REACHED();
3270 HRESULT STDMETHODCALLTYPE WebView::preferencesIdentifier(
3271 /* [retval][out] */ BSTR* /*anIdentifier*/)
3273 ASSERT_NOT_REACHED();
3277 static void systemParameterChanged(WPARAM parameter)
3280 if (parameter == SPI_SETFONTSMOOTHING || parameter == SPI_SETFONTSMOOTHINGTYPE || parameter == SPI_SETFONTSMOOTHINGCONTRAST || parameter == SPI_SETFONTSMOOTHINGORIENTATION)
3281 wkSystemFontSmoothingChanged();
3285 void WebView::windowReceivedMessage(HWND, UINT message, WPARAM wParam, LPARAM)
3289 updateActiveStateSoon();
3291 deleteBackingStoreSoon();
3293 case WM_SETTINGCHANGE:
3294 systemParameterChanged(wParam);
3299 void WebView::updateActiveStateSoon() const
3301 // This function is called while processing the WM_NCACTIVATE message.
3302 // While processing WM_NCACTIVATE when we are being deactivated, GetActiveWindow() will
3303 // still return our window. If we were to call updateActiveState() in that case, we would
3304 // wrongly think that we are still the active window. To work around this, we update our
3305 // active state after a 0-delay timer fires, at which point GetActiveWindow() will return
3306 // the newly-activated window.
3308 SetTimer(m_viewWindow, UpdateActiveStateTimer, 0, 0);
3311 void WebView::deleteBackingStoreSoon()
3313 if (pendingDeleteBackingStoreSet.size() > 2) {
3314 Vector<WebView*> views;
3315 HashSet<WebView*>::iterator end = pendingDeleteBackingStoreSet.end();
3316 for (HashSet<WebView*>::iterator it = pendingDeleteBackingStoreSet.begin(); it != end; ++it)
3318 for (int i = 0; i < views.size(); ++i)
3319 views[i]->deleteBackingStore();
3320 ASSERT(pendingDeleteBackingStoreSet.isEmpty());
3323 pendingDeleteBackingStoreSet.add(this);
3324 m_deleteBackingStoreTimerActive = true;
3325 SetTimer(m_viewWindow, DeleteBackingStoreTimer, delayBeforeDeletingBackingStoreMsec, 0);
3328 void WebView::cancelDeleteBackingStoreSoon()
3330 if (!m_deleteBackingStoreTimerActive)
3332 pendingDeleteBackingStoreSet.remove(this);
3333 m_deleteBackingStoreTimerActive = false;
3334 KillTimer(m_viewWindow, DeleteBackingStoreTimer);
3337 HRESULT STDMETHODCALLTYPE WebView::setHostWindow(
3338 /* [in] */ OLE_HANDLE oleWindow)
3340 HWND window = (HWND)(ULONG64)oleWindow;
3343 SetParent(m_viewWindow, window);
3344 else if (!isBeingDestroyed()) {
3345 // Turn the WebView into a message-only window so it will no longer be a child of the
3346 // old host window and will be hidden from screen. We only do this when
3347 // isBeingDestroyed() is false because doing this while handling WM_DESTROY can leave
3348 // m_viewWindow in a weird state (see <http://webkit.org/b/29337>).
3349 SetParent(m_viewWindow, HWND_MESSAGE);
3353 m_hostWindow = window;
3355 windowAncestryDidChange();
3360 HRESULT STDMETHODCALLTYPE WebView::hostWindow(
3361 /* [retval][out] */ OLE_HANDLE* window)
3363 *window = (OLE_HANDLE)(ULONG64)m_hostWindow;
3368 static Frame *incrementFrame(Frame *curr, bool forward, bool wrapFlag)
3371 ? curr->tree()->traverseNextWithWrap(wrapFlag)
3372 : curr->tree()->traversePreviousWithWrap(wrapFlag);
3375 HRESULT STDMETHODCALLTYPE WebView::searchFor(
3376 /* [in] */ BSTR str,
3377 /* [in] */ BOOL forward,
3378 /* [in] */ BOOL caseFlag,
3379 /* [in] */ BOOL wrapFlag,
3380 /* [retval][out] */ BOOL* found)
3383 return E_INVALIDARG;
3385 if (!m_page || !m_page->mainFrame())
3386 return E_UNEXPECTED;
3388 if (!str || !SysStringLen(str))
3389 return E_INVALIDARG;
3391 *found = m_page->findString(String(str, SysStringLen(str)), caseFlag ? TextCaseSensitive : TextCaseInsensitive, forward ? FindDirectionForward : FindDirectionBackward, wrapFlag);
3395 bool WebView::active()
3397 HWND activeWindow = GetActiveWindow();
3398 if (usesLayeredWindow() && activeWindow == m_viewWindow)
3401 return (activeWindow && m_topLevelParent == findTopLevelParent(activeWindow));
3404 void WebView::updateActiveState()
3406 m_page->focusController()->setActive(active());
3409 HRESULT STDMETHODCALLTYPE WebView::updateFocusedAndActiveState()
3411 updateActiveState();
3413 bool active = m_page->focusController()->isActive();
3414 Frame* mainFrame = m_page->mainFrame();
3415 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
3416 mainFrame->selection()->setFocused(active && mainFrame == focusedFrame);
3421 HRESULT STDMETHODCALLTYPE WebView::executeCoreCommandByName(BSTR bName, BSTR bValue)
3423 String name(bName, SysStringLen(bName));
3424 String value(bValue, SysStringLen(bValue));
3426 m_page->focusController()->focusedOrMainFrame()->editor()->command(name).execute(value);
3431 HRESULT STDMETHODCALLTYPE WebView::clearMainFrameName()
3433 m_page->mainFrame()->tree()->clearName();
3438 HRESULT STDMETHODCALLTYPE WebView::markAllMatchesForText(
3439 BSTR str, BOOL caseSensitive, BOOL highlight, UINT limit, UINT* matches)
3442 return E_INVALIDARG;
3444 if (!m_page || !m_page->mainFrame())
3445 return E_UNEXPECTED;
3447 if (!str || !SysStringLen(str))
3448 return E_INVALIDARG;
3450 *matches = m_page->markAllMatchesForText(String(str, SysStringLen(str)), caseSensitive ? TextCaseSensitive : TextCaseInsensitive, highlight, limit);
3454 HRESULT STDMETHODCALLTYPE WebView::unmarkAllTextMatches()
3456 if (!m_page || !m_page->mainFrame())
3457 return E_UNEXPECTED;
3459 m_page->unmarkAllTextMatches();
3463 HRESULT STDMETHODCALLTYPE WebView::rectsForTextMatches(
3464 IEnumTextMatches** pmatches)
3466 Vector<IntRect> allRects;
3467 WebCore::Frame* frame = m_page->mainFrame();
3469 if (Document* document = frame->document()) {
3470 IntRect visibleRect = frame->view()->visibleContentRect();
3471 Vector<IntRect> frameRects = document->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
3472 IntPoint frameOffset(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height());
3473 frameOffset = frame->view()->convertToContainingWindow(frameOffset);
3475 Vector<IntRect>::iterator end = frameRects.end();
3476 for (Vector<IntRect>::iterator it = frameRects.begin(); it < end; it++) {
3477 it->intersect(visibleRect);
3478 it->move(frameOffset.x(), frameOffset.y());
3479 allRects.append(*it);
3482 frame = incrementFrame(frame, true, false);
3485 return createMatchEnumerator(&allRects, pmatches);
3488 HRESULT STDMETHODCALLTYPE WebView::generateSelectionImage(BOOL forceWhiteText, OLE_HANDLE* hBitmap)
3492 WebCore::Frame* frame = m_page->focusController()->focusedOrMainFrame();
3495 HBITMAP bitmap = imageFromSelection(frame, forceWhiteText ? TRUE : FALSE);
3496 *hBitmap = (OLE_HANDLE)(ULONG64)bitmap;
3502 HRESULT STDMETHODCALLTYPE WebView::selectionRect(RECT* rc)
3504 WebCore::Frame* frame = m_page->focusController()->focusedOrMainFrame();
3507 IntRect ir = enclosingIntRect(frame->selection()->bounds());
3508 ir = frame->view()->convertToContainingWindow(ir);
3509 ir.move(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height());
3512 rc->bottom = rc->top + ir.height();
3513 rc->right = rc->left + ir.width();
3519 HRESULT STDMETHODCALLTYPE WebView::registerViewClass(
3520 /* [in] */ IWebDocumentView* /*view*/,
3521 /* [in] */ IWebDocumentRepresentation* /*representation*/,
3522 /* [in] */ BSTR /*forMIMEType*/)
3524 ASSERT_NOT_REACHED();
3528 HRESULT STDMETHODCALLTYPE WebView::setGroupName(
3529 /* [in] */ BSTR groupName)
3533 m_page->setGroupName(String(groupName, SysStringLen(groupName)));
3537 HRESULT STDMETHODCALLTYPE WebView::groupName(
3538 /* [retval][out] */ BSTR* groupName)
3543 String groupNameString = m_page->groupName();
3544 *groupName = SysAllocStringLen(groupNameString.characters(), groupNameString.length());
3545 if (!*groupName && groupNameString.length())
3546 return E_OUTOFMEMORY;
3550 HRESULT STDMETHODCALLTYPE WebView::estimatedProgress(
3551 /* [retval][out] */ double* estimatedProgress)
3553 *estimatedProgress = m_page->progress()->estimatedProgress();
3557 HRESULT STDMETHODCALLTYPE WebView::isLoading(
3558 /* [retval][out] */ BOOL* isLoading)
3560 COMPtr<IWebDataSource> dataSource;
3561 COMPtr<IWebDataSource> provisionalDataSource;
3571 if (SUCCEEDED(m_mainFrame->dataSource(&dataSource)))
3572 dataSource->isLoading(isLoading);
3577 if (SUCCEEDED(m_mainFrame->provisionalDataSource(&provisionalDataSource)))
3578 provisionalDataSource->isLoading(isLoading);
3582 HRESULT STDMETHODCALLTYPE WebView::elementAtPoint(
3583 /* [in] */ LPPOINT point,
3584 /* [retval][out] */ IPropertyBag** elementDictionary)
3586 if (!elementDictionary) {
3587 ASSERT_NOT_REACHED();
3591 *elementDictionary = 0;
3593 Frame* frame = core(m_mainFrame);
3597 IntPoint webCorePoint = IntPoint(point->x, point->y);
3598 HitTestResult result = HitTestResult(webCorePoint);
3599 if (frame->contentRenderer())
3600 result = frame->eventHandler()->hitTestResultAtPoint(webCorePoint, false);
3601 *elementDictionary = WebElementPropertyBag::createInstance(result);
3605 HRESULT STDMETHODCALLTYPE WebView::pasteboardTypesForSelection(
3606 /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
3608 ASSERT_NOT_REACHED();
3612 HRESULT STDMETHODCALLTYPE WebView::writeSelectionWithPasteboardTypes(
3613 /* [size_is][in] */ BSTR* /*types*/,
3614 /* [in] */ int /*cTypes*/,
3615 /* [in] */ IDataObject* /*pasteboard*/)
3617 ASSERT_NOT_REACHED();
3621 HRESULT STDMETHODCALLTYPE WebView::pasteboardTypesForElement(
3622 /* [in] */ IPropertyBag* /*elementDictionary*/,
3623 /* [retval][out] */ IEnumVARIANT** /*enumVariant*/)
3625 ASSERT_NOT_REACHED();
3629 HRESULT STDMETHODCALLTYPE WebView::writeElement(
3630 /* [in] */ IPropertyBag* /*elementDictionary*/,
3631 /* [size_is][in] */ BSTR* /*withPasteboardTypes*/,
3632 /* [in] */ int /*cWithPasteboardTypes*/,
3633 /* [in] */ IDataObject* /*pasteboard*/)
3635 ASSERT_NOT_REACHED();
3639 HRESULT STDMETHODCALLTYPE WebView::selectedText(
3640 /* [out, retval] */ BSTR* text)
3643 ASSERT_NOT_REACHED();
3649 Frame* focusedFrame = (m_page && m_page->focusController()) ? m_page->focusController()->focusedOrMainFrame() : 0;
3653 String frameSelectedText = focusedFrame->editor()->selectedText();
3654 *text = SysAllocStringLen(frameSelectedText.characters(), frameSelectedText.length());
3655 if (!*text && frameSelectedText.length())
3656 return E_OUTOFMEMORY;
3660 HRESULT STDMETHODCALLTYPE WebView::centerSelectionInVisibleArea(
3661 /* [in] */ IUnknown* /* sender */)
3663 Frame* coreFrame = core(m_mainFrame);
3667 coreFrame->selection()->revealSelection(ScrollAlignment::alignCenterAlways);
3672 HRESULT STDMETHODCALLTYPE WebView::moveDragCaretToPoint(
3673 /* [in] */ LPPOINT /*point*/)
3675 ASSERT_NOT_REACHED();
3679 HRESULT STDMETHODCALLTYPE WebView::removeDragCaret( void)
3681 ASSERT_NOT_REACHED();
3685 HRESULT STDMETHODCALLTYPE WebView::setDrawsBackground(
3686 /* [in] */ BOOL /*drawsBackground*/)
3688 ASSERT_NOT_REACHED();
3692 HRESULT STDMETHODCALLTYPE WebView::drawsBackground(
3693 /* [retval][out] */ BOOL* /*drawsBackground*/)
3695 ASSERT_NOT_REACHED();
3699 HRESULT STDMETHODCALLTYPE WebView::setMainFrameURL(
3700 /* [in] */ BSTR /*urlString*/)
3702 ASSERT_NOT_REACHED();
3706 HRESULT STDMETHODCALLTYPE WebView::mainFrameURL(
3707 /* [retval][out] */ BSTR* urlString)
3715 COMPtr<IWebDataSource> dataSource;
3717 if (FAILED(m_mainFrame->provisionalDataSource(&dataSource))) {
3718 if (FAILED(m_mainFrame->dataSource(&dataSource)))
3727 COMPtr<IWebMutableURLRequest> request;
3728 if (FAILED(dataSource->request(&request)) || !request)
3731 if (FAILED(request->URL(urlString)))
3737 HRESULT STDMETHODCALLTYPE WebView::mainFrameDocument(
3738 /* [retval][out] */ IDOMDocument** document)
3744 return m_mainFrame->DOMDocument(document);
3747 HRESULT STDMETHODCALLTYPE WebView::mainFrameTitle(
3748 /* [retval][out] */ BSTR* /*title*/)
3750 ASSERT_NOT_REACHED();
3754 HRESULT STDMETHODCALLTYPE WebView::mainFrameIcon(
3755 /* [retval][out] */ OLE_HANDLE* /*hBitmap*/)
3757 ASSERT_NOT_REACHED();
3761 HRESULT STDMETHODCALLTYPE WebView::registerURLSchemeAsLocal(
3762 /* [in] */ BSTR scheme)
3767 SchemeRegistry::registerURLSchemeAsLocal(String(scheme, ::SysStringLen(scheme)));
3772 // IWebIBActions ---------------------------------------------------------------
3774 HRESULT STDMETHODCALLTYPE WebView::takeStringURLFrom(
3775 /* [in] */ IUnknown* /*sender*/)
3777 ASSERT_NOT_REACHED();
3781 HRESULT STDMETHODCALLTYPE WebView::stopLoading(
3782 /* [in] */ IUnknown* /*sender*/)
3787 return m_mainFrame->stopLoading();
3790 HRESULT STDMETHODCALLTYPE WebView::reload(
3791 /* [in] */ IUnknown* /*sender*/)
3796 return m_mainFrame->reload();
3799 HRESULT STDMETHODCALLTYPE WebView::canGoBack(
3800 /* [in] */ IUnknown* /*sender*/,
3801 /* [retval][out] */ BOOL* result)
3803 *result = !!(m_page->backForwardList()->backItem() && !m_page->defersLoading());
3807 HRESULT STDMETHODCALLTYPE WebView::goBack(
3808 /* [in] */ IUnknown* /*sender*/)
3810 ASSERT_NOT_REACHED();
3814 HRESULT STDMETHODCALLTYPE WebView::canGoForward(
3815 /* [in] */ IUnknown* /*sender*/,
3816 /* [retval][out] */ BOOL* result)
3818 *result = !!(m_page->backForwardList()->forwardItem() && !m_page->defersLoading());
3822 HRESULT STDMETHODCALLTYPE WebView::goForward(
3823 /* [in] */ IUnknown* /*sender*/)
3825 ASSERT_NOT_REACHED();
3829 // FIXME: This code should move into WebCore so it can be shared by all the WebKits.
3830 #define MinimumZoomMultiplier 0.5f
3831 #define MaximumZoomMultiplier 3.0f
3832 #define ZoomMultiplierRatio 1.2f
3834 HRESULT STDMETHODCALLTYPE WebView::canMakeTextLarger(
3835 /* [in] */ IUnknown* /*sender*/,
3836 /* [retval][out] */ BOOL* result)
3838 bool canGrowMore = canZoomIn(m_zoomsTextOnly);
3839 *result = canGrowMore ? TRUE : FALSE;
3843 HRESULT STDMETHODCALLTYPE WebView::canZoomPageIn(
3844 /* [in] */ IUnknown* /*sender*/,
3845 /* [retval][out] */ BOOL* result)
3847 bool canGrowMore = canZoomIn(false);
3848 *result = canGrowMore ? TRUE : FALSE;
3852 bool WebView::canZoomIn(bool isTextOnly)
3854 return zoomMultiplier(isTextOnly) * ZoomMultiplierRatio < MaximumZoomMultiplier;
3857 HRESULT STDMETHODCALLTYPE WebView::makeTextLarger(
3858 /* [in] */ IUnknown* /*sender*/)
3860 return zoomIn(m_zoomsTextOnly);
3863 HRESULT STDMETHODCALLTYPE WebView::zoomPageIn(
3864 /* [in] */ IUnknown* /*sender*/)
3866 return zoomIn(false);
3869 HRESULT WebView::zoomIn(bool isTextOnly)
3871 if (!canZoomIn(isTextOnly))
3873 setZoomMultiplier(zoomMultiplier(isTextOnly) * ZoomMultiplierRatio, isTextOnly);
3877 HRESULT STDMETHODCALLTYPE WebView::canMakeTextSmaller(
3878 /* [in] */ IUnknown* /*sender*/,
3879 /* [retval][out] */ BOOL* result)
3881 bool canShrinkMore = canZoomOut(m_zoomsTextOnly);
3882 *result = canShrinkMore ? TRUE : FALSE;
3886 HRESULT STDMETHODCALLTYPE WebView::canZoomPageOut(
3887 /* [in] */ IUnknown* /*sender*/,
3888 /* [retval][out] */ BOOL* result)
3890 bool canShrinkMore = canZoomOut(false);
3891 *result = canShrinkMore ? TRUE : FALSE;
3895 bool WebView::canZoomOut(bool isTextOnly)
3897 return zoomMultiplier(isTextOnly) / ZoomMultiplierRatio > MinimumZoomMultiplier;
3900 HRESULT STDMETHODCALLTYPE WebView::makeTextSmaller(
3901 /* [in] */ IUnknown* /*sender*/)
3903 return zoomOut(m_zoomsTextOnly);
3906 HRESULT STDMETHODCALLTYPE WebView::zoomPageOut(
3907 /* [in] */ IUnknown* /*sender*/)
3909 return zoomOut(false);
3912 HRESULT WebView::zoomOut(bool isTextOnly)
3914 if (!canZoomOut(isTextOnly))
3916 setZoomMultiplier(zoomMultiplier(isTextOnly) / ZoomMultiplierRatio, isTextOnly);
3920 HRESULT STDMETHODCALLTYPE WebView::canMakeTextStandardSize(
3921 /* [in] */ IUnknown* /*sender*/,
3922 /* [retval][out] */ BOOL* result)
3924 // 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.
3925 bool notAlreadyStandard = canResetZoom(true);
3926 *result = notAlreadyStandard ? TRUE : FALSE;
3930 HRESULT STDMETHODCALLTYPE WebView::canResetPageZoom(
3931 /* [in] */ IUnknown* /*sender*/,
3932 /* [retval][out] */ BOOL* result)
3934 bool notAlreadyStandard = canResetZoom(false);
3935 *result = notAlreadyStandard ? TRUE : FALSE;
3939 bool WebView::canResetZoom(bool isTextOnly)
3941 return zoomMultiplier(isTextOnly) != 1.0f;
3944 HRESULT STDMETHODCALLTYPE WebView::makeTextStandardSize(
3945 /* [in] */ IUnknown* /*sender*/)
3947 return resetZoom(true);
3950 HRESULT STDMETHODCALLTYPE WebView::resetPageZoom(
3951 /* [in] */ IUnknown* /*sender*/)
3953 return resetZoom(false);
3956 HRESULT WebView::resetZoom(bool isTextOnly)
3958 if (!canResetZoom(isTextOnly))
3960 setZoomMultiplier(1.0f, isTextOnly);
3964 HRESULT STDMETHODCALLTYPE WebView::toggleContinuousSpellChecking(
3965 /* [in] */ IUnknown* /*sender*/)
3969 if (FAILED(hr = isContinuousSpellCheckingEnabled(&enabled)))
3971 return setContinuousSpellCheckingEnabled(enabled ? FALSE : TRUE);
3974 HRESULT STDMETHODCALLTYPE WebView::toggleSmartInsertDelete(
3975 /* [in] */ IUnknown* /*sender*/)
3977 BOOL enabled = FALSE;
3978 HRESULT hr = smartInsertDeleteEnabled(&enabled);
3982 return setSmartInsertDeleteEnabled(enabled ? FALSE : TRUE);
3985 HRESULT STDMETHODCALLTYPE WebView::toggleGrammarChecking(
3986 /* [in] */ IUnknown* /*sender*/)
3989 HRESULT hr = isGrammarCheckingEnabled(&enabled);
3993 return setGrammarCheckingEnabled(enabled ? FALSE : TRUE);
3996 HRESULT STDMETHODCALLTYPE WebView::reloadFromOrigin(
3997 /* [in] */ IUnknown* /*sender*/)
4002 return m_mainFrame->reloadFromOrigin();
4005 // IWebViewCSS -----------------------------------------------------------------
4007 HRESULT STDMETHODCALLTYPE WebView::computedStyleForElement(
4008 /* [in] */ IDOMElement* /*element*/,
4009 /* [in] */ BSTR /*pseudoElement*/,
4010 /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
4012 ASSERT_NOT_REACHED();
4016 // IWebViewEditing -------------------------------------------------------------
4018 HRESULT STDMETHODCALLTYPE WebView::editableDOMRangeForPoint(
4019 /* [in] */ LPPOINT /*point*/,
4020 /* [retval][out] */ IDOMRange** /*range*/)
4022 ASSERT_NOT_REACHED();
4026 HRESULT STDMETHODCALLTYPE WebView::setSelectedDOMRange(
4027 /* [in] */ IDOMRange* /*range*/,
4028 /* [in] */ WebSelectionAffinity /*affinity*/)
4030 ASSERT_NOT_REACHED();
4034 HRESULT STDMETHODCALLTYPE WebView::selectedDOMRange(
4035 /* [retval][out] */ IDOMRange** /*range*/)
4037 ASSERT_NOT_REACHED();
4041 HRESULT STDMETHODCALLTYPE WebView::selectionAffinity(
4042 /* [retval][out][retval][out] */ WebSelectionAffinity* /*affinity*/)
4044 ASSERT_NOT_REACHED();
4048 HRESULT STDMETHODCALLTYPE WebView::setEditable(
4049 /* [in] */ BOOL /*flag*/)
4051 ASSERT_NOT_REACHED();
4055 HRESULT STDMETHODCALLTYPE WebView::isEditable(
4056 /* [retval][out] */ BOOL* /*isEditable*/)
4058 ASSERT_NOT_REACHED();
4062 HRESULT STDMETHODCALLTYPE WebView::setTypingStyle(
4063 /* [in] */ IDOMCSSStyleDeclaration* /*style*/)
4065 ASSERT_NOT_REACHED();
4069 HRESULT STDMETHODCALLTYPE WebView::typingStyle(
4070 /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
4072 ASSERT_NOT_REACHED();
4076 HRESULT STDMETHODCALLTYPE WebView::setSmartInsertDeleteEnabled(
4077 /* [in] */ BOOL flag)
4079 m_smartInsertDeleteEnabled = !!flag;
4080 if (m_smartInsertDeleteEnabled)
4081 setSelectTrailingWhitespaceEnabled(false);
4085 HRESULT STDMETHODCALLTYPE WebView::smartInsertDeleteEnabled(
4086 /* [retval][out] */ BOOL* enabled)
4088 *enabled = m_smartInsertDeleteEnabled ? TRUE : FALSE;
4092 HRESULT STDMETHODCALLTYPE WebView::setSelectTrailingWhitespaceEnabled(
4093 /* [in] */ BOOL flag)
4095 m_selectTrailingWhitespaceEnabled = !!flag;
4096 if (m_selectTrailingWhitespaceEnabled)
4097 setSmartInsertDeleteEnabled(false);
4101 HRESULT STDMETHODCALLTYPE WebView::isSelectTrailingWhitespaceEnabled(
4102 /* [retval][out] */ BOOL* enabled)
4104 *enabled = m_selectTrailingWhitespaceEnabled ? TRUE : FALSE;
4108 HRESULT STDMETHODCALLTYPE WebView::setContinuousSpellCheckingEnabled(
4109 /* [in] */ BOOL flag)
4111 if (continuousSpellCheckingEnabled != !!flag) {
4112 continuousSpellCheckingEnabled = !!flag;
4113 COMPtr<IWebPreferences> prefs;
4114 if (SUCCEEDED(preferences(&prefs)))
4115 prefs->setContinuousSpellCheckingEnabled(flag);
4118 BOOL spellCheckingEnabled;
4119 if (SUCCEEDED(isContinuousSpellCheckingEnabled(&spellCheckingEnabled)) && spellCheckingEnabled)
4120 preflightSpellChecker();
4122 m_mainFrame->unmarkAllMisspellings();
4127 HRESULT STDMETHODCALLTYPE WebView::isContinuousSpellCheckingEnabled(
4128 /* [retval][out] */ BOOL* enabled)
4130 *enabled = (continuousSpellCheckingEnabled && continuousCheckingAllowed()) ? TRUE : FALSE;
4134 HRESULT STDMETHODCALLTYPE WebView::spellCheckerDocumentTag(
4135 /* [retval][out] */ int* tag)
4137 // we just use this as a flag to indicate that we've spell checked the document
4138 // and need to close the spell checker out when the view closes.
4140 m_hasSpellCheckerDocumentTag = true;
4144 static COMPtr<IWebEditingDelegate> spellingDelegateForTimer;
4146 static void preflightSpellCheckerNow()
4148 spellingDelegateForTimer->preflightChosenSpellServer();
4149 spellingDelegateForTimer = 0;
4152 static void CALLBACK preflightSpellCheckerTimerCallback(HWND, UINT, UINT_PTR id, DWORD)
4155 preflightSpellCheckerNow();
4158 void WebView::preflightSpellChecker()
4160 // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch.
4161 if (!m_editingDelegate)
4165 spellingDelegateForTimer = m_editingDelegate;
4166 if (SUCCEEDED(m_editingDelegate->sharedSpellCheckerExists(&exists)) && exists)
4167 preflightSpellCheckerNow();
4169 ::SetTimer(0, 0, 2000, preflightSpellCheckerTimerCallback);
4172 bool WebView::continuousCheckingAllowed()
4174 static bool allowContinuousSpellChecking = true;
4175 static bool readAllowContinuousSpellCheckingDefault = false;
4176 if (!readAllowContinuousSpellCheckingDefault) {
4177 COMPtr<IWebPreferences> prefs;
4178 if (SUCCEEDED(preferences(&prefs))) {
4180 prefs->allowContinuousSpellChecking(&allowed);
4181 allowContinuousSpellChecking = !!allowed;
4183 readAllowContinuousSpellCheckingDefault = true;
4185 return allowContinuousSpellChecking;
4188 HRESULT STDMETHODCALLTYPE WebView::undoManager(
4189 /* [retval][out] */ IWebUndoManager** /*manager*/)
4191 ASSERT_NOT_REACHED();
4195 HRESULT STDMETHODCALLTYPE WebView::setEditingDelegate(
4196 /* [in] */ IWebEditingDelegate* d)
4198 m_editingDelegate = d;
4202 HRESULT STDMETHODCALLTYPE WebView::editingDelegate(
4203 /* [retval][out] */ IWebEditingDelegate** d)
4206 ASSERT_NOT_REACHED();
4210 *d = m_editingDelegate.get();
4218 HRESULT STDMETHODCALLTYPE WebView::styleDeclarationWithText(
4219 /* [in] */ BSTR /*text*/,
4220 /* [retval][out] */ IDOMCSSStyleDeclaration** /*style*/)
4222 ASSERT_NOT_REACHED();
4226 HRESULT STDMETHODCALLTYPE WebView::hasSelectedRange(
4227 /* [retval][out] */ BOOL* hasSelectedRange)
4229 *hasSelectedRange = m_page->mainFrame()->selection()->isRange();
4233 HRESULT STDMETHODCALLTYPE WebView::cutEnabled(
4234 /* [retval][out] */ BOOL* enabled)
4236 Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
4237 *enabled = editor->canCut() || editor->canDHTMLCut();
4241 HRESULT STDMETHODCALLTYPE WebView::copyEnabled(
4242 /* [retval][out] */ BOOL* enabled)
4244 Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
4245 *enabled = editor->canCopy() || editor->canDHTMLCopy();
4249 HRESULT STDMETHODCALLTYPE WebView::pasteEnabled(
4250 /* [retval][out] */ BOOL* enabled)
4252 Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
4253 *enabled = editor->canPaste() || editor->canDHTMLPaste();
4257 HRESULT STDMETHODCALLTYPE WebView::deleteEnabled(
4258 /* [retval][out] */ BOOL* enabled)
4260 *enabled = m_page->focusController()->focusedOrMainFrame()->editor()->canDelete();
4264 HRESULT STDMETHODCALLTYPE WebView::editingEnabled(
4265 /* [retval][out] */ BOOL* enabled)
4267 *enabled = m_page->focusController()->focusedOrMainFrame()->editor()->canEdit();
4271 HRESULT STDMETHODCALLTYPE WebView::isGrammarCheckingEnabled(
4272 /* [retval][out] */ BOOL* enabled)
4274 *enabled = grammarCheckingEnabled ? TRUE : FALSE;
4278 HRESULT STDMETHODCALLTYPE WebView::setGrammarCheckingEnabled(
4281 if (!m_editingDelegate) {
4282 LOG_ERROR("No NSSpellChecker");
4286 if (grammarCheckingEnabled == !!enabled)
4289 grammarCheckingEnabled = !!enabled;
4290 COMPtr<IWebPreferences> prefs;
4291 if (SUCCEEDED(preferences(&prefs)))
4292 prefs->setGrammarCheckingEnabled(enabled);
4294 m_editingDelegate->updateGrammar();
4296 // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here
4297 // because grammar checking only occurs on code paths that already preflight spell checking appropriately.
4299 BOOL grammarEnabled;
4300 if (SUCCEEDED(isGrammarCheckingEnabled(&grammarEnabled)) && !grammarEnabled)
4301 m_mainFrame->unmarkAllBadGrammar();
4306 // IWebViewUndoableEditing -----------------------------------------------------
4308 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithNode(
4309 /* [in] */ IDOMNode* /*node*/)
4311 ASSERT_NOT_REACHED();
4315 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithText(
4316 /* [in] */ BSTR text)
4318 String textString(text, ::SysStringLen(text));
4319 Position start = m_page->mainFrame()->selection()->selection().start();
4320 m_page->focusController()->focusedOrMainFrame()->editor()->insertText(textString, 0);
4321 m_page->mainFrame()->selection()->setBase(start);
4325 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithMarkupString(
4326 /* [in] */ BSTR /*markupString*/)
4328 ASSERT_NOT_REACHED();
4332 HRESULT STDMETHODCALLTYPE WebView::replaceSelectionWithArchive(
4333 /* [in] */ IWebArchive* /*archive*/)
4335 ASSERT_NOT_REACHED();
4339 HRESULT STDMETHODCALLTYPE WebView::deleteSelection( void)
4341 Editor* editor = m_page->focusController()->focusedOrMainFrame()->editor();
4342 editor->deleteSelectionWithSmartDelete(editor->canSmartCopyOrDelete());
4346 HRESULT STDMETHODCALLTYPE WebView::clearSelection( void)
4348 m_page->focusController()->focusedOrMainFrame()->selection()->clear();
4352 HRESULT STDMETHODCALLTYPE WebView::applyStyle(
4353 /* [in] */ IDOMCSSStyleDeclaration* /*style*/)
4355 ASSERT_NOT_REACHED();
4359 // IWebViewEditingActions ------------------------------------------------------
4361 HRESULT STDMETHODCALLTYPE WebView::copy(
4362 /* [in] */ IUnknown* /*sender*/)
4364 m_page->focusController()->focusedOrMainFrame()->editor()->command("Copy").execute();
4368 HRESULT STDMETHODCALLTYPE WebView::cut(
4369 /* [in] */ IUnknown* /*sender*/)
4371 m_page->focusController()->focusedOrMainFrame()->editor()->command("Cut").execute();
4375 HRESULT STDMETHODCALLTYPE WebView::paste(
4376 /* [in] */ IUnknown* /*sender*/)
4378 m_page->focusController()->focusedOrMainFrame()->editor()->command("Paste").execute();
4382 HRESULT STDMETHODCALLTYPE WebView::copyURL(
4383 /* [in] */ BSTR url)
4385 m_page->focusController()->focusedOrMainFrame()->editor()->copyURL(MarshallingHelpers::BSTRToKURL(url), "");
4390 HRESULT STDMETHODCALLTYPE WebView::copyFont(
4391 /* [in] */ IUnknown* /*sender*/)
4393 ASSERT_NOT_REACHED();
4397 HRESULT STDMETHODCALLTYPE WebView::pasteFont(
4398 /* [in] */ IUnknown* /*sender*/)
4400 ASSERT_NOT_REACHED();
4404 HRESULT STDMETHODCALLTYPE WebView::delete_(
4405 /* [in] */ IUnknown* /*sender*/)
4407 m_page->focusController()->focusedOrMainFrame()->editor()->command("Delete").execute();
4411 HRESULT STDMETHODCALLTYPE WebView::pasteAsPlainText(
4412 /* [in] */ IUnknown* /*sender*/)
4414 ASSERT_NOT_REACHED();
4418 HRESULT STDMETHODCALLTYPE WebView::pasteAsRichText(
4419 /* [in] */ IUnknown* /*sender*/)
4421 ASSERT_NOT_REACHED();
4425 HRESULT STDMETHODCALLTYPE WebView::changeFont(
4426 /* [in] */ IUnknown* /*sender*/)
4428 ASSERT_NOT_REACHED();
4432 HRESULT STDMETHODCALLTYPE WebView::changeAttributes(
4433 /* [in] */ IUnknown* /*sender*/)
4435 ASSERT_NOT_REACHED();
4439 HRESULT STDMETHODCALLTYPE WebView::changeDocumentBackgroundColor(
4440 /* [in] */ IUnknown* /*sender*/)
4442 ASSERT_NOT_REACHED();
4446 HRESULT STDMETHODCALLTYPE WebView::changeColor(
4447 /* [in] */ IUnknown* /*sender*/)
4449 ASSERT_NOT_REACHED();
4453 HRESULT STDMETHODCALLTYPE WebView::alignCenter(
4454 /* [in] */ IUnknown* /*sender*/)
4456 ASSERT_NOT_REACHED();
4460 HRESULT STDMETHODCALLTYPE WebView::alignJustified(
4461 /* [in] */ IUnknown* /*sender*/)
4463 ASSERT_NOT_REACHED();
4467 HRESULT STDMETHODCALLTYPE WebView::alignLeft(
4468 /* [in] */ IUnknown* /*sender*/)
4470 ASSERT_NOT_REACHED();
4474 HRESULT STDMETHODCALLTYPE WebView::alignRight(
4475 /* [in] */ IUnknown* /*sender*/)
4477 ASSERT_NOT_REACHED();
4481 HRESULT STDMETHODCALLTYPE WebView::checkSpelling(
4482 /* [in] */ IUnknown* /*sender*/)
4484 if (!m_editingDelegate) {
4485 LOG_ERROR("No NSSpellChecker");
4489 core(m_mainFrame)->editor()->advanceToNextMisspelling();
4493 HRESULT STDMETHODCALLTYPE WebView::showGuessPanel(
4494 /* [in] */ IUnknown* /*sender*/)
4496 if (!m_editingDelegate) {
4497 LOG_ERROR("No NSSpellChecker");
4501 // Post-Tiger, this menu item is a show/hide toggle, to match AppKit. Leave Tiger behavior alone
4502 // to match rest of OS X.
4504 if (SUCCEEDED(m_editingDelegate->spellingUIIsShowing(&showing)) && showing) {
4505 m_editingDelegate->showSpellingUI(FALSE);
4508 core(m_mainFrame)->editor()->advanceToNextMisspelling(true);
4509 m_editingDelegate->showSpellingUI(TRUE);
4513 HRESULT STDMETHODCALLTYPE WebView::performFindPanelAction(
4514 /* [in] */ IUnknown* /*sender*/)
4516 ASSERT_NOT_REACHED();
4520 HRESULT STDMETHODCALLTYPE WebView::startSpeaking(
4521 /* [in] */ IUnknown* /*sender*/)
4523 ASSERT_NOT_REACHED();
4527 HRESULT STDMETHODCALLTYPE WebView::stopSpeaking(
4528 /* [in] */ IUnknown* /*sender*/)
4530 ASSERT_NOT_REACHED();
4534 // IWebNotificationObserver -----------------------------------------------------------------
4536 HRESULT STDMETHODCALLTYPE WebView::onNotify(
4537 /* [in] */ IWebNotification* notification)
4540 HRESULT hr = notification->name(&nameBSTR);
4545 name.adoptBSTR(nameBSTR);
4547 if (!wcscmp(name, WebIconDatabase::iconDatabaseDidAddIconNotification()))
4548 return notifyDidAddIcon(notification);
4550 if (!wcscmp(name, WebPreferences::webPreferencesChangedNotification()))
4551 return notifyPreferencesChanged(notification);
4556 HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification)
4560 COMPtr<IUnknown> unkPrefs;
4561 hr = notification->getObject(&unkPrefs);
4565 COMPtr<IWebPreferences> preferences(Query, unkPrefs);
4567 return E_NOINTERFACE;
4569 ASSERT(preferences == m_preferences);
4575 Settings* settings = m_page->settings();
4577 hr = preferences->cursiveFontFamily(&str);
4580 settings->setCursiveFontFamily(AtomicString(str, SysStringLen(str)));
4583 hr = preferences->defaultFixedFontSize(&size);
4586 settings->setDefaultFixedFontSize(size);
4588 hr = preferences->defaultFontSize(&size);
4591 settings->setDefaultFontSize(size);
4593 hr = preferences->defaultTextEncodingName(&str);
4596 settings->setDefaultTextEncodingName(String(str, SysStringLen(str)));
4599 hr = preferences->fantasyFontFamily(&str);
4602 settings->setFantasyFontFamily(AtomicString(str, SysStringLen(str)));
4605 hr = preferences->fixedFontFamily(&str);
4608 settings->setFixedFontFamily(AtomicString(str, SysStringLen(str)));
4611 #if ENABLE(VIDEO_TRACK)
4612 hr = preferences->shouldDisplaySubtitles(&enabled);
4615 settings->setShouldDisplaySubtitles(enabled);
4617 hr = preferences->shouldDisplayCaptions(&enabled);
4620 settings->setShouldDisplayCaptions(enabled);
4622 hr = preferences->shouldDisplayTextDescriptions(&enabled);
4625 settings->setShouldDisplayTextDescriptions(enabled);
4628 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
4630 hr = prefsPrivate->localStorageDatabasePath(&str);
4633 settings->setLocalStorageDatabasePath(String(str, SysStringLen(str)));
4637 hr = preferences->pictographFontFamily(&str);
4640 settings->setPictographFontFamily(AtomicString(str, SysStringLen(str)));
4643 hr = preferences->isJavaEnabled(&enabled);
4646 settings->setJavaEnabled(!!enabled);
4648 hr = preferences->isJavaScriptEnabled(&enabled);
4651 settings->setScriptEnabled(!!enabled);
4653 hr = preferences->javaScriptCanOpenWindowsAutomatically(&enabled);
4656 settings->setJavaScriptCanOpenWindowsAutomatically(!!enabled);
4658 hr = preferences->minimumFontSize(&size);
4661 settings->setMinimumFontSize(size);
4663 hr = preferences->minimumLogicalFontSize(&size);
4666 settings->setMinimumLogicalFontSize(size);
4668 hr = preferences->arePlugInsEnabled(&enabled);
4671 settings->setPluginsEnabled(!!enabled);
4673 hr = preferences->isCSSRegionsEnabled(&enabled);
4676 settings->setCSSRegionsEnabled(!!enabled);
4678 hr = preferences->privateBrowsingEnabled(&enabled);
4681 settings->setPrivateBrowsingEnabled(!!enabled);
4683 hr = preferences->sansSerifFontFamily(&str);
4686 settings->setSansSerifFontFamily(AtomicString(str, SysStringLen(str)));
4689 hr = preferences->serifFontFamily(&str);
4692 settings->setSerifFontFamily(AtomicString(str, SysStringLen(str)));
4695 hr = preferences->standardFontFamily(&str);
4698 settings->setStandardFontFamily(AtomicString(str, SysStringLen(str)));
4701 hr = preferences->loadsImagesAutomatically(&enabled);
4704 settings->setLoadsImagesAutomatically(!!enabled);
4706 hr = preferences->userStyleSheetEnabled(&enabled);
4710 hr = preferences->userStyleSheetLocation(&str);
4714 RetainPtr<CFStringRef> urlString(AdoptCF, String(str, SysStringLen(str)).createCFString());
4715 RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateWithString(kCFAllocatorDefault, urlString.get(), 0));
4717 // Check if the passed in string is a path and convert it to a URL.
4718 // FIXME: This is a workaround for nightly builds until we can get Safari to pass
4719 // in an URL here. See <rdar://problem/5478378>
4721 DWORD len = SysStringLen(str) + 1;
4723 int result = WideCharToMultiByte(CP_UTF8, 0, str, len, 0, 0, 0, 0);
4724 Vector<UInt8> utf8Path(result);
4725 if (!WideCharToMultiByte(CP_UTF8, 0, str, len, (LPSTR)utf8Path.data(), result, 0, 0))
4728 url.adoptCF(CFURLCreateFromFileSystemRepresentation(0, utf8Path.data(), result - 1, false));
4731 settings->setUserStyleSheetLocation(url.get());
4734 settings->setUserStyleSheetLocation(KURL());
4737 hr = preferences->shouldPrintBackgrounds(&enabled);
4740 settings->setShouldPrintBackgrounds(!!enabled);
4742 hr = preferences->textAreasAreResizable(&enabled);
4745 settings->setTextAreasAreResizable(!!enabled);
4747 WebKitEditableLinkBehavior behavior;
4748 hr = preferences->editableLinkBehavior(&behavior);
4751 settings->setEditableLinkBehavior((EditableLinkBehavior)behavior);
4753 hr = preferences->usesPageCache(&enabled);
4756 settings->setUsesPageCache(!!enabled);
4758 hr = preferences->isDOMPasteAllowed(&enabled);
4761 settings->setDOMPasteAllowed(!!enabled);
4763 hr = preferences->zoomsTextOnly(&enabled);
4767 if (m_zoomsTextOnly != !!enabled)
4768 setZoomMultiplier(m_zoomMultiplier, enabled);
4770 settings->setShowsURLsInToolTips(false);
4772 settings->setForceFTPDirectoryListings(true);
4773 settings->setDeveloperExtrasEnabled(developerExtrasEnabled());
4774 settings->setNeedsSiteSpecificQuirks(s_allowSiteSpecificHacks);
4776 FontSmoothingType smoothingType;
4777 hr = preferences->fontSmoothing(&smoothingType);
4780 settings->setFontRenderingMode(smoothingType != FontSmoothingTypeWindows ? NormalRenderingMode : AlternateRenderingMode);
4782 #if USE(AVFOUNDATION)
4783 hr = preferences->avFoundationEnabled(&enabled);
4786 settings->setAVFoundationEnabled(enabled);
4790 hr = prefsPrivate->authorAndUserStylesEnabled(&enabled);
4793 settings->setAuthorAndUserStylesEnabled(enabled);
4796 hr = prefsPrivate->inApplicationChromeMode(&enabled);
4799 settings->setApplicationChromeMode(enabled);
4801 hr = prefsPrivate->offlineWebApplicationCacheEnabled(&enabled);
4804 settings->setOfflineWebApplicationCacheEnabled(enabled);
4806 #if ENABLE(SQL_DATABASE)
4807 hr = prefsPrivate->databasesEnabled(&enabled);
4810 AbstractDatabase::setIsAvailable(enabled);
4813 hr = prefsPrivate->localStorageEnabled(&enabled);
4816 settings->setLocalStorageEnabled(enabled);
4818 hr = prefsPrivate->experimentalNotificationsEnabled(&enabled);
4821 settings->setExperimentalNotificationsEnabled(enabled);
4823 hr = prefsPrivate->isWebSecurityEnabled(&enabled);
4826 settings->setWebSecurityEnabled(!!enabled);
4828 hr = prefsPrivate->allowUniversalAccessFromFileURLs(&enabled);
4831 settings->setAllowUniversalAccessFromFileURLs(!!enabled);
4833 hr = prefsPrivate->allowFileAccessFromFileURLs(&enabled);
4836 settings->setAllowFileAccessFromFileURLs(!!enabled);
4838 hr = prefsPrivate->javaScriptCanAccessClipboard(&enabled);
4841 settings->setJavaScriptCanAccessClipboard(!!enabled);
4843 hr = prefsPrivate->isXSSAuditorEnabled(&enabled);
4846 settings->setXSSAuditorEnabled(!!enabled);
4848 #if USE(SAFARI_THEME)
4849 hr = prefsPrivate->shouldPaintNativeControls(&enabled);
4852 settings->setShouldPaintNativeControls(!!enabled);
4855 hr = prefsPrivate->shouldUseHighResolutionTimers(&enabled);
4858 settings->setShouldUseHighResolutionTimers(enabled);
4860 hr = prefsPrivate->isFrameFlatteningEnabled(&enabled);
4863 settings->setFrameFlatteningEnabled(enabled);
4865 #if USE(ACCELERATED_COMPOSITING)
4866 hr = prefsPrivate->acceleratedCompositingEnabled(&enabled);
4869 settings->setAcceleratedCompositingEnabled(enabled);
4872 hr = prefsPrivate->showDebugBorders(&enabled);
4875 settings->setShowDebugBorders(enabled);
4877 hr = prefsPrivate->showRepaintCounter(&enabled);
4880 settings->setShowRepaintCounter(enabled);
4882 #if ENABLE(WEB_AUDIO)
4883 settings->setWebAudioEnabled(true);
4884 #endif // ENABLE(WEB_AUDIO)
4887 settings->setWebGLEnabled(true);
4888 #endif // ENABLE(WEBGL)
4890 hr = prefsPrivate->isDNSPrefetchingEnabled(&enabled);
4893 settings->setDNSPrefetchingEnabled(enabled);
4895 hr = prefsPrivate->memoryInfoEnabled(&enabled);
4898 settings->setMemoryInfoEnabled(enabled);
4900 hr = prefsPrivate->hyperlinkAuditingEnabled(&enabled);
4903 settings->setHyperlinkAuditingEnabled(enabled);
4905 hr = prefsPrivate->loadsSiteIconsIgnoringImageLoadingPreference(&enabled);
4908 settings->setLoadsSiteIconsIgnoringImageLoadingSetting(!!enabled);
4910 hr = prefsPrivate->showsToolTipOverTruncatedText(&enabled);
4914 settings->setShowsToolTipOverTruncatedText(enabled);
4916 if (!m_closeWindowTimer)
4917 m_mainFrame->invalidate(); // FIXME
4919 hr = updateSharedSettingsFromPreferencesIfNeeded(preferences.get());
4923 #if ENABLE(FULLSCREEN_API)
4924 hr = prefsPrivate->isFullScreenEnabled(&enabled);
4927 settings->setFullScreenEnabled(enabled);
4930 hr = prefsPrivate->mediaPlaybackRequiresUserGesture(&enabled);
4933 settings->setMediaPlaybackRequiresUserGesture(enabled);
4935 hr = prefsPrivate->mediaPlaybackAllowsInline(&enabled);
4938 settings->setMediaPlaybackAllowsInline(enabled);
4940 hr = prefsPrivate->shouldInvertColors(&enabled);
4943 setShouldInvertColors(enabled);
4945 hr = prefsPrivate->requestAnimationFrameEnabled(&enabled);
4948 settings->setRequestAnimationFrameEnabled(enabled);
4953 HRESULT updateSharedSettingsFromPreferencesIfNeeded(IWebPreferences* preferences)
4955 if (preferences != WebPreferences::sharedStandardPreferences())
4958 WebKitCookieStorageAcceptPolicy acceptPolicy;
4959 HRESULT hr = preferences->cookieStorageAcceptPolicy(&acceptPolicy);
4964 // Set cookie storage accept policy
4965 if (RetainPtr<CFHTTPCookieStorageRef> cookieStorage = currentCFHTTPCookieStorage())
4966 CFHTTPCookieStorageSetCookieAcceptPolicy(cookieStorage.get(), acceptPolicy);
4972 // IWebViewPrivate ------------------------------------------------------------
4974 HRESULT STDMETHODCALLTYPE WebView::MIMETypeForExtension(
4975 /* [in] */ BSTR extension,
4976 /* [retval][out] */ BSTR* mimeType)
4981 String extensionStr(extension, SysStringLen(extension));
4983 *mimeType = BString(MIMETypeRegistry::getMIMETypeForExtension(extensionStr)).release();
4988 HRESULT STDMETHODCALLTYPE WebView::setCustomDropTarget(
4989 /* [in] */ IDropTarget* dt)
4991 ASSERT(::IsWindow(m_viewWindow));
4994 m_hasCustomDropTarget = true;
4996 return ::RegisterDragDrop(m_viewWindow,dt);
4999 HRESULT STDMETHODCALLTYPE WebView::removeCustomDropTarget()
5001 if (!m_hasCustomDropTarget)
5003 m_hasCustomDropTarget = false;
5005 return registerDragDrop();
5008 HRESULT STDMETHODCALLTYPE WebView::setInViewSourceMode(
5009 /* [in] */ BOOL flag)
5014 return m_mainFrame->setInViewSourceMode(flag);
5017 HRESULT STDMETHODCALLTYPE WebView::inViewSourceMode(
5018 /* [retval][out] */ BOOL* flag)
5023 return m_mainFrame->inViewSourceMode(flag);
5026 HRESULT STDMETHODCALLTYPE WebView::viewWindow(
5027 /* [retval][out] */ OLE_HANDLE *window)
5029 *window = (OLE_HANDLE)(ULONG64)m_viewWindow;
5033 HRESULT STDMETHODCALLTYPE WebView::setFormDelegate(
5034 /* [in] */ IWebFormDelegate *formDelegate)
5036 m_formDelegate = formDelegate;
5040 HRESULT STDMETHODCALLTYPE WebView::formDelegate(
5041 /* [retval][out] */ IWebFormDelegate **formDelegate)
5043 if (!m_formDelegate)
5046 return m_formDelegate.copyRefTo(formDelegate);
5049 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegatePrivate(
5050 /* [in] */ IWebFrameLoadDelegatePrivate* d)
5052 m_frameLoadDelegatePrivate = d;
5056 HRESULT STDMETHODCALLTYPE WebView::frameLoadDelegatePrivate(
5057 /* [out][retval] */ IWebFrameLoadDelegatePrivate** d)
5059 if (!m_frameLoadDelegatePrivate)
5062 return m_frameLoadDelegatePrivate.copyRefTo(d);
5065 HRESULT STDMETHODCALLTYPE WebView::scrollOffset(
5066 /* [retval][out] */ LPPOINT offset)
5070 IntSize offsetIntSize = m_page->mainFrame()->view()->scrollOffset();
5071 offset->x = offsetIntSize.width();
5072 offset->y = offsetIntSize.height();
5076 HRESULT STDMETHODCALLTYPE WebView::scrollBy(
5077 /* [in] */ LPPOINT offset)
5081 m_page->mainFrame()->view()->scrollBy(IntSize(offset->x, offset->y));
5085 HRESULT STDMETHODCALLTYPE WebView::visibleContentRect(
5086 /* [retval][out] */ LPRECT rect)
5090 FloatRect visibleContent = m_page->mainFrame()->view()->visibleContentRect();
5091 rect->left = (LONG) visibleContent.x();
5092 rect->top = (LONG) visibleContent.y();
5093 rect->right = (LONG) visibleContent.maxX();
5094 rect->bottom = (LONG) visibleContent.maxY();
5098 static DWORD dragOperationToDragCursor(DragOperation op) {
5099 DWORD res = DROPEFFECT_NONE;
5100 if (op & DragOperationCopy)
5101 res = DROPEFFECT_COPY;
5102 else if (op & DragOperationLink)
5103 res = DROPEFFECT_LINK;
5104 else if (op & DragOperationMove)
5105 res = DROPEFFECT_MOVE;
5106 else if (op & DragOperationGeneric)
5107 res = DROPEFFECT_MOVE; //This appears to be the Firefox behaviour
5111 DragOperation WebView::keyStateToDragOperation(DWORD grfKeyState) const
5114 return DragOperationNone;
5116 // Conforms to Microsoft's key combinations as documented for
5117 // IDropTarget::DragOver. Note, grfKeyState is the current
5118 // state of the keyboard modifier keys on the keyboard. See:
5119 // <http://msdn.microsoft.com/en-us/library/ms680129(VS.85).aspx>.
5120 DragOperation operation = m_page->dragController()->sourceDragOperation();
5122 if ((grfKeyState & (MK_CONTROL | MK_SHIFT)) == (MK_CONTROL | MK_SHIFT))
5123 operation = DragOperationLink;
5124 else if ((grfKeyState & MK_CONTROL) == MK_CONTROL)
5125 operation = DragOperationCopy;
5126 else if ((grfKeyState & MK_SHIFT) == MK_SHIFT)
5127 operation = DragOperationGeneric;
5132 HRESULT STDMETHODCALLTYPE WebView::DragEnter(
5133 IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
5137 if (m_dropTargetHelper)
5138 m_dropTargetHelper->DragEnter(m_viewWindow, pDataObject, (POINT*)&pt, *pdwEffect);
5140 POINTL localpt = pt;
5141 ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
5142 DragData data(pDataObject, IntPoint(localpt.x, localpt.y),
5143 IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
5144 *pdwEffect = dragOperationToDragCursor(m_page->dragController()->dragEntered(&data).operation);
5146 m_lastDropEffect = *pdwEffect;
5147 m_dragData = pDataObject;
5152 HRESULT STDMETHODCALLTYPE WebView::DragOver(
5153 DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
5155 if (m_dropTargetHelper)
5156 m_dropTargetHelper->DragOver((POINT*)&pt, *pdwEffect);
5159 POINTL localpt = pt;
5160 ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
5161 DragData data(m_dragData.get(), IntPoint(localpt.x, localpt.y),
5162 IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
5163 *pdwEffect = dragOperationToDragCursor(m_page->dragController()->dragUpdated(&data).operation);
5165 *pdwEffect = DROPEFFECT_NONE;
5167 m_lastDropEffect = *pdwEffect;
5171 HRESULT STDMETHODCALLTYPE WebView::DragLeave()
5173 if (m_dropTargetHelper)
5174 m_dropTargetHelper->DragLeave();
5177 DragData data(m_dragData.get(), IntPoint(), IntPoint(),
5179 m_page->dragController()->dragExited(&data);
5185 HRESULT STDMETHODCALLTYPE WebView::Drop(
5186 IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
5188 if (m_dropTargetHelper)
5189 m_dropTargetHelper->Drop(pDataObject, (POINT*)&pt, *pdwEffect);
5192 *pdwEffect = m_lastDropEffect;
5193 POINTL localpt = pt;
5194 ::ScreenToClient(m_viewWindow, (LPPOINT)&localpt);
5195 DragData data(pDataObject, IntPoint(localpt.x, localpt.y),
5196 IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
5197 m_page->dragController()->performDrag(&data);
5201 HRESULT STDMETHODCALLTYPE WebView::canHandleRequest(
5202 IWebURLRequest *request,
5205 COMPtr<WebMutableURLRequest> requestImpl;
5207 HRESULT hr = request->QueryInterface(&requestImpl);
5211 *result = !!canHandleRequest(requestImpl->resourceRequest());
5215 HRESULT STDMETHODCALLTYPE WebView::standardUserAgentWithApplicationName(
5216 BSTR applicationName,
5220 ASSERT_NOT_REACHED();
5226 if (!applicationName) {
5227 ASSERT_NOT_REACHED();
5231 BString applicationNameBString(applicationName);
5232 *groupName = BString(standardUserAgentWithApplicationName(String(applicationNameBString, SysStringLen(applicationNameBString)))).release();
5236 HRESULT STDMETHODCALLTYPE WebView::clearFocusNode()
5238 if (m_page && m_page->focusController())
5239 m_page->focusController()->setFocusedNode(0, 0);
5243 HRESULT STDMETHODCALLTYPE WebView::setInitialFocus(
5244 /* [in] */ BOOL forward)
5246 if (m_page && m_page->focusController()) {
5247 Frame* frame = m_page->focusController()->focusedOrMainFrame();
5248 frame->document()->setFocusedNode(0);
5249 m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0);
5254 HRESULT STDMETHODCALLTYPE WebView::setTabKeyCyclesThroughElements(
5255 /* [in] */ BOOL cycles)
5258 m_page->setTabKeyCyclesThroughElements(!!cycles);
5263 HRESULT STDMETHODCALLTYPE WebView::tabKeyCyclesThroughElements(
5264 /* [retval][out] */ BOOL* result)
5267 ASSERT_NOT_REACHED();
5271 *result = m_page && m_page->tabKeyCyclesThroughElements() ? TRUE : FALSE;
5275 HRESULT STDMETHODCALLTYPE WebView::setAllowSiteSpecificHacks(
5276 /* [in] */ BOOL allow)
5278 s_allowSiteSpecificHacks = !!allow;
5279 // FIXME: This sets a global so it needs to call notifyPreferencesChanged
5280 // on all WebView objects (not just itself).
5284 HRESULT STDMETHODCALLTYPE WebView::addAdditionalPluginDirectory(
5285 /* [in] */ BSTR directory)
5287 PluginDatabase::installedPlugins()->addExtraPluginDirectory(String(directory, SysStringLen(directory)));
5291 HRESULT STDMETHODCALLTYPE WebView::loadBackForwardListFromOtherView(
5292 /* [in] */ IWebView* otherView)
5297 // It turns out the right combination of behavior is done with the back/forward load
5298 // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items
5299 // in the back forward list, and go to the current one.
5300 BackForwardList* backForwardList = m_page->backForwardList();
5301 ASSERT(!backForwardList->currentItem()); // destination list should be empty
5303 COMPtr<WebView> otherWebView;
5304 if (FAILED(otherView->QueryInterface(&otherWebView)))
5306 BackForwardList* otherBackForwardList = otherWebView->m_page->backForwardList();
5307 if (!otherBackForwardList->currentItem())
5308 return S_OK; // empty back forward list, bail
5310 HistoryItem* newItemToGoTo = 0;
5312 int lastItemIndex = otherBackForwardList->forwardListCount();
5313 for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
5315 // If this item is showing , save away its current scroll and form state,
5316 // since that might have changed since loading and it is normally not saved
5317 // until we leave that page.
5318 otherWebView->m_page->mainFrame()->loader()->history()->saveDocumentAndScrollState();
5320 RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
5322 newItemToGoTo = newItem.get();
5323 backForwardList->addItem(newItem.release());
5326 ASSERT(newItemToGoTo);
5327 m_page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
5331 HRESULT STDMETHODCALLTYPE WebView::clearUndoRedoOperations()
5333 if (Frame* frame = m_page->focusController()->focusedOrMainFrame())
5334 frame->editor()->clearUndoRedoOperations();
5338 HRESULT STDMETHODCALLTYPE WebView::shouldClose(
5339 /* [retval][out] */ BOOL* result)
5342 ASSERT_NOT_REACHED();
5347 if (Frame* frame = m_page->mainFrame())
5348 *result = frame->loader()->shouldClose();
5352 HRESULT WebView::registerDragDrop()
5354 ASSERT(::IsWindow(m_viewWindow));
5355 return ::RegisterDragDrop(m_viewWindow, this);
5358 HRESULT WebView::revokeDragDrop()
5363 return ::RevokeDragDrop(m_viewWindow);
5366 HRESULT WebView::setProhibitsMainFrameScrolling(BOOL b)
5371 m_page->mainFrame()->view()->setProhibitsScrolling(b);
5375 HRESULT WebView::setShouldApplyMacFontAscentHack(BOOL b)
5377 SimpleFontData::setShouldApplyMacAscentHack(b);
5382 typedef HIMC (CALLBACK *getContextPtr)(HWND);
5383 typedef BOOL (CALLBACK *releaseContextPtr)(HWND, HIMC);
5384 typedef LONG (CALLBACK *getCompositionStringPtr)(HIMC, DWORD, LPVOID, DWORD);
5385 typedef BOOL (CALLBACK *setCandidateWindowPtr)(HIMC, LPCANDIDATEFORM);
5386 typedef BOOL (CALLBACK *setOpenStatusPtr)(HIMC, BOOL);
5387 typedef BOOL (CALLBACK *notifyIMEPtr)(HIMC, DWORD, DWORD, DWORD);
5388 typedef BOOL (CALLBACK *associateContextExPtr)(HWND, HIMC, DWORD);
5391 getContextPtr getContext;
5392 releaseContextPtr releaseContext;
5393 getCompositionStringPtr getCompositionString;
5394 setCandidateWindowPtr setCandidateWindow;
5395 setOpenStatusPtr setOpenStatus;
5396 notifyIMEPtr notifyIME;
5397 associateContextExPtr associateContextEx;
5399 static const IMMDict& dict();
5405 const IMMDict& IMMDict::dict()
5407 static IMMDict instance;
5413 m_instance = ::LoadLibraryW(L"IMM32.DLL");
5414 getContext = reinterpret_cast<getContextPtr>(::GetProcAddress(m_instance, "ImmGetContext"));
5416 releaseContext = reinterpret_cast<releaseContextPtr>(::GetProcAddress(m_instance, "ImmReleaseContext"));
5417 ASSERT(releaseContext);
5418 getCompositionString = reinterpret_cast<getCompositionStringPtr>(::GetProcAddress(m_instance, "ImmGetCompositionStringW"));
5419 ASSERT(getCompositionString);
5420 setCandidateWindow = reinterpret_cast<setCandidateWindowPtr>(::GetProcAddress(m_instance, "ImmSetCandidateWindow"));
5421 ASSERT(setCandidateWindow);
5422 setOpenStatus = reinterpret_cast<setOpenStatusPtr>(::GetProcAddress(m_instance, "ImmSetOpenStatus"));
5423 ASSERT(setOpenStatus);
5424 notifyIME = reinterpret_cast<notifyIMEPtr>(::GetProcAddress(m_instance, "ImmNotifyIME"));
5426 associateContextEx = reinterpret_cast<associateContextExPtr>(::GetProcAddress(m_instance, "ImmAssociateContextEx"));
5427 ASSERT(associateContextEx);
5430 HIMC WebView::getIMMContext()
5432 HIMC context = IMMDict::dict().getContext(m_viewWindow);
5436 void WebView::releaseIMMContext(HIMC hIMC)
5440 IMMDict::dict().releaseContext(m_viewWindow, hIMC);
5443 void WebView::prepareCandidateWindow(Frame* targetFrame, HIMC hInputContext)
5446 if (RefPtr<Range> range = targetFrame->selection()->selection().toNormalizedRange()) {
5447 ExceptionCode ec = 0;
5448 RefPtr<Range> tempRange = range->cloneRange(ec);
5449 caret = targetFrame->editor()->firstRectForRange(tempRange.get());
5451 caret = targetFrame->view()->contentsToWindow(caret);
5454 form.dwStyle = CFS_EXCLUDE;
5455 form.ptCurrentPos.x = caret.x();
5456 form.ptCurrentPos.y = caret.y() + caret.height();
5457 form.rcArea.top = caret.y();
5458 form.rcArea.bottom = caret.maxY();
5459 form.rcArea.left = caret.x();
5460 form.rcArea.right = caret.maxX();
5461 IMMDict::dict().setCandidateWindow(hInputContext, &form);
5464 void WebView::resetIME(Frame* targetFrame)
5467 targetFrame->editor()->cancelComposition();
5469 if (HIMC hInputContext = getIMMContext()) {
5470 IMMDict::dict().notifyIME(hInputContext, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
5471 releaseIMMContext(hInputContext);
5475 void WebView::updateSelectionForIME()
5477 Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
5478 if (!targetFrame || !targetFrame->editor()->hasComposition())
5481 if (targetFrame->editor()->ignoreCompositionSelectionChange())
5486 if (!targetFrame->editor()->getCompositionSelection(start, end))
5487 resetIME(targetFrame);
5490 void WebView::setInputMethodState(bool enabled)
5492 IMMDict::dict().associateContextEx(m_viewWindow, 0, enabled ? IACE_DEFAULT : 0);
5495 void WebView::selectionChanged()
5497 updateSelectionForIME();
5500 bool WebView::onIMEStartComposition()
5502 LOG(TextInput, "onIMEStartComposition");
5503 m_inIMEComposition++;
5504 Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
5508 HIMC hInputContext = getIMMContext();
5509 prepareCandidateWindow(targetFrame, hInputContext);
5510 releaseIMMContext(hInputContext);
5514 static bool getCompositionString(HIMC hInputContext, DWORD type, String& result)
5516 int compositionLength = IMMDict::dict().getCompositionString(hInputContext, type, 0, 0);
5517 if (compositionLength <= 0)
5519 Vector<UChar> compositionBuffer(compositionLength / 2);
5520 compositionLength = IMMDict::dict().getCompositionString(hInputContext, type, (LPVOID)compositionBuffer.data(), compositionLength);
5521 result = String(compositionBuffer.data(), compositionLength / 2);
5522 ASSERT(!compositionLength || compositionBuffer[0]);
5523 ASSERT(!compositionLength || compositionBuffer[compositionLength / 2 - 1]);
5527 static void compositionToUnderlines(const Vector<DWORD>& clauses, const Vector<BYTE>& attributes, Vector<CompositionUnderline>& underlines)
5529 if (clauses.isEmpty()) {
5534 const size_t numBoundaries = clauses.size() - 1;
5535 underlines.resize(numBoundaries);
5536 for (unsigned i = 0; i < numBoundaries; i++) {
5537 underlines[i].startOffset = clauses[i];
5538 underlines[i].endOffset = clauses[i + 1];
5539 BYTE attribute = attributes[clauses[i]];
5540 underlines[i].thick = attribute == ATTR_TARGET_CONVERTED || attribute == ATTR_TARGET_NOTCONVERTED;
5541 underlines[i].color = Color(0,0,0);
5546 #define APPEND_ARGUMENT_NAME(name) \
5547 if (lparam & name) { \
5551 needsComma = true; \
5554 static String imeCompositionArgumentNames(LPARAM lparam)
5557 bool needsComma = false;
5558 if (lparam & GCS_COMPATTR) {
5559 result = "GCS_COMPATTR";
5562 APPEND_ARGUMENT_NAME(GCS_COMPCLAUSE);
5563 APPEND_ARGUMENT_NAME(GCS_COMPREADSTR);
5564 APPEND_ARGUMENT_NAME(GCS_COMPREADATTR);
5565 APPEND_ARGUMENT_NAME(GCS_COMPREADCLAUSE);
5566 APPEND_ARGUMENT_NAME(GCS_COMPSTR);
5567 APPEND_ARGUMENT_NAME(GCS_CURSORPOS);
5568 APPEND_ARGUMENT_NAME(GCS_DELTASTART);
5569 APPEND_ARGUMENT_NAME(GCS_RESULTCLAUSE);
5570 APPEND_ARGUMENT_NAME(GCS_RESULTREADCLAUSE);
5571 APPEND_ARGUMENT_NAME(GCS_RESULTREADSTR);
5572 APPEND_ARGUMENT_NAME(GCS_RESULTSTR);
5573 APPEND_ARGUMENT_NAME(CS_INSERTCHAR);
5574 APPEND_ARGUMENT_NAME(CS_NOMOVECARET);
5579 static String imeNotificationName(WPARAM wparam)
5582 case IMN_CHANGECANDIDATE:
5583 return "IMN_CHANGECANDIDATE";
5584 case IMN_CLOSECANDIDATE:
5585 return "IMN_CLOSECANDIDATE";
5586 case IMN_CLOSESTATUSWINDOW:
5587 return "IMN_CLOSESTATUSWINDOW";
5589 return "IMN_GUIDELINE";
5590 case IMN_OPENCANDIDATE:
5591 return "IMN_OPENCANDIDATE";
5592 case IMN_OPENSTATUSWINDOW:
5593 return "IMN_OPENSTATUSWINDOW";
5594 case IMN_SETCANDIDATEPOS:
5595 return "IMN_SETCANDIDATEPOS";
5596 case IMN_SETCOMPOSITIONFONT:
5597 return "IMN_SETCOMPOSITIONFONT";
5598 case IMN_SETCOMPOSITIONWINDOW:
5599 return "IMN_SETCOMPOSITIONWINDOW";
5600 case IMN_SETCONVERSIONMODE:
5601 return "IMN_SETCONVERSIONMODE";
5602 case IMN_SETOPENSTATUS:
5603 return "IMN_SETOPENSTATUS";
5604 case IMN_SETSENTENCEMODE:
5605 return "IMN_SETSENTENCEMODE";
5606 case IMN_SETSTATUSWINDOWPOS:
5607 return "IMN_SETSTATUSWINDOWPOS";
5609 return "Unknown (" + String::number(wparam) + ")";
5613 static String imeRequestName(WPARAM wparam)
5616 case IMR_CANDIDATEWINDOW:
5617 return "IMR_CANDIDATEWINDOW";
5618 case IMR_COMPOSITIONFONT:
5619 return "IMR_COMPOSITIONFONT";
5620 case IMR_COMPOSITIONWINDOW:
5621 return "IMR_COMPOSITIONWINDOW";
5622 case IMR_CONFIRMRECONVERTSTRING:
5623 return "IMR_CONFIRMRECONVERTSTRING";
5624 case IMR_DOCUMENTFEED:
5625 return "IMR_DOCUMENTFEED";
5626 case IMR_QUERYCHARPOSITION:
5627 return "IMR_QUERYCHARPOSITION";
5628 case IMR_RECONVERTSTRING:
5629 return "IMR_RECONVERTSTRING";
5631 return "Unknown (" + String::number(wparam) + ")";
5636 bool WebView::onIMEComposition(LPARAM lparam)
5638 LOG(TextInput, "onIMEComposition %s", imeCompositionArgumentNames(lparam).latin1().data());
5639 HIMC hInputContext = getIMMContext();
5643 Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
5644 if (!targetFrame || !targetFrame->editor()->canEdit())
5647 prepareCandidateWindow(targetFrame, hInputContext);
5649 if (lparam & GCS_RESULTSTR || !lparam) {
5650 String compositionString;
5651 if (!getCompositionString(hInputContext, GCS_RESULTSTR, compositionString) && lparam)
5654 targetFrame->editor()->confirmComposition(compositionString);
5656 String compositionString;
5657 if (!getCompositionString(hInputContext, GCS_COMPSTR, compositionString))
5660 // Composition string attributes
5661 int numAttributes = IMMDict::dict().getCompositionString(hInputContext, GCS_COMPATTR, 0, 0);
5662 Vector<BYTE> attributes(numAttributes);
5663 IMMDict::dict().getCompositionString(hInputContext, GCS_COMPATTR, attributes.data(), numAttributes);
5666 int numClauses = IMMDict::dict().getCompositionString(hInputContext, GCS_COMPCLAUSE, 0, 0);
5667 Vector<DWORD> clauses(numClauses / sizeof(DWORD));
5668 IMMDict::dict().getCompositionString(hInputContext, GCS_COMPCLAUSE, clauses.data(), numClauses);
5670 Vector<CompositionUnderline> underlines;
5671 compositionToUnderlines(clauses, attributes, underlines);
5673 int cursorPosition = LOWORD(IMMDict::dict().getCompositionString(hInputContext, GCS_CURSORPOS, 0, 0));
5675 targetFrame->editor()->setComposition(compositionString, underlines, cursorPosition, 0);
5681 bool WebView::onIMEEndComposition()
5683 LOG(TextInput, "onIMEEndComposition");
5684 // If the composition hasn't been confirmed yet, it needs to be cancelled.
5685 // This happens after deleting the last character from inline input hole.
5686 Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
5687 if (targetFrame && targetFrame->editor()->hasComposition())
5688 targetFrame->editor()->confirmComposition(String());
5690 if (m_inIMEComposition)
5691 m_inIMEComposition--;
5696 bool WebView::onIMEChar(WPARAM wparam, LPARAM lparam)
5698 UNUSED_PARAM(wparam);
5699 UNUSED_PARAM(lparam);
5700 LOG(TextInput, "onIMEChar U+%04X %08X", wparam, lparam);
5704 bool WebView::onIMENotify(WPARAM wparam, LPARAM, LRESULT*)
5706 UNUSED_PARAM(wparam);
5707 LOG(TextInput, "onIMENotify %s", imeNotificationName(wparam).latin1().data());
5711 LRESULT WebView::onIMERequestCharPosition(Frame* targetFrame, IMECHARPOSITION* charPos)
5713 if (charPos->dwCharPos && !targetFrame->editor()->hasComposition())
5716 if (RefPtr<Range> range = targetFrame->editor()->hasComposition() ? targetFrame->editor()->compositionRange() : targetFrame->selection()->selection().toNormalizedRange()) {
5717 ExceptionCode ec = 0;
5718 RefPtr<Range> tempRange = range->cloneRange(ec);
5719 tempRange->setStart(tempRange->startContainer(ec), tempRange->startOffset(ec) + charPos->dwCharPos, ec);
5720 caret = targetFrame->editor()->firstRectForRange(tempRange.get());
5722 caret = targetFrame->view()->contentsToWindow(caret);
5723 charPos->pt.x = caret.x();
5724 charPos->pt.y = caret.y();
5725 ::ClientToScreen(m_viewWindow, &charPos->pt);
5726 charPos->cLineHeight = caret.height();
5727 ::GetWindowRect(m_viewWindow, &charPos->rcDocument);
5731 LRESULT WebView::onIMERequestReconvertString(Frame* targetFrame, RECONVERTSTRING* reconvertString)
5733 RefPtr<Range> selectedRange = targetFrame->selection()->toNormalizedRange();
5734 String text = selectedRange->text();
5735 if (!reconvertString)
5736 return sizeof(RECONVERTSTRING) + text.length() * sizeof(UChar);
5738 unsigned totalSize = sizeof(RECONVERTSTRING) + text.length() * sizeof(UChar);
5739 if (totalSize > reconvertString->dwSize)
5741 reconvertString->dwCompStrLen = text.length();
5742 reconvertString->dwStrLen = text.length();
5743 reconvertString->dwTargetStrLen = text.length();
5744 reconvertString->dwStrOffset = sizeof(RECONVERTSTRING);
5745 memcpy(reconvertString + 1, text.characters(), text.length() * sizeof(UChar));
5749 LRESULT WebView::onIMERequest(WPARAM request, LPARAM data)
5751 LOG(TextInput, "onIMERequest %s", imeRequestName(request).latin1().data());
5752 Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
5753 if (!targetFrame || !targetFrame->editor()->canEdit())
5757 case IMR_RECONVERTSTRING:
5758 return onIMERequestReconvertString(targetFrame, (RECONVERTSTRING*)data);
5760 case IMR_QUERYCHARPOSITION:
5761 return onIMERequestCharPosition(targetFrame, (IMECHARPOSITION*)data);
5766 bool WebView::onIMESelect(WPARAM wparam, LPARAM lparam)
5768 UNUSED_PARAM(wparam);
5769 UNUSED_PARAM(lparam);
5770 LOG(TextInput, "onIMESelect locale %ld %s", lparam, wparam ? "select" : "deselect");
5774 bool WebView::onIMESetContext(WPARAM wparam, LPARAM)
5776 LOG(TextInput, "onIMESetContext %s", wparam ? "active" : "inactive");
5780 HRESULT STDMETHODCALLTYPE WebView::inspector(IWebInspector** inspector)
5782 #if ENABLE(INSPECTOR)
5783 if (!m_webInspector)
5784 m_webInspector.adoptRef(WebInspector::createInstance(this, m_inspectorClient));
5786 return m_webInspector.copyRefTo(inspector);
5787 #else // !ENABLE(INSPECTOR)
5789 #endif // ENABLE(INSPECTOR)
5793 HRESULT STDMETHODCALLTYPE WebView::windowAncestryDidChange()
5797 newParent = findTopLevelParent(m_hostWindow);
5799 // There's no point in tracking active state changes of our parent window if we don't have
5800 // a window ourselves.
5804 if (newParent == m_topLevelParent)
5807 if (m_topLevelParent)
5808 WindowMessageBroadcaster::removeListener(m_topLevelParent, this);
5810 m_topLevelParent = newParent;
5812 if (m_topLevelParent)
5813 WindowMessageBroadcaster::addListener(m_topLevelParent, this);
5815 updateActiveState();
5820 HRESULT STDMETHODCALLTYPE WebView::paintDocumentRectToContext(
5821 /* [in] */ RECT rect,
5822 /* [in] */ OLE_HANDLE deviceContext)
5830 return m_mainFrame->paintDocumentRectToContext(rect, deviceContext);
5833 HRESULT STDMETHODCALLTYPE WebView::paintScrollViewRectToContextAtPoint(
5834 /* [in] */ RECT rect,
5835 /* [in] */ POINT pt,
5836 /* [in] */ OLE_HANDLE deviceContext)
5844 return m_mainFrame->paintScrollViewRectToContextAtPoint(rect, pt, deviceContext);
5847 HRESULT STDMETHODCALLTYPE WebView::reportException(
5848 /* [in] */ JSContextRef context,
5849 /* [in] */ JSValueRef exception)
5851 if (!context || !exception)
5854 JSC::ExecState* execState = toJS(context);
5855 JSC::JSLockHolder lock(execState);
5857 // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a WebView.
5858 if (!toJSDOMWindow(execState->lexicalGlobalObject()))
5861 WebCore::reportException(execState, toJS(execState, exception));
5865 HRESULT STDMETHODCALLTYPE WebView::elementFromJS(
5866 /* [in] */ JSContextRef context,
5867 /* [in] */ JSValueRef nodeObject,
5868 /* [retval][out] */ IDOMElement **element)
5881 JSC::ExecState* exec = toJS(context);
5882 JSC::JSLockHolder lock(exec);
5883 Element* elt = toElement(toJS(exec, nodeObject));
5887 *element = DOMElement::createInstance(elt);
5891 HRESULT STDMETHODCALLTYPE WebView::setCustomHTMLTokenizerTimeDelay(
5892 /* [in] */ double timeDelay)
5897 m_page->setCustomHTMLTokenizerTimeDelay(timeDelay);
5901 HRESULT STDMETHODCALLTYPE WebView::setCustomHTMLTokenizerChunkSize(
5902 /* [in] */ int chunkSize)
5907 m_page->setCustomHTMLTokenizerChunkSize(chunkSize);
5911 HRESULT STDMETHODCALLTYPE WebView::backingStore(
5912 /* [out, retval] */ OLE_HANDLE* hBitmap)
5916 if (!m_backingStoreBitmap)
5918 *hBitmap = reinterpret_cast<OLE_HANDLE>(m_backingStoreBitmap->handle());
5922 HRESULT STDMETHODCALLTYPE WebView::setTransparent(BOOL transparent)
5924 if (m_transparent == !!transparent)
5927 m_transparent = transparent;
5928 m_mainFrame->updateBackground();
5932 HRESULT STDMETHODCALLTYPE WebView::transparent(BOOL* transparent)
5937 *transparent = this->transparent() ? TRUE : FALSE;
5941 static bool setWindowStyle(HWND window, int index, LONG_PTR newValue)
5943 // According to MSDN, if the last value of the flag we are setting was zero,
5944 // then SetWindowLongPtr returns zero, even though the call succeeded. So,
5945 // we have to clear the error state, then check the last error after
5946 // setting the value to see if it actually was a failure.
5948 return ::SetWindowLongPtr(window, index, newValue) || !::GetLastError();
5951 HRESULT WebView::setUsesLayeredWindow(BOOL usesLayeredWindow)
5953 if (m_usesLayeredWindow == !!usesLayeredWindow)
5960 ::GetWindowRect(m_viewWindow, &rect);
5962 LONG_PTR origExStyle = ::GetWindowLongPtr(m_viewWindow, GWL_EXSTYLE);
5963 LONG_PTR origStyle = ::GetWindowLongPtr(m_viewWindow, GWL_STYLE);
5965 // The logic here has to account for the way SetParent works.
5966 // According to MSDN, to go from a child window to a popup window,
5967 // you must clear the child bit after setting the parent to 0.
5968 // On the other hand, to go from a popup window to a child, you
5969 // must clear the popup state before setting the parent.
5970 if (usesLayeredWindow) {
5971 LONG_PTR newExStyle = origExStyle | WS_EX_LAYERED;
5972 LONG_PTR newStyle = (origStyle & ~(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)) | WS_POPUP;
5974 HWND origParent = ::SetParent(m_viewWindow, 0);
5976 if (!setWindowStyle(m_viewWindow, GWL_STYLE, newStyle)) {
5977 ::SetParent(m_viewWindow, origParent);
5981 if (!setWindowStyle(m_viewWindow, GWL_EXSTYLE, newExStyle)) {
5982 setWindowStyle(m_viewWindow, GWL_STYLE, origStyle);
5983 ::SetParent(m_viewWindow, origParent);
5987 LONG_PTR newExStyle = origExStyle & ~WS_EX_LAYERED;
5988 LONG_PTR newStyle = (origStyle & ~WS_POPUP) | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
5990 if (!setWindowStyle(m_viewWindow, GWL_EXSTYLE, newExStyle))
5993 if (!setWindowStyle(m_viewWindow, GWL_STYLE, newStyle)) {
5994 setWindowStyle(m_viewWindow, GWL_EXSTYLE, origExStyle);
5998 ::SetParent(m_viewWindow, m_hostWindow ? m_hostWindow : HWND_MESSAGE);
6001 // MSDN indicates that SetWindowLongPtr doesn't take effect for some settings until a
6002 // SetWindowPos is called.
6003 ::SetWindowPos(m_viewWindow, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
6004 SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
6006 m_usesLayeredWindow = usesLayeredWindow;
6010 HRESULT WebView::usesLayeredWindow(BOOL* usesLayeredWindow)
6012 if (!usesLayeredWindow)
6015 *usesLayeredWindow = this->usesLayeredWindow() ? TRUE : FALSE;
6019 HRESULT STDMETHODCALLTYPE WebView::setCookieEnabled(BOOL enable)
6024 m_page->settings()->setCookieEnabled(enable);
6028 HRESULT STDMETHODCALLTYPE WebView::cookieEnabled(BOOL* enabled)
6036 *enabled = m_page->settings()->cookieEnabled();
6040 HRESULT STDMETHODCALLTYPE WebView::setMediaVolume(float volume)
6045 m_page->setMediaVolume(volume);
6049 HRESULT STDMETHODCALLTYPE WebView::mediaVolume(float* volume)
6057 *volume = m_page->mediaVolume();
6061 HRESULT STDMETHODCALLTYPE WebView::setDefersCallbacks(BOOL defersCallbacks)
6066 m_page->setDefersLoading(defersCallbacks);
6070 HRESULT STDMETHODCALLTYPE WebView::defersCallbacks(BOOL* defersCallbacks)
6072 if (!defersCallbacks)
6078 *defersCallbacks = m_page->defersLoading();
6082 HRESULT STDMETHODCALLTYPE WebView::globalHistoryItem(IWebHistoryItem** item)
6090 if (!m_globalHistoryItem) {
6095 *item = WebHistoryItem::createInstance(m_globalHistoryItem);
6099 HRESULT STDMETHODCALLTYPE WebView::setAlwaysUsesComplexTextCodePath(BOOL complex)
6101 WebCoreSetAlwaysUsesComplexTextCodePath(complex);
6106 HRESULT STDMETHODCALLTYPE WebView::alwaysUsesComplexTextCodePath(BOOL* complex)
6111 *complex = WebCoreAlwaysUsesComplexTextCodePath();
6115 HRESULT STDMETHODCALLTYPE WebView::registerEmbeddedViewMIMEType(BSTR mimeType)
6120 if (!m_embeddedViewMIMETypes)
6121 m_embeddedViewMIMETypes = adoptPtr(new HashSet<String>);
6123 m_embeddedViewMIMETypes->add(String(mimeType, ::SysStringLen(mimeType)));
6127 bool WebView::shouldUseEmbeddedView(const WTF::String& mimeType) const
6129 if (!m_embeddedViewMIMETypes)
6132 return m_embeddedViewMIMETypes->contains(mimeType);
6135 bool WebView::onGetObject(WPARAM wParam, LPARAM lParam, LRESULT& lResult) const
6139 if (lParam != OBJID_CLIENT)
6142 AXObjectCache::enableAccessibility();
6144 // Get the accessible object for the top-level frame.
6145 WebFrame* mainFrameImpl = topLevelFrame();
6149 COMPtr<IAccessible> accessible = mainFrameImpl->accessible();
6153 if (!accessibilityLib) {
6154 if (!(accessibilityLib = ::LoadLibraryW(L"oleacc.dll")))
6158 static LPFNLRESULTFROMOBJECT procPtr = reinterpret_cast<LPFNLRESULTFROMOBJECT>(::GetProcAddress(accessibilityLib, "LresultFromObject"));
6162 // LresultFromObject returns a reference to the accessible object, stored
6163 // in an LRESULT. If this call is not successful, Windows will handle the
6164 // request through DefWindowProc.
6165 return SUCCEEDED(lResult = procPtr(__uuidof(IAccessible), wParam, accessible.get()));
6168 STDMETHODIMP WebView::AccessibleObjectFromWindow(HWND hwnd, DWORD objectID, REFIID riid, void** ppObject)
6170 ASSERT(accessibilityLib);
6171 static LPFNACCESSIBLEOBJECTFROMWINDOW procPtr = reinterpret_cast<LPFNACCESSIBLEOBJECTFROMWINDOW>(::GetProcAddress(accessibilityLib, "AccessibleObjectFromWindow"));
6174 return procPtr(hwnd, objectID, riid, ppObject);
6177 HRESULT WebView::setMemoryCacheDelegateCallsEnabled(BOOL enabled)
6179 m_page->setMemoryCacheClientCallsEnabled(enabled);
6183 HRESULT WebView::setJavaScriptURLsAreAllowed(BOOL areAllowed)
6185 m_page->setJavaScriptURLsAreAllowed(areAllowed);
6189 HRESULT WebView::setCanStartPlugins(BOOL canStartPlugins)
6191 m_page->setCanStartMedia(canStartPlugins);
6195 static String toString(BSTR bstr)
6197 return String(bstr, SysStringLen(bstr));
6200 static KURL toKURL(BSTR bstr)
6202 return KURL(KURL(), toString(bstr));
6205 void WebView::enterFullscreenForNode(Node* node)
6207 if (!node->hasTagName(HTMLNames::videoTag) || !node->isElementNode())
6211 if (!static_cast<Element*>(node)->isMediaElement())
6213 HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(node);
6215 if (m_fullScreenVideoController) {
6216 if (m_fullScreenVideoController->mediaElement() == videoElement) {
6217 // The backend may just warn us that the underlaying plaftormMovie()
6218 // has changed. Just force an update.
6219 m_fullScreenVideoController->setMediaElement(videoElement);
6220 return; // No more to do.
6223 // First exit Fullscreen for the old mediaElement.
6224 m_fullScreenVideoController->mediaElement()->exitFullscreen();
6225 // This previous call has to trigger exitFullscreen,
6226 // which has to clear m_fullScreenVideoController.
6227 ASSERT(!m_fullScreenVideoController);
6230 m_fullScreenVideoController = adoptPtr(new FullscreenVideoController);
6231 m_fullScreenVideoController->setMediaElement(videoElement);
6232 m_fullScreenVideoController->enterFullscreen();
6236 void WebView::exitFullscreen()
6239 if (m_fullScreenVideoController)
6240 m_fullScreenVideoController->exitFullscreen();
6245 static PassOwnPtr<Vector<String> > toStringVector(unsigned patternsCount, BSTR* patterns)
6247 // Convert the patterns into a Vector.
6248 if (patternsCount == 0)
6250 OwnPtr<Vector<String> > patternsVector = adoptPtr(new Vector<String>);
6251 for (unsigned i = 0; i < patternsCount; ++i)
6252 patternsVector->append(toString(patterns[i]));
6253 return patternsVector.release();
6256 HRESULT WebView::addUserScriptToGroup(BSTR groupName, IWebScriptWorld* iWorld, BSTR source, BSTR url,
6257 unsigned whitelistCount, BSTR* whitelist,
6258 unsigned blacklistCount, BSTR* blacklist,
6259 WebUserScriptInjectionTime injectionTime)
6261 COMPtr<WebScriptWorld> world(Query, iWorld);
6265 String group = toString(groupName);
6266 if (group.isEmpty())
6267 return E_INVALIDARG;
6269 PageGroup* pageGroup = PageGroup::pageGroup(group);
6274 pageGroup->addUserScriptToWorld(world->world(), toString(source), toKURL(url),
6275 toStringVector(whitelistCount, whitelist), toStringVector(blacklistCount, blacklist),
6276 injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd,
6282 HRESULT WebView::addUserStyleSheetToGroup(BSTR groupName, IWebScriptWorld* iWorld, BSTR source, BSTR url,
6283 unsigned whitelistCount, BSTR* whitelist,
6284 unsigned blacklistCount, BSTR* blacklist)
6286 COMPtr<WebScriptWorld> world(Query, iWorld);
6290 String group = toString(groupName);
6291 if (group.isEmpty())
6292 return E_INVALIDARG;
6294 PageGroup* pageGroup = PageGroup::pageGroup(group);
6299 pageGroup->addUserStyleSheetToWorld(world->world(), toString(source), toKURL(url),
6300 toStringVector(whitelistCount, whitelist), toStringVector(blacklistCount, blacklist),
6306 HRESULT WebView::removeUserScriptFromGroup(BSTR groupName, IWebScriptWorld* iWorld, BSTR url)
6308 COMPtr<WebScriptWorld> world(Query, iWorld);
6312 String group = toString(groupName);
6313 if (group.isEmpty())
6314 return E_INVALIDARG;
6316 PageGroup* pageGroup = PageGroup::pageGroup(group);
6321 pageGroup->removeUserScriptFromWorld(world->world(), toKURL(url));
6326 HRESULT WebView::removeUserStyleSheetFromGroup(BSTR groupName, IWebScriptWorld* iWorld, BSTR url)
6328 COMPtr<WebScriptWorld> world(Query, iWorld);
6332 String group = toString(groupName);
6333 if (group.isEmpty())
6334 return E_INVALIDARG;
6336 PageGroup* pageGroup = PageGroup::pageGroup(group);
6341 pageGroup->removeUserStyleSheetFromWorld(world->world(), toKURL(url));
6346 HRESULT WebView::removeUserScriptsFromGroup(BSTR groupName, IWebScriptWorld* iWorld)
6348 COMPtr<WebScriptWorld> world(Query, iWorld);
6352 String group = toString(groupName);
6353 if (group.isEmpty())
6354 return E_INVALIDARG;
6356 PageGroup* pageGroup = PageGroup::pageGroup(group);
6361 pageGroup->removeUserScriptsFromWorld(world->world());
6365 HRESULT WebView::removeUserStyleSheetsFromGroup(BSTR groupName, IWebScriptWorld* iWorld)
6367 COMPtr<WebScriptWorld> world(Query, iWorld);
6371 String group = toString(groupName);
6372 if (group.isEmpty())
6373 return E_INVALIDARG;
6375 PageGroup* pageGroup = PageGroup::pageGroup(group);
6380 pageGroup->removeUserStyleSheetsFromWorld(world->world());
6384 HRESULT WebView::removeAllUserContentFromGroup(BSTR groupName)
6386 String group = toString(groupName);
6387 if (group.isEmpty())
6388 return E_INVALIDARG;
6390 PageGroup* pageGroup = PageGroup::pageGroup(group);
6395 pageGroup->removeAllUserContent();
6399 HRESULT WebView::invalidateBackingStore(const RECT* rect)
6401 if (!IsWindow(m_viewWindow))
6405 if (!GetClientRect(m_viewWindow, &clientRect))
6408 RECT rectToInvalidate;
6410 rectToInvalidate = clientRect;
6411 else if (!IntersectRect(&rectToInvalidate, &clientRect, rect))
6414 repaint(rectToInvalidate, true);
6418 HRESULT WebView::addOriginAccessWhitelistEntry(BSTR sourceOrigin, BSTR destinationProtocol, BSTR destinationHost, BOOL allowDestinationSubdomains)
6420 SecurityPolicy::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(String(sourceOrigin, SysStringLen(sourceOrigin))), String(destinationProtocol, SysStringLen(destinationProtocol)), String(destinationHost, SysStringLen(destinationHost)), allowDestinationSubdomains);
6424 HRESULT WebView::removeOriginAccessWhitelistEntry(BSTR sourceOrigin, BSTR destinationProtocol, BSTR destinationHost, BOOL allowDestinationSubdomains)
6426 SecurityPolicy::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(String(sourceOrigin, SysStringLen(sourceOrigin))), String(destinationProtocol, SysStringLen(destinationProtocol)), String(destinationHost, SysStringLen(destinationHost)), allowDestinationSubdomains);
6430 HRESULT WebView::resetOriginAccessWhitelists()
6432 SecurityPolicy::resetOriginAccessWhitelists();
6436 HRESULT WebView::setHistoryDelegate(IWebHistoryDelegate* historyDelegate)
6438 m_historyDelegate = historyDelegate;
6442 HRESULT WebView::historyDelegate(IWebHistoryDelegate** historyDelegate)
6444 if (!historyDelegate)
6447 return m_historyDelegate.copyRefTo(historyDelegate);
6450 HRESULT WebView::addVisitedLinks(BSTR* visitedURLs, unsigned visitedURLCount)
6452 PageGroup& group = core(this)->group();
6454 for (unsigned i = 0; i < visitedURLCount; ++i) {
6455 BSTR url = visitedURLs[i];
6456 unsigned length = SysStringLen(url);
6457 group.addVisitedLink(url, length);
6463 void WebView::downloadURL(const KURL& url)
6465 // It's the delegate's job to ref the WebDownload to keep it alive - otherwise it will be
6466 // destroyed when this function returns.
6467 COMPtr<WebDownload> download(AdoptCOM, WebDownload::createInstance(url, m_downloadDelegate.get()));
6471 #if USE(ACCELERATED_COMPOSITING)
6472 void WebView::setRootChildLayer(GraphicsLayer* layer)
6474 setAcceleratedCompositing(layer ? true : false);
6475 if (!m_backingLayer)
6477 m_backingLayer->addChild(layer);
6480 void WebView::flushPendingGraphicsLayerChangesSoon()
6482 if (!m_layerTreeHost)
6484 m_layerTreeHost->flushPendingGraphicsLayerChangesSoon();
6487 void WebView::setAcceleratedCompositing(bool accelerated)
6489 if (m_isAcceleratedCompositing == accelerated || !CACFLayerTreeHost::acceleratedCompositingAvailable())
6493 m_layerTreeHost = CACFLayerTreeHost::create();
6494 if (m_layerTreeHost) {
6495 m_isAcceleratedCompositing = true;
6497 m_layerTreeHost->setShouldInvertColors(m_shouldInvertColors);
6499 m_layerTreeHost->setClient(this);
6500 ASSERT(m_viewWindow);
6501 m_layerTreeHost->setWindow(m_viewWindow);
6503 // FIXME: We could perhaps get better performance by never allowing this layer to
6504 // become tiled (or choosing a higher-than-normal tiling threshold).
6505 // <http://webkit.org/b/52603>
6506 m_backingLayer = GraphicsLayer::create(this);
6507 m_backingLayer->setDrawsContent(true);
6508 m_backingLayer->setContentsOpaque(true);
6510 ::GetClientRect(m_viewWindow, &clientRect);
6511 m_backingLayer->setSize(IntRect(clientRect).size());
6512 m_backingLayer->setNeedsDisplay();
6514 m_layerTreeHost->setRootChildLayer(PlatformCALayer::platformCALayer(m_backingLayer->platformLayer()));
6516 // We aren't going to be using our backing store while we're in accelerated compositing
6517 // mode. But don't delete it immediately, in case we switch out of accelerated
6518 // compositing mode soon (e.g., if we're only compositing for a :hover animation).
6519 deleteBackingStoreSoon();
6522 ASSERT(m_layerTreeHost);
6523 m_layerTreeHost->setClient(0);
6524 m_layerTreeHost->setWindow(0);
6525 m_layerTreeHost = 0;
6526 m_backingLayer = nullptr;
6527 m_isAcceleratedCompositing = false;
6532 #if PLATFORM(WIN) && USE(AVFOUNDATION)
6533 WebCore::GraphicsDeviceAdapter* WebView::graphicsDeviceAdapter() const
6535 if (!m_layerTreeHost)
6537 return m_layerTreeHost->graphicsDeviceAdapter();
6541 HRESULT WebView::unused1()
6543 ASSERT_NOT_REACHED();
6547 HRESULT WebView::unused2()
6549 ASSERT_NOT_REACHED();
6553 HRESULT WebView::unused3()
6555 ASSERT_NOT_REACHED();
6559 HRESULT WebView::unused4()
6561 ASSERT_NOT_REACHED();
6565 HRESULT WebView::unused5()
6567 ASSERT_NOT_REACHED();
6571 HRESULT WebView::setGeolocationProvider(IWebGeolocationProvider* locationProvider)
6573 m_geolocationProvider = locationProvider;
6577 HRESULT WebView::geolocationProvider(IWebGeolocationProvider** locationProvider)
6579 if (!locationProvider)
6582 if (!m_geolocationProvider)
6585 return m_geolocationProvider.copyRefTo(locationProvider);
6588 HRESULT WebView::geolocationDidChangePosition(IWebGeolocationPosition* position)
6592 GeolocationController::from(m_page)->positionChanged(core(position));
6596 HRESULT WebView::geolocationDidFailWithError(IWebError* error)
6603 BSTR descriptionBSTR;
6604 if (FAILED(error->localizedDescription(&descriptionBSTR)))
6606 String descriptionString(descriptionBSTR, SysStringLen(descriptionBSTR));
6607 SysFreeString(descriptionBSTR);
6609 RefPtr<GeolocationError> geolocationError = GeolocationError::create(GeolocationError::PositionUnavailable, descriptionString);
6610 GeolocationController::from(m_page)->errorOccurred(geolocationError.get());
6614 HRESULT WebView::setDomainRelaxationForbiddenForURLScheme(BOOL forbidden, BSTR scheme)
6616 SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(forbidden, String(scheme, SysStringLen(scheme)));
6620 HRESULT WebView::registerURLSchemeAsSecure(BSTR scheme)
6622 SchemeRegistry::registerURLSchemeAsSecure(toString(scheme));
6626 HRESULT WebView::registerURLSchemeAsAllowingLocalStorageAccessInPrivateBrowsing(BSTR scheme)
6628 SchemeRegistry::registerURLSchemeAsAllowingLocalStorageAccessInPrivateBrowsing(toString(scheme));
6632 HRESULT WebView::registerURLSchemeAsAllowingDatabaseAccessInPrivateBrowsing(BSTR scheme)
6634 SchemeRegistry::registerURLSchemeAsAllowingDatabaseAccessInPrivateBrowsing(toString(scheme));
6638 HRESULT WebView::nextDisplayIsSynchronous()
6640 m_nextDisplayIsSynchronous = true;
6644 #if USE(ACCELERATED_COMPOSITING)
6645 void WebView::notifyAnimationStarted(const GraphicsLayer*, double)
6647 // We never set any animations on our backing layer.
6648 ASSERT_NOT_REACHED();
6651 void WebView::notifySyncRequired(const GraphicsLayer*)
6653 flushPendingGraphicsLayerChangesSoon();
6656 void WebView::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& inClip)
6658 Frame* frame = core(m_mainFrame);
6663 context.clip(inClip);
6664 frame->view()->paint(&context, inClip);
6668 bool WebView::showDebugBorders(const GraphicsLayer*) const
6670 return m_page->settings()->showDebugBorders();
6673 bool WebView::showRepaintCounter(const GraphicsLayer*) const
6675 return m_page->settings()->showRepaintCounter();
6678 void WebView::flushPendingGraphicsLayerChanges()
6680 Frame* coreFrame = core(m_mainFrame);
6683 FrameView* view = coreFrame->view();
6686 if (!m_backingLayer)
6689 view->updateLayoutAndStyleIfNeededRecursive();
6691 // Updating layout might have taken us out of compositing mode.
6693 m_backingLayer->syncCompositingStateForThisLayerOnly();
6695 view->syncCompositingStateIncludingSubframes();
6700 class EnumTextMatches : public IEnumTextMatches
6704 Vector<IntRect> m_rects;
6706 EnumTextMatches(Vector<IntRect>* rects) : m_index(0), m_ref(1)
6711 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv)
6713 if (IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IEnumTextMatches)) {
6718 return *ppv?S_OK:E_NOINTERFACE;
6721 virtual ULONG STDMETHODCALLTYPE AddRef()
6726 virtual ULONG STDMETHODCALLTYPE Release()
6736 virtual HRESULT STDMETHODCALLTYPE Next(ULONG, RECT* rect, ULONG* pceltFetched)
6738 if (m_index < m_rects.size()) {
6741 *rect = m_rects[m_index];
6751 virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
6756 virtual HRESULT STDMETHODCALLTYPE Reset(void)
6761 virtual HRESULT STDMETHODCALLTYPE Clone(IEnumTextMatches**)
6767 HRESULT createMatchEnumerator(Vector<IntRect>* rects, IEnumTextMatches** matches)
6769 *matches = new EnumTextMatches(rects);
6770 return (*matches)?S_OK:E_OUTOFMEMORY;
6773 Page* core(IWebView* iWebView)
6777 COMPtr<WebView> webView;
6778 if (SUCCEEDED(iWebView->QueryInterface(&webView)) && webView)
6779 page = webView->page();
6784 HRESULT WebView::defaultMinimumTimerInterval(double* interval)
6788 *interval = Settings::defaultMinDOMTimerInterval();
6792 HRESULT WebView::setMinimumTimerInterval(double interval)
6794 page()->settings()->setMinDOMTimerInterval(interval);
6798 HRESULT WebView::httpPipeliningEnabled(BOOL* enabled)
6802 *enabled = ResourceRequest::httpPipeliningEnabled();
6806 HRESULT WebView::setHTTPPipeliningEnabled(BOOL enabled)
6808 ResourceRequest::setHTTPPipeliningEnabled(enabled);
6812 void WebView::setGlobalHistoryItem(HistoryItem* historyItem)
6814 m_globalHistoryItem = historyItem;
6817 #if ENABLE(FULLSCREEN_API)
6818 bool WebView::supportsFullScreenForElement(const WebCore::Element*, bool withKeyboard) const
6823 BOOL enabled = FALSE;
6824 if (!m_preferences || FAILED(m_preferences->isFullScreenEnabled(&enabled)))
6830 bool WebView::isFullScreen() const
6832 return m_fullscreenController && m_fullscreenController->isFullScreen();
6835 FullScreenController* WebView::fullScreenController()
6837 if (!m_fullscreenController)
6838 m_fullscreenController = adoptPtr(new FullScreenController(this));
6839 return m_fullscreenController.get();
6842 void WebView::setFullScreenElement(PassRefPtr<Element> element)
6844 m_fullScreenElement = element;
6847 HWND WebView::fullScreenClientWindow() const
6849 return m_viewWindow;
6852 HWND WebView::fullScreenClientParentWindow() const
6854 return m_hostWindow;
6857 void WebView::fullScreenClientSetParentWindow(HWND hostWindow)
6859 setHostWindow(reinterpret_cast<OLE_HANDLE>(hostWindow));
6862 void WebView::fullScreenClientWillEnterFullScreen()
6864 ASSERT(m_fullScreenElement);
6865 m_fullScreenElement->document()->webkitWillEnterFullScreenForElement(m_fullScreenElement.get());
6868 void WebView::fullScreenClientDidEnterFullScreen()
6870 ASSERT(m_fullScreenElement);
6871 m_fullScreenElement->document()->webkitDidEnterFullScreenForElement(m_fullScreenElement.get());
6874 void WebView::fullScreenClientWillExitFullScreen()
6876 ASSERT(m_fullScreenElement);
6877 m_fullScreenElement->document()->webkitWillExitFullScreenForElement(m_fullScreenElement.get());
6880 void WebView::fullScreenClientDidExitFullScreen()
6882 ASSERT(m_fullScreenElement);
6883 m_fullScreenElement->document()->webkitDidExitFullScreenForElement(m_fullScreenElement.get());
6884 m_fullScreenElement = nullptr;
6887 void WebView::fullScreenClientForceRepaint()
6889 ASSERT(m_fullScreenElement);
6890 RECT windowRect = {0};
6891 frameRect(&windowRect);
6892 repaint(windowRect, true /*contentChanged*/, true /*immediate*/, false /*contentOnly*/);
6893 m_fullscreenController->repaintCompleted();
6897 // Used by TextInputController in DumpRenderTree
6899 HRESULT STDMETHODCALLTYPE WebView::setCompositionForTesting(
6900 /* [in] */ BSTR composition,
6901 /* [in] */ UINT from,
6902 /* [in] */ UINT length)
6907 Frame* frame = m_page->focusController()->focusedOrMainFrame();
6908 if (!frame || !frame->editor()->canEdit())
6911 String compositionStr(composition, SysStringLen(composition));
6913 Vector<CompositionUnderline> underlines;
6914 underlines.append(CompositionUnderline(0, compositionStr.length(), Color(Color::black), false));
6915 frame->editor()->setComposition(compositionStr, underlines, from, from + length);
6920 HRESULT STDMETHODCALLTYPE WebView::hasCompositionForTesting(/* [out, retval] */ BOOL* result)
6925 Frame* frame = m_page->focusController()->focusedOrMainFrame();
6929 *result = frame && frame->editor()->hasComposition();
6934 HRESULT STDMETHODCALLTYPE WebView::confirmCompositionForTesting(/* [in] */ BSTR composition)
6939 Frame* frame = m_page->focusController()->focusedOrMainFrame();
6940 if (!frame || !frame->editor()->canEdit())
6943 String compositionStr(composition, SysStringLen(composition));
6945 if (compositionStr.isNull())
6946 frame->editor()->confirmComposition();
6948 frame->editor()->confirmComposition(compositionStr);
6953 HRESULT STDMETHODCALLTYPE WebView::compositionRangeForTesting(/* [out] */ UINT* startPosition, /* [out] */ UINT* length)
6958 Frame* frame = m_page->focusController()->focusedOrMainFrame();
6959 if (!frame || !frame->editor()->canEdit())
6962 RefPtr<Range> range = frame->editor()->compositionRange();
6967 *startPosition = range->startOffset();
6968 *length = range->startOffset() + range->endOffset();
6974 HRESULT STDMETHODCALLTYPE WebView::firstRectForCharacterRangeForTesting(
6975 /* [in] */ UINT location,
6976 /* [in] */ UINT length,
6977 /* [out, retval] */ RECT* resultRect)
6982 Frame* frame = m_page->focusController()->focusedOrMainFrame();
6986 IntRect resultIntRect;
6987 resultIntRect.setLocation(IntPoint(0, 0));
6988 resultIntRect.setSize(IntSize(0, 0));
6990 if (location > INT_MAX)
6992 if (length > INT_MAX || location + length > INT_MAX)
6993 length = INT_MAX - location;
6995 RefPtr<Range> range = TextIterator::rangeFromLocationAndLength(frame->selection()->rootEditableElementOrDocumentElement(), location, length);
7000 ASSERT(range->startContainer());
7001 ASSERT(range->endContainer());
7003 IntRect rect = frame->editor()->firstRectForRange(range.get());
7004 resultIntRect = frame->view()->contentsToWindow(rect);
7006 resultRect->left = resultIntRect.x();
7007 resultRect->top = resultIntRect.y();
7008 resultRect->right = resultIntRect.x() + resultIntRect.width();
7009 resultRect->bottom = resultIntRect.y() + resultIntRect.height();
7014 HRESULT STDMETHODCALLTYPE WebView::selectedRangeForTesting(/* [out] */ UINT* location, /* [out] */ UINT* length)
7019 Frame* frame = m_page->focusController()->focusedOrMainFrame();
7023 RefPtr<Range> range = frame->editor()->selectedRange();
7025 size_t locationSize;
7027 if (range && TextIterator::getLocationAndLengthFromRange(frame->selection()->rootEditableElementOrDocumentElement(), range.get(), locationSize, lengthSize)) {
7028 *location = static_cast<UINT>(locationSize);
7029 *length = static_cast<UINT>(lengthSize);