Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 */ | 27 */ |
| 28 | 28 |
| 29 #include "core/loader/MixedContentChecker.h" | 29 #include "core/loader/MixedContentChecker.h" |
| 30 | 30 |
| 31 #include "core/dom/Document.h" | 31 #include "core/dom/Document.h" |
| 32 #include "core/frame/Frame.h" | |
| 32 #include "core/frame/LocalFrame.h" | 33 #include "core/frame/LocalFrame.h" |
| 33 #include "core/frame/Settings.h" | 34 #include "core/frame/Settings.h" |
| 34 #include "core/frame/UseCounter.h" | 35 #include "core/frame/UseCounter.h" |
| 35 #include "core/inspector/ConsoleMessage.h" | 36 #include "core/inspector/ConsoleMessage.h" |
| 36 #include "core/loader/DocumentLoader.h" | 37 #include "core/loader/DocumentLoader.h" |
| 37 #include "core/loader/FrameLoader.h" | 38 #include "core/loader/FrameLoader.h" |
| 38 #include "core/loader/FrameLoaderClient.h" | 39 #include "core/loader/FrameLoaderClient.h" |
| 39 #include "platform/RuntimeEnabledFeatures.h" | 40 #include "platform/RuntimeEnabledFeatures.h" |
| 40 #include "platform/weborigin/SchemeRegistry.h" | 41 #include "platform/weborigin/SchemeRegistry.h" |
| 41 #include "platform/weborigin/SecurityOrigin.h" | 42 #include "platform/weborigin/SecurityOrigin.h" |
| 42 #include "public/platform/Platform.h" | 43 #include "public/platform/Platform.h" |
| 43 #include "wtf/text/StringBuilder.h" | 44 #include "wtf/text/StringBuilder.h" |
| 44 | 45 |
| 45 namespace blink { | 46 namespace blink { |
| 46 | 47 |
| 47 static void measureStricterVersionOfIsMixedContent(LocalFrame* frame, const KURL & url) | 48 namespace { |
| 49 | |
| 50 // When a frame is local, use its full URL to represent the main | |
| 51 // resource. When the frame is remote, the full URL isn't accessible, so | |
| 52 // use the origin. This function is used, for example, to determine the | |
| 53 // URL to show in console messages about mixed content. | |
| 54 KURL mainResourceUrlForFrame(Frame* frame) | |
| 55 { | |
| 56 if (frame->isRemoteFrame()) | |
| 57 return KURL(KURL(), frame->securityContext()->securityOrigin()->toString ()); | |
| 58 return toLocalFrame(frame)->document()->url(); | |
| 59 } | |
| 60 | |
| 61 } // namespace | |
| 62 | |
| 63 static void measureStricterVersionOfIsMixedContent(Frame* frame, const KURL& url ) | |
|
Mike West
2016/01/22 12:59:21
Thanks for the reminder that I need to look at the
| |
| 48 { | 64 { |
| 49 // We're currently only checking for mixed content in `https://*` contexts. | 65 // We're currently only checking for mixed content in `https://*` contexts. |
| 50 // What about other "secure" contexts the SchemeRegistry knows about? We'll | 66 // What about other "secure" contexts the SchemeRegistry knows about? We'll |
| 51 // use this method to measure the occurance of non-webby mixed content to | 67 // use this method to measure the occurance of non-webby mixed content to |
| 52 // make sure we're not breaking the world without realizing it. | 68 // make sure we're not breaking the world without realizing it. |
| 53 SecurityOrigin* origin = frame->document()->securityOrigin(); | 69 SecurityOrigin* origin = frame->securityContext()->securityOrigin(); |
| 54 if (MixedContentChecker::isMixedContent(origin, url)) { | 70 if (MixedContentChecker::isMixedContent(origin, url)) { |
| 55 if (frame->document()->securityOrigin()->protocol() != "https") | 71 if (origin->protocol() != "https") |
| 56 UseCounter::count(frame, UseCounter::MixedContentInNonHTTPSFrameThat RestrictsMixedContent); | 72 UseCounter::count(frame, UseCounter::MixedContentInNonHTTPSFrameThat RestrictsMixedContent); |
| 57 } else if (!SecurityOrigin::isSecure(url) && SchemeRegistry::shouldTreatURLS chemeAsSecure(origin->protocol())) { | 73 } else if (!SecurityOrigin::isSecure(url) && SchemeRegistry::shouldTreatURLS chemeAsSecure(origin->protocol())) { |
| 58 UseCounter::count(frame, UseCounter::MixedContentInSecureFrameThatDoesNo tRestrictMixedContent); | 74 UseCounter::count(frame, UseCounter::MixedContentInSecureFrameThatDoesNo tRestrictMixedContent); |
| 59 } | 75 } |
| 60 } | 76 } |
| 61 | 77 |
| 62 bool requestIsSubframeSubresource(LocalFrame* frame, WebURLRequest::FrameType fr ameType) | 78 bool requestIsSubframeSubresource(Frame* frame, WebURLRequest::FrameType frameTy pe) |
| 63 { | 79 { |
| 64 return (frame && frame != frame->tree().top() && frameType != WebURLRequest: :FrameTypeNested); | 80 return (frame && frame != frame->tree().top() && frameType != WebURLRequest: :FrameTypeNested); |
| 65 } | 81 } |
| 66 | 82 |
| 67 // static | 83 // static |
| 68 bool MixedContentChecker::isMixedContent(SecurityOrigin* securityOrigin, const K URL& url) | 84 bool MixedContentChecker::isMixedContent(SecurityOrigin* securityOrigin, const K URL& url) |
| 69 { | 85 { |
| 70 if (!SchemeRegistry::shouldTreatURLSchemeAsRestrictingMixedContent(securityO rigin->protocol())) | 86 if (!SchemeRegistry::shouldTreatURLSchemeAsRestrictingMixedContent(securityO rigin->protocol())) |
| 71 return false; | 87 return false; |
| 72 | 88 |
| 73 // We're in a secure context, so |url| is mixed content if it's insecure. | 89 // We're in a secure context, so |url| is mixed content if it's insecure. |
| 74 return !SecurityOrigin::isSecure(url); | 90 return !SecurityOrigin::isSecure(url); |
| 75 } | 91 } |
| 76 | 92 |
| 77 // static | 93 // static |
| 78 LocalFrame* MixedContentChecker::inWhichFrameIsContentMixed(LocalFrame* frame, W ebURLRequest::FrameType frameType, const KURL& url) | 94 Frame* MixedContentChecker::inWhichFrameIsContentMixed(Frame* frame, WebURLReque st::FrameType frameType, const KURL& url) |
| 79 { | 95 { |
| 80 // We only care about subresource loads; top-level navigations cannot be mix ed content. Neither can frameless requests. | 96 // We only care about subresource loads; top-level navigations cannot be mix ed content. Neither can frameless requests. |
| 81 if (frameType == WebURLRequest::FrameTypeTopLevel || !frame) | 97 if (frameType == WebURLRequest::FrameTypeTopLevel || !frame) |
| 82 return nullptr; | 98 return nullptr; |
| 83 | 99 |
| 84 // Check the top frame first. | 100 // Check the top frame first. |
| 85 if (Frame* top = frame->tree().top()) { | 101 if (Frame* top = frame->tree().top()) { |
| 86 // FIXME: We need a way to access the top-level frame's SecurityOrigin w hen that frame | 102 measureStricterVersionOfIsMixedContent(top, url); |
| 87 // is in a different process from the current frame. Until that is done, we bail out. | 103 if (isMixedContent(top->securityContext()->securityOrigin(), url)) |
| 88 if (!top->isLocalFrame()) | 104 return top; |
| 89 return nullptr; | |
| 90 | |
| 91 LocalFrame* localTop = toLocalFrame(top); | |
| 92 measureStricterVersionOfIsMixedContent(localTop, url); | |
| 93 if (isMixedContent(localTop->document()->securityOrigin(), url)) | |
| 94 return localTop; | |
| 95 } | 105 } |
| 96 | 106 |
| 97 measureStricterVersionOfIsMixedContent(frame, url); | 107 measureStricterVersionOfIsMixedContent(frame, url); |
| 98 if (isMixedContent(frame->document()->securityOrigin(), url)) | 108 if (isMixedContent(frame->securityContext()->securityOrigin(), url)) |
| 99 return frame; | 109 return frame; |
| 100 | 110 |
| 101 // No mixed content, no problem. | 111 // No mixed content, no problem. |
| 102 return nullptr; | 112 return nullptr; |
| 103 } | 113 } |
| 104 | 114 |
| 105 // static | 115 // static |
| 106 MixedContentChecker::ContextType MixedContentChecker::contextTypeFromContext(Web URLRequest::RequestContext context, LocalFrame* frame) | 116 MixedContentChecker::ContextType MixedContentChecker::contextTypeFromContext(Web URLRequest::RequestContext context, Frame* frame) |
| 107 { | 117 { |
| 108 switch (context) { | 118 switch (context) { |
| 109 // "Optionally-blockable" mixed content | 119 // "Optionally-blockable" mixed content |
| 110 case WebURLRequest::RequestContextAudio: | 120 case WebURLRequest::RequestContextAudio: |
| 111 case WebURLRequest::RequestContextFavicon: | 121 case WebURLRequest::RequestContextFavicon: |
| 112 case WebURLRequest::RequestContextImage: | 122 case WebURLRequest::RequestContextImage: |
| 113 case WebURLRequest::RequestContextVideo: | 123 case WebURLRequest::RequestContextVideo: |
| 114 return ContextTypeOptionallyBlockable; | 124 return ContextTypeOptionallyBlockable; |
| 115 | 125 |
| 116 // Plugins! Oh how dearly we love plugin-loaded content! | 126 // Plugins! Oh how dearly we love plugin-loaded content! |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 231 case WebURLRequest::RequestContextXMLHttpRequest: | 241 case WebURLRequest::RequestContextXMLHttpRequest: |
| 232 return "XMLHttpRequest endpoint"; | 242 return "XMLHttpRequest endpoint"; |
| 233 case WebURLRequest::RequestContextXSLT: | 243 case WebURLRequest::RequestContextXSLT: |
| 234 return "XSLT"; | 244 return "XSLT"; |
| 235 } | 245 } |
| 236 ASSERT_NOT_REACHED(); | 246 ASSERT_NOT_REACHED(); |
| 237 return "resource"; | 247 return "resource"; |
| 238 } | 248 } |
| 239 | 249 |
| 240 // static | 250 // static |
| 241 void MixedContentChecker::logToConsoleAboutFetch(LocalFrame* frame, const KURL& url, WebURLRequest::RequestContext requestContext, bool allowed) | 251 void MixedContentChecker::logToConsoleAboutFetch(LocalFrame* frame, const KURL& mainResourceUrl, const KURL& url, WebURLRequest::RequestContext requestContext, bool allowed) |
| 242 { | 252 { |
| 243 String message = String::format( | 253 String message = String::format( |
| 244 "Mixed Content: The page at '%s' was loaded over HTTPS, but requested an insecure %s '%s'. %s", | 254 "Mixed Content: The page at '%s' was loaded over HTTPS, but requested an insecure %s '%s'. %s", |
| 245 frame->document()->url().elidedString().utf8().data(), typeNameFromConte xt(requestContext), url.elidedString().utf8().data(), | 255 mainResourceUrl.elidedString().utf8().data(), typeNameFromContext(reques tContext), url.elidedString().utf8().data(), |
| 246 allowed ? "This content should also be served over HTTPS." : "This reque st has been blocked; the content must be served over HTTPS."); | 256 allowed ? "This content should also be served over HTTPS." : "This reque st has been blocked; the content must be served over HTTPS."); |
| 247 MessageLevel messageLevel = allowed ? WarningMessageLevel : ErrorMessageLeve l; | 257 MessageLevel messageLevel = allowed ? WarningMessageLevel : ErrorMessageLeve l; |
| 248 frame->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessageS ource, messageLevel, message)); | 258 frame->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessageS ource, messageLevel, message)); |
| 249 } | 259 } |
| 250 | 260 |
| 251 // static | 261 // static |
| 252 void MixedContentChecker::count(LocalFrame* frame, WebURLRequest::RequestContext requestContext) | 262 void MixedContentChecker::count(Frame* frame, WebURLRequest::RequestContext requ estContext) |
| 253 { | 263 { |
| 254 UseCounter::count(frame, UseCounter::MixedContentPresent); | 264 UseCounter::count(frame, UseCounter::MixedContentPresent); |
| 255 | 265 |
| 256 // Roll blockable content up into a single counter, count unblocked types in dividually so we | 266 // Roll blockable content up into a single counter, count unblocked types in dividually so we |
| 257 // can determine when they can be safely moved to the blockable category: | 267 // can determine when they can be safely moved to the blockable category: |
| 258 ContextType contextType = contextTypeFromContext(requestContext, frame); | 268 ContextType contextType = contextTypeFromContext(requestContext, frame); |
| 259 if (contextType == ContextTypeBlockable) { | 269 if (contextType == ContextTypeBlockable) { |
| 260 UseCounter::count(frame, UseCounter::MixedContentBlockable); | 270 UseCounter::count(frame, UseCounter::MixedContentBlockable); |
| 261 return; | 271 return; |
| 262 } | 272 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 291 default: | 301 default: |
| 292 ASSERT_NOT_REACHED(); | 302 ASSERT_NOT_REACHED(); |
| 293 return; | 303 return; |
| 294 } | 304 } |
| 295 UseCounter::count(frame, feature); | 305 UseCounter::count(frame, feature); |
| 296 } | 306 } |
| 297 | 307 |
| 298 // static | 308 // static |
| 299 bool MixedContentChecker::shouldBlockFetch(LocalFrame* frame, WebURLRequest::Req uestContext requestContext, WebURLRequest::FrameType frameType, const KURL& url, MixedContentChecker::ReportingStatus reportingStatus) | 309 bool MixedContentChecker::shouldBlockFetch(LocalFrame* frame, WebURLRequest::Req uestContext requestContext, WebURLRequest::FrameType frameType, const KURL& url, MixedContentChecker::ReportingStatus reportingStatus) |
| 300 { | 310 { |
| 301 LocalFrame* mixedFrame = inWhichFrameIsContentMixed(frame, frameType, url); | 311 Frame* effectiveFrame = effectiveFrameForFrameType(frame, frameType); |
|
estark
2016/01/21 23:35:49
Mike: it used to be that FrameFetchContext called
Mike West
2016/01/22 12:59:21
I'm pretty sure we can remove that path entirely,
estark
2016/01/22 17:37:37
Perfect, thanks!
| |
| 312 Frame* mixedFrame = inWhichFrameIsContentMixed(effectiveFrame, frameType, ur l); | |
| 302 if (!mixedFrame) | 313 if (!mixedFrame) |
| 303 return false; | 314 return false; |
| 304 | 315 |
| 305 MixedContentChecker::count(mixedFrame, requestContext); | 316 MixedContentChecker::count(mixedFrame, requestContext); |
| 306 | 317 |
| 307 Settings* settings = mixedFrame->settings(); | 318 Settings* settings = mixedFrame->settings(); |
| 308 FrameLoaderClient* client = mixedFrame->loader().client(); | 319 // Use the current local frame's client; the embedder doesn't |
| 309 SecurityOrigin* securityOrigin = mixedFrame->document()->securityOrigin(); | 320 // distinguish mixed content signals from different frames on the |
| 321 // same page. | |
| 322 FrameLoaderClient* client = frame->loader().client(); | |
| 323 SecurityOrigin* securityOrigin = mixedFrame->securityContext()->securityOrig in(); | |
| 310 bool allowed = false; | 324 bool allowed = false; |
| 311 | 325 |
| 312 // If we're in strict mode, we'll automagically fail everything, and intenti onally skip | 326 // If we're in strict mode, we'll automagically fail everything, and intenti onally skip |
| 313 // the client checks in order to prevent degrading the site's security UI. | 327 // the client checks in order to prevent degrading the site's security UI. |
| 314 bool strictMode = mixedFrame->securityContext()->shouldEnforceStrictMixedCon tentChecking() || settings->strictMixedContentChecking(); | 328 bool strictMode = mixedFrame->securityContext()->shouldEnforceStrictMixedCon tentChecking() || settings->strictMixedContentChecking(); |
| 315 | 329 |
| 316 ContextType contextType = contextTypeFromContext(requestContext, mixedFrame) ; | 330 ContextType contextType = contextTypeFromContext(requestContext, mixedFrame) ; |
| 317 | 331 |
| 318 // If we're loading the main resource of a subframe, we need to take a close look at the loaded URL. | 332 // If we're loading the main resource of a subframe, we need to take a close look at the loaded URL. |
| 319 // If we're dealing with a CORS-enabled scheme, then block mixed frames as a ctive content. Otherwise, | 333 // If we're dealing with a CORS-enabled scheme, then block mixed frames as a ctive content. Otherwise, |
| 320 // treat frames as passive content. | 334 // treat frames as passive content. |
| 321 // | 335 // |
| 322 // FIXME: Remove this temporary hack once we have a reasonable API for launc hing external applications | 336 // FIXME: Remove this temporary hack once we have a reasonable API for launc hing external applications |
| 323 // via URLs. http://crbug.com/318788 and https://crbug.com/393481 | 337 // via URLs. http://crbug.com/318788 and https://crbug.com/393481 |
| 324 if (frameType == WebURLRequest::FrameTypeNested && !SchemeRegistry::shouldTr eatURLSchemeAsCORSEnabled(url.protocol())) | 338 if (frameType == WebURLRequest::FrameTypeNested && !SchemeRegistry::shouldTr eatURLSchemeAsCORSEnabled(url.protocol())) |
| 325 contextType = ContextTypeOptionallyBlockable; | 339 contextType = ContextTypeOptionallyBlockable; |
| 326 | 340 |
| 327 switch (contextType) { | 341 switch (contextType) { |
| 328 case ContextTypeOptionallyBlockable: | 342 case ContextTypeOptionallyBlockable: |
| 329 allowed = !strictMode && client->allowDisplayingInsecureContent(settings && settings->allowDisplayOfInsecureContent(), url); | 343 allowed = !strictMode && client->allowDisplayingInsecureContent(settings && settings->allowDisplayOfInsecureContent(), url); |
| 330 if (allowed) | 344 if (allowed) |
| 331 client->didDisplayInsecureContent(); | 345 client->didDisplayInsecureContent(); |
| 332 break; | 346 break; |
| 333 | 347 |
| 334 case ContextTypeBlockable: { | 348 case ContextTypeBlockable: { |
| 335 // Strictly block subresources in subframes, unless all insecure | 349 // Strictly block subresources in subframes, unless all insecure |
| 336 // content is allowed. | 350 // content is allowed. |
| 337 if (!settings->allowRunningOfInsecureContent() && requestIsSubframeSubre source(frame, frameType)) { | 351 if (!settings->allowRunningOfInsecureContent() && requestIsSubframeSubre source(effectiveFrame, frameType)) { |
| 338 UseCounter::count(mixedFrame, UseCounter::BlockableMixedContentInSub frameBlocked); | 352 UseCounter::count(mixedFrame, UseCounter::BlockableMixedContentInSub frameBlocked); |
| 339 allowed = false; | 353 allowed = false; |
| 340 break; | 354 break; |
| 341 } | 355 } |
| 342 | 356 |
| 343 bool shouldAskEmbedder = !strictMode && settings && (!settings->strictly BlockBlockableMixedContent() || settings->allowRunningOfInsecureContent()); | 357 bool shouldAskEmbedder = !strictMode && settings && (!settings->strictly BlockBlockableMixedContent() || settings->allowRunningOfInsecureContent()); |
| 344 allowed = shouldAskEmbedder && client->allowRunningInsecureContent(setti ngs && settings->allowRunningOfInsecureContent(), securityOrigin, url); | 358 allowed = shouldAskEmbedder && client->allowRunningInsecureContent(setti ngs && settings->allowRunningOfInsecureContent(), securityOrigin, url); |
| 345 if (allowed) { | 359 if (allowed) { |
| 346 client->didRunInsecureContent(securityOrigin, url); | 360 client->didRunInsecureContent(securityOrigin, url); |
| 347 UseCounter::count(mixedFrame, UseCounter::MixedContentBlockableAllow ed); | 361 UseCounter::count(mixedFrame, UseCounter::MixedContentBlockableAllow ed); |
| 348 } | 362 } |
| 349 break; | 363 break; |
| 350 } | 364 } |
| 351 | 365 |
| 352 case ContextTypeShouldBeBlockable: | 366 case ContextTypeShouldBeBlockable: |
| 353 allowed = !strictMode; | 367 allowed = !strictMode; |
| 354 if (allowed) | 368 if (allowed) |
| 355 client->didDisplayInsecureContent(); | 369 client->didDisplayInsecureContent(); |
| 356 break; | 370 break; |
| 357 case ContextTypeNotMixedContent: | 371 case ContextTypeNotMixedContent: |
| 358 ASSERT_NOT_REACHED(); | 372 ASSERT_NOT_REACHED(); |
| 359 break; | 373 break; |
| 360 }; | 374 }; |
| 361 | 375 |
| 362 if (reportingStatus == SendReport) | 376 if (reportingStatus == SendReport) |
| 363 logToConsoleAboutFetch(frame, url, requestContext, allowed); | 377 logToConsoleAboutFetch(frame, mainResourceUrlForFrame(mixedFrame), url, requestContext, allowed); |
|
estark
2016/01/21 23:35:49
Mike: there's a small regression here that I want
Mike West
2016/01/22 12:59:22
I think that's a reasonable tradeoff. It's unfortu
estark
2016/01/22 17:37:37
So the message does get printed to the console, bu
| |
| 364 return !allowed; | 378 return !allowed; |
| 365 } | 379 } |
| 366 | 380 |
| 367 // static | 381 // static |
| 368 void MixedContentChecker::logToConsoleAboutWebSocket(LocalFrame* frame, const KU RL& url, bool allowed) | 382 void MixedContentChecker::logToConsoleAboutWebSocket(LocalFrame* frame, const KU RL& mainResourceUrl, const KURL& url, bool allowed) |
| 369 { | 383 { |
| 370 String message = String::format( | 384 String message = String::format( |
| 371 "Mixed Content: The page at '%s' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint '%s'. %s", | 385 "Mixed Content: The page at '%s' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint '%s'. %s", |
| 372 frame->document()->url().elidedString().utf8().data(), url.elidedString( ).utf8().data(), | 386 mainResourceUrl.elidedString().utf8().data(), url.elidedString().utf8(). data(), |
| 373 allowed ? "This endpoint should be available via WSS. Insecure access is deprecated." : "This request has been blocked; this endpoint must be available over WSS."); | 387 allowed ? "This endpoint should be available via WSS. Insecure access is deprecated." : "This request has been blocked; this endpoint must be available over WSS."); |
| 374 MessageLevel messageLevel = allowed ? WarningMessageLevel : ErrorMessageLeve l; | 388 MessageLevel messageLevel = allowed ? WarningMessageLevel : ErrorMessageLeve l; |
| 375 frame->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessageS ource, messageLevel, message)); | 389 frame->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessageS ource, messageLevel, message)); |
| 376 } | 390 } |
| 377 | 391 |
| 378 // static | 392 // static |
| 379 bool MixedContentChecker::shouldBlockWebSocket(LocalFrame* frame, const KURL& ur l, MixedContentChecker::ReportingStatus reportingStatus) | 393 bool MixedContentChecker::shouldBlockWebSocket(LocalFrame* frame, const KURL& ur l, MixedContentChecker::ReportingStatus reportingStatus) |
| 380 { | 394 { |
| 381 LocalFrame* mixedFrame = inWhichFrameIsContentMixed(frame, WebURLRequest::Fr ameTypeNone, url); | 395 Frame* mixedFrame = inWhichFrameIsContentMixed(frame, WebURLRequest::FrameTy peNone, url); |
| 382 if (!mixedFrame) | 396 if (!mixedFrame) |
| 383 return false; | 397 return false; |
| 384 | 398 |
| 385 UseCounter::count(mixedFrame, UseCounter::MixedContentPresent); | 399 UseCounter::count(mixedFrame, UseCounter::MixedContentPresent); |
| 386 UseCounter::count(mixedFrame, UseCounter::MixedContentWebSocket); | 400 UseCounter::count(mixedFrame, UseCounter::MixedContentWebSocket); |
| 387 | 401 |
| 388 Settings* settings = mixedFrame->settings(); | 402 Settings* settings = mixedFrame->settings(); |
| 389 FrameLoaderClient* client = mixedFrame->loader().client(); | 403 // Use the current local frame's client; the embedder doesn't |
| 390 SecurityOrigin* securityOrigin = mixedFrame->document()->securityOrigin(); | 404 // distinguish mixed content signals from different frames on the |
| 405 // same page. | |
| 406 FrameLoaderClient* client = frame->loader().client(); | |
| 407 SecurityOrigin* securityOrigin = mixedFrame->securityContext()->securityOrig in(); | |
| 391 bool allowed = false; | 408 bool allowed = false; |
| 392 | 409 |
| 393 // If we're in strict mode, we'll automagically fail everything, and intenti onally skip | 410 // If we're in strict mode, we'll automagically fail everything, and intenti onally skip |
| 394 // the client checks in order to prevent degrading the site's security UI. | 411 // the client checks in order to prevent degrading the site's security UI. |
| 395 bool strictMode = mixedFrame->document()->shouldEnforceStrictMixedContentChe cking() || settings->strictMixedContentChecking(); | 412 bool strictMode = mixedFrame->securityContext()->shouldEnforceStrictMixedCon tentChecking() || settings->strictMixedContentChecking(); |
| 396 if (!strictMode) { | 413 if (!strictMode) { |
| 397 bool allowedPerSettings = settings && settings->allowRunningOfInsecureCo ntent(); | 414 bool allowedPerSettings = settings && settings->allowRunningOfInsecureCo ntent(); |
| 398 allowed = client->allowRunningInsecureContent(allowedPerSettings, securi tyOrigin, url); | 415 allowed = client->allowRunningInsecureContent(allowedPerSettings, securi tyOrigin, url); |
| 399 } | 416 } |
| 400 | 417 |
| 401 if (allowed) | 418 if (allowed) |
| 402 client->didRunInsecureContent(securityOrigin, url); | 419 client->didRunInsecureContent(securityOrigin, url); |
| 403 | 420 |
| 404 if (reportingStatus == SendReport) | 421 if (reportingStatus == SendReport) |
| 405 logToConsoleAboutWebSocket(frame, url, allowed); | 422 logToConsoleAboutWebSocket(frame, mainResourceUrlForFrame(mixedFrame), u rl, allowed); |
| 406 return !allowed; | 423 return !allowed; |
| 407 } | 424 } |
| 408 | 425 |
| 409 bool MixedContentChecker::isMixedFormAction(LocalFrame* frame, const KURL& url, ReportingStatus reportingStatus) | 426 bool MixedContentChecker::isMixedFormAction(LocalFrame* frame, const KURL& url, ReportingStatus reportingStatus) |
| 410 { | 427 { |
| 411 // For whatever reason, some folks handle forms via JavaScript, and submit t o `javascript:void(0)` | 428 // For whatever reason, some folks handle forms via JavaScript, and submit t o `javascript:void(0)` |
| 412 // rather than calling `preventDefault()`. We special-case `javascript:` URL s here, as they don't | 429 // rather than calling `preventDefault()`. We special-case `javascript:` URL s here, as they don't |
| 413 // introduce MixedContent for form submissions. | 430 // introduce MixedContent for form submissions. |
| 414 if (url.protocolIs("javascript")) | 431 if (url.protocolIs("javascript")) |
| 415 return false; | 432 return false; |
| 416 | 433 |
| 417 LocalFrame* mixedFrame = inWhichFrameIsContentMixed(frame, WebURLRequest::Fr ameTypeNone, url); | 434 Frame* mixedFrame = inWhichFrameIsContentMixed(frame, WebURLRequest::FrameTy peNone, url); |
| 418 if (!mixedFrame) | 435 if (!mixedFrame) |
| 419 return false; | 436 return false; |
| 420 | 437 |
| 421 UseCounter::count(mixedFrame, UseCounter::MixedContentPresent); | 438 UseCounter::count(mixedFrame, UseCounter::MixedContentPresent); |
| 422 | 439 |
| 423 mixedFrame->loader().client()->didDisplayInsecureContent(); | 440 // Use the current local frame's client; the embedder doesn't |
| 441 // distinguish mixed content signals from different frames on the | |
| 442 // same page. | |
| 443 frame->loader().client()->didDisplayInsecureContent(); | |
| 424 | 444 |
| 425 if (reportingStatus == SendReport) { | 445 if (reportingStatus == SendReport) { |
| 426 String message = String::format( | 446 String message = String::format( |
| 427 "Mixed Content: The page at '%s' was loaded over a secure connection , but contains a form which targets an insecure endpoint '%s'. This endpoint sho uld be made available over a secure connection.", | 447 "Mixed Content: The page at '%s' was loaded over a secure connection , but contains a form which targets an insecure endpoint '%s'. This endpoint sho uld be made available over a secure connection.", |
| 428 frame->document()->url().elidedString().utf8().data(), url.elidedStr ing().utf8().data()); | 448 mainResourceUrlForFrame(mixedFrame).elidedString().utf8().data(), ur l.elidedString().utf8().data()); |
| 429 mixedFrame->document()->addConsoleMessage(ConsoleMessage::create(Securit yMessageSource, WarningMessageLevel, message)); | 449 frame->document()->addConsoleMessage(ConsoleMessage::create(SecurityMess ageSource, WarningMessageLevel, message)); |
| 430 } | 450 } |
| 431 | 451 |
| 432 return true; | 452 return true; |
| 433 } | 453 } |
| 434 | 454 |
| 435 void MixedContentChecker::checkMixedPrivatePublic(LocalFrame* frame, const Atomi cString& resourceIPAddress) | 455 void MixedContentChecker::checkMixedPrivatePublic(LocalFrame* frame, const Atomi cString& resourceIPAddress) |
| 436 { | 456 { |
| 437 if (!frame || !frame->document() || !frame->document()->loader()) | 457 if (!frame || !frame->document() || !frame->document()->loader()) |
| 438 return; | 458 return; |
| 439 | 459 |
| 440 // Just count these for the moment, don't block them. | 460 // Just count these for the moment, don't block them. |
| 441 if (Platform::current()->isReservedIPAddress(resourceIPAddress) && !frame->d ocument()->isHostedInReservedIPRange()) | 461 if (Platform::current()->isReservedIPAddress(resourceIPAddress) && !frame->d ocument()->isHostedInReservedIPRange()) |
| 442 UseCounter::count(frame->document(), UseCounter::MixedContentPrivateHost nameInPublicHostname); | 462 UseCounter::count(frame->document(), UseCounter::MixedContentPrivateHost nameInPublicHostname); |
| 443 } | 463 } |
| 444 | 464 |
| 445 LocalFrame* MixedContentChecker::effectiveFrameForFrameType(LocalFrame* frame, W ebURLRequest::FrameType frameType) | 465 Frame* MixedContentChecker::effectiveFrameForFrameType(LocalFrame* frame, WebURL Request::FrameType frameType) |
| 446 { | 466 { |
| 447 // If we're loading the main resource of a subframe, ensure that we check | 467 // If we're loading the main resource of a subframe, ensure that we check |
| 448 // against the parent of the active frame, rather than the frame itself. | 468 // against the parent of the active frame, rather than the frame itself. |
| 449 LocalFrame* effectiveFrame = frame; | 469 if (frameType != WebURLRequest::FrameTypeNested) |
| 450 if (frameType == WebURLRequest::FrameTypeNested) { | 470 return frame; |
| 451 // FIXME: Deal with RemoteFrames. | 471 |
| 452 Frame* parentFrame = effectiveFrame->tree().parent(); | 472 Frame* parentFrame = frame->tree().parent(); |
| 453 ASSERT(parentFrame); | 473 ASSERT(parentFrame); |
| 454 if (parentFrame->isLocalFrame()) | 474 return parentFrame; |
| 455 effectiveFrame = toLocalFrame(parentFrame); | |
| 456 } | |
| 457 return effectiveFrame; | |
| 458 } | 475 } |
| 459 | 476 |
| 460 void MixedContentChecker::handleCertificateError(LocalFrame* frame, const Resour ceRequest& request, const ResourceResponse& response) | 477 void MixedContentChecker::handleCertificateError(LocalFrame* frame, const Resour ceRequest& request, const ResourceResponse& response) |
| 461 { | 478 { |
| 462 WebURLRequest::FrameType frameType = request.frameType(); | 479 WebURLRequest::FrameType frameType = request.frameType(); |
| 463 LocalFrame* effectiveFrame = effectiveFrameForFrameType(frame, frameType); | 480 Frame* effectiveFrame = effectiveFrameForFrameType(frame, frameType); |
| 464 if (frameType == WebURLRequest::FrameTypeTopLevel || !effectiveFrame) | 481 if (frameType == WebURLRequest::FrameTypeTopLevel || !effectiveFrame) |
| 465 return; | 482 return; |
| 466 | 483 |
| 467 FrameLoaderClient* client = effectiveFrame->loader().client(); | 484 // TODO(estark): handle remote frames, perhaps by omitting security info whe n the effective frame is remote. |
| 485 if (!effectiveFrame->isLocalFrame()) | |
| 486 return; | |
| 487 | |
| 488 LocalFrame* localEffectiveFrame = toLocalFrame(effectiveFrame); | |
| 489 | |
| 490 // Use the current local frame's client; the embedder doesn't | |
| 491 // distinguish mixed content signals from different frames on the | |
| 492 // same page. | |
| 493 FrameLoaderClient* client = frame->loader().client(); | |
| 468 WebURLRequest::RequestContext requestContext = request.requestContext(); | 494 WebURLRequest::RequestContext requestContext = request.requestContext(); |
| 469 ContextType contextType = MixedContentChecker::contextTypeFromContext(reques tContext, frame); | 495 ContextType contextType = MixedContentChecker::contextTypeFromContext(reques tContext, effectiveFrame); |
| 470 if (contextType == ContextTypeBlockable) { | 496 if (contextType == ContextTypeBlockable) { |
| 471 client->didRunContentWithCertificateErrors(response.url(), response.getS ecurityInfo(), effectiveFrame->document()->url(), effectiveFrame->loader().docum entLoader()->response().getSecurityInfo()); | 497 client->didRunContentWithCertificateErrors(response.url(), response.getS ecurityInfo(), mainResourceUrlForFrame(effectiveFrame), localEffectiveFrame->loa der().documentLoader()->response().getSecurityInfo()); |
| 472 } else { | 498 } else { |
| 473 // contextTypeFromContext() never returns NotMixedContent (it | 499 // contextTypeFromContext() never returns NotMixedContent (it |
| 474 // computes the type of mixed content, given that the content is | 500 // computes the type of mixed content, given that the content is |
| 475 // mixed). | 501 // mixed). |
| 476 ASSERT(contextType != ContextTypeNotMixedContent); | 502 ASSERT(contextType != ContextTypeNotMixedContent); |
| 477 client->didDisplayContentWithCertificateErrors(response.url(), response. getSecurityInfo(), effectiveFrame->document()->url(), effectiveFrame->loader().d ocumentLoader()->response().getSecurityInfo()); | 503 client->didDisplayContentWithCertificateErrors(response.url(), response. getSecurityInfo(), mainResourceUrlForFrame(effectiveFrame), localEffectiveFrame- >loader().documentLoader()->response().getSecurityInfo()); |
| 478 } | 504 } |
| 479 } | 505 } |
| 480 | 506 |
| 481 MixedContentChecker::ContextType MixedContentChecker::contextTypeForInspector(Lo calFrame* frame, const ResourceRequest& request) | 507 MixedContentChecker::ContextType MixedContentChecker::contextTypeForInspector(Lo calFrame* frame, const ResourceRequest& request) |
| 482 { | 508 { |
| 483 LocalFrame* effectiveFrame = effectiveFrameForFrameType(frame, request.frame Type()); | 509 Frame* effectiveFrame = effectiveFrameForFrameType(frame, request.frameType( )); |
| 484 | 510 |
| 485 LocalFrame* mixedFrame = inWhichFrameIsContentMixed(effectiveFrame, request. frameType(), request.url()); | 511 Frame* mixedFrame = inWhichFrameIsContentMixed(effectiveFrame, request.frame Type(), request.url()); |
| 486 if (!mixedFrame) | 512 if (!mixedFrame) |
| 487 return ContextTypeNotMixedContent; | 513 return ContextTypeNotMixedContent; |
| 488 | 514 |
| 489 // See comment in shouldBlockFetch() about loading the main resource of a su bframe. | 515 // See comment in shouldBlockFetch() about loading the main resource of a su bframe. |
| 490 if (request.frameType() == WebURLRequest::FrameTypeNested && !SchemeRegistry ::shouldTreatURLSchemeAsCORSEnabled(request.url().protocol())) { | 516 if (request.frameType() == WebURLRequest::FrameTypeNested && !SchemeRegistry ::shouldTreatURLSchemeAsCORSEnabled(request.url().protocol())) { |
| 491 return ContextTypeOptionallyBlockable; | 517 return ContextTypeOptionallyBlockable; |
| 492 } | 518 } |
| 493 | 519 |
| 494 return contextTypeFromContext(request.requestContext(), mixedFrame); | 520 return contextTypeFromContext(request.requestContext(), mixedFrame); |
| 495 } | 521 } |
| 496 | 522 |
| 497 } // namespace blink | 523 } // namespace blink |
| OLD | NEW |