c40d8904856c90110109e8b7610d59311a57aa81
[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
510     ResourceRequest r(d->frame->resourceRequest());    
511     r.m_responseMIMEType = "text/html";  // FIXME: get from PlatformResponse
512     d->frame->setResourceRequest(r);
513
514     d->frame->begin(kurl);
515
516     if (m_loadType != WebFrameLoadTypeBack && m_loadType != WebFrameLoadTypeForward && m_loadType != WebFrameLoadTypeIndexedBackForward && !m_quickRedirectComing) {
517         DeprecatedString urlStr = job->url().url();
518         BSTR urlBStr = SysAllocStringLen((LPCOLESTR)urlStr.unicode(), urlStr.length());
519         WebHistoryItem* historyItem = WebHistoryItem::createInstance();
520         if (SUCCEEDED(historyItem->initWithURLString(urlBStr, 0/*FIXME*/))) {
521             IWebBackForwardList* backForwardList;
522             if (SUCCEEDED(d->webView->backForwardList(&backForwardList))) {
523                 backForwardList->addItem(historyItem);
524                 backForwardList->Release();
525             }
526             historyItem->Release();
527         }
528     }
529
530     IWebFrameLoadDelegate* frameLoadDelegate;
531     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
532         frameLoadDelegate->didCommitLoadForFrame(d->webView, this);
533         frameLoadDelegate->Release();
534     }
535 }
536
537 void WebFrame::receivedData(ResourceLoader*, const char* data, int length)
538 {
539     // Ensure that WebFrame::receivedResponse was called.
540     _ASSERT(m_dataSource && !m_provisionalDataSource);
541
542     d->frame->write(data, length);
543 }
544
545 void WebFrame::receivedAllData(ResourceLoader* /*job*/)
546 {
547     m_quickRedirectComing = false;
548     m_loadType = WebFrameLoadTypeStandard;
549 }
550
551 void WebFrame::receivedAllData(ResourceLoader*, PlatformData data)
552 {
553     IWebFrameLoadDelegate* frameLoadDelegate;
554     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
555
556         if (data->loaded) {
557             frameLoadDelegate->didFinishLoadForFrame(d->webView, this);
558         }
559         else {
560             frameLoadDelegate->didFailLoadWithError(d->webView, 0/*FIXME*/, this);
561             m_quickRedirectComing = false;
562             m_loadType = WebFrameLoadTypeStandard;
563         }
564
565         frameLoadDelegate->Release();
566     }
567
568     d->frame->end();
569 }
570
571 // FrameWinClient
572
573 void WebFrame::createNewWindow(const WebCore::ResourceRequest&)
574 {
575     // FIXME: This seems to never get called. Is it necessary?
576     IWebUIDelegate* uiDelegate = NULL;
577     if (FAILED(d->webView->uiDelegate(&uiDelegate)) || !uiDelegate)
578         return;
579     IWebView* new_view = NULL;
580     uiDelegate->createWebViewWithRequest(d->webView, NULL, &new_view);
581 }
582
583 void WebFrame::createNewWindow(const WebCore::ResourceRequest&,
584                                const WebCore::WindowArgs&,
585                                WebCore::Frame*& part)
586 {
587     IWebUIDelegate* uiDelegate = NULL;
588     if (FAILED(d->webView->uiDelegate(&uiDelegate)) || !uiDelegate)
589         return;
590     IWebView* new_view = NULL;
591     if (FAILED(uiDelegate->createWebViewWithRequest(d->webView, NULL, &new_view)) || !new_view)
592         return;
593
594     IWebFrame* new_iwebframe = NULL;
595     if (FAILED(new_view->mainFrame(&new_iwebframe)) || !new_iwebframe)
596       return;
597
598     WebFrame* new_frame = static_cast<WebFrame*>(new_iwebframe);
599     part = new_frame->d->frame.get();
600 }
601
602 void WebFrame::openURL(const DeprecatedString& url, bool lockHistory)
603 {
604     DeprecatedString terminatedURL(url);
605     terminatedURL.append('\0');
606
607     m_quickRedirectComing = lockHistory;
608     BSTR urlBStr = SysAllocString((LPCTSTR)terminatedURL.unicode());
609     IWebMutableURLRequest* request = WebMutableURLRequest::createInstance();
610     if (SUCCEEDED(request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 0)))
611         loadRequest(request);
612     SysFreeString(urlBStr);
613     request->Release();
614 }
615
616 void WebFrame::submitForm(const String& method, const KURL& url, const FormData* submitFormData)
617 {
618     // FIXME: This is a dumb implementation, doesn't handle subframes, etc.
619
620     DeprecatedString terminatedURL(url.url());
621     terminatedURL.append('\0');
622     DeprecatedString terminatedMethod(method.deprecatedString());
623     terminatedMethod.append('\0');
624
625     m_quickRedirectComing = false;
626     m_loadType = WebFrameLoadTypeStandard;
627     BSTR urlBStr = SysAllocString((LPCTSTR)terminatedURL.unicode());
628     BSTR methodBStr = SysAllocString((LPCTSTR)terminatedMethod.unicode());
629     WebMutableURLRequest* request = WebMutableURLRequest::createInstance();
630     if (SUCCEEDED(request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 0))) {
631         request->setHTTPMethod(methodBStr);
632         request->setFormData(submitFormData);
633         loadRequest(request);
634     }
635     SysFreeString(urlBStr);
636     SysFreeString(methodBStr);
637     request->Release();
638 }
639
640 void WebFrame::setTitle(const String& title)
641 {
642     IWebFrameLoadDelegate* frameLoadDelegate;
643     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
644         BSTR titleBStr = SysAllocStringLen(title.characters(), title.length());
645         frameLoadDelegate->didReceiveTitle(d->webView, titleBStr, this);
646         SysFreeString(titleBStr);
647         frameLoadDelegate->Release();
648     }
649 }
650
651 void WebFrame::setStatusText(const String& statusText)
652 {
653     IWebUIDelegate* uiDelegate;
654     if (SUCCEEDED(d->webView->uiDelegate(&uiDelegate))) {
655         BSTR statusBStr = SysAllocStringLen(statusText.characters(), statusText.length());
656         uiDelegate->setStatusText(d->webView, statusBStr);
657         SysFreeString(statusBStr);
658         uiDelegate->Release();
659     }
660 }