Have is<>(T*) function do a null check on the pointer argument
[WebKit-https.git] / Source / WebCore / loader / SubframeLoader.cpp
index 3d7f5c5..7ee548f 100644 (file)
@@ -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. 
  *
 #include "config.h"
 #include "SubframeLoader.h"
 
+#include "Chrome.h"
+#include "ChromeClient.h"
 #include "ContentSecurityPolicy.h"
+#include "DiagnosticLoggingKeys.h"
 #include "Frame.h"
+#include "FrameLoader.h"
 #include "FrameLoaderClient.h"
 #include "HTMLAppletElement.h"
+#include "HTMLAudioElement.h"
 #include "HTMLFrameElementBase.h"
 #include "HTMLNames.h"
-#include "HTMLPlugInImageElement.h"
+#include "HTMLObjectElement.h"
 #include "MIMETypeRegistry.h"
 #include "Page.h"
 #include "PluginData.h"
 #include "PluginDocument.h"
 #include "RenderEmbeddedObject.h"
 #include "RenderView.h"
+#include "ScriptController.h"
 #include "SecurityOrigin.h"
 #include "SecurityPolicy.h"
 #include "Settings.h"
 
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
-#include "HTMLMediaElement.h"
-#include "RenderVideo.h"
-#endif
-
 namespace WebCore {
     
 using namespace HTMLNames;
 
-SubframeLoader::SubframeLoader(Frame* frame)
+SubframeLoader::SubframeLoader(Frame& frame)
     : m_containsPlugins(false)
     , m_frame(frame)
 {
@@ -70,11 +71,11 @@ 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">
-    KURL scriptURL;
-    KURL url;
+    URL scriptURL;
+    URL url;
     if (protocolIsJavaScript(urlString)) {
         scriptURL = completeURL(urlString); // completeURL() encodes the URL.
         url = blankURL();
@@ -86,14 +87,14 @@ bool SubframeLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const Str
         return false;
 
     if (!scriptURL.isEmpty())
-        frame->script()->executeIfJavaScriptURL(scriptURL);
+        frame->script().executeIfJavaScriptURL(scriptURL);
 
     return true;
 }
     
 bool SubframeLoader::resourceWillUsePlugin(const String& url, const String& mimeType, bool shouldPreferPlugInsForImages)
 {
-    KURL completedURL;
+    URL completedURL;
     if (!url.isEmpty())
         completedURL = completeURL(url);
 
@@ -101,175 +102,222 @@ bool SubframeLoader::resourceWillUsePlugin(const String& url, const String& mime
     return shouldUsePlugin(completedURL, mimeType, shouldPreferPlugInsForImages, false, useFallback);
 }
 
-bool SubframeLoader::requestPlugin(HTMLPlugInImageElement* ownerElement, const KURL& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
+bool SubframeLoader::pluginIsLoadable(HTMLPlugInImageElement& pluginElement, const URL& url, const String& mimeType)
 {
-    Settings* settings = m_frame->settings();
-    if ((!allowPlugins(AboutToInstantiatePlugin)
-         // 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.
-         && !MIMETypeRegistry::isApplicationPluginMIMEType(mimeType))
-        || ((!settings || !settings->isJavaEnabled()) && MIMETypeRegistry::isJavaAppletMIMEType(mimeType)))
-        return false;
+    if (MIMETypeRegistry::isJavaAppletMIMEType(mimeType)) {
+        if (!m_frame.settings().isJavaEnabled())
+            return false;
+        if (document() && document()->securityOrigin()->isLocal() && !m_frame.settings().isJavaEnabledForLocalFiles())
+            return false;
+    }
+
+    if (document()) {
+        if (document()->isSandboxed(SandboxPlugins))
+            return false;
 
-    if (m_frame->document()) {
-        if (m_frame->document()->isSandboxed(SandboxPlugins))
+        if (!document()->securityOrigin()->canDisplay(url)) {
+            FrameLoader::reportLocalLoadFailed(&m_frame, url.string());
             return false;
-        if (!m_frame->document()->contentSecurityPolicy()->allowObjectFromSource(url))
+        }
+
+        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))
             return false;
     }
 
-    ASSERT(ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag));
-    return loadPlugin(ownerElement, url, mimeType, paramNames, paramValues, useFallback);
+    return true;
 }
-bool SubframeLoader::requestObject(HTMLPlugInImageElement* ownerElement, const String& url, const AtomicString& frameName, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues)
+
+bool SubframeLoader::requestPlugin(HTMLPlugInImageElement& ownerElement, const URL& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
 {
-    if (url.isEmpty() && mimeType.isEmpty())
+    // 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)))
         return false;
 
-    // FIXME: None of this code should use renderers!
-    RenderEmbeddedObject* renderer = ownerElement->renderEmbeddedObject();
-    ASSERT(renderer);
-    if (!renderer)
+    if (!pluginIsLoadable(ownerElement, url, mimeType))
         return false;
 
-    KURL completedURL;
-    if (!url.isEmpty())
-        completedURL = completeURL(url);
+    ASSERT(ownerElement.hasTagName(objectTag) || ownerElement.hasTagName(embedTag));
+    return loadPlugin(ownerElement, url, mimeType, paramNames, paramValues, useFallback);
+}
 
-    bool useFallback;
-    if (shouldUsePlugin(completedURL, mimeType, ownerElement->shouldPreferPlugInsForImages(), renderer->hasFallbackContent(), useFallback))
-        return requestPlugin(ownerElement, completedURL, mimeType, paramNames, paramValues, useFallback);
+static String findPluginMIMETypeFromURL(Page* page, const String& url)
+{
+    if (!url)
+        return String();
 
-    // 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 RenderPart's widget, causing what was previously 
-    // in the widget to be torn down.
-    return loadOrRedirectSubframe(ownerElement, completedURL, frameName, true, true);
+    size_t dotIndex = url.reverseFind('.');
+    if (dotIndex == notFound)
+        return String();
+
+    String extension = url.substring(dotIndex + 1);
+
+    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;
+        }
+    }
+
+    return String();
 }
 
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
-PassRefPtr<Widget> SubframeLoader::loadMediaPlayerProxyPlugin(Node* node, const KURL& url,
-    const Vector<String>& paramNames, const Vector<String>& paramValues)
+static void logPluginRequest(Page* page, const String& mimeType, const String& url, bool success)
 {
-    ASSERT(node->hasTagName(videoTag) || node->hasTagName(audioTag));
+    if (!page || !page->settings().diagnosticLoggingEnabled())
+        return;
+
+    String newMIMEType = mimeType;
+    if (!newMIMEType) {
+        // Try to figure out the MIME type from the URL extension.
+        newMIMEType = findPluginMIMETypeFromURL(page, url);
+        if (!newMIMEType)
+            return;
+    }
 
-    KURL completedURL;
-    if (!url.isEmpty())
-        completedURL = completeURL(url);
+    String pluginFile = page->pluginData().pluginFileForMimeType(newMIMEType);
+    String description = !pluginFile ? newMIMEType : pluginFile;
 
-    if (!m_frame->document()->securityOrigin()->canDisplay(completedURL)) {
-        FrameLoader::reportLocalLoadFailed(m_frame, completedURL.string());
-        return 0;
-    }
+    ChromeClient& chromeClient = page->chrome().client();
+    chromeClient.logDiagnosticMessage(success ? DiagnosticLoggingKeys::pluginLoadedKey() : DiagnosticLoggingKeys::pluginLoadingFailedKey(), description, DiagnosticLoggingKeys::noopKey());
 
-    if (!m_frame->document()->contentSecurityPolicy()->allowMediaFromSource(completedURL))
-        return 0;
+    if (!page->hasSeenAnyPlugin())
+        chromeClient.logDiagnosticMessage(DiagnosticLoggingKeys::pageContainsAtLeastOnePluginKey(), emptyString(), DiagnosticLoggingKeys::noopKey());
+    
+    if (!page->hasSeenPlugin(description))
+        chromeClient.logDiagnosticMessage(DiagnosticLoggingKeys::pageContainsPluginKey(), description, DiagnosticLoggingKeys::noopKey());
 
-    HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(node);
-    RenderPart* renderer = toRenderPart(node->renderer());
-    IntSize size;
+    page->sawPlugin(description);
+}
 
-    if (renderer)
-        size = IntSize(renderer->contentWidth(), renderer->contentHeight());
-    else if (mediaElement->isVideo())
-        size = RenderVideo::defaultSize();
+bool SubframeLoader::requestObject(HTMLPlugInImageElement& ownerElement, const String& url, const AtomicString& frameName, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues)
+{
+    if (url.isEmpty() && mimeType.isEmpty())
+        return false;
 
-    if (!m_frame->loader()->checkIfRunInsecureContent(m_frame->document()->securityOrigin(), completedURL))
-        return 0;
+    URL completedURL;
+    if (!url.isEmpty())
+        completedURL = completeURL(url);
 
-    RefPtr<Widget> widget = m_frame->loader()->client()->createMediaPlayerProxyPlugin(size, mediaElement, completedURL,
-                                         paramNames, paramValues, "application/x-media-element-proxy-plugin");
+    bool hasFallbackContent = is<HTMLObjectElement>(ownerElement) && downcast<HTMLObjectElement>(ownerElement).hasFallbackContent();
 
-    if (widget && renderer) {
-        renderer->setWidget(widget);
-        renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange);
+    bool useFallback;
+    if (shouldUsePlugin(completedURL, mimeType, ownerElement.shouldPreferPlugInsForImages(), hasFallbackContent, useFallback)) {
+        bool success = requestPlugin(ownerElement, completedURL, mimeType, paramNames, paramValues, useFallback);
+        logPluginRequest(document()->page(), mimeType, completedURL, success);
+        return success;
     }
-    m_containsPlugins = true;
 
-    return widget ? widget.release() : 0;
+    // 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, LockHistory::Yes, LockBackForwardList::Yes);
 }
-#endif // ENABLE(PLUGIN_PROXY_FOR_VIDEO)
 
-PassRefPtr<Widget> SubframeLoader::createJavaAppletWidget(const LayoutSize& size, HTMLAppletElement* element, const HashMap<String, String>& args)
+PassRefPtr<Widget> SubframeLoader::createJavaAppletWidget(const IntSize& size, HTMLAppletElement& element, const Vector<String>& paramNames, const Vector<String>& paramValues)
 {
     String baseURLString;
     String codeBaseURLString;
-    Vector<String> paramNames;
-    Vector<String> paramValues;
-    HashMap<String, String>::const_iterator end = args.end();
-    for (HashMap<String, String>::const_iterator it = args.begin(); it != end; ++it) {
-        if (equalIgnoringCase(it->first, "baseurl"))
-            baseURLString = it->second;
-        else if (equalIgnoringCase(it->first, "codebase"))
-            codeBaseURLString = it->second;
-        paramNames.append(it->first);
-        paramValues.append(it->second);
+
+    for (size_t i = 0; i < paramNames.size(); ++i) {
+        if (equalIgnoringCase(paramNames[i], "baseurl"))
+            baseURLString = paramValues[i];
+        else if (equalIgnoringCase(paramNames[i], "codebase"))
+            codeBaseURLString = paramValues[i];
     }
 
     if (!codeBaseURLString.isEmpty()) {
-        KURL codeBaseURL = completeURL(codeBaseURLString);
-        if (!element->document()->securityOrigin()->canDisplay(codeBaseURL)) {
-            FrameLoader::reportLocalLoadFailed(m_frame, codeBaseURL.string());
-            return 0;
+        URL codeBaseURL = completeURL(codeBaseURLString);
+        if (!element.document().securityOrigin()->canDisplay(codeBaseURL)) {
+            FrameLoader::reportLocalLoadFailed(&m_frame, codeBaseURL.string());
+            return nullptr;
         }
 
-        if (!element->document()->contentSecurityPolicy()->allowObjectFromSource(codeBaseURL))
-            return 0;
+        const char javaAppletMimeType[] = "application/x-java-applet";
+        if (!element.document().contentSecurityPolicy()->allowObjectFromSource(codeBaseURL)
+            || !element.document().contentSecurityPolicy()->allowPluginType(javaAppletMimeType, javaAppletMimeType, codeBaseURL))
+            return nullptr;
     }
 
     if (baseURLString.isEmpty())
-        baseURLString = m_frame->document()->baseURL().string();
-    KURL baseURL = completeURL(baseURLString);
+        baseURLString = m_frame.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 (!widget)
-        return 0;
+        widget = m_frame.loader().client().createJavaAppletWidget(size, &element, baseURL, paramNames, paramValues);
+
+    logPluginRequest(document()->page(), element.serviceType(), String(), widget);
+
+    if (!widget) {
+        RenderEmbeddedObject* renderer = element.renderEmbeddedObject();
+
+        if (!renderer->isPluginUnavailable())
+            renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginMissing);
+        return nullptr;
+    }
 
     m_containsPlugins = true;
     return widget;
 }
 
-Frame* SubframeLoader::loadOrRedirectSubframe(HTMLFrameOwnerElement* ownerElement, const KURL& url, const AtomicString& frameName, bool lockHistory, bool lockBackForwardList)
+Frame* SubframeLoader::loadOrRedirectSubframe(HTMLFrameOwnerElement& ownerElement, const URL& url, const AtomicString& frameName, LockHistory lockHistory, LockBackForwardList lockBackForwardList)
 {
-    Frame* frame = ownerElement->contentFrame();
+    Frame* frame = ownerElement.contentFrame();
     if (frame)
-        frame->navigationScheduler()->scheduleLocationChange(m_frame->document()->securityOrigin(), url.string(), m_frame->loader()->outgoingReferrer(), lockHistory, lockBackForwardList);
+        frame->navigationScheduler().scheduleLocationChange(m_frame.document()->securityOrigin(), url, m_frame.loader().outgoingReferrer(), lockHistory, lockBackForwardList);
     else
-        frame = loadSubframe(ownerElement, url, frameName, m_frame->loader()->outgoingReferrer());
-    return frame;
+        frame = loadSubframe(ownerElement, url, frameName, m_frame.loader().outgoingReferrer());
+
+    if (!frame)
+        return nullptr;
+
+    ASSERT(ownerElement.contentFrame() == frame || !ownerElement.contentFrame());
+    return ownerElement.contentFrame();
 }
 
-Frame* SubframeLoader::loadSubframe(HTMLFrameOwnerElement* ownerElement, const KURL& url, const String& name, const String& referrer)
+Frame* SubframeLoader::loadSubframe(HTMLFrameOwnerElement& ownerElement, const URL& url, const String& name, const String& referrer)
 {
-    RefPtr<Frame> protect(m_frame);
+    Ref<Frame> protect(m_frame);
 
     bool allowsScrolling = true;
     int marginWidth = -1;
     int marginHeight = -1;
-    if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag)) {
-        HTMLFrameElementBase* o = static_cast<HTMLFrameElementBase*>(ownerElement);
-        allowsScrolling = o->scrollingMode() != ScrollbarAlwaysOff;
-        marginWidth = o->marginWidth();
-        marginHeight = o->marginHeight();
+    if (is<HTMLFrameElementBase>(ownerElement)) {
+        HTMLFrameElementBase& frameElementBase = downcast<HTMLFrameElementBase>(ownerElement);
+        allowsScrolling = frameElementBase.scrollingMode() != ScrollbarAlwaysOff;
+        marginWidth = frameElementBase.marginWidth();
+        marginHeight = frameElementBase.marginHeight();
     }
 
-    if (!ownerElement->document()->securityOrigin()->canDisplay(url)) {
-        FrameLoader::reportLocalLoadFailed(m_frame, url.string());
-        return 0;
+    if (!ownerElement.document().securityOrigin()->canDisplay(url)) {
+        FrameLoader::reportLocalLoadFailed(&m_frame, url.string());
+        return nullptr;
     }
 
-    if (!ownerElement->document()->contentSecurityPolicy()->allowChildFrameFromSource(url))
-        return 0;
+    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(ownerElement.document().referrerPolicy(), url, referrer);
+    RefPtr<Frame> frame = m_frame.loader().client().createFrame(url, name, &ownerElement, referrerToUse, allowsScrolling, marginWidth, marginHeight);
 
     if (!frame)  {
-        m_frame->loader()->checkCallImplicitClose();
-        return 0;
+        m_frame.loader().checkCallImplicitClose();
+        return nullptr;
     }
     
     // All new frames will have m_isComplete set to true at this point due to synchronously loading
@@ -278,14 +326,14 @@ Frame* SubframeLoader::loadSubframe(HTMLFrameOwnerElement* ownerElement, const K
     // actually completed below. (Note that we set m_isComplete to false even for synchronous
     // loads, so that checkCompleted() below won't bail early.)
     // FIXME: Can we remove this entirely? m_isComplete normally gets set to false when a load is committed.
-    frame->loader()->started();
+    frame->loader().started();
    
-    RenderObject* renderer = ownerElement->renderer();
+    RenderObject* renderer = ownerElement.renderer();
     FrameView* view = frame->view();
     if (renderer && renderer->isWidget() && view)
         toRenderWidget(renderer)->setWidget(view);
     
-    m_frame->loader()->checkCallImplicitClose();
+    m_frame.loader().checkCallImplicitClose();
     
     // Some loads are performed synchronously (e.g., about:blank and loads
     // cancelled by returning a null ResourceRequest from requestFromDelegate).
@@ -296,38 +344,33 @@ Frame* SubframeLoader::loadSubframe(HTMLFrameOwnerElement* ownerElement, const K
     // FIXME: In this case the Frame will have finished loading before 
     // it's being added to the child list. It would be a good idea to
     // create the child first, then invoke the loader separately.
-    if (frame->loader()->state() == FrameStateComplete && !frame->loader()->policyDocumentLoader())
-        frame->loader()->checkCompleted();
+    if (frame->loader().state() == FrameStateComplete && !frame->loader().policyDocumentLoader())
+        frame->loader().checkCompleted();
 
     return frame.get();
 }
 
-bool SubframeLoader::allowPlugins(ReasonForCallingAllowPlugins reason)
+bool SubframeLoader::allowPlugins(ReasonForCallingAllowPlugins)
 {
-    Settings* settings = m_frame->settings();
-    bool allowed = m_frame->loader()->client()->allowPlugins(settings && settings->arePluginsEnabled());
-    if (!allowed && reason == AboutToInstantiatePlugin)
-        m_frame->loader()->client()->didNotAllowPlugins();
-    return allowed;
+    return m_frame.settings().arePluginsEnabled();
 }
 
-bool SubframeLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bool shouldPreferPlugInsForImages, bool hasFallback, bool& useFallback)
+bool SubframeLoader::shouldUsePlugin(const URL& url, const String& mimeType, bool shouldPreferPlugInsForImages, bool hasFallback, bool& useFallback)
 {
-    if (m_frame->loader()->client()->shouldUsePluginDocument(mimeType)) {
+    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")) {
-        const PluginData* pluginData = m_frame->page()->pluginData();
-        String pluginName = pluginData ? pluginData->pluginNameForMimeType(mimeType) : String();
+    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, shouldPreferPlugInsForImages);
     // 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;
@@ -336,53 +379,46 @@ bool SubframeLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bo
 
 Document* SubframeLoader::document() const
 {
-    return m_frame->document();
+    return m_frame.document();
 }
 
-bool SubframeLoader::loadPlugin(HTMLPlugInImageElement* pluginElement, const KURL& url, const String& mimeType,
-    const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
+bool SubframeLoader::loadPlugin(HTMLPlugInImageElement& pluginElement, const URL& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
 {
-    RenderEmbeddedObject* renderer = pluginElement->renderEmbeddedObject();
+    RenderEmbeddedObject* renderer = pluginElement.renderEmbeddedObject();
 
     // FIXME: This code should not depend on renderer!
     if (!renderer || useFallback)
         return false;
 
-    if (!document()->securityOrigin()->canDisplay(url)) {
-        FrameLoader::reportLocalLoadFailed(m_frame, url.string());
-        return false;
-    }
+    pluginElement.subframeLoaderWillCreatePlugIn(url);
 
-    if (!document()->contentSecurityPolicy()->allowObjectFromSource(url))
-        return false;
+    IntSize contentSize = roundedIntSize(LayoutSize(renderer->contentWidth(), renderer->contentHeight()));
+    bool loadManually = is<PluginDocument>(*document()) && !m_containsPlugins && downcast<PluginDocument>(*document()).shouldLoadPluginManually();
 
-    FrameLoader* frameLoader = m_frame->loader();
-    if (!frameLoader->checkIfRunInsecureContent(document()->securityOrigin(), url))
-        return false;
+#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())
+        loadManually = false;
+#endif
 
-    IntSize contentSize(renderer->contentWidth(), renderer->contentHeight());
-    bool loadManually = document()->isPluginDocument() && !m_containsPlugins && toPluginDocument(document())->shouldLoadPluginManually();
-    RefPtr<Widget> widget = frameLoader->client()->createPlugin(contentSize,
-        pluginElement, url, paramNames, paramValues, mimeType, loadManually);
+    RefPtr<Widget> widget = m_frame.loader().client().createPlugin(contentSize, &pluginElement, url, paramNames, paramValues, mimeType, loadManually);
 
     if (!widget) {
-        renderer->setShowsMissingPluginIndicator();
+        if (!renderer->isPluginUnavailable())
+            renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginMissing);
         return false;
     }
 
+    pluginElement.subframeLoaderDidCreatePlugIn(widget.get());
     renderer->setWidget(widget);
     m_containsPlugins = true;
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) || ENABLE(3D_PLUGIN)
-    pluginElement->setNeedsStyleRecalc(SyntheticStyleChange);
-#endif
     return true;
 }
 
-KURL SubframeLoader::completeURL(const String& url) const
+URL SubframeLoader::completeURL(const String& url) const
 {
-    ASSERT(m_frame->document());
-    return m_frame->document()->completeURL(url);
+    ASSERT(m_frame.document());
+    return m_frame.document()->completeURL(url);
 }
 
 } // namespace WebCore