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