void EventSource::connect() { ASSERT(m_state == CONNECTING); ASSERT(!m_requestInFlight); ResourceRequest request(m_url); request.setHTTPMethod("GET"); request.setHTTPHeaderField("Accept", "text/event-stream"); request.setHTTPHeaderField("Cache-Control", "no-cache"); if (!m_lastEventId.isEmpty()) request.setHTTPHeaderField("Last-Event-ID", m_lastEventId); SecurityOrigin* origin = scriptExecutionContext()->securityOrigin(); ThreadableLoaderOptions options; options.sendLoadCallbacks = SendCallbacks; options.sniffContent = DoNotSniffContent; options.allowCredentials = (origin->canRequest(m_url) || m_withCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials; options.preflightPolicy = PreventPreflight; options.crossOriginRequestPolicy = UseAccessControl; options.dataBufferingPolicy = DoNotBufferData; options.securityOrigin = origin; m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, options); if (m_loader) m_requestInFlight = true; }
void EventSource::connect() { ASSERT(m_state == CONNECTING); ASSERT(!m_requestInFlight); ASSERT(executionContext()); ExecutionContext& executionContext = *this->executionContext(); ResourceRequest request(m_url); request.setHTTPMethod("GET"); request.setHTTPHeaderField("Accept", "text/event-stream"); request.setHTTPHeaderField("Cache-Control", "no-cache"); request.setRequestContext(WebURLRequest::RequestContextEventSource); if (!m_lastEventId.isEmpty()) request.setHTTPHeaderField("Last-Event-ID", m_lastEventId); SecurityOrigin* origin = executionContext.securityOrigin(); ThreadableLoaderOptions options; options.preflightPolicy = PreventPreflight; options.crossOriginRequestPolicy = UseAccessControl; options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypassMainWorld(&executionContext) ? DoNotEnforceContentSecurityPolicy : EnforceConnectSrcDirective; ResourceLoaderOptions resourceLoaderOptions; resourceLoaderOptions.allowCredentials = (origin->canRequest(m_url) || m_withCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials; resourceLoaderOptions.credentialsRequested = m_withCredentials ? ClientRequestedCredentials : ClientDidNotRequestCredentials; resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData; resourceLoaderOptions.securityOrigin = origin; InspectorInstrumentation::willSendEventSourceRequest(&executionContext, this); // InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient will be called synchronously. m_loader = ThreadableLoader::create(executionContext, this, request, options, resourceLoaderOptions); if (m_loader) m_requestInFlight = true; }
void EventSource::connect() { ASSERT(m_state == CONNECTING); ASSERT(!m_requestInFlight); ResourceRequest request(m_url); request.setHTTPMethod("GET"); request.setHTTPHeaderField("Accept", "text/event-stream"); request.setHTTPHeaderField("Cache-Control", "no-cache"); if (!m_lastEventId.isEmpty()) request.setHTTPHeaderField("Last-Event-ID", m_lastEventId); SecurityOrigin* origin = executionContext()->securityOrigin(); ThreadableLoaderOptions options; options.sniffContent = DoNotSniffContent; options.allowCredentials = (origin->canRequest(m_url) || m_withCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials; options.credentialsRequested = m_withCredentials ? ClientRequestedCredentials : ClientDidNotRequestCredentials; options.preflightPolicy = PreventPreflight; options.crossOriginRequestPolicy = UseAccessControl; options.dataBufferingPolicy = DoNotBufferData; options.securityOrigin = origin; options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypassMainWorld(executionContext()) ? DoNotEnforceContentSecurityPolicy : EnforceConnectSrcDirective; m_loader = ThreadableLoader::create(executionContext(), this, request, options); if (m_loader) m_requestInFlight = true; }
FetchRequest PreloadRequest::resourceRequest(Document* document) { ASSERT(isMainThread()); FetchInitiatorInfo initiatorInfo; initiatorInfo.name = AtomicString(m_initiatorName); initiatorInfo.position = m_initiatorPosition; ResourceRequest resourceRequest(completeURL(document)); resourceRequest.setHTTPReferrer(SecurityPolicy::generateReferrer(m_referrerPolicy, resourceRequest.url(), document->outgoingReferrer())); FetchRequest request(resourceRequest, initiatorInfo); if (m_resourceType == Resource::ImportResource) { SecurityOrigin* securityOrigin = document->contextDocument()->securityOrigin(); bool sameOrigin = securityOrigin->canRequest(request.url()); request.setCrossOriginAccessControl(securityOrigin, sameOrigin ? AllowStoredCredentials : DoNotAllowStoredCredentials, ClientDidNotRequestCredentials); } if (m_isCORSEnabled) request.setCrossOriginAccessControl(document->securityOrigin(), m_allowCredentials); request.setDefer(m_defer); request.setResourceWidth(m_resourceWidth); request.clientHintsPreferences().updateFrom(m_clientHintsPreferences); return request; }
void DOMWindowFileSystem::webkitResolveLocalFileSystemURL(DOMWindow* window, const String& url, PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback) { if (!window->isCurrentlyDisplayedInFrame()) return; Document* document = window->document(); if (!document) return; SecurityOrigin* securityOrigin = document->securityOrigin(); KURL completedURL = document->completeURL(url); if (!securityOrigin->canAccessFileSystem() || !securityOrigin->canRequest(completedURL)) { DOMFileSystem::scheduleCallback(document, errorCallback, FileError::create(FileError::SECURITY_ERR)); return; } FileSystemType type; String filePath; if (!completedURL.isValid() || !DOMFileSystemBase::crackFileSystemURL(completedURL, type, filePath)) { DOMFileSystem::scheduleCallback(document, errorCallback, FileError::create(FileError::ENCODING_ERR)); return; } LocalFileSystem::from(document)->readFileSystem(document, type, ResolveURICallbacks::create(successCallback, errorCallback, document, type, filePath)); }
void DOMWindowFileSystem::webkitResolveLocalFileSystemURL(LocalDOMWindow& window, const String& url, EntryCallback* successCallback, ErrorCallback* errorCallback) { if (!window.isCurrentlyDisplayedInFrame()) return; Document* document = window.document(); if (!document) return; SecurityOrigin* securityOrigin = document->securityOrigin(); KURL completedURL = document->completeURL(url); if (!securityOrigin->canAccessFileSystem() || !securityOrigin->canRequest(completedURL)) { DOMFileSystem::scheduleCallback(document, errorCallback, FileError::create(FileError::SECURITY_ERR)); return; } if (!completedURL.isValid()) { DOMFileSystem::scheduleCallback(document, errorCallback, FileError::create(FileError::ENCODING_ERR)); return; } LocalFileSystem::from(*document)->resolveURL(document, completedURL, ResolveURICallbacks::create(successCallback, errorCallback, document)); }
ResourceRequestBlockedReason FrameFetchContext::canRequestInternal(Resource::Type type, const ResourceRequest& resourceRequest, const KURL& url, const ResourceLoaderOptions& options, bool forPreload, FetchRequest::OriginRestriction originRestriction, ResourceRequest::RedirectStatus redirectStatus) const { if (InspectorInstrumentation::shouldBlockRequest(frame(), resourceRequest)) return ResourceRequestBlockedReasonInspector; SecurityOrigin* securityOrigin = options.securityOrigin.get(); if (!securityOrigin && m_document) securityOrigin = m_document->getSecurityOrigin(); if (originRestriction != FetchRequest::NoOriginRestriction && securityOrigin && !securityOrigin->canDisplay(url)) { if (!forPreload) FrameLoader::reportLocalLoadFailed(frame(), url.elidedString()); WTF_LOG(ResourceLoading, "ResourceFetcher::requestResource URL was not allowed by SecurityOrigin::canDisplay"); return ResourceRequestBlockedReasonOther; } // Some types of resources can be loaded only from the same origin. Other // types of resources, like Images, Scripts, and CSS, can be loaded from // any URL. switch (type) { case Resource::MainResource: case Resource::Image: case Resource::CSSStyleSheet: case Resource::Script: case Resource::Font: case Resource::Raw: case Resource::LinkPrefetch: case Resource::LinkPreload: case Resource::TextTrack: case Resource::ImportResource: case Resource::Media: case Resource::Manifest: // By default these types of resources can be loaded from any origin. // FIXME: Are we sure about Resource::Font? if (originRestriction == FetchRequest::RestrictToSameOrigin && !securityOrigin->canRequest(url)) { printAccessDeniedMessage(url); return ResourceRequestBlockedReasonOrigin; } break; case Resource::XSLStyleSheet: ASSERT(RuntimeEnabledFeatures::xsltEnabled()); case Resource::SVGDocument: if (!securityOrigin->canRequest(url)) { printAccessDeniedMessage(url); return ResourceRequestBlockedReasonOrigin; } break; } // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved. bool shouldBypassMainWorldCSP = frame()->script().shouldBypassMainWorldCSP() || options.contentSecurityPolicyOption == DoNotCheckContentSecurityPolicy; // Don't send CSP messages for preloads, we might never actually display those items. ContentSecurityPolicy::ReportingStatus cspReporting = forPreload ? ContentSecurityPolicy::SuppressReport : ContentSecurityPolicy::SendReport; if (m_document) { DCHECK(m_document->contentSecurityPolicy()); if (!shouldBypassMainWorldCSP && !m_document->contentSecurityPolicy()->allowRequest(resourceRequest.requestContext(), url, options.contentSecurityPolicyNonce, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; } if (type == Resource::Script || type == Resource::ImportResource) { ASSERT(frame()); if (!frame()->loader().client()->allowScriptFromSource(!frame()->settings() || frame()->settings()->scriptEnabled(), url)) { frame()->loader().client()->didNotAllowScript(); // TODO(estark): Use a different ResourceRequestBlockedReason // here, since this check has nothing to do with // CSP. https://crbug.com/600795 return ResourceRequestBlockedReasonCSP; } } else if (type == Resource::Media || type == Resource::TextTrack) { ASSERT(frame()); if (!frame()->loader().client()->allowMedia(url)) return ResourceRequestBlockedReasonOther; } // SVG Images have unique security rules that prevent all subresource requests // except for data urls. if (type != Resource::MainResource && frame()->chromeClient().isSVGImageChromeClient() && !url.protocolIsData()) return ResourceRequestBlockedReasonOrigin; // Measure the number of legacy URL schemes ('ftp://') and the number of embedded-credential // ('http://*****:*****@...') resources embedded as subresources. in the hopes that we can // block them at some point in the future. if (resourceRequest.frameType() != WebURLRequest::FrameTypeTopLevel) { ASSERT(frame()->document()); if (SchemeRegistry::shouldTreatURLSchemeAsLegacy(url.protocol()) && !SchemeRegistry::shouldTreatURLSchemeAsLegacy(frame()->document()->getSecurityOrigin()->protocol())) UseCounter::count(frame()->document(), UseCounter::LegacyProtocolEmbeddedAsSubresource); if (!url.user().isEmpty() || !url.pass().isEmpty()) UseCounter::count(frame()->document(), UseCounter::RequestedSubresourceWithEmbeddedCredentials); } // Check for mixed content. We do this second-to-last so that when folks block // mixed content with a CSP policy, they don't get a warning. They'll still // get a warning in the console about CSP blocking the load. MixedContentChecker::ReportingStatus mixedContentReporting = forPreload ? MixedContentChecker::SuppressReport : MixedContentChecker::SendReport; if (MixedContentChecker::shouldBlockFetch(frame(), resourceRequest, url, mixedContentReporting)) return ResourceRequestBlockedReasonMixedContent; // Let the client have the final say into whether or not the load should proceed. DocumentLoader* documentLoader = masterDocumentLoader(); if (documentLoader && documentLoader->subresourceFilter() && type != Resource::MainResource && type != Resource::ImportResource && !documentLoader->subresourceFilter()->allowLoad(url, resourceRequest.requestContext())) return ResourceRequestBlockedReasonSubresourceFilter; return ResourceRequestBlockedReasonNone; }
ResourceRequestBlockedReason FrameFetchContext::canRequestInternal(Resource::Type type, const ResourceRequest& resourceRequest, const KURL& url, const ResourceLoaderOptions& options, bool forPreload, FetchRequest::OriginRestriction originRestriction) const { InstrumentingAgents* agents = InspectorInstrumentation::instrumentingAgentsFor(frame()); if (agents && agents->inspectorResourceAgent()) { if (agents->inspectorResourceAgent()->shouldBlockRequest(resourceRequest)) return ResourceRequestBlockedReasonInspector; } SecurityOrigin* securityOrigin = options.securityOrigin.get(); if (!securityOrigin && m_document) securityOrigin = m_document->securityOrigin(); if (originRestriction != FetchRequest::NoOriginRestriction && securityOrigin && !securityOrigin->canDisplay(url)) { if (!forPreload) FrameLoader::reportLocalLoadFailed(frame(), url.elidedString()); WTF_LOG(ResourceLoading, "ResourceFetcher::requestResource URL was not allowed by SecurityOrigin::canDisplay"); return ResourceRequestBlockedReasonOther; } // Some types of resources can be loaded only from the same origin. Other // types of resources, like Images, Scripts, and CSS, can be loaded from // any URL. switch (type) { case Resource::MainResource: case Resource::Image: case Resource::CSSStyleSheet: case Resource::Script: case Resource::Font: case Resource::Raw: case Resource::LinkPrefetch: case Resource::LinkSubresource: case Resource::LinkPreload: case Resource::TextTrack: case Resource::ImportResource: case Resource::Media: // By default these types of resources can be loaded from any origin. // FIXME: Are we sure about Resource::Font? if (originRestriction == FetchRequest::RestrictToSameOrigin && !securityOrigin->canRequest(url)) { printAccessDeniedMessage(url); return ResourceRequestBlockedReasonOrigin; } break; case Resource::XSLStyleSheet: ASSERT(RuntimeEnabledFeatures::xsltEnabled()); case Resource::SVGDocument: if (!securityOrigin->canRequest(url)) { printAccessDeniedMessage(url); return ResourceRequestBlockedReasonOrigin; } break; } // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved. bool shouldBypassMainWorldCSP = frame()->script().shouldBypassMainWorldCSP() || options.contentSecurityPolicyOption == DoNotCheckContentSecurityPolicy; // Don't send CSP messages for preloads, we might never actually display those items. ContentSecurityPolicy::ReportingStatus cspReporting = forPreload ? ContentSecurityPolicy::SuppressReport : ContentSecurityPolicy::SendReport; // As of CSP2, for requests that are the results of redirects, the match // algorithm should ignore the path component of the URL. ContentSecurityPolicy::RedirectStatus redirectStatus = resourceRequest.followedRedirect() ? ContentSecurityPolicy::DidRedirect : ContentSecurityPolicy::DidNotRedirect; // m_document can be null, but not in any of the cases where csp is actually used below. // ImageResourceTest.MultipartImage crashes w/o the m_document null check. // I believe it's the Resource::Raw case. const ContentSecurityPolicy* csp = m_document ? m_document->contentSecurityPolicy() : nullptr; // FIXME: This would be cleaner if moved this switch into an allowFromSource() // helper on this object which took a Resource::Type, then this block would // collapse to about 10 lines for handling Raw and Script special cases. switch (type) { case Resource::XSLStyleSheet: ASSERT(RuntimeEnabledFeatures::xsltEnabled()); ASSERT(ContentSecurityPolicy::isScriptResource(resourceRequest)); if (!shouldBypassMainWorldCSP && !csp->allowScriptFromSource(url, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; break; case Resource::Script: case Resource::ImportResource: ASSERT(ContentSecurityPolicy::isScriptResource(resourceRequest)); if (!shouldBypassMainWorldCSP && !csp->allowScriptFromSource(url, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; if (!frame()->loader().client()->allowScriptFromSource(!frame()->settings() || frame()->settings()->scriptEnabled(), url)) { frame()->loader().client()->didNotAllowScript(); return ResourceRequestBlockedReasonCSP; } break; case Resource::CSSStyleSheet: ASSERT(ContentSecurityPolicy::isStyleResource(resourceRequest)); if (!shouldBypassMainWorldCSP && !csp->allowStyleFromSource(url, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; break; case Resource::SVGDocument: case Resource::Image: ASSERT(ContentSecurityPolicy::isImageResource(resourceRequest)); if (!shouldBypassMainWorldCSP && !csp->allowImageFromSource(url, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; break; case Resource::Font: { ASSERT(ContentSecurityPolicy::isFontResource(resourceRequest)); if (!shouldBypassMainWorldCSP && !csp->allowFontFromSource(url, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; break; } case Resource::MainResource: case Resource::Raw: case Resource::LinkPrefetch: case Resource::LinkSubresource: case Resource::LinkPreload: break; case Resource::Media: case Resource::TextTrack: ASSERT(ContentSecurityPolicy::isMediaResource(resourceRequest)); if (!shouldBypassMainWorldCSP && !csp->allowMediaFromSource(url, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; if (!frame()->loader().client()->allowMedia(url)) return ResourceRequestBlockedReasonOther; break; } // SVG Images have unique security rules that prevent all subresource requests // except for data urls. if (type != Resource::MainResource && frame()->chromeClient().isSVGImageChromeClient() && !url.protocolIsData()) return ResourceRequestBlockedReasonOrigin; // FIXME: Once we use RequestContext for CSP (http://crbug.com/390497), remove this extra check. if (resourceRequest.requestContext() == WebURLRequest::RequestContextManifest) { if (!shouldBypassMainWorldCSP && !csp->allowManifestFromSource(url, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; } // Measure the number of legacy URL schemes ('ftp://') and the number of embedded-credential // ('http://*****:*****@...') resources embedded as subresources. in the hopes that we can // block them at some point in the future. if (resourceRequest.frameType() != WebURLRequest::FrameTypeTopLevel) { ASSERT(frame()->document()); if (SchemeRegistry::shouldTreatURLSchemeAsLegacy(url.protocol()) && !SchemeRegistry::shouldTreatURLSchemeAsLegacy(frame()->document()->securityOrigin()->protocol())) UseCounter::count(frame()->document(), UseCounter::LegacyProtocolEmbeddedAsSubresource); if (!url.user().isEmpty() || !url.pass().isEmpty()) UseCounter::count(frame()->document(), UseCounter::RequestedSubresourceWithEmbeddedCredentials); } // Measure the number of pages that load resources after a redirect // when a CSP is active, to see if implementing CSP // 'unsafe-redirect' is feasible. if (csp && csp->isActive() && resourceRequest.frameType() != WebURLRequest::FrameTypeTopLevel && resourceRequest.frameType() != WebURLRequest::FrameTypeAuxiliary && redirectStatus == ContentSecurityPolicy::DidRedirect) { ASSERT(frame()->document()); UseCounter::count(frame()->document(), UseCounter::ResourceLoadedAfterRedirectWithCSP); } // Last of all, check for mixed content. We do this last so that when // folks block mixed content with a CSP policy, they don't get a warning. // They'll still get a warning in the console about CSP blocking the load. MixedContentChecker::ReportingStatus mixedContentReporting = forPreload ? MixedContentChecker::SuppressReport : MixedContentChecker::SendReport; if (MixedContentChecker::shouldBlockFetch(MixedContentChecker::effectiveFrameForFrameType(frame(), resourceRequest.frameType()), resourceRequest, url, mixedContentReporting)) return ResourceRequestBlockedReasonMixedContent; return ResourceRequestBlockedReasonNone; }