Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / loader / MixedContentChecker.cpp
index e7a6674..62bbf61 100644 (file)
 #include "core/dom/Document.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/Settings.h"
+#include "core/frame/UseCounter.h"
 #include "core/inspector/ConsoleMessage.h"
+#include "core/loader/DocumentLoader.h"
 #include "core/loader/FrameLoader.h"
 #include "core/loader/FrameLoaderClient.h"
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/weborigin/SchemeRegistry.h"
 #include "platform/weborigin/SecurityOrigin.h"
+#include "public/platform/Platform.h"
 #include "wtf/text/StringBuilder.h"
 
 namespace blink {
 
+namespace {
+} // namespace
+
 MixedContentChecker::MixedContentChecker(LocalFrame* frame)
     : m_frame(frame)
 {
@@ -62,6 +68,213 @@ bool MixedContentChecker::isMixedContent(SecurityOrigin* securityOrigin, const K
     return !SecurityOrigin::isSecure(url);
 }
 
+// static
+MixedContentChecker::ContextType MixedContentChecker::contextTypeFromContext(WebURLRequest::RequestContext context)
+{
+    switch (context) {
+    // "Optionally-blockable" mixed content
+    case WebURLRequest::RequestContextAudio:
+    case WebURLRequest::RequestContextFavicon:
+    case WebURLRequest::RequestContextImage:
+    case WebURLRequest::RequestContextVideo:
+        return ContextTypeOptionallyBlockable;
+
+    // "Blockable" mixed content
+    case WebURLRequest::RequestContextBeacon:
+    case WebURLRequest::RequestContextCSPReport:
+    case WebURLRequest::RequestContextEmbed:
+    case WebURLRequest::RequestContextFetch:
+    case WebURLRequest::RequestContextFont:
+    case WebURLRequest::RequestContextForm:
+    case WebURLRequest::RequestContextFrame:
+    case WebURLRequest::RequestContextHyperlink:
+    case WebURLRequest::RequestContextIframe:
+    case WebURLRequest::RequestContextImageSet:
+    case WebURLRequest::RequestContextImport:
+    case WebURLRequest::RequestContextLocation:
+    case WebURLRequest::RequestContextManifest:
+    case WebURLRequest::RequestContextObject:
+    case WebURLRequest::RequestContextPing:
+    case WebURLRequest::RequestContextScript:
+    case WebURLRequest::RequestContextServiceWorker:
+    case WebURLRequest::RequestContextSharedWorker:
+    case WebURLRequest::RequestContextStyle:
+    case WebURLRequest::RequestContextSubresource:
+    case WebURLRequest::RequestContextTrack:
+    case WebURLRequest::RequestContextWorker:
+    case WebURLRequest::RequestContextXSLT:
+        return ContextTypeBlockable;
+
+    // "Blockable" mixed content whose behavior changed recently, and which is thus guarded behind the "lax" flag
+    case WebURLRequest::RequestContextEventSource:
+    case WebURLRequest::RequestContextXMLHttpRequest:
+        return ContextTypeBlockableUnlessLax;
+
+    // FIXME: Contexts that we should block, but don't currently. https://crbug.com/388650
+    case WebURLRequest::RequestContextDownload:
+    case WebURLRequest::RequestContextInternal:
+    case WebURLRequest::RequestContextPlugin:
+    case WebURLRequest::RequestContextPrefetch:
+        return ContextTypeShouldBeBlockable;
+
+    case WebURLRequest::RequestContextUnspecified:
+        ASSERT_NOT_REACHED();
+    }
+    ASSERT_NOT_REACHED();
+    return ContextTypeBlockable;
+}
+
+// static
+const char* MixedContentChecker::typeNameFromContext(WebURLRequest::RequestContext context)
+{
+    switch (context) {
+    case WebURLRequest::RequestContextAudio:
+        return "audio file";
+    case WebURLRequest::RequestContextBeacon:
+        return "Beacon endpoint";
+    case WebURLRequest::RequestContextCSPReport:
+        return "Content Security Policy reporting endpoint";
+    case WebURLRequest::RequestContextDownload:
+        return "download";
+    case WebURLRequest::RequestContextEmbed:
+        return "plugin resource";
+    case WebURLRequest::RequestContextEventSource:
+        return "EventSource endpoint";
+    case WebURLRequest::RequestContextFavicon:
+        return "favicon";
+    case WebURLRequest::RequestContextFetch:
+        return "resource";
+    case WebURLRequest::RequestContextFont:
+        return "font";
+    case WebURLRequest::RequestContextForm:
+        return "form action";
+    case WebURLRequest::RequestContextFrame:
+        return "frame";
+    case WebURLRequest::RequestContextHyperlink:
+        return "resource";
+    case WebURLRequest::RequestContextIframe:
+        return "frame";
+    case WebURLRequest::RequestContextImage:
+        return "image";
+    case WebURLRequest::RequestContextImageSet:
+        return "image";
+    case WebURLRequest::RequestContextImport:
+        return "HTML Import";
+    case WebURLRequest::RequestContextInternal:
+        return "resource";
+    case WebURLRequest::RequestContextLocation:
+        return "resource";
+    case WebURLRequest::RequestContextManifest:
+        return "manifest";
+    case WebURLRequest::RequestContextObject:
+        return "plugin resource";
+    case WebURLRequest::RequestContextPing:
+        return "hyperlink auditing endpoint";
+    case WebURLRequest::RequestContextPlugin:
+        return "plugin data";
+    case WebURLRequest::RequestContextPrefetch:
+        return "prefetch resource";
+    case WebURLRequest::RequestContextScript:
+        return "script";
+    case WebURLRequest::RequestContextServiceWorker:
+        return "Service Worker script";
+    case WebURLRequest::RequestContextSharedWorker:
+        return "Shared Worker script";
+    case WebURLRequest::RequestContextStyle:
+        return "stylesheet";
+    case WebURLRequest::RequestContextSubresource:
+        return "resource";
+    case WebURLRequest::RequestContextTrack:
+        return "Text Track";
+    case WebURLRequest::RequestContextUnspecified:
+        return "resource";
+    case WebURLRequest::RequestContextVideo:
+        return "video";
+    case WebURLRequest::RequestContextWorker:
+        return "Worker script";
+    case WebURLRequest::RequestContextXMLHttpRequest:
+        return "XMLHttpRequest endpoint";
+    case WebURLRequest::RequestContextXSLT:
+        return "XSLT";
+    }
+    ASSERT_NOT_REACHED();
+    return "resource";
+}
+
+// static
+void MixedContentChecker::logToConsole(LocalFrame* frame, const KURL& url, WebURLRequest::RequestContext requestContext, bool allowed)
+{
+    String message = String::format(
+        "Mixed Content: The page at '%s' was loaded over HTTPS, but requested an insecure %s '%s'. %s",
+        frame->document()->url().elidedString().utf8().data(), typeNameFromContext(requestContext), url.elidedString().utf8().data(),
+        allowed ? "This content should also be served over HTTPS." : "This request has been blocked; the content must be served over HTTPS.");
+    MessageLevel messageLevel = allowed ? WarningMessageLevel : ErrorMessageLevel;
+    frame->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessageSource, messageLevel, message));
+}
+
+// static
+bool MixedContentChecker::shouldBlockFetch(LocalFrame* frame, const ResourceRequest& resourceRequest, const KURL& url)
+{
+    // No frame, no mixed content:
+    if (!frame)
+        return false;
+
+    // Check the top frame first.
+    if (Frame* top = frame->tree().top()) {
+        // FIXME: We need a way to access the top-level frame's SecurityOrigin when that frame
+        // is in a different process from the current frame. Until that is done, we bail out
+        // early and allow the load.
+        if (!top->isLocalFrame())
+            return false;
+
+        LocalFrame* localTop = toLocalFrame(top);
+        if (frame != localTop && shouldBlockFetch(localTop, resourceRequest, url))
+            return true;
+    }
+
+    // We only care about subresource loads; top-level navigations cannot be mixed content.
+    if (resourceRequest.frameType() == WebURLRequest::FrameTypeTopLevel)
+        return false;
+
+    // No mixed content, no problem.
+    if (!isMixedContent(frame->document()->securityOrigin(), url))
+        return false;
+
+    Settings* settings = frame->settings();
+    FrameLoaderClient* client = frame->loader().client();
+    SecurityOrigin* securityOrigin = frame->document()->securityOrigin();
+    bool allowed = false;
+
+    ContextType contextType = contextTypeFromContext(resourceRequest.requestContext());
+    if (contextType == ContextTypeBlockableUnlessLax)
+        contextType = RuntimeEnabledFeatures::laxMixedContentCheckingEnabled() ? ContextTypeOptionallyBlockable : ContextTypeBlockable;
+
+    switch (contextType) {
+    case ContextTypeOptionallyBlockable:
+        allowed = client->allowDisplayingInsecureContent(settings && settings->allowDisplayOfInsecureContent(), securityOrigin, url);
+        if (allowed)
+            client->didDisplayInsecureContent();
+        break;
+
+    case ContextTypeBlockable:
+        allowed = client->allowRunningInsecureContent(settings && settings->allowRunningOfInsecureContent(), securityOrigin, url);
+        if (allowed)
+            client->didRunInsecureContent(securityOrigin, url);
+        break;
+
+    case ContextTypeShouldBeBlockable:
+        return false;
+
+    case ContextTypeBlockableUnlessLax:
+        // We map this to either OptionallyBlockable or Blockable above.
+        ASSERT_NOT_REACHED();
+        return true;
+    };
+
+    logToConsole(frame, url, resourceRequest.requestContext(), allowed);
+    return !allowed;
+}
+
 bool MixedContentChecker::canDisplayInsecureContentInternal(SecurityOrigin* securityOrigin, const KURL& url, const MixedContentType type) const
 {
     // Check the top frame if it differs from MixedContentChecker's m_frame.
@@ -75,6 +288,10 @@ bool MixedContentChecker::canDisplayInsecureContentInternal(SecurityOrigin* secu
     if (top != m_frame && !toLocalFrame(top)->loader().mixedContentChecker()->canDisplayInsecureContent(toLocalFrame(top)->document()->securityOrigin(), url))
         return false;
 
+    // Just count these for the moment, don't block them.
+    if (Platform::current()->isReservedIPAddress(url) && !Platform::current()->isReservedIPAddress(KURL(ParsedURLString, securityOrigin->toString())))
+        UseCounter::count(m_frame->document(), UseCounter::MixedContentPrivateIPInPublicWebsitePassive);
+
     // Then check the current frame:
     if (!isMixedContent(securityOrigin, url))
         return true;
@@ -96,12 +313,16 @@ bool MixedContentChecker::canRunInsecureContentInternal(SecurityOrigin* security
         // FIXME: We need a way to access the top-level frame's MixedContentChecker when that frame
         // is in a different process from the current frame. Until that is done, we always allow
         // loads in remote frames.
-        return false;
+        return true;
     }
     Frame* top = m_frame->tree().top();
     if (top != m_frame && !toLocalFrame(top)->loader().mixedContentChecker()->canRunInsecureContent(toLocalFrame(top)->document()->securityOrigin(), url))
         return false;
 
+    // Just count these for the moment, don't block them.
+    if (Platform::current()->isReservedIPAddress(url) && !Platform::current()->isReservedIPAddress(KURL(ParsedURLString, securityOrigin->toString())))
+        UseCounter::count(m_frame->document(), UseCounter::MixedContentPrivateIPInPublicWebsiteActive);
+
     // Then check the current frame:
     if (!isMixedContent(securityOrigin, url))
         return true;
@@ -171,4 +392,24 @@ void MixedContentChecker::logWarning(bool allowed, const KURL& target, const Mix
     m_frame->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessageSource, messageLevel, message.toString()));
 }
 
+void MixedContentChecker::checkMixedPrivatePublic(LocalFrame* frame, const AtomicString& resourceIPAddress)
+{
+    if (!frame || !frame->document() || !frame->document()->loader())
+        return;
+
+    KURL documentIP(ParsedURLString, "http://" + frame->document()->loader()->response().remoteIPAddress());
+    KURL resourceIP(ParsedURLString, "http://" + resourceIPAddress);
+
+    // Just count these for the moment, don't block them.
+    //
+    // FIXME: Once we know how we want to check this, adjust the platform APIs to avoid the KURL construction.
+    if (Platform::current()->isReservedIPAddress(resourceIP) && !Platform::current()->isReservedIPAddress(documentIP))
+        UseCounter::count(frame->document(), UseCounter::MixedContentPrivateHostnameInPublicHostname);
+}
+
+void MixedContentChecker::trace(Visitor* visitor)
+{
+    visitor->trace(m_frame);
+}
+
 } // namespace blink