0769e86eb22fe8e1a17d088d0296868063f09426
[WebKit-https.git] / WebKit / COM / WebFrame.cpp
1 /*
2  * Copyright (C) 2006 Apple Computer, 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
29 #include "IWebURLResponse.h"
30 #include "WebMutableURLRequest.h"
31 #include "WebFrame.h"
32 #include "WebView.h"
33 #include "WebDataSource.h"
34 #include "WebHistoryItem.h"
35
36 #pragma warning( push, 0 )
37 #include "Cache.h"
38 #include "Document.h"
39 #include "FrameView.h"
40 #include "FrameWin.h"
41 #include "GraphicsContext.h"
42 #include "Page.h"
43 #include "RenderFrame.h"
44 #include "cairo.h"
45 #include "cairo-win32.h"
46 #include "ResourceLoader.h"
47 #include "ResourceLoaderWin.h"
48 #pragma warning(pop)
49
50 using namespace WebCore;
51
52 // WebFramePrivate ------------------------------------------------------------
53
54 class WebFrame::WebFramePrivate {
55 public:
56     WebFramePrivate() { }
57     ~WebFramePrivate() { }
58
59     RefPtr<Frame> frame;
60     RefPtr<FrameView> frameView;
61     WebView* webView;
62 };
63
64 // WebFrame ----------------------------------------------------------------
65
66 WebFrame::WebFrame()
67 : m_refCount(0)
68 , d(new WebFrame::WebFramePrivate)
69 , m_dataSource(0)
70 , m_provisionalDataSource(0)
71 , m_quickRedirectComing(false)
72 {
73     gClassCount++;
74 }
75
76 WebFrame::~WebFrame()
77 {
78     delete d->frame->page();
79     delete d;
80     gClassCount--;
81 }
82
83 WebFrame* WebFrame::createInstance()
84 {
85     WebFrame* instance = new WebFrame();
86     instance->AddRef();
87     return instance;
88 }
89
90 // IUnknown -------------------------------------------------------------------
91
92 HRESULT STDMETHODCALLTYPE WebFrame::QueryInterface(REFIID riid, void** ppvObject)
93 {
94     *ppvObject = 0;
95     if (IsEqualGUID(riid, IID_IUnknown))
96         *ppvObject = static_cast<IWebFrame*>(this);
97     else if (IsEqualGUID(riid, IID_IWebFrame))
98         *ppvObject = static_cast<IWebFrame*>(this);
99     else
100         return E_NOINTERFACE;
101
102     AddRef();
103     return S_OK;
104 }
105
106 ULONG STDMETHODCALLTYPE WebFrame::AddRef(void)
107 {
108     return ++m_refCount;
109 }
110
111 ULONG STDMETHODCALLTYPE WebFrame::Release(void)
112 {
113     ULONG newRef = --m_refCount;
114     if (!newRef)
115         delete(this);
116
117     return newRef;
118 }
119
120 // IWebFrame -------------------------------------------------------------------
121
122 HRESULT STDMETHODCALLTYPE WebFrame::initWithName( 
123     /* [in] */ BSTR /*name*/,
124     /* [in] */ IWebFrameView* /*view*/,
125     /* [in] */ IWebView* webView)
126 {
127     if (webView)
128         webView->AddRef();
129
130     d->webView = static_cast<WebView*>(webView);
131     HWND windowHandle;
132     HRESULT hr = d->webView->viewWindow(&windowHandle);
133     if (FAILED(hr))
134         return hr;
135
136     Page* page = new Page();
137     Frame* frame = new FrameWin(page, 0, this);
138
139     // FIXME: This is one-time initialization, but it gets the value of the setting from the
140     // current WebView. That's a mismatch and not good!
141     static bool initializedObjectCacheSize = false;
142     if (!initializedObjectCacheSize) {
143         Cache::setSize(getObjectCacheSize());
144         initializedObjectCacheSize = true;
145     }
146
147     d->frame = frame;
148     frame->deref(); // Frames are created with a refcount of 1.  Release this ref, since we've assigned it to a RefPtr
149     page->setMainFrame(frame);
150     FrameView* frameView = new FrameView(frame);
151     d->frameView = frameView;
152     frameView->deref(); // FrameViews are created with a refcount of 1.  Release this ref, since we've assigned it to a RefPtr
153     d->frame->setView(frameView);
154     d->frameView->setContainingWindow(windowHandle);
155
156     return S_OK;
157 }
158
159 HRESULT STDMETHODCALLTYPE WebFrame::name( 
160     /* [retval][out] */ BSTR* /*frameName*/)
161 {
162     DebugBreak();
163     return E_NOTIMPL;
164 }
165
166 HRESULT STDMETHODCALLTYPE WebFrame::webView( 
167     /* [retval][out] */ IWebView* /*view*/)
168 {
169     DebugBreak();
170     return E_NOTIMPL;
171 }
172
173 HRESULT STDMETHODCALLTYPE WebFrame::frameView( 
174     /* [retval][out] */ IWebFrameView* /*view*/)
175 {
176     DebugBreak();
177     return E_NOTIMPL;
178 }
179
180 HRESULT STDMETHODCALLTYPE WebFrame::DOMDocument( 
181     /* [retval][out] */ IDOMDocument** /*document*/)
182 {
183     DebugBreak();
184     return E_NOTIMPL;
185 }
186
187 HRESULT STDMETHODCALLTYPE WebFrame::frameElement( 
188     /* [retval][out] */ IDOMHTMLElement* /*frameElement*/)
189 {
190     DebugBreak();
191     return E_NOTIMPL;
192 }
193
194 HRESULT STDMETHODCALLTYPE WebFrame::loadRequest( 
195     /* [in] */ IWebURLRequest* request)
196 {
197     HRESULT hr = S_OK;
198
199     if (m_provisionalDataSource) {
200         m_provisionalDataSource->Release();
201         m_provisionalDataSource = 0;
202         // FIXME - cancel the outstanding request?
203     }
204
205     m_provisionalDataSource = WebDataSource::createInstance(this);
206     hr = m_provisionalDataSource->initWithRequest(request);
207
208     return hr;
209 }
210
211 HRESULT STDMETHODCALLTYPE WebFrame::loadData( 
212     /* [in] */ IStream* /*data*/,
213     /* [in] */ BSTR /*mimeType*/,
214     /* [in] */ BSTR /*textEncodingName*/,
215     /* [in] */ BSTR /*url*/)
216 {
217     DebugBreak();
218     return E_NOTIMPL;
219 }
220
221 HRESULT STDMETHODCALLTYPE WebFrame::loadHTMLString( 
222     /* [in] */ BSTR string,
223     /* [in] */ BSTR baseURL)
224 {
225     DeprecatedString htmlString((DeprecatedChar*)string, SysStringLen(string));
226
227     if (baseURL) {
228         DeprecatedString baseURLString((DeprecatedChar*)baseURL, SysStringLen(baseURL));
229         d->frame->begin(KURL(baseURLString));
230     }
231     else
232         d->frame->begin();
233     d->frame->write(htmlString);
234     d->frame->end();
235
236     return S_OK;
237 }
238
239 HRESULT STDMETHODCALLTYPE WebFrame::loadAlternateHTMLString( 
240     /* [in] */ BSTR /*str*/,
241     /* [in] */ BSTR /*baseURL*/,
242     /* [in] */ BSTR /*unreachableURL*/)
243 {
244     DebugBreak();
245     return E_NOTIMPL;
246 }
247
248 HRESULT STDMETHODCALLTYPE WebFrame::loadArchive( 
249     /* [in] */ IWebArchive* /*archive*/)
250 {
251     DebugBreak();
252     return E_NOTIMPL;
253 }
254
255 HRESULT STDMETHODCALLTYPE WebFrame::dataSource( 
256     /* [retval][out] */ IWebDataSource** source)
257 {
258     if (m_dataSource)
259         m_dataSource->AddRef();
260     *source = m_dataSource;
261
262     return S_OK;
263 }
264
265 HRESULT STDMETHODCALLTYPE WebFrame::provisionalDataSource( 
266     /* [retval][out] */ IWebDataSource** source)
267 {
268     if (m_provisionalDataSource)
269         m_provisionalDataSource->AddRef();
270     *source = m_provisionalDataSource;
271
272     return S_OK;
273 }
274
275 HRESULT STDMETHODCALLTYPE WebFrame::stopLoading( void)
276 {
277 //    DebugBreak();
278     return E_NOTIMPL;
279 }
280
281 HRESULT STDMETHODCALLTYPE WebFrame::reload( void)
282 {
283     if (!d->frame->url().url().startsWith("javascript:", false))
284         d->frame->scheduleLocationChange(d->frame->url().url(), d->frame->referrer(), true/*lock history*/, true/*userGesture*/);
285     return S_OK;
286 }
287
288 HRESULT STDMETHODCALLTYPE WebFrame::findFrameNamed( 
289     /* [in] */ BSTR /*name*/,
290     /* [retval][out] */ IWebFrame** /*frame*/)
291 {
292     DebugBreak();
293     return E_NOTIMPL;
294 }
295
296 HRESULT STDMETHODCALLTYPE WebFrame::parentFrame( 
297     /* [retval][out] */ IWebFrame** /*frame*/)
298 {
299     DebugBreak();
300     return E_NOTIMPL;
301 }
302
303 HRESULT STDMETHODCALLTYPE WebFrame::childFrames( 
304     /* [out] */ int* /*frameCount*/,
305     /* [retval][out] */ IWebFrame*** /*frames*/)
306 {
307     DebugBreak();
308     return E_NOTIMPL;
309 }
310
311 // WebFrame ---------------------------------------------------------------
312
313 void WebFrame::paint()
314 {
315     d->frameView->layout();
316
317     HWND windowHandle;
318     if (FAILED(d->webView->viewWindow(&windowHandle)))
319         return;
320
321     PAINTSTRUCT ps;
322     HDC hdc = BeginPaint(windowHandle, &ps);
323     cairo_surface_t* finalSurface = cairo_win32_surface_create(hdc);
324     cairo_surface_t* surface = cairo_win32_surface_create_with_dib(CAIRO_FORMAT_ARGB32,  
325                                                             ps.rcPaint.right - ps.rcPaint.left,  
326                                                             ps.rcPaint.bottom - ps.rcPaint.top); 
327
328     cairo_t* context = cairo_create(surface);
329     GraphicsContext gc(context);
330     
331     IntRect documentDirtyRect = ps.rcPaint;
332     documentDirtyRect.move(d->frameView->contentsX(), d->frameView->contentsY());
333
334     HDC surfaceDC = cairo_win32_surface_get_dc(surface);
335     SaveDC(surfaceDC);
336     cairo_translate(context, -d->frameView->contentsX() - ps.rcPaint.left, 
337                              -d->frameView->contentsY() - ps.rcPaint.top);
338     d->frame->paint(&gc, documentDirtyRect);
339     RestoreDC(surfaceDC, -1);
340
341     cairo_destroy(context);
342     context = cairo_create(finalSurface);
343     cairo_set_operator(context, CAIRO_OPERATOR_SOURCE);
344     cairo_set_source_surface(context, surface, ps.rcPaint.left, ps.rcPaint.top);
345     cairo_rectangle(context, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
346     cairo_fill(context);
347     cairo_destroy(context);
348
349     cairo_surface_destroy(surface);
350     cairo_surface_destroy(finalSurface);
351
352     EndPaint(windowHandle, &ps);
353 }
354
355 Frame* WebFrame::impl()
356 {
357     return d->frame.get();
358 }
359
360 HRESULT WebFrame::loadDataSource(WebDataSource* dataSource)
361 {
362     HRESULT hr = S_OK;
363     BSTR url = 0;
364     BSTR method = 0;
365
366     IWebMutableURLRequest* request;
367     hr = dataSource->request(&request);
368     if (SUCCEEDED(hr)) {
369         HRESULT hr = request->URL(&url);
370         if (SUCCEEDED(hr)) {
371             hr = request->HTTPMethod(&method);
372             if (SUCCEEDED(hr)) {
373                 KURL kurl(DeprecatedString((DeprecatedChar*)url, SysStringLen(url)));
374                 d->frame->didOpenURL(kurl);
375                 String methodString(method, SysStringLen(method));
376                 const FormData* formData = 0;
377                 if (wcscmp(method, TEXT("GET"))) {
378                     WebMutableURLRequest* requestImpl = static_cast<WebMutableURLRequest*>(request);
379                     formData = requestImpl->formData();
380                 }
381                 RefPtr<ResourceLoader> loader = formData ?
382                   ResourceLoader::create(this, methodString, kurl, *formData) :
383                   ResourceLoader::create(this, methodString, kurl);
384                 loader->start(d->frame->document()->docLoader());
385                 IWebFrameLoadDelegate* frameLoadDelegate;
386                 if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
387                     frameLoadDelegate->didStartProvisionalLoadForFrame(d->webView, this);
388                     frameLoadDelegate->Release();
389                 }
390             }
391         }
392         request->Release();
393     }
394
395     SysFreeString(url);
396     SysFreeString(method);
397
398     return hr;
399 }
400
401 bool WebFrame::loading()
402 {
403     return !!m_provisionalDataSource;
404 }
405
406 HRESULT WebFrame::goToItem(IWebHistoryItem* item, WebFrameLoadType withLoadType)
407 {
408     IWebBackForwardList* backForwardList;
409     HRESULT hr = d->webView->backForwardList(&backForwardList);
410     if (SUCCEEDED(hr)) {
411         backForwardList->goToItem(item);
412         backForwardList->Release();
413         hr = loadItem(item, withLoadType);
414     }
415     return hr;
416 }
417
418 HRESULT WebFrame::loadItem(IWebHistoryItem* item, WebFrameLoadType withLoadType)
419 {
420     m_loadType = withLoadType;
421
422     BSTR urlBStr;
423     HRESULT hr = item->URLString(&urlBStr);
424     if (FAILED(hr))
425         return hr;
426
427     IWebMutableURLRequest* request = WebMutableURLRequest::createInstance();
428     hr = request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 0);
429     if (SUCCEEDED(hr))
430         loadRequest(request);
431
432     SysFreeString(urlBStr);
433     request->Release();
434
435     return hr;
436 }
437
438 static unsigned long long WebSystemMainMemory()
439 {
440     MEMORYSTATUSEX statex;
441     
442     statex.dwLength = sizeof (statex);
443     GlobalMemoryStatusEx (&statex);
444     return statex.ullTotalPhys;
445 }
446
447 int WebFrame::getObjectCacheSize()
448 {
449     const int WebKitObjectCacheSizePreferenceKey = 16777216; // FIXME!
450
451     unsigned long long memSize = WebSystemMainMemory();
452     int cacheSize = WebKitObjectCacheSizePreferenceKey;
453     int multiplier = 1;
454     if (memSize >= 1024 * 1024 * 1000 /*1024*/)
455         multiplier = 4;
456     else if (memSize >= 512 * 1024 * 1024)
457         multiplier = 2;
458
459     return cacheSize * multiplier;
460 }
461
462 // ResourceLoaderClient
463
464 void WebFrame::receivedRedirect(ResourceLoader*, const KURL& url)
465 {
466     DeprecatedString urlStr(url.url());
467     urlStr.append('\0');
468
469     // FIXME: is this the correct way to handle a redirect?
470
471     IWebMutableURLRequest* request = WebMutableURLRequest::createInstance();
472     BSTR urlBStr = SysAllocString((LPCTSTR)urlStr.unicode());
473     if (SUCCEEDED(request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 0))) {
474         _ASSERT(m_provisionalDataSource);
475         static_cast<WebDataSource*>(m_provisionalDataSource)->replaceRequest(request);
476     }
477     SysFreeString(urlBStr);
478     request->Release();
479
480     IWebFrameLoadDelegate* frameLoadDelegate;
481     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
482         frameLoadDelegate->didReceiveServerRedirectForProvisionalLoadForFrame(d->webView, this);
483         frameLoadDelegate->Release();
484     }
485 }
486
487 void WebFrame::receivedResponse(ResourceLoader* job, PlatformResponse)
488 {
489     // Commit the provisional data source
490
491     if (m_provisionalDataSource) {
492         m_dataSource = m_provisionalDataSource;
493         m_provisionalDataSource = 0;
494     }
495
496     // Tell the Frame to expect new data.  We use the URL of the data source in
497     // order to account for redirects.
498
499     IWebMutableURLRequest* request;
500     m_dataSource->request(&request);
501
502     BSTR url;
503     request->URL(&url);
504     request->Release();
505
506     KURL kurl(DeprecatedString((DeprecatedChar*)url, SysStringLen(url)));
507     SysFreeString(url);
508
509     // Update MIME info (FIXME: get from PlatformResponse)
510     d->frame->setResponseMIMEType(String(L"text/html"));
511
512     d->frame->begin(kurl);
513
514     if (m_loadType != WebFrameLoadTypeBack && m_loadType != WebFrameLoadTypeForward && m_loadType != WebFrameLoadTypeIndexedBackForward && !m_quickRedirectComing) {
515         DeprecatedString urlStr = job->url().url();
516         BSTR urlBStr = SysAllocStringLen((LPCOLESTR)urlStr.unicode(), urlStr.length());
517         WebHistoryItem* historyItem = WebHistoryItem::createInstance();
518         if (SUCCEEDED(historyItem->initWithURLString(urlBStr, 0/*FIXME*/))) {
519             IWebBackForwardList* backForwardList;
520             if (SUCCEEDED(d->webView->backForwardList(&backForwardList))) {
521                 backForwardList->addItem(historyItem);
522                 backForwardList->Release();
523             }
524             historyItem->Release();
525         }
526     }
527
528     IWebFrameLoadDelegate* frameLoadDelegate;
529     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
530         frameLoadDelegate->didCommitLoadForFrame(d->webView, this);
531         frameLoadDelegate->Release();
532     }
533 }
534
535 void WebFrame::receivedData(ResourceLoader*, const char* data, int length)
536 {
537     // Ensure that WebFrame::receivedResponse was called.
538     _ASSERT(m_dataSource && !m_provisionalDataSource);
539
540     d->frame->write(data, length);
541 }
542
543 void WebFrame::receivedAllData(ResourceLoader* /*job*/)
544 {
545     m_quickRedirectComing = false;
546     m_loadType = WebFrameLoadTypeStandard;
547 }
548
549 void WebFrame::receivedAllData(ResourceLoader*, PlatformData data)
550 {
551     IWebFrameLoadDelegate* frameLoadDelegate;
552     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
553
554         if (data->loaded) {
555             frameLoadDelegate->didFinishLoadForFrame(d->webView, this);
556         }
557         else {
558             frameLoadDelegate->didFailLoadWithError(d->webView, 0/*FIXME*/, this);
559             m_quickRedirectComing = false;
560             m_loadType = WebFrameLoadTypeStandard;
561         }
562
563         frameLoadDelegate->Release();
564     }
565
566     d->frame->end();
567 }
568
569 // FrameWinClient
570
571 void WebFrame::createNewWindow(const WebCore::ResourceRequest&)
572 {
573     // FIXME: This seems to never get called. Is it necessary?
574     IWebUIDelegate* uiDelegate = NULL;
575     if (FAILED(d->webView->uiDelegate(&uiDelegate)) || !uiDelegate)
576         return;
577     IWebView* new_view = NULL;
578     uiDelegate->createWebViewWithRequest(d->webView, NULL, &new_view);
579 }
580
581 void WebFrame::createNewWindow(const WebCore::ResourceRequest&,
582                                const WebCore::WindowArgs&,
583                                WebCore::Frame*& part)
584 {
585     IWebUIDelegate* uiDelegate = NULL;
586     if (FAILED(d->webView->uiDelegate(&uiDelegate)) || !uiDelegate)
587         return;
588     IWebView* new_view = NULL;
589     if (FAILED(uiDelegate->createWebViewWithRequest(d->webView, NULL, &new_view)) || !new_view)
590         return;
591
592     IWebFrame* new_iwebframe = NULL;
593     if (FAILED(new_view->mainFrame(&new_iwebframe)) || !new_iwebframe)
594       return;
595
596     WebFrame* new_frame = static_cast<WebFrame*>(new_iwebframe);
597     part = new_frame->d->frame.get();
598 }
599
600 void WebFrame::openURL(const DeprecatedString& url, bool lockHistory)
601 {
602     DeprecatedString terminatedURL(url);
603     terminatedURL.append('\0');
604
605     m_quickRedirectComing = lockHistory;
606     BSTR urlBStr = SysAllocString((LPCTSTR)terminatedURL.unicode());
607     IWebMutableURLRequest* request = WebMutableURLRequest::createInstance();
608     if (SUCCEEDED(request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 0)))
609         loadRequest(request);
610     SysFreeString(urlBStr);
611     request->Release();
612 }
613
614 void WebFrame::submitForm(const String& method, const KURL& url, const FormData* submitFormData)
615 {
616     // FIXME: This is a dumb implementation, doesn't handle subframes, etc.
617
618     DeprecatedString terminatedURL(url.url());
619     terminatedURL.append('\0');
620     DeprecatedString terminatedMethod(method.deprecatedString());
621     terminatedMethod.append('\0');
622
623     m_quickRedirectComing = false;
624     m_loadType = WebFrameLoadTypeStandard;
625     BSTR urlBStr = SysAllocString((LPCTSTR)terminatedURL.unicode());
626     BSTR methodBStr = SysAllocString((LPCTSTR)terminatedMethod.unicode());
627     WebMutableURLRequest* request = WebMutableURLRequest::createInstance();
628     if (SUCCEEDED(request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 0))) {
629         request->setHTTPMethod(methodBStr);
630         request->setFormData(submitFormData);
631         loadRequest(request);
632     }
633     SysFreeString(urlBStr);
634     SysFreeString(methodBStr);
635     request->Release();
636 }
637
638 void WebFrame::setTitle(const String& title)
639 {
640     IWebFrameLoadDelegate* frameLoadDelegate;
641     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
642         BSTR titleBStr = SysAllocStringLen(title.characters(), title.length());
643         frameLoadDelegate->didReceiveTitle(d->webView, titleBStr, this);
644         SysFreeString(titleBStr);
645         frameLoadDelegate->Release();
646     }
647 }
648
649 void WebFrame::setStatusText(const String& statusText)
650 {
651     IWebUIDelegate* uiDelegate;
652     if (SUCCEEDED(d->webView->uiDelegate(&uiDelegate))) {
653         BSTR statusBStr = SysAllocStringLen(statusText.characters(), statusText.length());
654         uiDelegate->setStatusText(d->webView, statusBStr);
655         SysFreeString(statusBStr);
656         uiDelegate->Release();
657     }
658 }