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