void Page::userStyleSheetLocationChanged() { // FIXME: Eventually we will move to a model of just being handed the sheet // text instead of loading the URL ourselves. KURL url = m_settings->userStyleSheetLocation(); m_didLoadUserStyleSheet = false; m_userStyleSheet = String(); m_userStyleSheetModificationTime = 0; // Data URLs with base64-encoded UTF-8 style sheets are common. We can process them // synchronously and avoid using a loader. if (url.protocolIsData() && url.string().startsWith("data:text/css;charset=utf-8;base64,")) { m_didLoadUserStyleSheet = true; Vector<char> styleSheetAsUTF8; if (base64Decode(decodeURLEscapeSequences(url.string().substring(35)), styleSheetAsUTF8, Base64IgnoreWhitespace)) m_userStyleSheet = String::fromUTF8(styleSheetAsUTF8.data(), styleSheetAsUTF8.size()); } for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) { if (frame->document()) frame->document()->styleSheetCollection()->updatePageUserSheet(); } }
void HTMLAnchorElement::handleClick(Event* event) { event->setDefaultHandled(); LocalFrame* frame = document().frame(); if (!frame) return; StringBuilder url; url.append(stripLeadingAndTrailingHTMLSpaces(fastGetAttribute(hrefAttr))); appendServerMapMousePosition(url, event); KURL completedURL = document().completeURL(url.toString()); // Schedule the ping before the frame load. Prerender in Chrome may kill the renderer as soon as the navigation is // sent out. sendPings(completedURL); ResourceRequest request(completedURL); request.setUIStartTime(event->uiCreateTime()); request.setInputPerfMetricReportPolicy(InputToLoadPerfMetricReportPolicy::ReportLink); if (hasAttribute(downloadAttr)) { request.setRequestContext(blink::WebURLRequest::RequestContextDownload); bool isSameOrigin = completedURL.protocolIsData() || document().securityOrigin()->canRequest(completedURL); const AtomicString& suggestedName = (isSameOrigin ? fastGetAttribute(downloadAttr) : nullAtom); frame->loader().client()->loadURLExternally(request, NavigationPolicyDownload, suggestedName); } else { request.setRequestContext(blink::WebURLRequest::RequestContextHyperlink); FrameLoadRequest frameRequest(&document(), request, getAttribute(targetAttr)); frameRequest.setTriggeringEvent(event); if (hasRel(RelationNoReferrer)) frameRequest.setShouldSendReferrer(NeverSendReferrer); frame->loader().load(frameRequest); } }
bool ImageLoader::shouldLoadImmediately(const KURL& url) const { // We force any image loads which might require alt content through the // asynchronous path so that we can add the shadow DOM for the alt-text // content when style recalc is over and DOM mutation is allowed again. if (!url.isNull()) { Resource* resource = memoryCache()->resourceForURL( url, m_element->document().fetcher()->getCacheIdentifier()); if (resource && !resource->errorOccurred()) return true; } return (isHTMLObjectElement(m_element) || isHTMLEmbedElement(m_element) || url.protocolIsData()); }
bool CanvasRenderingContext::wouldTaintOrigin(const KURL& url) { if (!canvas()->originClean() || m_cleanURLs.contains(url.string())) return false; if (canvas()->securityOrigin()->taintsCanvas(url)) return true; if (url.protocolIsData()) return false; m_cleanURLs.add(url.string()); return false; }
// static bool MixedContentChecker::isMixedContent(SecurityOrigin* securityOrigin, const KURL& url) { if (!SchemeRegistry::shouldTreatURLSchemeAsRestrictingMixedContent(securityOrigin->protocol())) return false; // |url| is mixed content if its origin is not potentially trustworthy, and // its protocol is not 'data'. We do a quick check against `SecurityOrigin::isSecure` // to catch things like `about:blank`, which cannot be sanely passed into // `SecurityOrigin::create` (as their origin depends on their context). bool isAllowed = url.protocolIsData() || SecurityOrigin::isSecure(url) || SecurityOrigin::create(url)->isPotentiallyTrustworthy(); // TODO(mkwst): Remove this once 'localhost' is no longer considered potentially trustworthy: if (isAllowed && url.protocolIs("http") && url.host() == "localhost") isAllowed = false; return !isAllowed; }
bool SecurityOrigin::taintsCanvas(const KURL& url) const { if (canRequest(url)) return false; // This function exists because we treat data URLs as having a unique origin, // contrary to the current (9/19/2009) draft of the HTML5 specification. // We still want to let folks paint data URLs onto untainted canvases, so // we special case data URLs below. If we change to match HTML5 w.r.t. // data URL security, then we can remove this function in favor of // !canRequest. if (url.protocolIsData()) return false; return true; }
void HTMLAnchorElement::handleClick(Event* event) { event->setDefaultHandled(); LocalFrame* frame = document().frame(); if (!frame) return; StringBuilder url; url.append(stripLeadingAndTrailingHTMLSpaces(fastGetAttribute(hrefAttr))); appendServerMapMousePosition(url, event); KURL completedURL = document().completeURL(url.toString()); // Schedule the ping before the frame load. Prerender in Chrome may kill the renderer as soon as the navigation is // sent out. sendPings(completedURL); ResourceRequest request(completedURL); request.setUIStartTime(event->platformTimeStamp()); request.setInputPerfMetricReportPolicy(InputToLoadPerfMetricReportPolicy::ReportLink); ReferrerPolicy policy; if (hasAttribute(referrerpolicyAttr) && SecurityPolicy::referrerPolicyFromString(fastGetAttribute(referrerpolicyAttr), &policy) && !hasRel(RelationNoReferrer)) { request.setHTTPReferrer(SecurityPolicy::generateReferrer(policy, completedURL, document().outgoingReferrer())); } if (hasAttribute(downloadAttr)) { request.setRequestContext(WebURLRequest::RequestContextDownload); bool isSameOrigin = completedURL.protocolIsData() || document().getSecurityOrigin()->canRequest(completedURL); const AtomicString& suggestedName = (isSameOrigin ? fastGetAttribute(downloadAttr) : nullAtom); frame->loader().client()->loadURLExternally(request, NavigationPolicyDownload, suggestedName, false); } else { request.setRequestContext(WebURLRequest::RequestContextHyperlink); FrameLoadRequest frameRequest(&document(), request, getAttribute(targetAttr)); frameRequest.setTriggeringEvent(event); if (hasRel(RelationNoReferrer)) { frameRequest.setShouldSendReferrer(NeverSendReferrer); frameRequest.setShouldSetOpener(NeverSetOpener); } if (hasRel(RelationNoOpener)) frameRequest.setShouldSetOpener(NeverSetOpener); // TODO(japhet): Link clicks can be emulated via JS without a user gesture. // Why doesn't this go through NavigationScheduler? frame->loader().load(frameRequest); } }
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; }
bool CSSFontFaceSrcValue::shouldSetCrossOriginAccessControl(const KURL& resource, SecurityOrigin* securityOrigin) { if (resource.isLocalFile() || resource.protocolIsData()) return false; return !securityOrigin->canRequest(resource); }
bool PageSerializer::shouldAddURL(const KURL& url) { return url.isValid() && !m_resourceURLs.contains(url) && !url.protocolIsData(); }
bool ImageLoader::shouldLoadImmediately(const KURL& url, LoadType loadType) const { return url.protocolIsData() || memoryCache()->resourceForURL(url) || loadType == ForceLoadImmediately; }
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; }