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 FrameLoaderClientEfl::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>) { ASSERT(function); ASSERT(m_frame); if (resourceRequest.isNull()) { callPolicyFunction(function, PolicyIgnore); return; } // if not acceptNavigationRequest - look at Qt -> PolicyIgnore; // FIXME: do proper check and only reset forms when on PolicyIgnore CString url = resourceRequest.url().string().utf8(); CString firstParty = resourceRequest.firstPartyForCookies().string().utf8(); CString httpMethod = resourceRequest.httpMethod().utf8(); Ewk_Frame_Resource_Request request = { url.data(), firstParty.data(), httpMethod.data(), 0, m_frame, false }; bool ret = ewk_view_navigation_policy_decision(m_view, &request, static_cast<Ewk_Navigation_Type>(action.type())); PolicyAction policy; if (!ret) policy = PolicyIgnore; else { if (action.type() == NavigationTypeFormSubmitted || action.type() == NavigationTypeFormResubmitted) { Frame* f = EWKPrivate::coreFrame(m_frame); f->loader()->resetMultipleFormSubmissionProtection(); } policy = PolicyUse; } callPolicyFunction(function, policy); }
void FrameLoaderClientEfl::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>) { ASSERT(function); ASSERT(m_frame); if (resourceRequest.isNull()) { callPolicyFunction(function, PolicyIgnore); return; } // if not acceptNavigationRequest - look at Qt -> PolicyIgnore; // FIXME: do proper check and only reset forms when on PolicyIgnore char* url = strdup(resourceRequest.url().string().utf8().data()); Ewk_Frame_Resource_Request request = { url, 0 }; bool ret = ewk_view_navigation_policy_decision(m_view, &request); free(url); PolicyAction policy; if (!ret) policy = PolicyIgnore; else { if (action.type() == NavigationTypeFormSubmitted || action.type() == NavigationTypeFormResubmitted) { Frame* f = EWKPrivate::coreFrame(m_frame); f->loader()->resetMultipleFormSubmissionProtection(); } policy = PolicyUse; } callPolicyFunction(function, policy); }
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 FrameLoaderClientBlackBerry::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState>) { PolicyAction decision = PolicyIgnore; const KURL& url = request.url(); if (!url.isNull()) { // Fragment scrolls on the same page should always be handled internally. // (Only count as a fragment scroll if we are scrolling to a #fragment url, not back to the top, and reloading // the same url is not a fragment scroll even if it has a #fragment.) const KURL& currentUrl = m_frame->document()->url(); bool isFragmentScroll = url.hasFragmentIdentifier() && url != currentUrl && equalIgnoringFragmentIdentifier(currentUrl, url); decision = decidePolicyForExternalLoad(request, isFragmentScroll); // Let the client have a chance to say whether this navigation should // be ignored or not. NetworkRequest platformRequest; request.initializePlatformRequest(platformRequest, cookiesEnabled()); if (platformRequest.getTargetType() == NetworkRequest::TargetIsUnknown) platformRequest.setTargetType(isMainFrame() ? NetworkRequest::TargetIsMainFrame : NetworkRequest::TargetIsSubframe); if (isMainFrame() && !m_webPagePrivate->m_client->acceptNavigationRequest( platformRequest, BlackBerry::Platform::NavigationType(action.type()))) { if (action.type() == NavigationTypeFormSubmitted || action.type() == NavigationTypeFormResubmitted) m_frame->loader()->resetMultipleFormSubmissionProtection(); if (action.type() == NavigationTypeLinkClicked && url.hasFragmentIdentifier()) { ResourceRequest emptyRequest; m_frame->loader()->activeDocumentLoader()->setLastCheckedRequest(emptyRequest); } decision = PolicyIgnore; } } // If we abort here, dispatchDidCancelClientRedirect will not be called. // So call it by hand. if (decision == PolicyIgnore) dispatchDidCancelClientRedirect(); (m_frame->loader()->policyChecker()->*function)(decision); if (m_webPagePrivate->m_dumpRenderTree) m_webPagePrivate->m_dumpRenderTree->didDecidePolicyForNavigationAction(action, request); }
InjectedBundleNavigationAction::InjectedBundleNavigationAction(WebFrame* frame, const NavigationAction& navigationAction, PassRefPtr<FormState> prpFormState) : m_navigationType(navigationAction.type()) , m_modifiers(modifiersForNavigationAction(navigationAction)) , m_mouseButton(WebMouseEvent::NoButton) , m_downloadAttribute(navigationAction.downloadAttribute()) , m_shouldOpenExternalURLs(navigationAction.shouldOpenExternalURLsPolicy() == ShouldOpenExternalURLsPolicy::ShouldAllow || navigationAction.shouldOpenExternalURLsPolicy() == ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes) , m_shouldTryAppLinks(navigationAction.shouldOpenExternalURLsPolicy() == ShouldOpenExternalURLsPolicy::ShouldAllow) { if (const MouseEvent* mouseEvent = mouseEventForNavigationAction(navigationAction)) { m_hitTestResult = InjectedBundleHitTestResult::create(frame->coreFrame()->eventHandler().hitTestResultAtPoint(mouseEvent->absoluteLocation())); m_mouseButton = mouseButtonForMouseEvent(mouseEvent); } RefPtr<FormState> formState = prpFormState; if (formState) { ASSERT(formState->form()); m_formElement = InjectedBundleNodeHandle::getOrCreate(formState->form()); } }
void FrameLoaderClientAndroid::dispatchDecidePolicyForNavigationAction(FramePolicyFunction func, const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState) { ASSERT(m_frame); ASSERT(func); if (!func) return; if (request.isNull()) { (m_frame->loader()->policyChecker()->*func)(PolicyIgnore); return; } // Reset multiple form submission protection. If this is a resubmission, we check with the // user and reset the protection if they choose to resubmit the form (see WebCoreFrameBridge.cpp) if (action.type() == NavigationTypeFormSubmitted) m_frame->loader()->resetMultipleFormSubmissionProtection(); if (action.type() == NavigationTypeFormResubmitted) { m_webFrame->decidePolicyForFormResubmission(func); return; } else { (m_frame->loader()->policyChecker()->*func)(PolicyUse); } }
void FrameLoaderClientAndroid::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction func, const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName) { ASSERT(m_frame); ASSERT(func); if (!func) return; if (request.isNull()) { (m_frame->loader()->policyChecker()->*func)(PolicyIgnore); return; } if (action.type() == NavigationTypeFormSubmitted || action.type() == NavigationTypeFormResubmitted) m_frame->loader()->resetMultipleFormSubmissionProtection(); // If we get to this point it means that a link has a target that was not // found by the frame tree. Instead of creating a new frame, return the // current frame in dispatchCreatePage. if (canHandleRequest(request)) (m_frame->loader()->policyChecker()->*func)(PolicyUse); else (m_frame->loader()->policyChecker()->*func)(PolicyIgnore); }
void FrameLoaderClientWx::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState>) { if (!m_webFrame) return; if (m_webView) { wxWebViewBeforeLoadEvent wkEvent(m_webView); wkEvent.SetNavigationType(wxNavTypeFromWebNavType(action.type())); wkEvent.SetURL(request.url().string()); m_webView->GetEventHandler()->ProcessEvent(wkEvent); if (wkEvent.IsCancelled()) (m_frame->loader()->policyChecker()->*function)(PolicyIgnore); else (m_frame->loader()->policyChecker()->*function)(PolicyUse); } }
void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const NavigationAction& navigationAction, const ResourceRequest& request, PassRefPtr<FormState>) { if (m_frame->coreFrame()->loader()->documentLoader()->url().isEmpty() && request.url() == blankURL()) { // WebKit2 loads initial about:blank documents synchronously, without consulting the policy delegate ASSERT(m_frame->coreFrame()->loader()->stateMachine()->committingFirstRealLoad()); (m_frame->coreFrame()->loader()->policyChecker()->*function)(PolicyUse); return; } WebPage* webPage = m_frame->page(); if (!webPage) return; uint64_t listenerID = m_frame->setUpPolicyListener(function); // FIXME: Pass more than just the navigation action type. const String& url = request.url().string(); // FIXME: Pass entire request. uint32_t modifiers = modifiersForNavigationAction(navigationAction); WebProcess::shared().connection()->send(WebPageProxyMessage::DecidePolicyForNavigationAction, webPage->pageID(), CoreIPC::In(m_frame->frameID(), (uint32_t)navigationAction.type(), modifiers, url, listenerID)); }
void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function, const NavigationAction& navigationAction, const ResourceRequest& request, PassRefPtr<FormState>, const String& frameName) { WebPage* webPage = m_frame->page(); if (!webPage) return; uint64_t listenerID = m_frame->setUpPolicyListener(function); // FIXME: Pass more than just the navigation action type. // FIXME: Pass the frame name. const String& url = request.url().string(); // FIXME: Pass entire request. uint32_t modifiers = modifiersForNavigationAction(navigationAction); WebProcess::shared().connection()->send(WebPageProxyMessage::DecidePolicyForNewWindowAction, webPage->pageID(), CoreIPC::In(m_frame->frameID(), (uint32_t)navigationAction.type(), modifiers, url, listenerID)); }
static uint32_t modifiersForNavigationAction(const NavigationAction& navigationAction) { uint32_t modifiers = 0; if (const UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(navigationAction.event()))) { if (keyStateEvent->shiftKey()) modifiers |= WebEvent::ShiftKey; if (keyStateEvent->ctrlKey()) modifiers |= WebEvent::ControlKey; if (keyStateEvent->altKey()) modifiers |= WebEvent::AltKey; if (keyStateEvent->metaKey()) modifiers |= WebEvent::MetaKey; } return modifiers; }
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; }
WebEvent::Modifiers InjectedBundleNavigationAction::modifiersForNavigationAction(const NavigationAction& navigationAction) { uint32_t modifiers = 0; const UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(navigationAction.event())); if (keyStateEvent && keyStateEvent->isTrusted()) { if (keyStateEvent->shiftKey()) modifiers |= WebEvent::ShiftKey; if (keyStateEvent->ctrlKey()) modifiers |= WebEvent::ControlKey; if (keyStateEvent->altKey()) modifiers |= WebEvent::AltKey; if (keyStateEvent->metaKey()) modifiers |= WebEvent::MetaKey; } return static_cast<WebEvent::Modifiers>(modifiers); }