OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 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 are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * 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 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
340 else if (url.isLocalFile() || m_document->url().isLocalFile()) | 340 else if (url.isLocalFile() || m_document->url().isLocalFile()) |
341 message = "Unsafe attempt to load URL " + url.elidedString() + " from fr ame with URL " + m_document->url().elidedString() + ". 'file:' URLs are treated as unique security origins.\n"; | 341 message = "Unsafe attempt to load URL " + url.elidedString() + " from fr ame with URL " + m_document->url().elidedString() + ". 'file:' URLs are treated as unique security origins.\n"; |
342 else | 342 else |
343 message = "Unsafe attempt to load URL " + url.elidedString() + " from fr ame with URL " + m_document->url().elidedString() + ". Domains, protocols and po rts must match.\n"; | 343 message = "Unsafe attempt to load URL " + url.elidedString() + " from fr ame with URL " + m_document->url().elidedString() + ". Domains, protocols and po rts must match.\n"; |
344 | 344 |
345 frame()->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessag eSource, ErrorMessageLevel, message)); | 345 frame()->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessag eSource, ErrorMessageLevel, message)); |
346 } | 346 } |
347 | 347 |
348 bool FrameFetchContext::canRequest(Resource::Type type, const ResourceRequest& r esourceRequest, const KURL& url, const ResourceLoaderOptions& options, bool forP reload, FetchRequest::OriginRestriction originRestriction) const | 348 bool FrameFetchContext::canRequest(Resource::Type type, const ResourceRequest& r esourceRequest, const KURL& url, const ResourceLoaderOptions& options, bool forP reload, FetchRequest::OriginRestriction originRestriction) const |
349 { | 349 { |
350 class BlockedRequestInspectorNotification { | |
pfeldman
2015/09/02 02:49:21
Why not return the enum?
dgozman
2015/09/02 22:59:56
Updated.
| |
351 public: | |
352 BlockedRequestInspectorNotification(LocalFrame* frame, const ResourceReq uest& request, DocumentLoader* loader, const FetchInitiatorInfo& initiatorInfo) | |
353 : m_frame(frame) | |
354 , m_request(request) | |
355 , m_loader(loader) | |
356 , m_initiatorInfo(initiatorInfo) | |
357 , m_reason(InspectorRequestBlockedReasonNone) {} | |
358 | |
359 ~BlockedRequestInspectorNotification() | |
360 { | |
361 if (m_reason != InspectorRequestBlockedReasonNone) | |
362 InspectorInstrumentation::didBlockRequest(m_frame, m_request, m_ loader, m_initiatorInfo, m_reason); | |
363 } | |
364 | |
365 void setReason(InspectorRequestBlockedReason reason) { m_reason = reason ; } | |
366 | |
367 private: | |
368 LocalFrame* m_frame; | |
369 const ResourceRequest& m_request; | |
370 DocumentLoader* m_loader; | |
371 const FetchInitiatorInfo& m_initiatorInfo; | |
372 InspectorRequestBlockedReason m_reason; | |
373 | |
374 } inspectorNotification(frame(), resourceRequest, ensureLoaderForNotificatio ns(), options.initiatorInfo); | |
375 // Note: any return from this function must call inspectorNotification.setRe ason. | |
376 | |
350 InstrumentingAgents* agents = InspectorInstrumentation::instrumentingAgentsF or(frame()); | 377 InstrumentingAgents* agents = InspectorInstrumentation::instrumentingAgentsF or(frame()); |
351 if (agents && agents->inspectorResourceAgent()) { | 378 if (agents && agents->inspectorResourceAgent()) { |
352 if (agents->inspectorResourceAgent()->shouldBlockRequest(frame(), resour ceRequest, ensureLoaderForNotifications(), options.initiatorInfo)) | 379 if (agents->inspectorResourceAgent()->shouldBlockRequest(resourceRequest )) { |
380 inspectorNotification.setReason(InspectorRequestBlockedReasonInspect or); | |
353 return false; | 381 return false; |
382 } | |
354 } | 383 } |
355 | 384 |
356 SecurityOrigin* securityOrigin = options.securityOrigin.get(); | 385 SecurityOrigin* securityOrigin = options.securityOrigin.get(); |
357 if (!securityOrigin && m_document) | 386 if (!securityOrigin && m_document) |
358 securityOrigin = m_document->securityOrigin(); | 387 securityOrigin = m_document->securityOrigin(); |
359 | 388 |
360 if (originRestriction != FetchRequest::NoOriginRestriction && securityOrigin && !securityOrigin->canDisplay(url)) { | 389 if (originRestriction != FetchRequest::NoOriginRestriction && securityOrigin && !securityOrigin->canDisplay(url)) { |
361 if (!forPreload) | 390 if (!forPreload) |
362 FrameLoader::reportLocalLoadFailed(frame(), url.elidedString()); | 391 FrameLoader::reportLocalLoadFailed(frame(), url.elidedString()); |
363 WTF_LOG(ResourceLoading, "ResourceFetcher::requestResource URL was not a llowed by SecurityOrigin::canDisplay"); | 392 WTF_LOG(ResourceLoading, "ResourceFetcher::requestResource URL was not a llowed by SecurityOrigin::canDisplay"); |
393 inspectorNotification.setReason(InspectorRequestBlockedReasonOther); | |
364 return false; | 394 return false; |
365 } | 395 } |
366 | 396 |
367 // Some types of resources can be loaded only from the same origin. Other | 397 // Some types of resources can be loaded only from the same origin. Other |
368 // types of resources, like Images, Scripts, and CSS, can be loaded from | 398 // types of resources, like Images, Scripts, and CSS, can be loaded from |
369 // any URL. | 399 // any URL. |
370 switch (type) { | 400 switch (type) { |
371 case Resource::MainResource: | 401 case Resource::MainResource: |
372 case Resource::Image: | 402 case Resource::Image: |
373 case Resource::CSSStyleSheet: | 403 case Resource::CSSStyleSheet: |
374 case Resource::Script: | 404 case Resource::Script: |
375 case Resource::Font: | 405 case Resource::Font: |
376 case Resource::Raw: | 406 case Resource::Raw: |
377 case Resource::LinkPrefetch: | 407 case Resource::LinkPrefetch: |
378 case Resource::LinkSubresource: | 408 case Resource::LinkSubresource: |
379 case Resource::LinkPreload: | 409 case Resource::LinkPreload: |
380 case Resource::TextTrack: | 410 case Resource::TextTrack: |
381 case Resource::ImportResource: | 411 case Resource::ImportResource: |
382 case Resource::Media: | 412 case Resource::Media: |
383 // By default these types of resources can be loaded from any origin. | 413 // By default these types of resources can be loaded from any origin. |
384 // FIXME: Are we sure about Resource::Font? | 414 // FIXME: Are we sure about Resource::Font? |
385 if (originRestriction == FetchRequest::RestrictToSameOrigin && !security Origin->canRequest(url)) { | 415 if (originRestriction == FetchRequest::RestrictToSameOrigin && !security Origin->canRequest(url)) { |
386 printAccessDeniedMessage(url); | 416 printAccessDeniedMessage(url); |
417 inspectorNotification.setReason(InspectorRequestBlockedReasonOrigin) ; | |
387 return false; | 418 return false; |
388 } | 419 } |
389 break; | 420 break; |
390 case Resource::XSLStyleSheet: | 421 case Resource::XSLStyleSheet: |
391 ASSERT(RuntimeEnabledFeatures::xsltEnabled()); | 422 ASSERT(RuntimeEnabledFeatures::xsltEnabled()); |
392 case Resource::SVGDocument: | 423 case Resource::SVGDocument: |
393 if (!securityOrigin->canRequest(url)) { | 424 if (!securityOrigin->canRequest(url)) { |
394 printAccessDeniedMessage(url); | 425 printAccessDeniedMessage(url); |
426 inspectorNotification.setReason(InspectorRequestBlockedReasonOrigin) ; | |
395 return false; | 427 return false; |
396 } | 428 } |
397 break; | 429 break; |
398 } | 430 } |
399 | 431 |
400 // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved. | 432 // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved. |
401 bool shouldBypassMainWorldCSP = frame()->script().shouldBypassMainWorldCSP() || options.contentSecurityPolicyOption == DoNotCheckContentSecurityPolicy; | 433 bool shouldBypassMainWorldCSP = frame()->script().shouldBypassMainWorldCSP() || options.contentSecurityPolicyOption == DoNotCheckContentSecurityPolicy; |
402 | 434 |
403 // Don't send CSP messages for preloads, we might never actually display tho se items. | 435 // Don't send CSP messages for preloads, we might never actually display tho se items. |
404 ContentSecurityPolicy::ReportingStatus cspReporting = forPreload ? | 436 ContentSecurityPolicy::ReportingStatus cspReporting = forPreload ? |
405 ContentSecurityPolicy::SuppressReport : ContentSecurityPolicy::SendRepor t; | 437 ContentSecurityPolicy::SuppressReport : ContentSecurityPolicy::SendRepor t; |
406 | 438 |
407 // As of CSP2, for requests that are the results of redirects, the match | 439 // As of CSP2, for requests that are the results of redirects, the match |
408 // algorithm should ignore the path component of the URL. | 440 // algorithm should ignore the path component of the URL. |
409 ContentSecurityPolicy::RedirectStatus redirectStatus = resourceRequest.follo wedRedirect() ? ContentSecurityPolicy::DidRedirect : ContentSecurityPolicy::DidN otRedirect; | 441 ContentSecurityPolicy::RedirectStatus redirectStatus = resourceRequest.follo wedRedirect() ? ContentSecurityPolicy::DidRedirect : ContentSecurityPolicy::DidN otRedirect; |
410 | 442 |
411 // m_document can be null, but not in any of the cases where csp is actually used below. | 443 // m_document can be null, but not in any of the cases where csp is actually used below. |
412 // ImageResourceTest.MultipartImage crashes w/o the m_document null check. | 444 // ImageResourceTest.MultipartImage crashes w/o the m_document null check. |
413 // I believe it's the Resource::Raw case. | 445 // I believe it's the Resource::Raw case. |
414 const ContentSecurityPolicy* csp = m_document ? m_document->contentSecurityP olicy() : nullptr; | 446 const ContentSecurityPolicy* csp = m_document ? m_document->contentSecurityP olicy() : nullptr; |
447 inspectorNotification.setReason(InspectorRequestBlockedReasonCSP); | |
415 | 448 |
416 // FIXME: This would be cleaner if moved this switch into an allowFromSource () | 449 // FIXME: This would be cleaner if moved this switch into an allowFromSource () |
417 // helper on this object which took a Resource::Type, then this block would | 450 // helper on this object which took a Resource::Type, then this block would |
418 // collapse to about 10 lines for handling Raw and Script special cases. | 451 // collapse to about 10 lines for handling Raw and Script special cases. |
419 switch (type) { | 452 switch (type) { |
420 case Resource::XSLStyleSheet: | 453 case Resource::XSLStyleSheet: |
421 ASSERT(RuntimeEnabledFeatures::xsltEnabled()); | 454 ASSERT(RuntimeEnabledFeatures::xsltEnabled()); |
422 ASSERT(ContentSecurityPolicy::isScriptResource(resourceRequest)); | 455 ASSERT(ContentSecurityPolicy::isScriptResource(resourceRequest)); |
423 if (!shouldBypassMainWorldCSP && !csp->allowScriptFromSource(url, redire ctStatus, cspReporting)) | 456 if (!shouldBypassMainWorldCSP && !csp->allowScriptFromSource(url, redire ctStatus, cspReporting)) |
424 return false; | 457 return false; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
456 case Resource::LinkPrefetch: | 489 case Resource::LinkPrefetch: |
457 case Resource::LinkSubresource: | 490 case Resource::LinkSubresource: |
458 case Resource::LinkPreload: | 491 case Resource::LinkPreload: |
459 break; | 492 break; |
460 case Resource::Media: | 493 case Resource::Media: |
461 case Resource::TextTrack: | 494 case Resource::TextTrack: |
462 ASSERT(ContentSecurityPolicy::isMediaResource(resourceRequest)); | 495 ASSERT(ContentSecurityPolicy::isMediaResource(resourceRequest)); |
463 if (!shouldBypassMainWorldCSP && !csp->allowMediaFromSource(url, redirec tStatus, cspReporting)) | 496 if (!shouldBypassMainWorldCSP && !csp->allowMediaFromSource(url, redirec tStatus, cspReporting)) |
464 return false; | 497 return false; |
465 | 498 |
466 if (!frame()->loader().client()->allowMedia(url)) | 499 if (!frame()->loader().client()->allowMedia(url)) { |
500 inspectorNotification.setReason(InspectorRequestBlockedReasonOther); | |
467 return false; | 501 return false; |
502 } | |
468 break; | 503 break; |
469 } | 504 } |
470 | 505 |
471 // SVG Images have unique security rules that prevent all subresource reques ts | 506 // SVG Images have unique security rules that prevent all subresource reques ts |
472 // except for data urls. | 507 // except for data urls. |
473 if (type != Resource::MainResource && frame()->chromeClient().isSVGImageChro meClient() && !url.protocolIsData()) | 508 if (type != Resource::MainResource && frame()->chromeClient().isSVGImageChro meClient() && !url.protocolIsData()) { |
509 inspectorNotification.setReason(InspectorRequestBlockedReasonOrigin); | |
474 return false; | 510 return false; |
511 } | |
475 | 512 |
476 // FIXME: Once we use RequestContext for CSP (http://crbug.com/390497), remo ve this extra check. | 513 // FIXME: Once we use RequestContext for CSP (http://crbug.com/390497), remo ve this extra check. |
477 if (resourceRequest.requestContext() == WebURLRequest::RequestContextManifes t) { | 514 if (resourceRequest.requestContext() == WebURLRequest::RequestContextManifes t) { |
478 if (!shouldBypassMainWorldCSP && !csp->allowManifestFromSource(url, redi rectStatus, cspReporting)) | 515 if (!shouldBypassMainWorldCSP && !csp->allowManifestFromSource(url, redi rectStatus, cspReporting)) { |
516 inspectorNotification.setReason(InspectorRequestBlockedReasonCSP); | |
479 return false; | 517 return false; |
518 } | |
480 } | 519 } |
481 | 520 |
482 // Measure the number of legacy URL schemes ('ftp://') and the number of emb edded-credential | 521 // Measure the number of legacy URL schemes ('ftp://') and the number of emb edded-credential |
483 // ('http://user:password@...') resources embedded as subresources. in the h opes that we can | 522 // ('http://user:password@...') resources embedded as subresources. in the h opes that we can |
484 // block them at some point in the future. | 523 // block them at some point in the future. |
485 if (resourceRequest.frameType() != WebURLRequest::FrameTypeTopLevel) { | 524 if (resourceRequest.frameType() != WebURLRequest::FrameTypeTopLevel) { |
486 ASSERT(frame()->document()); | 525 ASSERT(frame()->document()); |
487 if (SchemeRegistry::shouldTreatURLSchemeAsLegacy(url.protocol()) && !Sch emeRegistry::shouldTreatURLSchemeAsLegacy(frame()->document()->securityOrigin()- >protocol())) | 526 if (SchemeRegistry::shouldTreatURLSchemeAsLegacy(url.protocol()) && !Sch emeRegistry::shouldTreatURLSchemeAsLegacy(frame()->document()->securityOrigin()- >protocol())) |
488 UseCounter::count(frame()->document(), UseCounter::LegacyProtocolEmb eddedAsSubresource); | 527 UseCounter::count(frame()->document(), UseCounter::LegacyProtocolEmb eddedAsSubresource); |
489 if (!url.user().isEmpty() || !url.pass().isEmpty()) | 528 if (!url.user().isEmpty() || !url.pass().isEmpty()) |
490 UseCounter::count(frame()->document(), UseCounter::RequestedSubresou rceWithEmbeddedCredentials); | 529 UseCounter::count(frame()->document(), UseCounter::RequestedSubresou rceWithEmbeddedCredentials); |
491 } | 530 } |
492 | 531 |
493 // Measure the number of pages that load resources after a redirect | 532 // Measure the number of pages that load resources after a redirect |
494 // when a CSP is active, to see if implementing CSP | 533 // when a CSP is active, to see if implementing CSP |
495 // 'unsafe-redirect' is feasible. | 534 // 'unsafe-redirect' is feasible. |
496 if (csp && csp->isActive() && resourceRequest.frameType() != WebURLRequest:: FrameTypeTopLevel && resourceRequest.frameType() != WebURLRequest::FrameTypeAuxi liary && redirectStatus == ContentSecurityPolicy::DidRedirect) { | 535 if (csp && csp->isActive() && resourceRequest.frameType() != WebURLRequest:: FrameTypeTopLevel && resourceRequest.frameType() != WebURLRequest::FrameTypeAuxi liary && redirectStatus == ContentSecurityPolicy::DidRedirect) { |
497 ASSERT(frame()->document()); | 536 ASSERT(frame()->document()); |
498 UseCounter::count(frame()->document(), UseCounter::ResourceLoadedAfterRe directWithCSP); | 537 UseCounter::count(frame()->document(), UseCounter::ResourceLoadedAfterRe directWithCSP); |
499 } | 538 } |
500 | 539 |
501 // Last of all, check for mixed content. We do this last so that when | 540 // Last of all, check for mixed content. We do this last so that when |
502 // folks block mixed content with a CSP policy, they don't get a warning. | 541 // folks block mixed content with a CSP policy, they don't get a warning. |
503 // They'll still get a warning in the console about CSP blocking the load. | 542 // They'll still get a warning in the console about CSP blocking the load. |
504 MixedContentChecker::ReportingStatus mixedContentReporting = forPreload ? | 543 MixedContentChecker::ReportingStatus mixedContentReporting = forPreload ? |
505 MixedContentChecker::SuppressReport : MixedContentChecker::SendReport; | 544 MixedContentChecker::SuppressReport : MixedContentChecker::SendReport; |
506 return !MixedContentChecker::shouldBlockFetch(MixedContentChecker::effective FrameForFrameType(frame(), resourceRequest.frameType()), resourceRequest, url, m ixedContentReporting); | 545 if (MixedContentChecker::shouldBlockFetch(MixedContentChecker::effectiveFram eForFrameType(frame(), resourceRequest.frameType()), resourceRequest, url, mixed ContentReporting)) { |
546 inspectorNotification.setReason(InspectorRequestBlockedReasonMixedConten t); | |
547 return false; | |
548 } | |
549 | |
550 inspectorNotification.setReason(InspectorRequestBlockedReasonNone); | |
551 return true; | |
507 } | 552 } |
508 | 553 |
509 bool FrameFetchContext::isControlledByServiceWorker() const | 554 bool FrameFetchContext::isControlledByServiceWorker() const |
510 { | 555 { |
511 ASSERT(m_documentLoader || frame()->loader().documentLoader()); | 556 ASSERT(m_documentLoader || frame()->loader().documentLoader()); |
512 if (m_documentLoader) | 557 if (m_documentLoader) |
513 return frame()->loader().client()->isControlledByServiceWorker(*m_docume ntLoader); | 558 return frame()->loader().client()->isControlledByServiceWorker(*m_docume ntLoader); |
514 // m_documentLoader is null while loading resources from an HTML import. | 559 // m_documentLoader is null while loading resources from an HTML import. |
515 // In such cases whether the request is controlled by ServiceWorker or not | 560 // In such cases whether the request is controlled by ServiceWorker or not |
516 // is determined by the document loader of the frame. | 561 // is determined by the document loader of the frame. |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
685 | 730 |
686 | 731 |
687 DEFINE_TRACE(FrameFetchContext) | 732 DEFINE_TRACE(FrameFetchContext) |
688 { | 733 { |
689 visitor->trace(m_document); | 734 visitor->trace(m_document); |
690 visitor->trace(m_documentLoader); | 735 visitor->trace(m_documentLoader); |
691 FetchContext::trace(visitor); | 736 FetchContext::trace(visitor); |
692 } | 737 } |
693 | 738 |
694 } // namespace blink | 739 } // namespace blink |
OLD | NEW |