diff options
Diffstat (limited to 'Source/WebCore/loader/SubframeLoader.cpp')
-rw-r--r-- | Source/WebCore/loader/SubframeLoader.cpp | 255 |
1 files changed, 110 insertions, 145 deletions
diff --git a/Source/WebCore/loader/SubframeLoader.cpp b/Source/WebCore/loader/SubframeLoader.cpp index 2d8ba8164..234625280 100644 --- a/Source/WebCore/loader/SubframeLoader.cpp +++ b/Source/WebCore/loader/SubframeLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2006-2017 Apple Inc. All rights reserved. * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * Copyright (C) 2008 Alp Toker <alp@atoker.com> @@ -14,7 +14,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -33,19 +33,19 @@ #include "config.h" #include "SubframeLoader.h" -#include "Chrome.h" -#include "ChromeClient.h" #include "ContentSecurityPolicy.h" +#include "DiagnosticLoggingClient.h" #include "DiagnosticLoggingKeys.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameLoaderClient.h" #include "HTMLAppletElement.h" -#include "HTMLAudioElement.h" -#include "HTMLFrameElementBase.h" +#include "HTMLFrameElement.h" +#include "HTMLIFrameElement.h" #include "HTMLNames.h" #include "HTMLObjectElement.h" #include "MIMETypeRegistry.h" +#include "MainFrame.h" #include "Page.h" #include "PluginData.h" #include "PluginDocument.h" @@ -56,11 +56,6 @@ #include "SecurityPolicy.h" #include "Settings.h" -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) -#include "HTMLMediaElement.h" -#include "RenderVideo.h" -#endif - namespace WebCore { using namespace HTMLNames; @@ -76,7 +71,7 @@ void SubframeLoader::clear() m_containsPlugins = false; } -bool SubframeLoader::requestFrame(HTMLFrameOwnerElement& ownerElement, const String& urlString, const AtomicString& frameName, bool lockHistory, bool lockBackForwardList) +bool SubframeLoader::requestFrame(HTMLFrameOwnerElement& ownerElement, const String& urlString, const AtomicString& frameName, LockHistory lockHistory, LockBackForwardList lockBackForwardList) { // Support for <frame src="javascript:string"> URL scriptURL; @@ -87,55 +82,50 @@ bool SubframeLoader::requestFrame(HTMLFrameOwnerElement& ownerElement, const Str } else url = completeURL(urlString); + if (shouldConvertInvalidURLsToBlank() && !url.isValid()) + url = blankURL(); + Frame* frame = loadOrRedirectSubframe(ownerElement, url, frameName, lockHistory, lockBackForwardList); if (!frame) return false; - if (!scriptURL.isEmpty()) + if (!scriptURL.isEmpty() && ownerElement.isURLAllowed(scriptURL)) frame->script().executeIfJavaScriptURL(scriptURL); return true; } -bool SubframeLoader::resourceWillUsePlugin(const String& url, const String& mimeType, bool shouldPreferPlugInsForImages) +bool SubframeLoader::resourceWillUsePlugin(const String& url, const String& mimeType) { URL completedURL; if (!url.isEmpty()) completedURL = completeURL(url); bool useFallback; - return shouldUsePlugin(completedURL, mimeType, shouldPreferPlugInsForImages, false, useFallback); + return shouldUsePlugin(completedURL, mimeType, false, useFallback); } -bool SubframeLoader::pluginIsLoadable(HTMLPlugInImageElement& pluginElement, const URL& url, const String& mimeType) +bool SubframeLoader::pluginIsLoadable(const URL& url, const String& mimeType) { + auto* document = m_frame.document(); + if (MIMETypeRegistry::isJavaAppletMIMEType(mimeType)) { if (!m_frame.settings().isJavaEnabled()) return false; - if (document() && document()->securityOrigin()->isLocal() && !m_frame.settings().isJavaEnabledForLocalFiles()) + if (document && document->securityOrigin().isLocal() && !m_frame.settings().isJavaEnabledForLocalFiles()) return false; } - if (document()) { - if (document()->isSandboxed(SandboxPlugins)) + if (document) { + if (document->isSandboxed(SandboxPlugins)) return false; - if (!document()->securityOrigin()->canDisplay(url)) { + if (!document->securityOrigin().canDisplay(url)) { FrameLoader::reportLocalLoadFailed(&m_frame, url.string()); return false; } - String declaredMimeType = document()->isPluginDocument() && document()->ownerElement() ? - document()->ownerElement()->fastGetAttribute(HTMLNames::typeAttr) : - pluginElement.fastGetAttribute(HTMLNames::typeAttr); - if (!document()->contentSecurityPolicy()->allowObjectFromSource(url) - || !document()->contentSecurityPolicy()->allowPluginType(mimeType, declaredMimeType, url)) { - RenderEmbeddedObject* renderer = pluginElement.renderEmbeddedObject(); - renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginBlockedByContentSecurityPolicy); - return false; - } - - if (!m_frame.loader().mixedContentChecker().canRunInsecureContent(document()->securityOrigin(), url)) + if (!m_frame.loader().mixedContentChecker().canRunInsecureContent(document->securityOrigin(), url)) return false; } @@ -147,10 +137,10 @@ bool SubframeLoader::requestPlugin(HTMLPlugInImageElement& ownerElement, const U // Application plug-ins are plug-ins implemented by the user agent, for example Qt plug-ins, // as opposed to third-party code such as Flash. The user agent decides whether or not they are // permitted, rather than WebKit. - if ((!allowPlugins(AboutToInstantiatePlugin) && !MIMETypeRegistry::isApplicationPluginMIMEType(mimeType))) + if ((!allowPlugins() && !MIMETypeRegistry::isApplicationPluginMIMEType(mimeType))) return false; - if (!pluginIsLoadable(ownerElement, url, mimeType)) + if (!pluginIsLoadable(url, mimeType)) return false; ASSERT(ownerElement.hasTagName(objectTag) || ownerElement.hasTagName(embedTag)); @@ -170,11 +160,13 @@ static String findPluginMIMETypeFromURL(Page* page, const String& url) const PluginData& pluginData = page->pluginData(); - for (size_t i = 0; i < pluginData.mimes().size(); ++i) { - const MimeClassInfo& mimeClassInfo = pluginData.mimes()[i]; - for (size_t j = 0; j < mimeClassInfo.extensions.size(); ++j) { - if (equalIgnoringCase(extension, mimeClassInfo.extensions[j])) - return mimeClassInfo.type; + Vector<MimeClassInfo> mimes; + Vector<size_t> mimePluginIndices; + pluginData.getWebVisibleMimesAndPluginIndices(mimes, mimePluginIndices); + for (auto& mime : mimes) { + for (auto& mimeExtension : mime.extensions) { + if (equalIgnoringASCIICase(extension, mimeExtension)) + return mime.type; } } @@ -183,7 +175,7 @@ static String findPluginMIMETypeFromURL(Page* page, const String& url) static void logPluginRequest(Page* page, const String& mimeType, const String& url, bool success) { - if (!page || !page->settings().diagnosticLoggingEnabled()) + if (!page) return; String newMIMEType = mimeType; @@ -194,17 +186,17 @@ static void logPluginRequest(Page* page, const String& mimeType, const String& u return; } - String pluginFile = page->pluginData().pluginFileForMimeType(newMIMEType); + String pluginFile = page->pluginData().pluginFileForWebVisibleMimeType(newMIMEType); String description = !pluginFile ? newMIMEType : pluginFile; - ChromeClient& chromeClient = page->chrome().client(); - chromeClient.logDiagnosticMessage(success ? DiagnosticLoggingKeys::pluginLoadedKey() : DiagnosticLoggingKeys::pluginLoadingFailedKey(), description, DiagnosticLoggingKeys::noopKey()); + DiagnosticLoggingClient& diagnosticLoggingClient = page->diagnosticLoggingClient(); + diagnosticLoggingClient.logDiagnosticMessage(success ? DiagnosticLoggingKeys::pluginLoadedKey() : DiagnosticLoggingKeys::pluginLoadingFailedKey(), description, ShouldSample::No); if (!page->hasSeenAnyPlugin()) - chromeClient.logDiagnosticMessage(DiagnosticLoggingKeys::pageContainsAtLeastOnePluginKey(), emptyString(), DiagnosticLoggingKeys::noopKey()); - + diagnosticLoggingClient.logDiagnosticMessage(DiagnosticLoggingKeys::pageContainsAtLeastOnePluginKey(), emptyString(), ShouldSample::No); + if (!page->hasSeenPlugin(description)) - chromeClient.logDiagnosticMessage(DiagnosticLoggingKeys::pageContainsPluginKey(), description, DiagnosticLoggingKeys::noopKey()); + diagnosticLoggingClient.logDiagnosticMessage(DiagnosticLoggingKeys::pageContainsPluginKey(), description, ShouldSample::No); page->sawPlugin(description); } @@ -214,99 +206,66 @@ bool SubframeLoader::requestObject(HTMLPlugInImageElement& ownerElement, const S if (url.isEmpty() && mimeType.isEmpty()) return false; + auto& document = ownerElement.document(); + URL completedURL; if (!url.isEmpty()) completedURL = completeURL(url); - bool hasFallbackContent = isHTMLObjectElement(ownerElement) && toHTMLObjectElement(ownerElement).hasFallbackContent(); + document.contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(completedURL, ContentSecurityPolicy::InsecureRequestType::Load); + + bool hasFallbackContent = is<HTMLObjectElement>(ownerElement) && downcast<HTMLObjectElement>(ownerElement).hasFallbackContent(); bool useFallback; - if (shouldUsePlugin(completedURL, mimeType, ownerElement.shouldPreferPlugInsForImages(), hasFallbackContent, useFallback)) { + if (shouldUsePlugin(completedURL, mimeType, hasFallbackContent, useFallback)) { bool success = requestPlugin(ownerElement, completedURL, mimeType, paramNames, paramValues, useFallback); - logPluginRequest(document()->page(), mimeType, completedURL, success); + logPluginRequest(document.page(), mimeType, completedURL, success); return success; } // If the plug-in element already contains a subframe, loadOrRedirectSubframe will re-use it. Otherwise, // it will create a new frame and set it as the RenderWidget's Widget, causing what was previously // in the widget to be torn down. - return loadOrRedirectSubframe(ownerElement, completedURL, frameName, true, true); + return loadOrRedirectSubframe(ownerElement, completedURL, frameName, LockHistory::Yes, LockBackForwardList::Yes); } -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) -PassRefPtr<Widget> SubframeLoader::loadMediaPlayerProxyPlugin(HTMLMediaElement& mediaElement, const URL& url, const Vector<String>& paramNames, const Vector<String>& paramValues) -{ - ASSERT(mediaElement.hasTagName(videoTag) || isHTMLAudioElement(mediaElement)); - - URL completedURL; - if (!url.isEmpty()) - completedURL = completeURL(url); - - if (!m_frame.document()->securityOrigin()->canDisplay(completedURL)) { - FrameLoader::reportLocalLoadFailed(&m_frame, completedURL.string()); - return nullptr; - } - - if (!m_frame.document()->contentSecurityPolicy()->allowMediaFromSource(completedURL)) - return nullptr; - - RenderWidget* renderer = toRenderWidget(mediaElement.renderer()); - IntSize size; - - if (renderer) - size = roundedIntSize(LayoutSize(renderer->contentWidth(), renderer->contentHeight())); - else if (mediaElement.isVideo()) - size = RenderVideo::defaultSize(); - - if (!m_frame.loader().mixedContentChecker().canRunInsecureContent(m_frame.document()->securityOrigin(), completedURL)) - return nullptr; - - RefPtr<Widget> widget = m_frame.loader().client().createMediaPlayerProxyPlugin(size, &mediaElement, completedURL, paramNames, paramValues, "application/x-media-element-proxy-plugin"); - - if (widget && renderer) { - renderer->setWidget(widget); - renderer->frameOwnerElement().setNeedsStyleRecalc(SyntheticStyleChange); - } - m_containsPlugins = true; - - return widget ? widget.release() : nullptr; -} -#endif // ENABLE(PLUGIN_PROXY_FOR_VIDEO) - -PassRefPtr<Widget> SubframeLoader::createJavaAppletWidget(const IntSize& size, HTMLAppletElement& element, const Vector<String>& paramNames, const Vector<String>& paramValues) +RefPtr<Widget> SubframeLoader::createJavaAppletWidget(const IntSize& size, HTMLAppletElement& element, const Vector<String>& paramNames, const Vector<String>& paramValues) { String baseURLString; String codeBaseURLString; for (size_t i = 0; i < paramNames.size(); ++i) { - if (equalIgnoringCase(paramNames[i], "baseurl")) + if (equalLettersIgnoringASCIICase(paramNames[i], "baseurl")) baseURLString = paramValues[i]; - else if (equalIgnoringCase(paramNames[i], "codebase")) + else if (equalLettersIgnoringASCIICase(paramNames[i], "codebase")) codeBaseURLString = paramValues[i]; } if (!codeBaseURLString.isEmpty()) { URL codeBaseURL = completeURL(codeBaseURLString); - if (!element.document().securityOrigin()->canDisplay(codeBaseURL)) { + if (!element.document().securityOrigin().canDisplay(codeBaseURL)) { FrameLoader::reportLocalLoadFailed(&m_frame, codeBaseURL.string()); return nullptr; } const char javaAppletMimeType[] = "application/x-java-applet"; - if (!element.document().contentSecurityPolicy()->allowObjectFromSource(codeBaseURL) - || !element.document().contentSecurityPolicy()->allowPluginType(javaAppletMimeType, javaAppletMimeType, codeBaseURL)) + ASSERT(element.document().contentSecurityPolicy()); + auto& contentSecurityPolicy = *element.document().contentSecurityPolicy(); + // Elements in user agent show tree should load whatever the embedding document policy is. + if (!element.isInUserAgentShadowTree() + && (!contentSecurityPolicy.allowObjectFromSource(codeBaseURL) || !contentSecurityPolicy.allowPluginType(javaAppletMimeType, javaAppletMimeType, codeBaseURL))) return nullptr; } if (baseURLString.isEmpty()) - baseURLString = m_frame.document()->baseURL().string(); + baseURLString = element.document().baseURL().string(); URL baseURL = completeURL(baseURLString); RefPtr<Widget> widget; - if (allowPlugins(AboutToInstantiatePlugin)) - widget = m_frame.loader().client().createJavaAppletWidget(size, &element, baseURL, paramNames, paramValues); + if (allowPlugins()) + widget = m_frame.loader().client().createJavaAppletWidget(size, element, baseURL, paramNames, paramValues); - logPluginRequest(document()->page(), element.serviceType(), String(), widget); + logPluginRequest(m_frame.page(), element.serviceType(), String(), widget); if (!widget) { RenderEmbeddedObject* renderer = element.renderEmbeddedObject(); @@ -320,13 +279,18 @@ PassRefPtr<Widget> SubframeLoader::createJavaAppletWidget(const IntSize& size, H return widget; } -Frame* SubframeLoader::loadOrRedirectSubframe(HTMLFrameOwnerElement& ownerElement, const URL& url, const AtomicString& frameName, bool lockHistory, bool lockBackForwardList) +Frame* SubframeLoader::loadOrRedirectSubframe(HTMLFrameOwnerElement& ownerElement, const URL& requestURL, const AtomicString& frameName, LockHistory lockHistory, LockBackForwardList lockBackForwardList) { - Frame* frame = ownerElement.contentFrame(); + auto& initiatingDocument = ownerElement.document(); + + URL upgradedRequestURL = requestURL; + initiatingDocument.contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(upgradedRequestURL, ContentSecurityPolicy::InsecureRequestType::Load); + + auto* frame = ownerElement.contentFrame(); if (frame) - frame->navigationScheduler().scheduleLocationChange(m_frame.document()->securityOrigin(), url.string(), m_frame.loader().outgoingReferrer(), lockHistory, lockBackForwardList); + frame->navigationScheduler().scheduleLocationChange(initiatingDocument, initiatingDocument.securityOrigin(), upgradedRequestURL, m_frame.loader().outgoingReferrer(), lockHistory, lockBackForwardList); else - frame = loadSubframe(ownerElement, url, frameName, m_frame.loader().outgoingReferrer()); + frame = loadSubframe(ownerElement, upgradedRequestURL, frameName, m_frame.loader().outgoingReferrer()); if (!frame) return nullptr; @@ -342,14 +306,16 @@ Frame* SubframeLoader::loadSubframe(HTMLFrameOwnerElement& ownerElement, const U bool allowsScrolling = true; int marginWidth = -1; int marginHeight = -1; - if (ownerElement.hasTagName(frameTag) || ownerElement.hasTagName(iframeTag)) { - HTMLFrameElementBase& frameElementBase = toHTMLFrameElementBase(ownerElement); + if (is<HTMLFrameElementBase>(ownerElement)) { + auto& frameElementBase = downcast<HTMLFrameElementBase>(ownerElement); allowsScrolling = frameElementBase.scrollingMode() != ScrollbarAlwaysOff; marginWidth = frameElementBase.marginWidth(); marginHeight = frameElementBase.marginHeight(); } - if (!ownerElement.document().securityOrigin()->canDisplay(url)) { + auto document = makeRef(ownerElement.document()); + + if (!document->securityOrigin().canDisplay(url)) { FrameLoader::reportLocalLoadFailed(&m_frame, url.string()); return nullptr; } @@ -357,14 +323,20 @@ Frame* SubframeLoader::loadSubframe(HTMLFrameOwnerElement& ownerElement, const U if (!SubframeLoadingDisabler::canLoadFrame(ownerElement)) return nullptr; - String referrerToUse = SecurityPolicy::generateReferrerHeader(ownerElement.document().referrerPolicy(), url, referrer); - RefPtr<Frame> frame = m_frame.loader().client().createFrame(url, name, &ownerElement, referrerToUse, allowsScrolling, marginWidth, marginHeight); + String referrerToUse = SecurityPolicy::generateReferrerHeader(document->referrerPolicy(), url, referrer); + + // Prevent initial empty document load from triggering load events. + document->incrementLoadEventDelayCount(); + + auto frame = m_frame.loader().client().createFrame(url, name, ownerElement, referrerToUse, allowsScrolling, marginWidth, marginHeight); + + document->decrementLoadEventDelayCount(); if (!frame) { m_frame.loader().checkCallImplicitClose(); return nullptr; } - + // All new frames will have m_isComplete set to true at this point due to synchronously loading // an empty document in FrameLoader::init(). But many frames will now be starting an // asynchronous load of url, so we set m_isComplete to false and then check if the load is @@ -373,13 +345,13 @@ Frame* SubframeLoader::loadSubframe(HTMLFrameOwnerElement& ownerElement, const U // FIXME: Can we remove this entirely? m_isComplete normally gets set to false when a load is committed. frame->loader().started(); - RenderObject* renderer = ownerElement.renderer(); - FrameView* view = frame->view(); - if (renderer && renderer->isWidget() && view) - toRenderWidget(renderer)->setWidget(view); - + auto* renderer = ownerElement.renderer(); + auto* view = frame->view(); + if (is<RenderWidget>(renderer) && view) + downcast<RenderWidget>(*renderer).setWidget(view); + m_frame.loader().checkCallImplicitClose(); - + // Some loads are performed synchronously (e.g., about:blank and loads // cancelled by returning a null ResourceRequest from requestFromDelegate). // In these cases, the synchronous load would have finished @@ -395,36 +367,24 @@ Frame* SubframeLoader::loadSubframe(HTMLFrameOwnerElement& ownerElement, const U return frame.get(); } -bool SubframeLoader::allowPlugins(ReasonForCallingAllowPlugins) +bool SubframeLoader::allowPlugins() { - return m_frame.loader().client().allowPlugins(m_frame.settings().arePluginsEnabled()); + return m_frame.settings().arePluginsEnabled(); } -bool SubframeLoader::shouldUsePlugin(const URL& url, const String& mimeType, bool shouldPreferPlugInsForImages, bool hasFallback, bool& useFallback) +bool SubframeLoader::shouldUsePlugin(const URL& url, const String& mimeType, bool hasFallback, bool& useFallback) { if (m_frame.loader().client().shouldAlwaysUsePluginDocument(mimeType)) { useFallback = false; return true; } - // Allow other plug-ins to win over QuickTime because if the user has installed a plug-in that - // can handle TIFF (which QuickTime can also handle) they probably intended to override QT. - if (m_frame.page() && (mimeType == "image/tiff" || mimeType == "image/tif" || mimeType == "image/x-tiff")) { - String pluginName = m_frame.page()->pluginData().pluginNameForMimeType(mimeType); - if (!pluginName.isEmpty() && !pluginName.contains("QuickTime", false)) - return true; - } - - ObjectContentType objectType = m_frame.loader().client().objectContentType(url, mimeType, shouldPreferPlugInsForImages); + ObjectContentType objectType = m_frame.loader().client().objectContentType(url, mimeType); // If an object's content can't be handled and it has no fallback, let // it be handled as a plugin to show the broken plugin icon. - useFallback = objectType == ObjectContentNone && hasFallback; - return objectType == ObjectContentNone || objectType == ObjectContentNetscapePlugin || objectType == ObjectContentOtherPlugin; -} + useFallback = objectType == ObjectContentType::None && hasFallback; -Document* SubframeLoader::document() const -{ - return m_frame.document(); + return objectType == ObjectContentType::None || objectType == ObjectContentType::PlugIn; } bool SubframeLoader::loadPlugin(HTMLPlugInImageElement& pluginElement, const URL& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback) @@ -432,7 +392,9 @@ bool SubframeLoader::loadPlugin(HTMLPlugInImageElement& pluginElement, const URL if (useFallback) return false; - RenderEmbeddedObject* renderer = pluginElement.renderEmbeddedObject(); + auto& document = pluginElement.document(); + auto* renderer = pluginElement.renderEmbeddedObject(); + // FIXME: This code should not depend on renderer! if (!renderer) return false; @@ -440,17 +402,19 @@ bool SubframeLoader::loadPlugin(HTMLPlugInImageElement& pluginElement, const URL pluginElement.subframeLoaderWillCreatePlugIn(url); IntSize contentSize = roundedIntSize(LayoutSize(renderer->contentWidth(), renderer->contentHeight())); - bool loadManually = document()->isPluginDocument() && !m_containsPlugins && toPluginDocument(document())->shouldLoadPluginManually(); + bool loadManually = is<PluginDocument>(document) && !m_containsPlugins && downcast<PluginDocument>(document).shouldLoadPluginManually(); #if PLATFORM(IOS) // On iOS, we only tell the plugin to be in full page mode if the containing plugin document is the top level document. - if (document()->ownerElement()) + if (document.ownerElement()) loadManually = false; #endif - WeakPtr<RenderWidget> weakRenderer = renderer->createWeakPtr(); - // createPlugin *may* cause this renderer to disappear from underneath. - RefPtr<Widget> widget = m_frame.loader().client().createPlugin(contentSize, &pluginElement, url, paramNames, paramValues, mimeType, loadManually); + auto weakRenderer = renderer->createWeakPtr(); + + auto widget = m_frame.loader().client().createPlugin(contentSize, pluginElement, url, paramNames, paramValues, mimeType, loadManually); + + // The call to createPlugin *may* cause this renderer to disappear from underneath. if (!weakRenderer) return false; @@ -460,13 +424,9 @@ bool SubframeLoader::loadPlugin(HTMLPlugInImageElement& pluginElement, const URL return false; } - pluginElement.subframeLoaderDidCreatePlugIn(widget.get()); - renderer->setWidget(widget); + pluginElement.subframeLoaderDidCreatePlugIn(*widget); + renderer->setWidget(WTFMove(widget)); m_containsPlugins = true; - -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) - pluginElement.setNeedsStyleRecalc(SyntheticStyleChange); -#endif return true; } @@ -476,4 +436,9 @@ URL SubframeLoader::completeURL(const String& url) const return m_frame.document()->completeURL(url); } +bool SubframeLoader::shouldConvertInvalidURLsToBlank() const +{ + return m_frame.settings().shouldConvertInvalidURLsToBlank(); +} + } // namespace WebCore |