Chromium Code Reviews| 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 |