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