diff options
Diffstat (limited to 'WebKit/win/WebFrame.cpp')
-rw-r--r-- | WebKit/win/WebFrame.cpp | 968 |
1 files changed, 951 insertions, 17 deletions
diff --git a/WebKit/win/WebFrame.cpp b/WebKit/win/WebFrame.cpp index 0a87263..ebaa7b3 100644 --- a/WebKit/win/WebFrame.cpp +++ b/WebKit/win/WebFrame.cpp @@ -31,9 +31,16 @@ #include "COMPtr.h" #include "DefaultPolicyDelegate.h" #include "DOMCoreClasses.h" -#include "FormValuesPropertyBag.h" +#include "IWebError.h" +#include "IWebErrorPrivate.h" +#include "IWebHistory.h" +#include "IWebHistoryItemPrivate.h" +#include "IWebFrameLoadDelegatePrivate.h" +#include "IWebFormDelegate.h" +#include "IWebUIDelegatePrivate.h" #include "MarshallingHelpers.h" #include "WebActionPropertyBag.h" +#include "WebCachedPagePlatformData.h" #include "WebChromeClient.h" #include "WebDocumentLoader.h" #include "WebDownload.h" @@ -50,8 +57,10 @@ #include "WebHistoryItem.h" #include "WebScriptDebugger.h" #include "WebScriptDebugServer.h" +#include "WebURLAuthenticationChallenge.h" #include "WebURLResponse.h" #pragma warning( push, 0 ) +#include <WebCore/AuthenticationChallenge.h> #include <WebCore/BString.h> #include <WebCore/Cache.h> #include <WebCore/Document.h> @@ -122,6 +131,12 @@ const float PrintingMinimumShrinkFactor = 1.25f; // behavior matches MacIE and Mozilla, at least) const float PrintingMaximumShrinkFactor = 2.0f; + +// {A3676398-4485-4a9d-87DC-CB5A40E6351D} +const GUID IID_WebFrame = +{ 0xa3676398, 0x4485, 0x4a9d, { 0x87, 0xdc, 0xcb, 0x5a, 0x40, 0xe6, 0x35, 0x1d } }; + + //----------------------------------------------------------------------------- // Helpers to convert from WebCore to WebKit type WebFrame* kit(Frame* frame) @@ -150,6 +165,202 @@ Frame* core(const WebFrame* webFrame) return const_cast<WebFrame*>(webFrame)->impl(); } +WebView* kit(Page* page) +{ + return page ? static_cast<WebChromeClient*>(page->chrome()->client())->webView() : 0; +} + +//----------------------------------------------------------------------------- + +class FormValuesPropertyBag : public IPropertyBag, public IPropertyBag2 +{ +public: + FormValuesPropertyBag(HashMap<String, String>* formValues) : m_formValues(formValues) {} + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(void); + virtual ULONG STDMETHODCALLTYPE Release(void); + + // IPropertyBag + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Read( + /* [in] */ LPCOLESTR pszPropName, + /* [out][in] */ VARIANT* pVar, + /* [in] */ IErrorLog* pErrorLog); + + virtual HRESULT STDMETHODCALLTYPE Write( + /* [in] */ LPCOLESTR pszPropName, + /* [in] */ VARIANT* pVar); + + // IPropertyBag2 + virtual HRESULT STDMETHODCALLTYPE Read( + /* [in] */ ULONG cProperties, + /* [in] */ PROPBAG2 *pPropBag, + /* [in] */ IErrorLog *pErrLog, + /* [out] */ VARIANT *pvarValue, + /* [out] */ HRESULT *phrError); + + virtual HRESULT STDMETHODCALLTYPE Write( + /* [in] */ ULONG cProperties, + /* [in] */ PROPBAG2 *pPropBag, + /* [in] */ VARIANT *pvarValue); + + virtual HRESULT STDMETHODCALLTYPE CountProperties( + /* [out] */ ULONG *pcProperties); + + virtual HRESULT STDMETHODCALLTYPE GetPropertyInfo( + /* [in] */ ULONG iProperty, + /* [in] */ ULONG cProperties, + /* [out] */ PROPBAG2 *pPropBag, + /* [out] */ ULONG *pcProperties); + + virtual HRESULT STDMETHODCALLTYPE LoadObject( + /* [in] */ LPCOLESTR pstrName, + /* [in] */ DWORD dwHint, + /* [in] */ IUnknown *pUnkObject, + /* [in] */ IErrorLog *pErrLog); + +protected: + HashMap<String, String>* m_formValues; +}; + +HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::QueryInterface(REFIID riid, void** ppvObject) +{ + *ppvObject = 0; + if (IsEqualGUID(riid, IID_IUnknown)) + *ppvObject = this; + else if (IsEqualGUID(riid, IID_IPropertyBag)) + *ppvObject = static_cast<IPropertyBag*>(this); + else if (IsEqualGUID(riid, IID_IPropertyBag2)) + *ppvObject = static_cast<IPropertyBag2*>(this); + else + return E_NOINTERFACE; + + AddRef(); + return S_OK; +} + +ULONG STDMETHODCALLTYPE FormValuesPropertyBag::AddRef(void) +{ + return 1; +} + +ULONG STDMETHODCALLTYPE FormValuesPropertyBag::Release(void) +{ + return 0; +} + +HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* /*pErrorLog*/) +{ + HRESULT hr = S_OK; + + if (!pszPropName || !pVar) + return E_POINTER; + + String key(pszPropName); + if (!m_formValues->contains(key)) + return E_INVALIDARG; + + String value = m_formValues->get(key); + + VARTYPE requestedType = V_VT(pVar); + VariantClear(pVar); + V_VT(pVar) = VT_BSTR; + V_BSTR(pVar) = SysAllocStringLen(value.characters(), value.length()); + if (value.length() && !V_BSTR(pVar)) + return E_OUTOFMEMORY; + + if (requestedType != VT_BSTR && requestedType != VT_EMPTY) + hr = VariantChangeType(pVar, pVar, VARIANT_NOUSEROVERRIDE | VARIANT_ALPHABOOL, requestedType); + + return hr; +} + +HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::Write(LPCOLESTR pszPropName, VARIANT* pVar) +{ + if (!pszPropName || !pVar) + return E_POINTER; + VariantClear(pVar); + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::Read( + /* [in] */ ULONG cProperties, + /* [in] */ PROPBAG2* pPropBag, + /* [in] */ IErrorLog* pErrLog, + /* [out] */ VARIANT* pvarValue, + /* [out] */ HRESULT* phrError) +{ + if (cProperties > (size_t)m_formValues->size()) + return E_INVALIDARG; + if (!pPropBag || !pvarValue || !phrError) + return E_POINTER; + + for (ULONG i=0; i<cProperties; i++) { + VariantInit(&pvarValue[i]); + phrError[i] = Read(pPropBag->pstrName, &pvarValue[i], pErrLog); + } + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::Write( + /* [in] */ ULONG /*cProperties*/, + /* [in] */ PROPBAG2* pPropBag, + /* [in] */ VARIANT* pvarValue) +{ + if (!pPropBag || !pvarValue) + return E_POINTER; + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::CountProperties( + /* [out] */ ULONG* pcProperties) +{ + *pcProperties = m_formValues->size(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::GetPropertyInfo( + /* [in] */ ULONG iProperty, + /* [in] */ ULONG cProperties, + /* [out] */ PROPBAG2* pPropBag, + /* [out] */ ULONG* pcProperties) +{ + if (iProperty > (size_t)m_formValues->size() || iProperty+cProperties > (size_t)m_formValues->size()) + return E_INVALIDARG; + if (!pPropBag || !pcProperties) + return E_POINTER; + + *pcProperties = 0; + ULONG i = 0; + ULONG endProperty = iProperty + cProperties; + for (HashMap<String, String>::iterator it = m_formValues->begin(); i<endProperty; i++) { + if (i >= iProperty) { + int storeIndex = (*pcProperties)++; + pPropBag[storeIndex].dwType = PROPBAG2_TYPE_DATA; + pPropBag[storeIndex].vt = VT_BSTR; + pPropBag[storeIndex].cfType = CF_TEXT; + pPropBag[storeIndex].dwHint = 0; + pPropBag[storeIndex].pstrName = const_cast<LPOLESTR>(it->first.charactersWithNullTermination()); + } + ++it; + } + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::LoadObject( + /* [in] */ LPCOLESTR pstrName, + /* [in] */ DWORD /*dwHint*/, + /* [in] */ IUnknown* pUnkObject, + /* [in] */ IErrorLog* /*pErrLog*/) +{ + if (!pstrName || !pUnkObject) + return E_POINTER; + return E_FAIL; +} + //----------------------------------------------------------------------------- static Element *elementFromDOMElement(IDOMElement *element) @@ -210,6 +421,8 @@ public: : frame(0) , webView(0) , m_policyFunction(0) + , m_pluginView(0) + , m_hasSentResponseToPlugin(false) { } @@ -220,13 +433,16 @@ public: WebView* webView; FramePolicyFunction m_policyFunction; COMPtr<WebFramePolicyListener> m_policyListener; + + // Points to the plugin view that data should be redirected to. + PluginView* m_pluginView; + bool m_hasSentResponseToPlugin; }; // WebFrame ---------------------------------------------------------------- WebFrame::WebFrame() - : WebFrameLoaderClient(this) - , m_refCount(0) + : m_refCount(0) , d(new WebFrame::WebFramePrivate) , m_quickRedirectComing(false) , m_inPrintingMode(false) @@ -278,7 +494,7 @@ HRESULT STDMETHODCALLTYPE WebFrame::allowsScrolling( HRESULT STDMETHODCALLTYPE WebFrame::QueryInterface(REFIID riid, void** ppvObject) { *ppvObject = 0; - if (IsEqualGUID(riid, __uuidof(WebFrame))) + if (IsEqualGUID(riid, IID_WebFrame)) *ppvObject = this; else if (IsEqualGUID(riid, IID_IUnknown)) *ppvObject = static_cast<IWebFrame*>(this); @@ -421,8 +637,8 @@ void WebFrame::loadData(PassRefPtr<WebCore::SharedBuffer> data, BSTR mimeType, B mimeTypeString = "text/html"; String encodingString(textEncodingName, SysStringLen(textEncodingName)); - KURL baseKURL(String(baseURL ? baseURL : L"", SysStringLen(baseURL))); - KURL failingKURL(String(failingURL, SysStringLen(failingURL))); + KURL baseKURL = DeprecatedString((DeprecatedChar*)baseURL, SysStringLen(baseURL)); + KURL failingKURL = DeprecatedString((DeprecatedChar*)failingURL, SysStringLen(failingURL)); ResourceRequest request(baseKURL); SubstituteData substituteData(data, mimeTypeString, encodingString, failingKURL); @@ -716,14 +932,21 @@ HRESULT STDMETHODCALLTYPE WebFrame::childFrames( HRESULT STDMETHODCALLTYPE WebFrame::renderTreeAsExternalRepresentation( /* [retval][out] */ BSTR *result) { - if (!result) + if (!result) { + ASSERT_NOT_REACHED(); return E_POINTER; + } + + *result = 0; Frame* coreFrame = core(this); if (!coreFrame) return E_FAIL; - *result = BString(externalRepresentation(coreFrame->renderer())).release(); + DeprecatedString representation = externalRepresentation(coreFrame->renderer()); + + *result = SysAllocStringLen((LPCOLESTR)representation.unicode(), representation.length()); + return S_OK; } @@ -1079,6 +1302,18 @@ HRESULT WebFrame::canProvideDocumentSource(bool* result) return hr; } +// FrameWinClient + +void WebFrame::ref() +{ + this->AddRef(); +} + +void WebFrame::deref() +{ + this->Release(); +} + void WebFrame::frameLoaderDestroyed() { // The FrameLoader going away is equivalent to the Frame going away, @@ -1088,11 +1323,180 @@ void WebFrame::frameLoaderDestroyed() this->Release(); } +PassRefPtr<Frame> WebFrame::createFrame(const KURL& URL, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer) +{ + Frame* coreFrame = core(this); + ASSERT(coreFrame); + + COMPtr<WebFrame> webFrame; + webFrame.adoptRef(WebFrame::createInstance()); + + webFrame->initWithWebFrameView(0, d->webView, coreFrame->page(), ownerElement); + + RefPtr<Frame> childFrame(adoptRef(core(webFrame.get()))); // We have to adopt, because Frames start out with a refcount of 1. + ASSERT(childFrame); + + coreFrame->tree()->appendChild(childFrame); + childFrame->tree()->setName(name); + childFrame->init(); + + loadURLIntoChild(URL, referrer, webFrame.get()); + + // The frame's onload handler may have removed it from the document. + if (!childFrame->tree()->parent()) + return 0; + + return childFrame.release(); +} + +void WebFrame::loadURLIntoChild(const KURL& originalURL, const String& referrer, WebFrame* childFrame) +{ + ASSERT(childFrame); + ASSERT(core(childFrame)); + + Frame* coreFrame = core(this); + ASSERT(coreFrame); + + HistoryItem* parentItem = coreFrame->loader()->currentHistoryItem(); + FrameLoadType loadType = coreFrame->loader()->loadType(); + FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedHistory; + + KURL url = originalURL; + + // If we're moving in the backforward list, we might want to replace the content + // of this child frame with whatever was there at that point. + // Reload will maintain the frame contents, LoadSame will not. + if (parentItem && parentItem->children().size() && + (isBackForwardLoadType(loadType) + || loadType == FrameLoadTypeReload + || loadType == FrameLoadTypeReloadAllowingStaleData)) + { + if (HistoryItem* childItem = parentItem->childItemWithName(core(childFrame)->tree()->name())) { + // Use the original URL to ensure we get all the side-effects, such as + // onLoad handlers, of any redirects that happened. An example of where + // this is needed is Radar 3213556. + url = childItem->originalURLString().deprecatedString(); + // These behaviors implied by these loadTypes should apply to the child frames + childLoadType = loadType; + + if (isBackForwardLoadType(loadType)) + // For back/forward, remember this item so we can traverse any child items as child frames load + core(childFrame)->loader()->setProvisionalHistoryItem(childItem); + else + // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item + core(childFrame)->loader()->setCurrentHistoryItem(childItem); + } + } + + // FIXME: Handle loading WebArchives here + + core(childFrame)->loader()->load(url, referrer, childLoadType, String(), 0, 0); +} + +void WebFrame::openURL(const String& URL, const Event* triggeringEvent, bool newWindow, bool lockHistory) +{ + bool ctrlPressed = false; + bool shiftPressed = false; + if (triggeringEvent) { + if (triggeringEvent->isMouseEvent()) { + const MouseRelatedEvent* mouseEvent = static_cast<const MouseRelatedEvent*>(triggeringEvent); + ctrlPressed = mouseEvent->ctrlKey(); + shiftPressed = mouseEvent->shiftKey(); + } else if (triggeringEvent->isKeyboardEvent()) { + const KeyboardEvent* keyEvent = static_cast<const KeyboardEvent*>(triggeringEvent); + ctrlPressed = keyEvent->ctrlKey(); + shiftPressed = keyEvent->shiftKey(); + } + } + + if (ctrlPressed) + newWindow = true; + + BString urlBStr = URL; + + IWebMutableURLRequest* request = WebMutableURLRequest::createInstance(); + if (FAILED(request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 0))) + goto exit; + + if (newWindow) { + // new tab/window + IWebUIDelegate* ui; + IWebView* newWebView; + if (SUCCEEDED(d->webView->uiDelegate(&ui)) && ui) { + if (SUCCEEDED(ui->createWebViewWithRequest(d->webView, request, &newWebView))) { + if (shiftPressed) { + // Ctrl-Option-Shift-click: Opens a link in a new window and selects it. + // Ctrl-Shift-click: Opens a link in a new tab and selects it. + ui->webViewShow(d->webView); + } + newWebView->Release(); + newWebView = 0; + } + ui->Release(); + } + } else { + m_quickRedirectComing = lockHistory; + loadRequest(request); + } + +exit: + request->Release(); +} + +void WebFrame::dispatchDidHandleOnloadEvents() +{ + IWebFrameLoadDelegatePrivate* frameLoadDelegatePriv; + if (SUCCEEDED(d->webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv) { + frameLoadDelegatePriv->didHandleOnloadEventsForFrame(d->webView, this); + frameLoadDelegatePriv->Release(); + } +} + +void WebFrame::windowScriptObjectAvailable(JSContextRef context, JSObjectRef windowObject) +{ + IWebFrameLoadDelegate* frameLoadDelegate; + if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate)) && frameLoadDelegate) { + frameLoadDelegate->windowScriptObjectAvailable(d->webView, context, windowObject); + frameLoadDelegate->Release(); + } +} + +WebHistory* WebFrame::webHistory() +{ + if (this != d->webView->topLevelFrame()) + return 0; + + IWebHistoryPrivate* historyInternal = WebHistory::optionalSharedHistoryInternal(); // does not add a ref + if (!historyInternal) + return 0; + + WebHistory* webHistory; + if (FAILED(historyInternal->QueryInterface(&webHistory))) + return 0; + + return webHistory; +} + +bool WebFrame::hasWebView() const +{ + return !!d->webView; +} + +bool WebFrame::hasFrameView() const +{ + return !!d->frameView(); +} + void WebFrame::makeRepresentation(DocumentLoader*) { notImplemented(); } +void WebFrame::forceLayout() +{ + core(this)->forceLayout(true); +} + void WebFrame::forceLayoutForNonHTML() { notImplemented(); @@ -1103,6 +1507,11 @@ void WebFrame::setCopiesOnScroll() notImplemented(); } +void WebFrame::detachedFromParent1() +{ + notImplemented(); +} + void WebFrame::detachedFromParent2() { notImplemented(); @@ -1118,6 +1527,96 @@ void WebFrame::detachedFromParent4() notImplemented(); } +void WebFrame::dispatchDidReceiveServerRedirectForProvisionalLoad() +{ + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->didReceiveServerRedirectForProvisionalLoadForFrame(d->webView, this); +} + +void WebFrame::dispatchDidCancelClientRedirect() +{ + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->didCancelClientRedirectForFrame(d->webView, this); +} + +void WebFrame::dispatchWillPerformClientRedirect(const KURL& url, double delay, double fireDate) +{ + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->willPerformClientRedirectToURL(d->webView, BString(url.string()), delay, MarshallingHelpers::CFAbsoluteTimeToDATE(fireDate), this); +} + +void WebFrame::dispatchDidChangeLocationWithinPage() +{ + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->didChangeLocationWithinPageForFrame(d->webView, this); +} + +void WebFrame::dispatchWillClose() +{ + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->willCloseFrame(d->webView, this); +} + +void WebFrame::dispatchDidReceiveIcon() +{ + d->webView->dispatchDidReceiveIconFromWebFrame(this); +} + +void WebFrame::dispatchDidStartProvisionalLoad() +{ + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->didStartProvisionalLoadForFrame(d->webView, this); +} + +void WebFrame::dispatchDidReceiveTitle(const String& title) +{ + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->didReceiveTitle(d->webView, BString(title), this); +} + +void WebFrame::dispatchDidCommitLoad() +{ + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->didCommitLoadForFrame(d->webView, this); +} + +void WebFrame::dispatchDidFinishDocumentLoad() +{ + COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv; + if (SUCCEEDED(d->webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv) + frameLoadDelegatePriv->didFinishDocumentLoadForFrame(d->webView, this); +} + +void WebFrame::dispatchDidFinishLoad() +{ + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->didFinishLoadForFrame(d->webView, this); +} + +void WebFrame::dispatchDidFirstLayout() +{ + COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv; + if (SUCCEEDED(d->webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv) + frameLoadDelegatePriv->didFirstLayoutInFrame(d->webView, this); +} + +void WebFrame::dispatchShow() +{ + COMPtr<IWebUIDelegate> ui; + + if (SUCCEEDED(d->webView->uiDelegate(&ui))) + ui->webViewShow(d->webView); +} + void WebFrame::cancelPolicyCheck() { if (d->m_policyListener) { @@ -1153,6 +1652,19 @@ void WebFrame::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<F (coreFrame->loader()->*function)(PolicyUse); } +void WebFrame::dispatchDidLoadMainResource(DocumentLoader* loader) +{ + if (WebScriptDebugServer::listenerCount() > 0) { + Frame* coreFrame = core(this); + if (!coreFrame) + return; + + WebScriptDebugServer::sharedWebScriptDebugServer()->didLoadMainResourceForDataSource( + kit(coreFrame->page()), + loader ? static_cast<WebDocumentLoader*>(loader)->dataSource() : 0); + } +} + void WebFrame::revertToProvisionalState(DocumentLoader*) { notImplemented(); @@ -1178,6 +1690,21 @@ void WebFrame::didChangeTitle(DocumentLoader*) notImplemented(); } +void WebFrame::finishedLoading(DocumentLoader* loader) +{ + // Telling the frame we received some data and passing 0 as the data is our + // way to get work done that is normally done when the first bit of data is + // received, even for the case of a document with no data (like about:blank) + if (!d->m_pluginView) + committedLoad(loader, 0, 0); + else { + if (d->m_pluginView->status() == PluginStatusLoadedSuccessfully) + d->m_pluginView->didFinishLoading(); + d->m_pluginView = 0; + d->m_hasSentResponseToPlugin = false; + } +} + void WebFrame::finalSetupForReplace(DocumentLoader*) { notImplemented(); @@ -1264,19 +1791,159 @@ void WebFrame::prepareForDataSourceReplacement() notImplemented(); } +void WebFrame::setTitle(const String& title, const KURL& url) +{ + BOOL privateBrowsingEnabled = FALSE; + COMPtr<IWebPreferences> preferences; + if (SUCCEEDED(d->webView->preferences(&preferences))) + preferences->privateBrowsingEnabled(&privateBrowsingEnabled); + if (!privateBrowsingEnabled) { + // update title in global history + COMPtr<WebHistory> history; + history.adoptRef(webHistory()); + if (history) { + COMPtr<IWebHistoryItem> item; + if (SUCCEEDED(history->itemForURL(BString(url.string()), &item))) { + COMPtr<IWebHistoryItemPrivate> itemPrivate; + if (SUCCEEDED(item->QueryInterface(IID_IWebHistoryItemPrivate, (void**)&itemPrivate))) + itemPrivate->setTitle(BString(title)); + } + } + } +} + String WebFrame::userAgent(const KURL& url) { return d->webView->userAgentForKURL(url); } +void WebFrame::savePlatformDataToCachedPage(CachedPage* cachedPage) +{ + Frame* coreFrame = core(this); + if (!coreFrame) + return; + + ASSERT(coreFrame->loader()->documentLoader() == cachedPage->documentLoader()); + + WebCachedPagePlatformData* webPlatformData = new WebCachedPagePlatformData(static_cast<IWebDataSource*>(getWebDataSource(coreFrame->loader()->documentLoader()))); + cachedPage->setCachedPagePlatformData(webPlatformData); +} + void WebFrame::transitionToCommittedFromCachedPage(CachedPage*) { } +void WebFrame::transitionToCommittedForNewPage() +{ + Frame* frame = core(this); + ASSERT(frame); + + Page* page = frame->page(); + ASSERT(page); + + bool isMainFrame = frame == page->mainFrame(); + + if (isMainFrame && frame->view()) + frame->view()->detachFromWindow(); + + frame->setView(0); + + FrameView* frameView; + if (isMainFrame) { + RECT rect; + d->webView->frameRect(&rect); + frameView = new FrameView(frame, IntRect(rect).size()); + } else + frameView = new FrameView(frame); + + frame->setView(frameView); + frameView->deref(); // FrameViews are created with a ref count of 1. Release this ref since we've assigned it to frame. + + HWND viewWindow; + if (SUCCEEDED(d->webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow)))) + frameView->setContainingWindow(viewWindow); + + if (isMainFrame) + frameView->attachToWindow(); + + if (frame->ownerRenderer()) + frame->ownerRenderer()->setWidget(frameView); + + if (HTMLFrameOwnerElement* owner = frame->ownerElement()) + frame->view()->setScrollbarsMode(owner->scrollingMode()); +} + +void WebFrame::updateGlobalHistoryForStandardLoad(const KURL& url) +{ + COMPtr<WebHistory> history; + history.adoptRef(webHistory()); + + if (!history) + return; + + history->addItemForURL(BString(url.string()), 0); +} + +void WebFrame::updateGlobalHistoryForReload(const KURL& url) +{ + BString urlBStr(url.string()); + + COMPtr<WebHistory> history; + history.adoptRef(webHistory()); + + if (!history) + return; + + COMPtr<IWebHistoryItem> item; + if (SUCCEEDED(history->itemForURL(urlBStr, &item))) { + COMPtr<IWebHistoryItemPrivate> itemPrivate; + if (SUCCEEDED(item->QueryInterface(IID_IWebHistoryItemPrivate, (void**)&itemPrivate))) { + SYSTEMTIME currentTime; + GetSystemTime(¤tTime); + DATE visitedTime = 0; + SystemTimeToVariantTime(¤tTime, &visitedTime); + + // FIXME - bumping the last visited time doesn't mark the history as changed + itemPrivate->setLastVisitedTimeInterval(visitedTime); + } + } +} + +bool WebFrame::shouldGoToHistoryItem(HistoryItem*) const +{ + return true; +} + void WebFrame::saveViewStateToItem(HistoryItem*) { } +bool WebFrame::canCachePage() const +{ + return true; +} + +PassRefPtr<DocumentLoader> WebFrame::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData) +{ + RefPtr<WebDocumentLoader> loader = new WebDocumentLoader(request, substituteData); + + COMPtr<WebDataSource> dataSource; + dataSource.adoptRef(WebDataSource::createInstance(loader.get())); + + loader->setDataSource(dataSource.get()); + return loader.release(); +} + +void WebFrame::setMainDocumentError(DocumentLoader*, const ResourceError& error) +{ + if (d->m_pluginView) { + if (d->m_pluginView->status() == PluginStatusLoadedSuccessfully) + d->m_pluginView->didFail(error); + d->m_pluginView = 0; + d->m_hasSentResponseToPlugin = false; + } +} + ResourceError WebFrame::cancelledError(const ResourceRequest& request) { // FIXME: Need ChickenCat to include CFNetwork/CFURLError.h to get these values @@ -1319,6 +1986,22 @@ bool WebFrame::shouldFallBack(const ResourceError& error) return error.errorCode() != WebURLErrorCancelled; } +void WebFrame::receivedData(const char* data, int length, const String& textEncoding) +{ + Frame* coreFrame = core(this); + if (!coreFrame) + return; + + // Set the encoding. This only needs to be done once, but it's harmless to do it again later. + String encoding = coreFrame->loader()->documentLoader()->overrideEncoding(); + bool userChosen = !encoding.isNull(); + if (encoding.isNull()) + encoding = textEncoding; + coreFrame->loader()->setEncoding(encoding, userChosen); + + coreFrame->loader()->addData(data, length); +} + COMPtr<WebFramePolicyListener> WebFrame::setUpPolicyListener(WebCore::FramePolicyFunction function) { // FIXME: <rdar://5634381> We need to support multiple active policy listeners. @@ -1351,6 +2034,28 @@ void WebFrame::receivedPolicyDecision(PolicyAction action) (coreFrame->loader()->*function)(action); } +void WebFrame::committedLoad(DocumentLoader* loader, const char* data, int length) +{ + // FIXME: This should probably go through the data source. + const String& textEncoding = loader->response().textEncodingName(); + + if (!d->m_pluginView) + receivedData(data, length, textEncoding); + + if (d->m_pluginView && d->m_pluginView->status() == PluginStatusLoadedSuccessfully) { + if (!d->m_hasSentResponseToPlugin) { + d->m_pluginView->didReceiveResponse(d->frame->loader()->documentLoader()->response()); + // didReceiveResponse sets up a new stream to the plug-in. on a full-page plug-in, a failure in + // setting up this stream can cause the main document load to be cancelled, setting m_pluginView + // to null + if (!d->m_pluginView) + return; + d->m_hasSentResponseToPlugin = true; + } + d->m_pluginView->didReceiveData(data, length); + } +} + void WebFrame::dispatchDecidePolicyForMIMEType(FramePolicyFunction function, const String& mimeType, const ResourceRequest& request) { Frame* coreFrame = core(this); @@ -1439,6 +2144,76 @@ bool WebFrame::willUseArchive(ResourceLoader*, const ResourceRequest&, const KUR return false; } +void WebFrame::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request) +{ + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) { + COMPtr<IWebURLRequest> webURLRequest; + webURLRequest.adoptRef(WebMutableURLRequest::createInstance(request)); + + resourceLoadDelegate->identifierForInitialRequest(d->webView, webURLRequest.get(), getWebDataSource(loader), identifier); + } +} + +void WebFrame::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse) +{ + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) { + COMPtr<IWebURLRequest> webURLRequest; + webURLRequest.adoptRef(WebMutableURLRequest::createInstance(request)); + COMPtr<IWebURLResponse> webURLRedirectResponse; + webURLRedirectResponse.adoptRef(WebURLResponse::createInstance(redirectResponse)); + COMPtr<IWebURLRequest> newWebURLRequest; + + if (FAILED(resourceLoadDelegate->willSendRequest(d->webView, identifier, webURLRequest.get(), webURLRedirectResponse.get(), getWebDataSource(loader), &newWebURLRequest))) + return; + + if (webURLRequest == newWebURLRequest) + return; + + COMPtr<WebMutableURLRequest> newWebURLRequestImpl; + if (FAILED(newWebURLRequest->QueryInterface(&newWebURLRequestImpl))) + return; + + request = newWebURLRequestImpl->resourceRequest(); + } +} + +void WebFrame::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response) +{ + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) { + COMPtr<IWebURLResponse> webURLResponse; + webURLResponse.adoptRef(WebURLResponse::createInstance(response)); + + resourceLoadDelegate->didReceiveResponse(d->webView, identifier, webURLResponse.get(), getWebDataSource(loader)); + } +} + +void WebFrame::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int length) +{ + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) + resourceLoadDelegate->didReceiveContentLength(d->webView, identifier, length, getWebDataSource(loader)); +} + +void WebFrame::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier) +{ + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) + resourceLoadDelegate->didFinishLoadingFromDataSource(d->webView, identifier, getWebDataSource(loader)); +} + +void WebFrame::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& error) +{ + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) { + COMPtr<IWebError> webError; + webError.adoptRef(WebError::createInstance(error)); + resourceLoadDelegate->didFailLoadingWithError(d->webView, identifier, webError.get(), getWebDataSource(loader)); + } +} + bool WebFrame::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int /*length*/) { notImplemented(); @@ -1465,14 +2240,178 @@ void WebFrame::dispatchDidFailLoad(const ResourceError& error) } } +Frame* WebFrame::dispatchCreatePage() +{ + COMPtr<IWebUIDelegate> ui; + + if (SUCCEEDED(d->webView->uiDelegate(&ui))) { + COMPtr<IWebView> newWebView; + + if (SUCCEEDED(ui->createWebViewWithRequest(d->webView, 0, &newWebView))) { + COMPtr<IWebFrame> mainFrame; + + if (SUCCEEDED(newWebView->mainFrame(&mainFrame))) { + COMPtr<WebFrame> mainFrameImpl; + + if (SUCCEEDED(mainFrame->QueryInterface(IID_WebFrame, (void**)&mainFrameImpl))) + return core(mainFrameImpl.get()); + } + } + } + return 0; +} + +void WebFrame::postProgressStartedNotification() +{ + static BSTR progressStartedName = SysAllocString(WebViewProgressStartedNotification); + IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal(); + notifyCenter->postNotificationName(progressStartedName, static_cast<IWebView*>(d->webView), 0); +} + +void WebFrame::postProgressEstimateChangedNotification() +{ + static BSTR progressEstimateChangedName = SysAllocString(WebViewProgressEstimateChangedNotification); + IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal(); + notifyCenter->postNotificationName(progressEstimateChangedName, static_cast<IWebView*>(d->webView), 0); +} + +void WebFrame::postProgressFinishedNotification() +{ + static BSTR progressFinishedName = SysAllocString(WebViewProgressFinishedNotification); + IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal(); + notifyCenter->postNotificationName(progressFinishedName, static_cast<IWebView*>(d->webView), 0); +} + void WebFrame::startDownload(const ResourceRequest&) { notImplemented(); } +void WebFrame::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge) +{ + ASSERT(challenge.sourceHandle()); + + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) { + COMPtr<IWebURLAuthenticationChallenge> webChallenge(AdoptCOM, WebURLAuthenticationChallenge::createInstance(challenge)); + + if (SUCCEEDED(resourceLoadDelegate->didReceiveAuthenticationChallenge(d->webView, identifier, webChallenge.get(), getWebDataSource(loader)))) + return; + } + + // If the ResourceLoadDelegate doesn't exist or fails to handle the call, we tell the ResourceHandle + // to continue without credential - this is the best approximation of Mac behavior + challenge.sourceHandle()->receivedRequestToContinueWithoutCredential(challenge); +} + +void WebFrame::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge) +{ + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) { + COMPtr<IWebURLAuthenticationChallenge> webChallenge(AdoptCOM, WebURLAuthenticationChallenge::createInstance(challenge)); + + if (SUCCEEDED(resourceLoadDelegate->didCancelAuthenticationChallenge(d->webView, identifier, webChallenge.get(), getWebDataSource(loader)))) + return; + } +} + +PassRefPtr<Frame> WebFrame::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, + const String& referrer, bool /*allowsScrolling*/, int /*marginWidth*/, int /*marginHeight*/) +{ + RefPtr<Frame> result = createFrame(url, name, ownerElement, referrer); + if (!result) + return 0; + + // Propagate the marginwidth/height and scrolling modes to the view. + if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag)) { + HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement); + if (frameElt->scrollingMode() == ScrollbarAlwaysOff) + result->view()->setScrollbarsMode(ScrollbarAlwaysOff); + int marginWidth = frameElt->getMarginWidth(); + int marginHeight = frameElt->getMarginHeight(); + if (marginWidth != -1) + result->view()->setMarginWidth(marginWidth); + if (marginHeight != -1) + result->view()->setMarginHeight(marginHeight); + } + + return result.release(); +} + +Widget* WebFrame::createPlugin(const IntSize& pluginSize, Element* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually) +{ + PluginView* pluginView = PluginDatabase::installedPlugins()->createPluginView(core(this), pluginSize, element, url, paramNames, paramValues, mimeType, loadManually); + + if (pluginView->status() == PluginStatusLoadedSuccessfully) + return pluginView; + + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + + if (FAILED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) + return pluginView; + + RetainPtr<CFMutableDictionaryRef> userInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + + unsigned count = (unsigned)paramNames.size(); + for (unsigned i = 0; i < count; i++) { + if (paramNames[i] == "pluginspage") { + static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorPlugInPageURLStringKey); + RetainPtr<CFStringRef> str(AdoptCF, paramValues[i].createCFString()); + CFDictionarySetValue(userInfo.get(), key, str.get()); + break; + } + } + + if (!mimeType.isNull()) { + static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorMIMETypeKey); + + RetainPtr<CFStringRef> str(AdoptCF, mimeType.createCFString()); + CFDictionarySetValue(userInfo.get(), key, str.get()); + } + + String pluginName; + if (pluginView->plugin()) + pluginName = pluginView->plugin()->name(); + if (!pluginName.isNull()) { + static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorPlugInNameKey); + RetainPtr<CFStringRef> str(AdoptCF, pluginName.createCFString()); + CFDictionarySetValue(userInfo.get(), key, str.get()); + } + + COMPtr<CFDictionaryPropertyBag> userInfoBag(AdoptCOM, CFDictionaryPropertyBag::createInstance()); + userInfoBag->setDictionary(userInfo.get()); + + int errorCode = 0; + switch (pluginView->status()) { + case PluginStatusCanNotFindPlugin: + errorCode = WebKitErrorCannotFindPlugIn; + break; + case PluginStatusCanNotLoadPlugin: + errorCode = WebKitErrorCannotLoadPlugIn; + break; + default: + ASSERT_NOT_REACHED(); + } + + ResourceError resourceError(String(WebKitErrorDomain), errorCode, url.string(), String()); + COMPtr<IWebError> error(AdoptCOM, WebError::createInstance(resourceError, userInfoBag.get())); + + resourceLoadDelegate->plugInFailedWithError(d->webView, error.get(), getWebDataSource(d->frame->loader()->documentLoader())); + + return pluginView; +} + +void WebFrame::redirectDataToPlugin(Widget* pluginWidget) +{ + // Ideally, this function shouldn't be necessary, see <rdar://problem/4852889> + + d->m_pluginView = static_cast<PluginView*>(pluginWidget); +} + Widget* WebFrame::createJavaAppletWidget(const IntSize& pluginSize, Element* element, const KURL& /*baseURL*/, const Vector<String>& paramNames, const Vector<String>& paramValues) { - PluginView* pluginView = PluginView::create(core(this), pluginSize, element, KURL(), paramNames, paramValues, "application/x-java-applet", false); + PluginView* pluginView = PluginDatabase::installedPlugins()-> + createPluginView(core(this), pluginSize, element, KURL(), paramNames, paramValues, "application/x-java-applet", false); // Check if the plugin can be loaded successfully if (pluginView->plugin() && pluginView->plugin()->load()) @@ -1496,7 +2435,7 @@ ObjectContentType WebFrame::objectContentType(const KURL& url, const String& mim { String mimeType = mimeTypeIn; if (mimeType.isEmpty()) - mimeType = MIMETypeRegistry::getMIMETypeForExtension(url.path().substring(url.path().reverseFind('.') + 1)); + mimeType = MIMETypeRegistry::getMIMETypeForExtension(url.path().mid(url.path().findRev('.')+1)); if (mimeType.isEmpty()) return ObjectContentFrame; // Go ahead and hope that we can display the content. @@ -1931,8 +2870,8 @@ HRESULT STDMETHODCALLTYPE WebFrame::isDescendantOfFrame( *result = FALSE; Frame* coreFrame = core(this); - COMPtr<WebFrame> ancestorWebFrame(Query, ancestor); - if (!ancestorWebFrame) + COMPtr<WebFrame> ancestorWebFrame; + if (!ancestor || FAILED(ancestor->QueryInterface(IID_WebFrame, (void**)&ancestorWebFrame))) return S_OK; *result = (coreFrame && coreFrame->tree()->isDescendantOf(core(ancestorWebFrame.get()))) ? TRUE : FALSE; @@ -1962,8 +2901,3 @@ void WebFrame::unmarkAllBadGrammar() doc->removeMarkers(DocumentMarker::Grammar); } } - -WebView* WebFrame::webView() const -{ - return d->webView; -} |