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