bool DocumentLoader::shouldContinueForNavigationPolicy(const ResourceRequest& request) { NavigationAction action = triggeringAction(); if (action.isEmpty()) { action = NavigationAction(request, NavigationTypeOther); setTriggeringAction(action); } // Don't ask if we are loading an empty URL. if (!request.isNull() && request.url().isEmpty()) return true; // We are always willing to show alternate content for unreachable URLs; // treat it like a reload so it maintains the right state for b/f list. if (m_substituteData.isValid() && !m_substituteData.failingURL().isEmpty()) { if (isBackForwardLoadType(frameLoader()->loadType())) frameLoader()->setLoadType(FrameLoadTypeReload); return true; } // If we're loading content into a subframe, check against the parent's Content Security Policy // and kill the load if that check fails. if (m_frame->ownerElement() && !m_frame->ownerElement()->document()->contentSecurityPolicy()->allowChildFrameFromSource(request.url())) return false; PolicyAction policy = frameLoader()->client()->decidePolicyForNavigationAction(action, request); if (policy == PolicyDownload) { ResourceRequest mutableRequest(request); frameLoader()->setOriginalURLForDownloadRequest(mutableRequest); frameLoader()->client()->startDownload(mutableRequest); } return policy == PolicyUse; }
void PolicyChecker::checkNavigationPolicy(const ResourceRequest& request, DocumentLoader* loader, PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument) { NavigationAction action = loader->triggeringAction(); if (action.isEmpty()) { action = NavigationAction(request.url(), NavigationTypeOther); loader->setTriggeringAction(action); } // Don't ask more than once for the same request or if we are loading an empty URL. // This avoids confusion on the part of the client. if (equalIgnoringHeaderFields(request, loader->lastCheckedRequest()) || (!request.isNull() && request.url().isEmpty())) { function(argument, request, 0, true); loader->setLastCheckedRequest(request); return; } // We are always willing to show alternate content for unreachable URLs; // treat it like a reload so it maintains the right state for b/f list. if (loader->substituteData().isValid() && !loader->substituteData().failingURL().isEmpty()) { if (isBackForwardLoadType(m_loadType)) m_loadType = FrameLoadTypeReload; function(argument, request, 0, true); return; } loader->setLastCheckedRequest(request); m_callback.set(request, formState.get(), function, argument); m_delegateIsDecidingNavigationPolicy = true; m_frame->loader()->client()->dispatchDecidePolicyForNavigationAction(&PolicyChecker::continueAfterNavigationPolicy, action, request, formState); m_delegateIsDecidingNavigationPolicy = false; }
void PolicyChecker::checkNavigationPolicy(const ResourceRequest& request, bool didReceiveRedirectResponse, DocumentLoader* loader, PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function) { NavigationAction action = loader->triggeringAction(); if (action.isEmpty()) { action = NavigationAction(request, NavigationType::Other, loader->shouldOpenExternalURLsPolicyToPropagate()); loader->setTriggeringAction(action); } // Don't ask more than once for the same request or if we are loading an empty URL. // This avoids confusion on the part of the client. if (equalIgnoringHeaderFields(request, loader->lastCheckedRequest()) || (!request.isNull() && request.url().isEmpty())) { function(request, 0, true); loader->setLastCheckedRequest(request); return; } // We are always willing to show alternate content for unreachable URLs; // treat it like a reload so it maintains the right state for b/f list. if (loader->substituteData().isValid() && !loader->substituteData().failingURL().isEmpty()) { if (isBackForwardLoadType(m_loadType)) m_loadType = FrameLoadType::Reload; function(request, 0, true); return; } if (!isAllowedByContentSecurityPolicy(request.url(), m_frame.ownerElement(), didReceiveRedirectResponse)) { function(request, 0, false); return; } loader->setLastCheckedRequest(request); m_callback.set(request, formState.get(), WTFMove(function)); #if USE(QUICK_LOOK) // Always allow QuickLook-generated URLs based on the protocol scheme. if (!request.isNull() && request.url().protocolIs(QLPreviewProtocol())) { continueAfterNavigationPolicy(PolicyUse); return; } #endif #if ENABLE(CONTENT_FILTERING) if (m_contentFilterUnblockHandler.canHandleRequest(request)) { RefPtr<Frame> frame { &m_frame }; m_contentFilterUnblockHandler.requestUnblockAsync([frame](bool unblocked) { if (unblocked) frame->loader().reload(); }); continueAfterNavigationPolicy(PolicyIgnore); return; } m_contentFilterUnblockHandler = { }; #endif m_delegateIsDecidingNavigationPolicy = true; m_suggestedFilename = action.downloadAttribute(); m_frame.loader().client().dispatchDecidePolicyForNavigationAction(action, request, formState, [this](PolicyAction action) { continueAfterNavigationPolicy(action); }); m_delegateIsDecidingNavigationPolicy = false; }