source: webkit/trunk/Source/WebCore/loader/FrameLoader.cpp

Last change on this file was 295270, checked in by Chris Dumez, 3 years ago

Drop operator==() overload for comparing a String to a const char*
https://bugs.webkit.org/show_bug.cgi?id=241285

Reviewed by Darin Adler.

Drop operator==() overload for comparing a String to a const char*. This
encourages people to use ""_s for string literals.

  • Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitEqualityOpImpl):

  • Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp:

(JSC::ApplyFunctionCallDotNode::emitBytecode):

  • Source/JavaScriptCore/inspector/ScriptCallFrame.cpp:

(Inspector::ScriptCallFrame::isNative const):

  • Source/JavaScriptCore/inspector/remote/cocoa/RemoteInspectorXPCConnection.mm:

(Inspector::RemoteInspectorXPCConnection::handleEvent):

  • Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_protocol_types_implementation.py:

(CppProtocolTypesImplementationGenerator):

  • Source/JavaScriptCore/jit/ExecutableAllocator.cpp:

(JSC::isJITEnabled):
(JSC::ExecutableAllocator::setJITEnabled):

  • Source/JavaScriptCore/jsc.cpp:

(dumpException):

  • Source/JavaScriptCore/runtime/IntlCollator.cpp:

(JSC::IntlCollator::initializeCollator):

  • Source/JavaScriptCore/runtime/IntlObject.cpp:

(JSC::removeUnicodeLocaleExtension):

  • Source/JavaScriptCore/runtime/JSObject.cpp:

(JSC::JSObject::calculatedClassName):

  • Source/JavaScriptCore/runtime/Options.cpp:

(JSC::canUseJITCage):

  • Source/JavaScriptCore/runtime/StringPrototype.cpp:

(JSC::JSC_DEFINE_HOST_FUNCTION):

  • Source/JavaScriptCore/runtime/TypeSet.cpp:

(JSC::StructureShape::leastCommonAncestor):

  • Source/JavaScriptCore/tools/JSDollarVM.cpp:
  • Source/JavaScriptCore/yarr/YarrUnicodeProperties.cpp:

(JSC::Yarr::unicodeMatchPropertyValue):

  • Source/WTF/wtf/URL.cpp:

(WTF::URL::setProtocol):

  • Source/WTF/wtf/cocoa/Entitlements.h:
  • Source/WTF/wtf/cocoa/Entitlements.mm:

(WTF::hasEntitlement):
(WTF::processHasEntitlement):
(WTF::hasEntitlementValue):

  • Source/WTF/wtf/text/WTFString.h:
  • Source/WebCore/Modules/applepay/PaymentRequestValidator.mm:

(WebCore::validateCountryCode):
(WebCore::validateCurrencyCode):

  • Source/WebCore/Modules/async-clipboard/ios/ClipboardImageReaderIOS.mm:

(WebCore::ClipboardImageReader::readBuffer):

  • Source/WebCore/Modules/async-clipboard/mac/ClipboardImageReaderMac.mm:

(WebCore::ClipboardImageReader::readBuffer):

  • Source/WebCore/Modules/cache/DOMCache.cpp:

(WebCore::DOMCache::requestFromInfo):

  • Source/WebCore/Modules/cache/DOMCacheEngine.cpp:

(WebCore::DOMCacheEngine::matchURLs):

  • Source/WebCore/Modules/fetch/FetchLoader.cpp:

(WebCore::FetchLoader::start):

  • Source/WebCore/Modules/fetch/FetchRequest.cpp:

(WebCore::methodCanHaveBody):
(WebCore::FetchRequest::initializeOptions):
(WebCore::FetchRequest::referrer const):

  • Source/WebCore/Modules/mediasource/MediaSource.cpp:

(WebCore::MediaSource::contentTypeShouldGenerateTimestamps):

  • Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp:

(WebCore::MediaStreamTrack::setContentHint):

  • Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp:

(WebCore::RTCRtpSFrameTransform::setEncryptionKey):

  • Source/WebCore/Modules/mediastream/RTCRtpSender.cpp:

(WebCore::RTCRtpSender::dtmf):

  • Source/WebCore/Modules/mediastream/gstreamer/GStreamerMediaEndpoint.cpp:

(WebCore::GStreamerMediaEndpoint::createTransceiverBackends):

  • Source/WebCore/Modules/mediastream/gstreamer/GStreamerStatsCollector.cpp:

(WebCore::iceCandidateType):

  • Source/WebCore/Modules/mediastream/gstreamer/GStreamerWebRTCUtils.cpp:

(WebCore::toRTCIceProtocol):
(WebCore::toRTCIceTcpCandidateType):
(WebCore::toRTCIceCandidateType):
(WebCore::parseIceCandidateSDP):

  • Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp:

(WebCore::LibWebRTCMediaEndpoint::addTransceiver):

  • Source/WebCore/Modules/webauthn/cbor/CBORValue.cpp:

(cbor::CBORValue::CBORValue):

  • Source/WebCore/Modules/webauthn/cbor/CBORValue.h:
  • Source/WebCore/Modules/webauthn/fido/AuthenticatorGetInfoResponse.cpp:

(fido::encodeAsCBOR):

  • Source/WebCore/Modules/webauthn/fido/FidoConstants.h:
  • Source/WebCore/Modules/websockets/WebSocket.cpp:

(WebCore::WebSocket::setBinaryType):

  • Source/WebCore/PAL/pal/graphics/WebGPU/Impl/WebGPUAdapterImpl.cpp:

(PAL::WebGPU::AdapterImpl::requestDevice):

  • Source/WebCore/accessibility/AccessibilityNodeObject.cpp:

(WebCore::AccessibilityNodeObject::canSetValueAttribute const):

  • Source/WebCore/accessibility/AccessibilityObject.cpp:

(WebCore::AccessibilityObject::currentState const):
(WebCore::AccessibilityObject::attributeValue const):

  • Source/WebCore/accessibility/AccessibilityTableCell.cpp:

(WebCore::AccessibilityTableCell::isColumnHeaderCell const):
(WebCore::AccessibilityTableCell::isRowHeaderCell const):
(WebCore::AccessibilityTableCell::columnHeaders):
(WebCore::AccessibilityTableCell::rowHeaders):
(WebCore::AccessibilityTableCell::axRowSpan const):

  • Source/WebCore/accessibility/atspi/AXObjectCacheAtspi.cpp:

(WebCore::AXObjectCache::postPlatformNotification):

  • Source/WebCore/accessibility/atspi/AccessibilityObjectAtspi.cpp:

(WebCore::AccessibilityObjectAtspi::state const):

  • Source/WebCore/accessibility/atspi/AccessibilityObjectTextAtspi.cpp:

(WebCore::AccessibilityObjectAtspi::textAttributes const):

  • Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp:

(WebCore::AXIsolatedObject::attributeValue const):

  • Source/WebCore/accessibility/win/AccessibilityObjectWrapperWin.cpp:

(WebCore::AccessibilityObjectWrapper::accessibilityAttributeValue):

  • Source/WebCore/animation/KeyframeEffect.cpp:

(WebCore::IDLAttributeNameToAnimationPropertyName):

  • Source/WebCore/bindings/js/IDBBindingUtilities.cpp:

(WebCore::get):

  • Source/WebCore/bindings/js/JSDOMGlobalObject.cpp:

(WebCore::JSC_DEFINE_HOST_FUNCTION):

  • Source/WebCore/bindings/js/JSDOMWindowCustom.cpp:

(WebCore::jsDOMWindowInstanceFunction_openDatabaseBody):

  • Source/WebCore/bindings/scripts/CodeGeneratorJS.pm:

(GenerateIsLegacyUnforgeablePropertyName):

  • Source/WebCore/bindings/scripts/test/JS/JSTestNamedSetterWithLegacyUnforgeableProperties.cpp:

(WebCore::JSTestNamedSetterWithLegacyUnforgeableProperties::defineOwnProperty):

  • Source/WebCore/bindings/scripts/test/JS/JSTestNamedSetterWithLegacyUnforgeablePropertiesAndLegacyOverrideBuiltIns.cpp:

(WebCore::JSTestNamedSetterWithLegacyUnforgeablePropertiesAndLegacyOverrideBuiltIns::defineOwnProperty):

  • Source/WebCore/contentextensions/ContentExtensionActions.cpp:

(WebCore::ContentExtensions::ModifyHeadersAction::ModifyHeaderInfo::parse):
(WebCore::ContentExtensions::RedirectAction::URLTransformAction::parse):

  • Source/WebCore/contentextensions/ContentExtensionParser.cpp:

(WebCore::ContentExtensions::loadAction):

  • Source/WebCore/crypto/algorithms/CryptoAlgorithmECDH.cpp:

(WebCore::CryptoAlgorithmECDH::importKey):

  • Source/WebCore/crypto/algorithms/CryptoAlgorithmECDSA.cpp:

(WebCore::CryptoAlgorithmECDSA::importKey):

  • Source/WebCore/crypto/algorithms/CryptoAlgorithmRSAES_PKCS1_v1_5.cpp:

(WebCore::CryptoAlgorithmRSAES_PKCS1_v1_5::importKey):

  • Source/WebCore/crypto/algorithms/CryptoAlgorithmRSASSA_PKCS1_v1_5.cpp:

(WebCore::CryptoAlgorithmRSASSA_PKCS1_v1_5::importKey):

  • Source/WebCore/crypto/algorithms/CryptoAlgorithmRSA_OAEP.cpp:

(WebCore::CryptoAlgorithmRSA_OAEP::importKey):

  • Source/WebCore/crypto/algorithms/CryptoAlgorithmRSA_PSS.cpp:

(WebCore::CryptoAlgorithmRSA_PSS::importKey):

  • Source/WebCore/crypto/keys/CryptoKeyAES.cpp:

(WebCore::CryptoKeyAES::importJwk):

  • Source/WebCore/crypto/keys/CryptoKeyEC.cpp:

(WebCore::CryptoKeyEC::importJwk):

  • Source/WebCore/crypto/keys/CryptoKeyHMAC.cpp:

(WebCore::CryptoKeyHMAC::importJwk):

  • Source/WebCore/crypto/keys/CryptoKeyRSA.cpp:

(WebCore::CryptoKeyRSA::importJwk):

  • Source/WebCore/css/CSSBasicShapes.cpp:

(WebCore::buildInsetRadii):

  • Source/WebCore/css/CSSPrimitiveValue.cpp:

(WebCore::CSSPrimitiveValue::formatNumberForCustomCSSText const):

  • Source/WebCore/css/CSSPropertySourceData.cpp:

(WebCore::CSSPropertySourceData::toString const):

  • Source/WebCore/css/CSSSelector.cpp:

(WebCore::CSSSelector::selectorText const):

  • Source/WebCore/css/MediaQuery.cpp:

(WebCore::MediaQuery::serialize const):

  • Source/WebCore/css/SelectorCheckerTestFunctions.h:

(WebCore::matchesLangPseudoClass):

  • Source/WebCore/css/StyleProperties.cpp:

(WebCore::StyleProperties::borderPropertyValue const):
(WebCore::StyleProperties::asTextInternal const):

  • Source/WebCore/css/parser/CSSPropertyParser.cpp:

(WebCore::parseGridTemplateAreasRow):
(WebCore::CSSPropertyParser::canParseTypedCustomPropertyValue):
(WebCore::CSSPropertyParser::collectParsedCustomPropertyValueDependencies):
(WebCore::CSSPropertyParser::parseTypedCustomPropertyValue):

  • Source/WebCore/dom/DataTransfer.cpp:

(WebCore::DataTransfer::getDataForItem const):
(WebCore::DataTransfer::readStringFromPasteboard const):
(WebCore::DataTransfer::setDataFromItemList):
(WebCore::dragOpFromIEOp):
(WebCore::DataTransfer::dropEffect const):
(WebCore::DataTransfer::setDropEffect):

  • Source/WebCore/dom/DataTransfer.h:

(WebCore::DataTransfer::dropEffectIsUninitialized const):

  • Source/WebCore/dom/Document.cpp:

(WebCore::Document::originIdentifierForPasteboard const):

  • Source/WebCore/dom/ProcessingInstruction.cpp:

(WebCore::ProcessingInstruction::checkStyleSheet):

  • Source/WebCore/dom/Range.cpp:

(WebCore::Range::expand):

  • Source/WebCore/dom/UIEventWithKeyState.cpp:

(WebCore::UIEventWithKeyState::getModifierState const):

  • Source/WebCore/editing/Editing.cpp:

(WebCore::isMailBlockquote):

  • Source/WebCore/editing/Editor.cpp:

(WebCore::Editor::handleTextEvent):
(WebCore::Editor::insertTextWithoutSendingTextEvent):

  • Source/WebCore/editing/HTMLInterchange.h:
  • Source/WebCore/editing/InsertTextCommand.cpp:

(WebCore::InsertTextCommand::doApply):

  • Source/WebCore/editing/ReplaceSelectionCommand.cpp:

(WebCore::isInterchangeNewlineNode):
(WebCore::isInterchangeConvertedSpaceSpan):
(WebCore::isInlineNodeWithStyle):

  • Source/WebCore/editing/cocoa/HTMLConverter.mm:

(HTMLConverter::computedAttributesForElement):
(HTMLConverter::_addAttachmentForElement):
(HTMLConverter::_enterElement):
(HTMLConverter::_addTableForElement):
(HTMLConverter::_addTableCellForElement):
(HTMLConverter::_processElement):
(HTMLConverter::_exitElement):
(HTMLConverter::_processText):

  • Source/WebCore/editing/markup.cpp:

(WebCore::StyledMarkupAccumulator::appendNodeToPreserveMSOList):
(WebCore::createFragmentFromText):
(WebCore::createFragmentForTransformToFragment):

  • Source/WebCore/html/BaseCheckableInputType.cpp:

(WebCore::BaseCheckableInputType::handleKeydownEvent):

  • Source/WebCore/html/BaseClickableWithKeyInputType.cpp:

(WebCore::BaseClickableWithKeyInputType::handleKeydownEvent):
(WebCore::BaseClickableWithKeyInputType::handleKeyupEvent):

  • Source/WebCore/html/CheckboxInputType.cpp:

(WebCore::CheckboxInputType::handleKeyupEvent):

  • Source/WebCore/html/FTPDirectoryDocument.cpp:

(WebCore::FTPDirectoryDocumentParser::parseAndAppendOneLine):

  • Source/WebCore/html/FormController.cpp:

(WebCore::FormController::SavedFormState::appendReferencedFilePaths const):

  • Source/WebCore/html/HTMLAnchorElement.cpp:

(WebCore::isEnterKeyKeydownEvent):

  • Source/WebCore/html/HTMLAttachmentElement.cpp:

(WebCore::HTMLAttachmentElement::parseAttribute):

  • Source/WebCore/html/HTMLButtonElement.cpp:

(WebCore::HTMLButtonElement::defaultEventHandler):

  • Source/WebCore/html/HTMLCanvasElement.cpp:

(WebCore::HTMLCanvasElement::is2dType):
(WebCore::HTMLCanvasElement::isWebGLType):
(WebCore::HTMLCanvasElement::toWebGLVersion):
(WebCore::HTMLCanvasElement::isBitmapRendererType):

  • Source/WebCore/html/HTMLFrameSetElement.cpp:

(WebCore::HTMLFrameSetElement::parseAttribute):

  • Source/WebCore/html/HTMLInputElement.cpp:

(WebCore::HTMLInputElement::setValueFromRenderer):

  • Source/WebCore/html/HTMLLIElement.cpp:

(WebCore::HTMLLIElement::collectPresentationalHintsForAttribute):

  • Source/WebCore/html/HTMLMarqueeElement.cpp:

(WebCore::HTMLMarqueeElement::collectPresentationalHintsForAttribute):

  • Source/WebCore/html/HTMLOListElement.cpp:

(WebCore::HTMLOListElement::collectPresentationalHintsForAttribute):

  • Source/WebCore/html/HTMLSelectElement.cpp:

(WebCore::HTMLSelectElement::platformHandleKeydownEvent):
(WebCore::HTMLSelectElement::menuListDefaultEventHandler):
(WebCore::HTMLSelectElement::listBoxDefaultEventHandler):

  • Source/WebCore/html/HTMLSelectElementWin.cpp:

(WebCore::HTMLSelectElement::platformHandleKeydownEvent):

  • Source/WebCore/html/HTMLSummaryElement.cpp:

(WebCore::HTMLSummaryElement::defaultEventHandler):

  • Source/WebCore/html/HTMLTextFormControlElement.cpp:

(WebCore::HTMLTextFormControlElement::setSelectionRange):

  • Source/WebCore/html/MediaDocument.cpp:

(WebCore::MediaDocument::defaultEventHandler):

  • Source/WebCore/html/MediaFragmentURIParser.cpp:

(WebCore::MediaFragmentURIParser::parseTimeFragment):

  • Source/WebCore/html/RadioInputType.cpp:

(WebCore::RadioInputType::handleKeydownEvent):
(WebCore::RadioInputType::handleKeyupEvent):

  • Source/WebCore/html/RangeInputType.cpp:

(WebCore::RangeInputType::handleKeydownEvent):

  • Source/WebCore/html/SearchInputType.cpp:

(WebCore::SearchInputType::handleKeydownEvent):

  • Source/WebCore/html/TextFieldInputType.cpp:

(WebCore::TextFieldInputType::handleKeydownEvent):
(WebCore::TextFieldInputType::handleKeydownEventForSpinButton):
(WebCore::TextFieldInputType::shouldSubmitImplicitly):

  • Source/WebCore/html/canvas/CanvasPattern.cpp:

(WebCore::CanvasPattern::parseRepetitionType):

  • Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp:

(WebCore::CanvasRenderingContext2DBase::setLineCap):
(WebCore::CanvasRenderingContext2DBase::setLineJoin):

  • Source/WebCore/html/parser/HTMLConstructionSite.cpp:

(WebCore::HTMLConstructionSite::setCompatibilityModeFromDoctype):

  • Source/WebCore/html/shadow/DateTimeFieldElement.cpp:

(WebCore::DateTimeFieldElement::defaultKeyboardEventHandler):

  • Source/WebCore/inspector/InspectorAuditAccessibilityObject.cpp:

(WebCore::InspectorAuditAccessibilityObject::getComputedProperties):

  • Source/WebCore/inspector/InspectorCanvas.cpp:

(WebCore::shouldSnapshotBitmapRendererAction):
(WebCore::shouldSnapshotWebGLAction):
(WebCore::shouldSnapshotWebGL2Action):

  • Source/WebCore/inspector/InspectorFrontendHost.cpp:

(WebCore::dockSideFromString):
(WebCore::populateContextMenu):

  • Source/WebCore/inspector/InspectorStyleSheet.cpp:

(WebCore::buildArrayForGroupings):
(WebCore::InspectorStyle::shorthandValue const):

  • Source/WebCore/inspector/agents/InspectorDOMAgent.cpp:

(WebCore::InspectorDOMAgent::buildObjectForAccessibilityProperties):

  • Source/WebCore/loader/CrossOriginAccessControl.cpp:

(WebCore::isOnAccessControlSimpleRequestMethodAllowlist):
(WebCore::passesAccessControlCheck):

  • Source/WebCore/loader/DocumentLoader.cpp:

(WebCore::isRedirectToGetAfterPost):
(WebCore::DocumentLoader::isPostOrRedirectAfterPost):
(WebCore::DocumentLoader::responseReceived):

  • Source/WebCore/loader/FormSubmission.cpp:

(WebCore::FormSubmission::Attributes::updateEncodingType):

  • Source/WebCore/loader/FrameLoader.cpp:

(WebCore::FrameLoader::changeLocation):
(WebCore::FrameLoader::loadFrameRequest):
(WebCore::FrameLoader::loadURL):
(WebCore::FrameLoader::reload):
(WebCore::FrameLoader::addHTTPOriginIfNeeded):
(WebCore::createWindow):

  • Source/WebCore/loader/MixedContentChecker.cpp:

(WebCore::MixedContentChecker::isMixedContent):

  • Source/WebCore/loader/PrivateClickMeasurement.cpp:

(WebCore::PrivateClickMeasurement::parseAttributionRequestQuery):

  • Source/WebCore/loader/ResourceLoader.cpp:

(WebCore::ResourceLoader::loadDataURL):

  • Source/WebCore/loader/SubframeLoader.cpp:

(WebCore::FrameLoader::SubframeLoader::requestFrame):

  • Source/WebCore/loader/archive/mhtml/MHTMLParser.cpp:

(WebCore::MHTMLParser::parseArchiveWithHeader):

  • Source/WebCore/loader/cache/MemoryCache.cpp:

(WebCore::MemoryCache::add):

  • Source/WebCore/loader/mac/LoaderNSURLExtras.mm:

(suggestedFilenameWithMIMEType):

  • Source/WebCore/mathml/MathMLElement.cpp:

(WebCore::convertMathSizeIfNeeded):

  • Source/WebCore/mathml/MathMLOperatorElement.cpp:

(WebCore::MathMLOperatorElement::computeDictionaryProperty):

  • Source/WebCore/mathml/MathMLPresentationElement.cpp:

(WebCore::MathMLPresentationElement::parseMathVariantAttribute):

  • Source/WebCore/mathml/MathMLSelectElement.cpp:

(WebCore::MathMLSelectElement::isMathMLEncoding):
(WebCore::MathMLSelectElement::isSVGEncoding):
(WebCore::MathMLSelectElement::isHTMLEncoding):
(WebCore::MathMLSelectElement::getSelectedActionChild):
(WebCore::MathMLSelectElement::defaultEventHandler):
(WebCore::MathMLSelectElement::willRespondToMouseClickEventsWithEditability const):

  • Source/WebCore/page/DOMWindow.cpp:

(WebCore::DOMWindow::postMessage):

  • Source/WebCore/page/EventHandler.cpp:

(WebCore::convertDropZoneOperationToDragOperation):
(WebCore::EventHandler::accessibilityPreventsEventPropagation):
(WebCore::EventHandler::defaultKeyboardEventHandler):
(WebCore::EventHandler::isKeyboardOptionTab):

  • Source/WebCore/page/Performance.cpp:

(WebCore::Performance::getEntriesByType const):
(WebCore::Performance::getEntriesByName const):
(WebCore::Performance::appendBufferedEntriesByType const):

  • Source/WebCore/page/PerformanceEntry.cpp:

(WebCore::PerformanceEntry::parseEntryTypeString):

  • Source/WebCore/page/Quirks.cpp:

(WebCore::isTwitterDocument):
(WebCore::isYouTubeDocument):
(WebCore::Quirks::shouldDispatchSimulatedMouseEvents const):
(WebCore::Quirks::shouldDispatchedSimulatedMouseEventsAssumeDefaultPrevented const):
(WebCore::Quirks::shouldMakeTouchEventNonCancelableForTarget const):
(WebCore::Quirks::shouldEnableLegacyGetUserMediaQuirk const):
(WebCore::Quirks::shouldDisableElementFullscreenQuirk const):
(WebCore::Quirks::needsCanPlayAfterSeekedQuirk const):
(WebCore::Quirks::shouldAllowNavigationToCustomProtocolWithoutUserGesture):

  • Source/WebCore/page/SecurityOrigin.cpp:

(WebCore::SecurityOrigin::canDisplay const):
(WebCore::SecurityOrigin::toString const):
(WebCore::areOriginsMatching):

  • Source/WebCore/page/SecurityOrigin.h:

(WebCore::SecurityOrigin::isHTTPFamily const):

  • Source/WebCore/page/SecurityOriginData.cpp:

(WebCore::SecurityOriginData::toString const):

  • Source/WebCore/page/SecurityPolicy.cpp:

(WebCore::SecurityPolicy::referrerToOriginString):

  • Source/WebCore/page/UserContentURLPattern.cpp:

(WebCore::UserContentURLPattern::matches const):

  • Source/WebCore/page/WindowFeatures.cpp:

(WebCore::boolFeature):

  • Source/WebCore/page/cocoa/ResourceUsageThreadCocoa.mm:

(WebCore::ResourceUsageThread::platformCollectCPUData):

  • Source/WebCore/page/csp/ContentSecurityPolicy.cpp:

(WebCore::ContentSecurityPolicy::reportViolation const):

  • Source/WebCore/page/csp/ContentSecurityPolicySource.cpp:

(WebCore::ContentSecurityPolicySource::schemeMatches const):

  • Source/WebCore/page/linux/ResourceUsageThreadLinux.cpp:

(WebCore::ResourceUsageThread::platformCollectCPUData):

  • Source/WebCore/platform/KeyboardScrollingAnimator.cpp:

(WebCore::keyboardScrollingKeyFromEvent):

  • Source/WebCore/platform/KeypressCommand.h:

(WebCore::KeypressCommand::KeypressCommand):

  • Source/WebCore/platform/LocalizedStrings.cpp:

(WebCore::localizedMediaControlElementString):
(WebCore::localizedMediaControlElementHelpText):

  • Source/WebCore/platform/Pasteboard.cpp:

(WebCore::Pasteboard::isSafeTypeForDOMToReadAndWrite):

  • Source/WebCore/platform/RegistrableDomain.h:

(WebCore::RegistrableDomain::operator== const):

  • Source/WebCore/platform/Theme.cpp:

(WebCore::Theme::drawNamedImage const):

  • Source/WebCore/platform/UserAgentQuirks.cpp:

(WebCore::urlRequiresChromeBrowser):
(WebCore::urlRequiresFirefoxBrowser):
(WebCore::urlRequiresMacintoshPlatform):
(WebCore::urlRequiresUnbrandedUserAgent):

  • Source/WebCore/platform/cocoa/ThemeCocoa.mm:

(WebCore::ThemeCocoa::drawNamedImage const):

  • Source/WebCore/platform/graphics/GLContext.cpp:

(WebCore::GLContext::version):

  • Source/WebCore/platform/graphics/Image.cpp:

(WebCore::Image::create):

  • Source/WebCore/platform/graphics/MIMETypeCache.cpp:

(WebCore::MIMETypeCache::shouldOverrideExtendedType):

  • Source/WebCore/platform/graphics/VP9Utilities.cpp:

(WebCore::parseVPCodecParameters):

  • Source/WebCore/platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.mm:

(WebCore::CDMPrivateMediaSourceAVFObjC::supportsMIMEType):

  • Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp:

(WebCore::AVFWrapper::shouldWaitForLoadingOfResource):

  • Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:

(WebCore::MediaPlayerPrivateAVFoundationObjC::shouldWaitForLoadingOfResource):

  • Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp:

(WebCore::encodeImage):

  • Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp:

(WebCore::ImageDecoderCG::frameHasAlphaAtIndex const):
(WebCore::ImageDecoderCG::createFrameImageAtIndex):

  • Source/WebCore/platform/graphics/cg/ImageSourceCGWin.cpp:

(WebCore::MIMETypeForImageType):

  • Source/WebCore/platform/graphics/cocoa/VP9UtilitiesCocoa.mm:

(WebCore::isVPCodecConfigurationRecordSupported):
(WebCore::createVideoInfoFromVPCodecConfigurationRecord):

  • Source/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp:

(WebCore::getFamilyNameStringFromFamily):

  • Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:

(WebCore::isMediaDiskCacheDisabled):

  • Source/WebCore/platform/graphics/gstreamer/mse/SourceBufferPrivateGStreamer.cpp:

(WebCore::SourceBufferPrivateGStreamer::platformMaximumBufferSize const):

  • Source/WebCore/platform/graphics/opengl/ExtensionsGLOpenGL.cpp:

(WebCore::ExtensionsGLOpenGL::platformSupportsExtension):

  • Source/WebCore/platform/graphics/opengl/ExtensionsGLOpenGLCommon.cpp:

(WebCore::ExtensionsGLOpenGLCommon::supports):
(WebCore::ExtensionsGLOpenGLCommon::ensureEnabled):
(WebCore::ExtensionsGLOpenGLCommon::isEnabled):

  • Source/WebCore/platform/graphics/opengl/ExtensionsGLOpenGLES.cpp:

(WebCore::ExtensionsGLOpenGLES::isEnabled):
(WebCore::ExtensionsGLOpenGLES::platformSupportsExtension):

  • Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.cpp:

(WebCore::GraphicsContextGLOpenGL::checkVaryingsPacking const):

  • Source/WebCore/platform/gtk/PasteboardGtk.cpp:

(WebCore::selectionDataTypeFromHTMLClipboardType):

  • Source/WebCore/platform/ios/PlatformEventFactoryIOS.mm:

(WebCore::PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder):

  • Source/WebCore/platform/ios/PlatformPasteboardIOS.mm:

(WebCore::PlatformPasteboard::platformPasteboardTypeForSafeTypeForDOMToReadAndWrite):

  • Source/WebCore/platform/ios/PreviewConverterIOS.mm:

(WebCore::PreviewConverter::isPlatformPasswordError const):

  • Source/WebCore/platform/mac/PasteboardMac.mm:

(WebCore::cocoaTypeFromHTMLClipboardType):
(WebCore::Pasteboard::addHTMLClipboardTypesForCocoaType):

  • Source/WebCore/platform/mac/PlatformPasteboardMac.mm:

(WebCore::PlatformPasteboard::typesSafeForDOMToReadAndWrite const):
(WebCore::PlatformPasteboard::platformPasteboardTypeForSafeTypeForDOMToReadAndWrite):

  • Source/WebCore/platform/mac/PublicSuffixMac.mm:

(WebCore::topPrivatelyControlledDomain):

  • Source/WebCore/platform/mediastream/RealtimeMediaSourceSettings.cpp:

(WebCore::RealtimeMediaSourceSettings::videoFacingModeEnum):

  • Source/WebCore/platform/mediastream/libwebrtc/gstreamer/GStreamerVideoEncoderFactory.cpp:

(WebCore::GStreamerH264Encoder::GStreamerH264Encoder):

  • Source/WebCore/platform/mock/MediaEngineConfigurationFactoryMock.cpp:

(WebCore::canDecodeMedia):
(WebCore::canSmoothlyDecodeMedia):
(WebCore::canPowerEfficientlyDecodeMedia):
(WebCore::canEncodeMedia):
(WebCore::canSmoothlyEncodeMedia):
(WebCore::canPowerEfficientlyEncodeMedia):

  • Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.cpp:

(WebCore::MockMediaPlayerMediaSource::supportsType):

  • Source/WebCore/platform/network/CacheValidation.cpp:

(WebCore::verifyVaryingRequestHeadersInternal):

  • Source/WebCore/platform/network/ResourceResponseBase.h:

(WebCore::ResourceResponseBase::isMultipart const):

  • Source/WebCore/platform/network/cf/ResourceErrorCF.cpp:

(WebCore::ResourceError::cfStreamError const):

  • Source/WebCore/platform/network/curl/CookieJarDB.cpp:

(WebCore::CookieJarDB::checkDatabaseValidity):

  • Source/WebCore/platform/network/curl/CookieJarDB.h:

(WebCore::CookieJarDB::isOnMemory const):

  • Source/WebCore/platform/network/curl/CurlDownload.cpp:

(WebCore::CurlDownload::shouldRedirectAsGET):

  • Source/WebCore/platform/network/curl/CurlRequest.cpp:

(WebCore::CurlRequest::setupTransfer):

  • Source/WebCore/platform/network/curl/PublicSuffixCurl.cpp:

(WebCore::topPrivatelyControlledDomain):

  • Source/WebCore/platform/network/curl/ResourceHandleCurl.cpp:

(WebCore::ResourceHandle::start):
(WebCore::ResourceHandle::shouldRedirectAsGET):

  • Source/WebCore/platform/network/ios/WebCoreURLResponseIOS.h:

(WebCore::shouldUseQuickLookForMIMEType):

  • Source/WebCore/platform/soup/PublicSuffixSoup.cpp:

(WebCore::topPrivatelyControlledDomain):

  • Source/WebCore/platform/win/SearchPopupMenuDB.cpp:

(WebCore::SearchPopupMenuDB::checkDatabaseValidity):

  • Source/WebCore/rendering/RenderBlockFlow.cpp:

(WebCore::needsAppleMailPaginationQuirk):

  • Source/WebCore/rendering/RenderCounter.cpp:

(WebCore::planCounter):

  • Source/WebCore/rendering/RenderTextControlMultiLine.cpp:

(WebCore::RenderTextControlMultiLine::getAverageCharWidth):

  • Source/WebCore/rendering/RenderTextControlSingleLine.cpp:

(WebCore::RenderTextControlSingleLine::getAverageCharWidth):
(WebCore::RenderTextControlSingleLine::preferredContentLogicalWidth const):

  • Source/WebCore/rendering/RenderTreeAsText.cpp:

(WebCore::isEmptyOrUnstyledAppleStyleSpan):

  • Source/WebCore/svg/SVGAElement.cpp:

(WebCore::SVGAElement::defaultEventHandler):

  • Source/WebCore/svg/SVGComponentTransferFunctionElement.h:

(WebCore::SVGPropertyTraits<ComponentTransferType>::fromString):

  • Source/WebCore/svg/SVGFEColorMatrixElement.h:

(WebCore::SVGPropertyTraits<ColorMatrixType>::fromString):

  • Source/WebCore/svg/SVGFECompositeElement.h:

(WebCore::SVGPropertyTraits<CompositeOperationType>::fromString):

  • Source/WebCore/svg/SVGFEConvolveMatrixElement.h:

(WebCore::SVGPropertyTraits<EdgeModeType>::fromString):

  • Source/WebCore/svg/SVGFEDisplacementMapElement.h:

(WebCore::SVGPropertyTraits<ChannelSelectorType>::fromString):

  • Source/WebCore/svg/SVGFEMorphologyElement.h:

(WebCore::SVGPropertyTraits<MorphologyOperatorType>::fromString):

  • Source/WebCore/svg/SVGFETurbulenceElement.h:

(WebCore::SVGPropertyTraits<SVGStitchOptions>::fromString):
(WebCore::SVGPropertyTraits<TurbulenceType>::fromString):

  • Source/WebCore/svg/SVGGradientElement.h:

(WebCore::SVGPropertyTraits<SVGSpreadMethodType>::fromString):

  • Source/WebCore/svg/SVGMarkerTypes.h:

(WebCore::SVGPropertyTraits<SVGMarkerUnitsType>::fromString):

  • Source/WebCore/svg/SVGTests.cpp:

(WebCore::SVGTests::hasFeatureForLegacyBindings):

  • Source/WebCore/svg/SVGTextContentElement.cpp:

(WebCore::SVGTextContentElement::collectPresentationalHintsForAttribute):

  • Source/WebCore/svg/SVGTextContentElement.h:

(WebCore::SVGPropertyTraits<SVGLengthAdjustType>::fromString):

  • Source/WebCore/svg/SVGTextPathElement.h:

(WebCore::SVGPropertyTraits<SVGTextPathMethodType>::fromString):
(WebCore::SVGPropertyTraits<SVGTextPathSpacingType>::fromString):

  • Source/WebCore/svg/SVGUnitTypes.h:

(WebCore::SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString):

  • Source/WebCore/svg/SVGZoomAndPanType.h:

(WebCore::SVGPropertyTraits<SVGZoomAndPanType>::fromString):

  • Source/WebCore/svg/animation/SVGSMILElement.cpp:

(WebCore::SVGSMILElement::createInstanceTimesFromSyncbase):

  • Source/WebCore/svg/properties/SVGPropertyTraits.h:

(WebCore::SVGPropertyTraits<bool>::fromString):

  • Source/WebCore/testing/Internals.cpp:

(WebCore::Internals::pseudoElement):
(WebCore::Internals::setViewBaseBackgroundColor):
(WebCore::Internals::setPagination):
(WebCore::parseFindOptions):
(WebCore::Internals::countMatchesForText):
(WebCore::Internals::setOverridePreferredDynamicRangeMode):
(WebCore::taskSourceFromString):
(WebCore::Internals::hasSandboxMachLookupAccessToGlobalName):
(WebCore::Internals::hasSandboxMachLookupAccessToXPCServiceName):

  • Source/WebCore/testing/MockLibWebRTCPeerConnection.cpp:

(WebCore::createConnection):

  • Source/WebCore/workers/WorkerFontLoadRequest.cpp:

(WebCore::WorkerFontLoadRequest::load):

  • Source/WebCore/workers/WorkerScriptLoader.cpp:

(WebCore::WorkerScriptLoader::loadAsynchronously):

  • Source/WebCore/workers/service/server/RegistrationDatabase.cpp:

(WebCore::stringToUpdateViaCache):
(WebCore::stringToWorkerType):

  • Source/WebCore/xml/DOMParser.cpp:

(WebCore::DOMParser::parseFromString):

  • Source/WebCore/xml/XMLHttpRequest.cpp:

(WebCore::XMLHttpRequest::send):
(WebCore::XMLHttpRequest::sendBytesData):
(WebCore::XMLHttpRequest::createRequest):

  • Source/WebCore/xml/XPathFunctions.cpp:

(WebCore::XPath::Function::setArguments):

  • Source/WebCore/xml/XPathParser.cpp:

(WebCore::XPath::Parser::nextTokenInternal):

  • Source/WebCore/xml/XSLTProcessor.cpp:

(WebCore::XSLTProcessor::createDocumentFromSource):

  • Source/WebCore/xml/XSLTProcessorLibxslt.cpp:

(WebCore::XSLTProcessor::transformToString):

  • Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp:

(WebCore::shouldAllowExternalLoad):
(WebCore::XMLDocumentParser::supportsXMLVersion):
(WebCore::externalSubsetHandler):

  • Source/WebDriver/CommandResult.cpp:

(WebDriver::CommandResult::CommandResult):

  • Source/WebDriver/Session.cpp:

(WebDriver::Session::newWindow):
(WebDriver::Session::isElementSelected):
(WebDriver::Session::elementClick):

  • Source/WebDriver/WebDriverService.cpp:

(WebDriver::deserializeTimeouts):
(WebDriver::deserializeProxy):
(WebDriver::deserializePageLoadStrategy):
(WebDriver::deserializeUnhandledPromptBehavior):
(WebDriver::WebDriverService::validatedCapabilities const):
(WebDriver::WebDriverService::matchCapabilities const):
(WebDriver::WebDriverService::newWindow):
(WebDriver::isValidStrategy):
(WebDriver::findStrategyAndSelectorOrCompleteWithError):
(WebDriver::processNullAction):
(WebDriver::processKeyAction):
(WebDriver::processPointerMoveAction):
(WebDriver::processPointerAction):
(WebDriver::processWheelAction):
(WebDriver::processPointerParameters):
(WebDriver::processInputActionSequence):

  • Source/WebDriver/glib/WebDriverServiceGLib.cpp:

(WebDriver::WebDriverService::platformSupportProxyType const):

  • Source/WebDriver/gtk/WebDriverServiceGtk.cpp:

(WebDriver::WebDriverService::platformValidateCapability const):

  • Source/WebDriver/socket/HTTPParser.cpp:

(WebDriver::HTTPParser::expectedBodyLength const):

  • Source/WebDriver/socket/SessionHostSocket.cpp:

(WebDriver::SessionHost::parseTargetList):

  • Source/WebDriver/soup/HTTPServerSoup.cpp:

(WebDriver::soupServerListen):

  • Source/WebDriver/wpe/WebDriverServiceWPE.cpp:

(WebDriver::WebDriverService::platformValidateCapability const):

  • Source/WebGPU/WGSLUnitTests/WGSLParserTests.mm:

(-[WGSLParserTests testParsingStruct]):
(-[WGSLParserTests testParsingGlobalVariable]):
(-[WGSLParserTests testParsingFunctionDecl]):
(-[WGSLParserTests testTrivialGraphicsShader]):

  • Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.cpp:

(WebKit::ResourceLoadStatisticsStore::shouldSkip const):

  • Source/WebKit/NetworkProcess/DatabaseUtilities.cpp:

(WebKit::insertDistinctValuesInTableStatement):

  • Source/WebKit/NetworkProcess/NetworkProcess.cpp:

(WebKit::NetworkProcess::allowsPrivateClickMeasurementTestFunctionality const):

  • Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp:

(WebKit::NetworkResourceLoader::isCrossOriginPrefetch const):

  • Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp:

(WebKit::ServiceWorkerFetchTask::ServiceWorkerFetchTask):

  • Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp:

(WebKit::CacheStorage::getDirectorySize):

  • Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.cpp:

(WebKit::CacheStorage::queryCache):
(WebKit::CacheStorage::Cache::retrieveRecords):

  • Source/WebKit/NetworkProcess/cache/NetworkCache.cpp:

(WebKit::NetworkCache::makeRetrieveDecision):
(WebKit::NetworkCache::makeStoreDecision):

  • Source/WebKit/NetworkProcess/cache/NetworkCacheEntry.cpp:

(WebKit::NetworkCache::Entry::Entry):

  • Source/WebKit/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp:

(WebKit::NetworkCache::SpeculativeLoadManager::shouldRegisterLoad):
(WebKit::NetworkCache::SpeculativeLoadManager::retrieveSubresourcesEntry):

  • Source/WebKit/NetworkProcess/cache/NetworkCacheSubresourcesEntry.cpp:

(WebKit::NetworkCache::SubresourcesEntry::SubresourcesEntry):

  • Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm:

(WebKit::isActingOnBehalfOfAFullWebBrowser):

  • Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp:

(WebKit::NetworkDataTaskCurl::shouldRedirectAsGET):

  • Source/WebKit/NetworkProcess/ios/NetworkProcessIOS.mm:

(WebKit::NetworkProcess::parentProcessHasServiceWorkerEntitlement const):

  • Source/WebKit/NetworkProcess/storage/FileSystemStorageHandle.cpp:

(WebKit::isValidFileName):

  • Source/WebKit/NetworkProcess/storage/OriginStorageManager.cpp:

(WebKit::OriginStorageManager::StorageBucket::isEmpty):

  • Source/WebKit/Scripts/PreferencesTemplates/WebPreferencesExperimentalFeatures.cpp.erb:
  • Source/WebKit/Scripts/PreferencesTemplates/WebPreferencesInternalDebugFeatures.cpp.erb:
  • Source/WebKit/Shared/AuxiliaryProcess.h:
  • Source/WebKit/Shared/Cocoa/AuxiliaryProcessCocoa.mm:

(WebKit::AuxiliaryProcess::parentProcessHasEntitlement):
(WebKit::AuxiliaryProcess::setPreferenceValue):

  • Source/WebKit/Shared/Cocoa/DefaultWebBrowserChecks.mm:

(WebKit::appBoundDomainsForTesting):
(WebKit::isParentProcessAFullWebBrowser):
(WebKit::isFullWebBrowser):

  • Source/WebKit/Shared/Cocoa/XPCEndpoint.mm:

(WebKit::XPCEndpoint::XPCEndpoint):

  • Source/WebKit/Shared/Cocoa/XPCEndpointClient.mm:

(WebKit::XPCEndpointClient::setEndpoint):

  • Source/WebKit/Shared/Daemon/DaemonUtilities.h:
  • Source/WebKit/Shared/Daemon/DaemonUtilities.mm:

(WebKit::startListeningForMachServiceConnections):

  • Source/WebKit/Shared/Databases/IndexedDB/IDBUtilities.cpp:

(WebKit::uniqueDatabaseIdentifier):

  • Source/WebKit/Shared/EntryPointUtilities/Cocoa/Daemon/PCMDaemonEntryPoint.mm:

(WebKit::PCMDaemonMain):

  • Source/WebKit/Shared/EntryPointUtilities/Cocoa/XPCService/XPCServiceEntryPoint.h:
  • Source/WebKit/Shared/EntryPointUtilities/Cocoa/XPCService/XPCServiceEntryPoint.mm:

(WebKit::XPCServiceInitializerDelegate::checkEntitlements):
(WebKit::XPCServiceInitializerDelegate::hasEntitlement):

  • Source/WebKit/Shared/IPCTester.cpp:

(WebKit::messageTestDriver):

  • Source/WebKit/Shared/WebPreferencesDefaultValues.cpp:

(WebKit::defaultMediaSessionCoordinatorEnabled):

  • Source/WebKit/Shared/glib/InputMethodState.cpp:

(WebKit::inputElementHasDigitsPattern):

  • Source/WebKit/Shared/ios/WebIOSEventFactory.mm:

(WebIOSEventFactory::createWebKeyboardEvent):

  • Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:

(WebKit::tryApplyCachedSandbox):
(WebKit::AuxiliaryProcess::initializeSandbox):

  • Source/WebKit/UIProcess/API/C/WKMockMediaDevice.cpp:

(WKAddMockMediaDevice):

  • Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView _setupPageConfiguration:]):

  • Source/WebKit/UIProcess/API/Cocoa/WKWebpagePreferences.mm:

(-[WKWebpagePreferences _setCaptivePortalModeEnabled:]):

  • Source/WebKit/UIProcess/API/Cocoa/_WKSystemPreferences.mm:

(+[_WKSystemPreferences isCaptivePortalModeEnabled]):
(+[_WKSystemPreferences setCaptivePortalModeEnabled:]):

  • Source/WebKit/UIProcess/API/Cocoa/_WKSystemPreferencesInternal.h:
  • Source/WebKit/UIProcess/API/glib/WebKitAutomationSession.cpp:

(parseProxyCapabilities):

  • Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp:

(addOriginToMap):

  • Source/WebKit/UIProcess/API/gtk/DropTargetGtk4.cpp:

(WebKit::DropTarget::accept):

  • Source/WebKit/UIProcess/ApplicationStateTracker.mm:

(WebKit::applicationType):

  • Source/WebKit/UIProcess/Cocoa/MediaPermissionUtilities.mm:

(WebKit::applicationVisibleNameFromOrigin):

  • Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm:

(WebKit::WebViewImpl::collectKeyboardLayoutCommandsForEvent):

  • Source/WebKit/UIProcess/Downloads/DownloadProxyMap.cpp:

(WebKit::DownloadProxyMap::DownloadProxyMap):

  • Source/WebKit/UIProcess/Inspector/glib/RemoteInspectorClient.cpp:

(WebKit::debuggableType):

  • Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp:

(WebKit::ProcessLauncher::launchProcess):

  • Source/WebKit/UIProcess/WebFrameProxy.cpp:

(WebKit::WebFrameProxy::isDisplayingMarkupDocument const):

  • Source/WebKit/UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::requestAttachmentIcon):

  • Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm:

(WebKit::WebsiteDataStore::networkProcessHasEntitlementForTesting):

  • Source/WebKit/UIProcess/WebsiteData/WebsiteDataRecord.cpp:

(WebKit::WebsiteDataRecord::displayNameForCookieHostName):
(WebKit::WebsiteDataRecord::displayNameForOrigin):

  • Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreWayland.cpp:

(WebKit::isEGLImageAvailable):

  • Source/WebKit/UIProcess/gtk/Clipboard.cpp:

(WebKit::Clipboard::get):

  • Source/WebKit/UIProcess/gtk/WebDataListSuggestionsDropdownGtk.cpp:

(WebKit::WebDataListSuggestionsDropdownGtk::handleKeydownWithIdentifier):

  • Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp:

(WebKit::WebDateTimePickerGtk::update):

  • Source/WebKit/UIProcess/ios/WKActionSheetAssistant.mm:

(applicationHasAppLinkEntitlements):

  • Source/WebKit/UIProcess/ios/WKPDFView.mm:

(+[WKPDFView web_requiresCustomSnapshotting]):

  • Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm:

(WebKit::WebContextMenuProxyMac::setupServicesMenu):

  • Source/WebKit/UIProcess/mac/WebDataListSuggestionsDropdownMac.mm:

(WebKit::WebDataListSuggestionsDropdownMac::handleKeydownWithIdentifier):
(-[WKDataListSuggestionsController moveSelectionByDirection:]):

  • Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.cpp:

(WebKit::evaluateJavaScriptCallback):

  • Source/WebKit/WebProcess/InjectedBundle/API/glib/WebKitWebPage.cpp:

(webkitWebPageDidReceiveMessage):

  • Source/WebKit/WebProcess/Plugins/PDF/PDFPluginPasswordField.mm:

(WebKit::PDFPluginPasswordField::handleEvent):

  • Source/WebKit/WebProcess/Plugins/PDF/PDFPluginTextAnnotation.mm:

(WebKit::PDFPluginTextAnnotation::handleEvent):

  • Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp:

(WebKit::getActionTypeForKeyEvent):

  • Source/WebKit/WebProcess/WebPage/Cocoa/TextCheckingControllerProxy.mm:

(WebKit::TextCheckingControllerProxy::removeAnnotationRelativeToSelection):

  • Source/WebKit/WebProcess/WebPage/IPCTestingAPI.cpp:

(WebKit::IPCTestingAPI::encodeArgument):

  • Source/WebKit/WebProcess/WebPage/WebFrame.cpp:

(WebKit::WebFrame::setTextDirection):

  • Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:

(WebKit::WebPage::parentProcessHasServiceWorkerEntitlement const):
(WebKit::WebPage::focusedElementInformation):
(WebKit::WebPage::platformUserAgent const):

  • Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm:

(WebKit::WebPage::executeKeypressCommandsInternal):
(WebKit::WebPage::handleEditingKeyboardEvent):
(WebKit::WebPage::performNonEditingBehaviorForSelector):

  • Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm:

(WebKit::WebProcess::platformInitializeProcess):
(WebKit::WebProcess::handlePreferenceChange):

  • Source/WebKit/webpushd/PushClientConnection.h:
  • Source/WebKit/webpushd/PushClientConnection.mm:

(WebPushD::ClientConnection::hostHasEntitlement):

  • Source/WebKitLegacy/cf/WebCoreSupport/WebInspectorClientCF.cpp:

(WebInspectorClient::inspectorAttachDisabled):
(WebInspectorClient::inspectorStartsAttached):

  • Source/WebKitLegacy/mac/Plugins/WebBasePluginPackage.mm:

(-[WebBasePluginPackage isQuickTimePlugIn]):

  • Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.mm:

(selectorForKeyEvent):

  • Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.mm:

(WebFrameLoaderClient::transitionToCommittedForNewPage):

  • Source/WebKitLegacy/mac/WebView/WebHTMLView.mm:

(-[WebHTMLView _executeSavedKeypressCommands]):

  • Source/WebKitLegacy/win/WebFrame.cpp:

(WebFrame::setTextDirection):
(WebFrame::canProvideDocumentSource):

  • Tools/DumpRenderTree/win/DumpRenderTree.cpp:

(runTest):

  • Tools/TestWebKitAPI/Tests/WTF/AtomString.cpp:

(TestWebKitAPI::TEST):

  • Tools/TestWebKitAPI/Tests/WTF/JSONValue.cpp:

(TestWebKitAPI::TEST):

  • Tools/TestWebKitAPI/Tests/WTF/Vector.cpp:

(TestWebKitAPI::TEST):

  • Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp:

(TestWebKitAPI::TEST):

  • Tools/TestWebKitAPI/Tests/WTF/cocoa/TextStreamCocoa.cpp:

(TEST):

  • Tools/TestWebKitAPI/Tests/WTF/cocoa/TextStreamCocoa.mm:

(TEST):

  • Tools/TestWebKitAPI/Tests/WebCore/CBORReaderTest.cpp:

(TestWebKitAPI::TEST):

  • Tools/TestWebKitAPI/Tests/WebCore/CBORValueTest.cpp:

(TestWebKitAPI::TEST):

  • Tools/TestWebKitAPI/Tests/WebCore/ColorTests.cpp:

(TestWebKitAPI::TEST):

  • Tools/TestWebKitAPI/Tests/WebCore/FontShadowTests.cpp:

(TestWebKitAPI::TEST_F):

  • Tools/TestWebKitAPI/Tests/WebCore/LineBreaking.mm:

(breakingLocationsFromICU):

  • Tools/TestWebKitAPI/Tests/WebCore/NowPlayingInfoTests.cpp:

(TestWebKitAPI::TEST):

  • Tools/TestWebKitAPI/Tests/WebCore/PrivateClickMeasurement.cpp:

(TestWebKitAPI::TEST):

  • Tools/TestWebKitAPI/Tests/WebCore/SecurityOrigin.cpp:

(TestWebKitAPI::TEST_F):

  • Tools/TestWebKitAPI/Tests/WebCore/SharedBuffer.cpp:

(TestWebKitAPI::TEST_F):

  • Tools/TestWebKitAPI/Tests/WebCore/StringWithDirection.cpp:

(TestWebKitAPI::TEST):

  • Tools/TestWebKitAPI/Tests/WebKit/MediaSessionCoordinatorTest.mm:

(TestWebKitAPI::TEST_F):

  • Tools/TestWebKitAPI/Tests/WebKit/OverrideAppleLanguagesPreference.mm:

(TEST_F):

  • Tools/TestWebKitAPI/Tests/WebKitCocoa/CookiePrivateBrowsing.mm:

(TEST):

  • Tools/TestWebKitAPI/Tests/WebKitCocoa/MediaLoading.mm:

(TestWebKitAPI::TEST):

  • Tools/TestWebKitAPI/Tests/WebKitCocoa/ResourceLoadStatistics.mm:

(TEST):

  • Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm:

(-[SyncScheme webView:startURLSchemeTask:]):

  • Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:

(WTR::dumpErrorDescriptionSuitableForTestResult):

  • Tools/WebKitTestRunner/InjectedBundle/atspi/AccessibilityUIElementAtspi.cpp:

(WTR::attributesOfElement):
(WTR::AccessibilityUIElement::stringAttributeValue):
(WTR::AccessibilityUIElement::numberAttributeValue):
(WTR::AccessibilityUIElement::boolAttributeValue):
(WTR::AccessibilityUIElement::isAttributeSettable):
(WTR::AccessibilityUIElement::isAttributeSupported):
(WTR::AccessibilityUIElement::isPressActionSupported):

  • Tools/WebKitTestRunner/TestController.cpp:

(WTR::TestController::setPluginSupportedMode):

  • Tools/WebKitTestRunner/cocoa/CrashReporterInfo.mm:

(WTR::testPathFromURL):

  • Tools/WebKitTestRunner/cocoa/UIScriptControllerCocoa.mm:

(WTR::UIScriptControllerCocoa::overridePreference):

  • Tools/WebKitTestRunner/gtk/UIScriptControllerGtk.cpp:

(WTR::UIScriptControllerGtk::overridePreference):

Canonical link: https://commits.webkit.org/251316@main

  • Property svn:eol-style set to native
File size: 180.4 KB
Line 
1/*
2 * Copyright (C) 2006-2021 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
5 * Copyright (C) 2008 Alp Toker <[email protected]>
6 * Copyright (C) Research In Motion Limited 2009. All rights reserved.
7 * Copyright (C) 2011 Kris Jordan <[email protected]>
8 * Copyright (C) 2011 Google Inc. All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
20 * its contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include "config.h"
36#include "FrameLoader.h"
37
38#include "AXObjectCache.h"
39#include "ApplicationCacheHost.h"
40#include "BackForwardCache.h"
41#include "BackForwardController.h"
42#include "BeforeUnloadEvent.h"
43#include "CachePolicy.h"
44#include "CachedPage.h"
45#include "CachedResourceLoader.h"
46#include "Chrome.h"
47#include "ChromeClient.h"
48#include "CommonVM.h"
49#include "ContentFilter.h"
50#include "ContentRuleListResults.h"
51#include "ContentSecurityPolicy.h"
52#include "CrossOriginAccessControl.h"
53#include "CrossOriginEmbedderPolicy.h"
54#include "DOMWindow.h"
55#include "DatabaseManager.h"
56#include "DiagnosticLoggingClient.h"
57#include "DiagnosticLoggingKeys.h"
58#include "DocumentInlines.h"
59#include "DocumentLoader.h"
60#include "Editor.h"
61#include "EditorClient.h"
62#include "ElementInlines.h"
63#include "Event.h"
64#include "EventHandler.h"
65#include "EventNames.h"
66#include "FloatRect.h"
67#include "FormState.h"
68#include "FormSubmission.h"
69#include "Frame.h"
70#include "FrameLoadRequest.h"
71#include "FrameLoaderClient.h"
72#include "FrameNetworkingContext.h"
73#include "FrameTree.h"
74#include "FrameView.h"
75#include "GCController.h"
76#include "HTMLFormElement.h"
77#include "HTMLInputElement.h"
78#include "HTMLNames.h"
79#include "HTMLObjectElement.h"
80#include "HTMLParserIdioms.h"
81#include "HTTPHeaderNames.h"
82#include "HTTPHeaderValues.h"
83#include "HTTPParsers.h"
84#include "HistoryController.h"
85#include "HistoryItem.h"
86#include "IgnoreOpensDuringUnloadCountIncrementer.h"
87#include "InspectorController.h"
88#include "InspectorInstrumentation.h"
89#include "LinkLoader.h"
90#include "LoaderStrategy.h"
91#include "Logging.h"
92#include "MemoryCache.h"
93#include "MemoryRelease.h"
94#include "NavigationDisabler.h"
95#include "NavigationScheduler.h"
96#include "Node.h"
97#include "Page.h"
98#include "PageTransitionEvent.h"
99#include "Performance.h"
100#include "PerformanceLogging.h"
101#include "PlatformStrategies.h"
102#include "PluginData.h"
103#include "PluginDocument.h"
104#include "PolicyChecker.h"
105#include "ProgressTracker.h"
106#include "ResourceHandle.h"
107#include "ResourceLoadInfo.h"
108#include "ResourceLoadObserver.h"
109#include "ResourceRequest.h"
110#include "SVGLocatable.h"
111#include "SVGNames.h"
112#include "SVGViewElement.h"
113#include "SVGViewSpec.h"
114#include "ScriptController.h"
115#include "ScriptSourceCode.h"
116#include "ScrollAnimator.h"
117#include "SecurityOrigin.h"
118#include "SecurityPolicy.h"
119#include "SegmentedString.h"
120#include "SerializedScriptValue.h"
121#include "Settings.h"
122#include "ShouldTreatAsContinuingLoad.h"
123#include "StyleTreeResolver.h"
124#include "SubframeLoader.h"
125#include "SubresourceLoader.h"
126#include "TextResourceDecoder.h"
127#include "UserContentController.h"
128#include "UserGestureIndicator.h"
129#include "WindowFeatures.h"
130#include "XMLDocumentParser.h"
131#include <dom/ScriptDisallowedScope.h>
132#include <wtf/CompletionHandler.h>
133#include <wtf/URL.h>
134#include <wtf/Ref.h>
135#include <wtf/SetForScope.h>
136#include <wtf/StdLibExtras.h>
137#include <wtf/SystemTracing.h>
138#include <wtf/text/CString.h>
139#include <wtf/text/WTFString.h>
140
141#if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
142#include "Archive.h"
143#endif
144
145#if ENABLE(DATA_DETECTION)
146#include "DataDetection.h"
147#include "DataDetectionResultsStorage.h"
148#endif
149
150#if PLATFORM(IOS_FAMILY)
151#include "DocumentType.h"
152#include "ResourceLoader.h"
153#include "RuntimeApplicationChecks.h"
154#endif
155
156#define PAGE_ID (valueOrDefault(pageID()).toUInt64())
157#define FRAME_ID (valueOrDefault(frameID()).toUInt64())
158#define FRAMELOADER_RELEASE_LOG(channel, fmt, ...) RELEASE_LOG(channel, "%p - [pageID=%" PRIu64 ", frameID=%" PRIu64 ", isMainFrame=%d] FrameLoader::" fmt, this, PAGE_ID, FRAME_ID, m_frame.isMainFrame(), ##__VA_ARGS__)
159#define FRAMELOADER_RELEASE_LOG_ERROR(channel, fmt, ...) RELEASE_LOG_ERROR(channel, "%p - [pageID=%" PRIu64 ", frameID=%" PRIu64 ", isMainFrame=%d] FrameLoader::" fmt, this, PAGE_ID, FRAME_ID, m_frame.isMainFrame(), ##__VA_ARGS__)
160
161namespace WebCore {
162
163using namespace HTMLNames;
164using namespace SVGNames;
165
166bool isBackForwardLoadType(FrameLoadType type)
167{
168 switch (type) {
169 case FrameLoadType::Standard:
170 case FrameLoadType::Reload:
171 case FrameLoadType::ReloadFromOrigin:
172 case FrameLoadType::ReloadExpiredOnly:
173 case FrameLoadType::Same:
174 case FrameLoadType::RedirectWithLockedBackForwardList:
175 case FrameLoadType::Replace:
176 return false;
177 case FrameLoadType::Back:
178 case FrameLoadType::Forward:
179 case FrameLoadType::IndexedBackForward:
180 return true;
181 }
182 ASSERT_NOT_REACHED();
183 return false;
184}
185
186bool isReload(FrameLoadType type)
187{
188 switch (type) {
189 case FrameLoadType::Reload:
190 case FrameLoadType::ReloadFromOrigin:
191 case FrameLoadType::ReloadExpiredOnly:
192 return true;
193 case FrameLoadType::Standard:
194 case FrameLoadType::Same:
195 case FrameLoadType::RedirectWithLockedBackForwardList:
196 case FrameLoadType::Replace:
197 case FrameLoadType::Back:
198 case FrameLoadType::Forward:
199 case FrameLoadType::IndexedBackForward:
200 return false;
201 }
202 ASSERT_NOT_REACHED();
203 return false;
204}
205
206// This is not in the FrameLoader class to emphasize that it does not depend on
207// private FrameLoader data, and to avoid increasing the number of public functions
208// with access to private data. Since only this .cpp file needs it, making it
209// non-member lets us exclude it from the header file, thus keeping FrameLoader.h's
210// API simpler.
211//
212static bool isDocumentSandboxed(Frame& frame, SandboxFlags mask)
213{
214 return frame.document() && frame.document()->isSandboxed(mask);
215}
216
217static bool isInVisibleAndActivePage(const Frame& frame)
218{
219 auto* page = frame.page();
220 return page && page->isVisibleAndActive();
221}
222
223class PageLevelForbidScope {
224protected:
225 explicit PageLevelForbidScope(Page* page)
226 : m_page(page)
227 {
228 }
229
230 ~PageLevelForbidScope() = default;
231
232 WeakPtr<Page> m_page;
233};
234
235struct ForbidPromptsScope : public PageLevelForbidScope {
236 explicit ForbidPromptsScope(Page* page)
237 : PageLevelForbidScope(page)
238 {
239 if (m_page)
240 m_page->forbidPrompts();
241 }
242
243 ~ForbidPromptsScope()
244 {
245 if (m_page)
246 m_page->allowPrompts();
247 }
248};
249
250struct ForbidSynchronousLoadsScope : public PageLevelForbidScope {
251 explicit ForbidSynchronousLoadsScope(Page* page)
252 : PageLevelForbidScope(page)
253 {
254 if (m_page)
255 m_page->forbidSynchronousLoads();
256 }
257
258 ~ForbidSynchronousLoadsScope()
259 {
260 if (m_page)
261 m_page->allowSynchronousLoads();
262 }
263};
264
265class FrameLoader::FrameProgressTracker {
266 WTF_MAKE_FAST_ALLOCATED;
267public:
268 explicit FrameProgressTracker(Frame& frame)
269 : m_frame(frame)
270 , m_inProgress(false)
271 {
272 }
273
274 ~FrameProgressTracker()
275 {
276 if (m_inProgress && m_frame.page())
277 m_frame.page()->progress().progressCompleted(m_frame);
278 }
279
280 void progressStarted()
281 {
282 ASSERT(m_frame.page());
283 if (!m_inProgress)
284 m_frame.page()->progress().progressStarted(m_frame);
285 m_inProgress = true;
286 }
287
288 void progressCompleted()
289 {
290 ASSERT(m_inProgress);
291 ASSERT(m_frame.page());
292 m_inProgress = false;
293 m_frame.page()->progress().progressCompleted(m_frame);
294 platformStrategies()->loaderStrategy()->pageLoadCompleted(*m_frame.page());
295 }
296
297private:
298 Frame& m_frame;
299 bool m_inProgress;
300};
301
302FrameLoader::FrameLoader(Frame& frame, UniqueRef<FrameLoaderClient>&& client)
303 : m_frame(frame)
304 , m_client(WTFMove(client))
305 , m_policyChecker(makeUnique<PolicyChecker>(frame))
306 , m_history(makeUnique<HistoryController>(frame))
307 , m_notifier(frame)
308 , m_subframeLoader(makeUnique<SubframeLoader>(frame))
309 , m_state(FrameState::Provisional)
310 , m_loadType(FrameLoadType::Standard)
311 , m_quickRedirectComing(false)
312 , m_sentRedirectNotification(false)
313 , m_inStopAllLoaders(false)
314 , m_isExecutingJavaScriptFormAction(false)
315 , m_didCallImplicitClose(true)
316 , m_wasUnloadEventEmitted(false)
317 , m_isComplete(false)
318 , m_needsClear(false)
319 , m_checkTimer(*this, &FrameLoader::checkTimerFired)
320 , m_shouldCallCheckCompleted(false)
321 , m_shouldCallCheckLoadComplete(false)
322 , m_opener(nullptr)
323 , m_loadingFromCachedPage(false)
324 , m_currentNavigationHasShownBeforeUnloadConfirmPanel(false)
325 , m_loadsSynchronously(false)
326 , m_forcedSandboxFlags(SandboxNone)
327{
328}
329
330FrameLoader::~FrameLoader()
331{
332 setOpener(nullptr);
333 detachFromAllOpenedFrames();
334
335 if (m_networkingContext)
336 m_networkingContext->invalidate();
337}
338
339void FrameLoader::detachFromAllOpenedFrames()
340{
341 for (auto& frame : m_openedFrames)
342 frame.loader().m_opener = nullptr;
343 m_openedFrames.clear();
344}
345
346void FrameLoader::init()
347{
348 // This somewhat odd set of steps gives the frame an initial empty document.
349 setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(URL({ }, emptyString())), SubstituteData()).ptr());
350 setProvisionalDocumentLoader(m_policyDocumentLoader.get());
351 m_provisionalDocumentLoader->startLoadingMainResource();
352
353 Ref<Frame> protect(m_frame);
354 Ref document { *m_frame.document() };
355 document->cancelParsing();
356 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
357
358 m_networkingContext = m_client->createNetworkingContext();
359 m_progressTracker = makeUnique<FrameProgressTracker>(m_frame);
360}
361
362void FrameLoader::initForSynthesizedDocument(const URL&)
363{
364 // FIXME: We need to initialize the document URL to the specified URL. Currently the URL is empty and hence
365 // FrameLoader::checkCompleted() will overwrite the URL of the document to be activeDocumentLoader()->documentURL().
366
367 auto loader = m_client->createDocumentLoader(ResourceRequest(URL({ }, emptyString())), SubstituteData());
368 loader->attachToFrame(m_frame);
369 loader->setResponse(ResourceResponse(URL(), "text/html"_s, 0, String()));
370 loader->setCommitted(true);
371 setDocumentLoader(loader.ptr());
372
373 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
374 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
375 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
376 m_client->transitionToCommittedForNewPage();
377
378 m_didCallImplicitClose = true;
379 m_isComplete = true;
380 m_state = FrameState::Complete;
381 m_needsClear = true;
382
383 m_networkingContext = m_client->createNetworkingContext();
384 m_progressTracker = makeUnique<FrameProgressTracker>(m_frame);
385}
386
387std::optional<PageIdentifier> FrameLoader::pageID() const
388{
389 return client().pageID();
390}
391
392std::optional<FrameIdentifier> FrameLoader::frameID() const
393{
394 return client().frameID();
395}
396
397Frame* FrameLoader::opener()
398{
399 return m_opener.get();
400}
401
402const Frame* FrameLoader::opener() const
403{
404 return m_opener.get();
405}
406
407void FrameLoader::setDefersLoading(bool defers)
408{
409 if (m_documentLoader)
410 m_documentLoader->setDefersLoading(defers);
411 if (m_provisionalDocumentLoader)
412 m_provisionalDocumentLoader->setDefersLoading(defers);
413 if (m_policyDocumentLoader)
414 m_policyDocumentLoader->setDefersLoading(defers);
415 history().setDefersLoading(defers);
416
417 if (!defers) {
418 m_frame.navigationScheduler().startTimer();
419 startCheckCompleteTimer();
420 }
421}
422
423void FrameLoader::checkContentPolicy(const ResourceResponse& response, PolicyCheckIdentifier identifier, ContentPolicyDecisionFunction&& function)
424{
425 if (!activeDocumentLoader()) {
426 // Load was cancelled
427 function(PolicyAction::Ignore, identifier);
428 return;
429 }
430
431 // FIXME: Validate the policy check identifier.
432 client().dispatchDecidePolicyForResponse(response, activeDocumentLoader()->request(), identifier, activeDocumentLoader()->downloadAttribute(), WTFMove(function));
433}
434
435void FrameLoader::changeLocation(const URL& url, const AtomString& passedTarget, Event* triggeringEvent, const ReferrerPolicy& referrerPolicy, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, std::optional<NewFrameOpenerPolicy> openerPolicy, const AtomString& downloadAttribute, const SystemPreviewInfo& systemPreviewInfo, std::optional<PrivateClickMeasurement>&& privateClickMeasurement)
436{
437 auto* frame = lexicalFrameFromCommonVM();
438 auto initiatedByMainFrame = frame && frame->isMainFrame() ? InitiatedByMainFrame::Yes : InitiatedByMainFrame::Unknown;
439
440 NewFrameOpenerPolicy newFrameOpenerPolicy = openerPolicy.value_or(referrerPolicy == ReferrerPolicy::NoReferrer ? NewFrameOpenerPolicy::Suppress : NewFrameOpenerPolicy::Allow);
441 FrameLoadRequest frameLoadRequest(*m_frame.document(), m_frame.document()->securityOrigin(), { url }, passedTarget, initiatedByMainFrame, downloadAttribute, systemPreviewInfo);
442 frameLoadRequest.setNewFrameOpenerPolicy(newFrameOpenerPolicy);
443 frameLoadRequest.setReferrerPolicy(referrerPolicy);
444 frameLoadRequest.setShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicy);
445 frameLoadRequest.disableShouldReplaceDocumentIfJavaScriptURL();
446 changeLocation(WTFMove(frameLoadRequest), triggeringEvent, WTFMove(privateClickMeasurement));
447}
448
449void FrameLoader::changeLocation(FrameLoadRequest&& frameRequest, Event* triggeringEvent, std::optional<PrivateClickMeasurement>&& privateClickMeasurement)
450{
451 FRAMELOADER_RELEASE_LOG(ResourceLoading, "changeLocation: frame load started");
452 ASSERT(frameRequest.resourceRequest().httpMethod() == "GET"_s);
453
454 Ref<Frame> protect(m_frame);
455
456 if (frameRequest.frameName().isEmpty())
457 frameRequest.setFrameName(m_frame.document()->baseTarget());
458
459 m_frame.document()->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(frameRequest.resourceRequest(), ContentSecurityPolicy::InsecureRequestType::Navigation);
460
461 loadFrameRequest(WTFMove(frameRequest), triggeringEvent, { }, WTFMove(privateClickMeasurement));
462}
463
464void FrameLoader::submitForm(Ref<FormSubmission>&& submission)
465{
466 ASSERT(submission->method() == FormSubmission::Method::Post || submission->method() == FormSubmission::Method::Get);
467
468 // FIXME: Find a good spot for these.
469 ASSERT(!submission->state().sourceDocument().frame() || submission->state().sourceDocument().frame() == &m_frame);
470
471 if (!m_frame.page())
472 return;
473
474 if (submission->action().isEmpty())
475 return;
476
477 if (isDocumentSandboxed(m_frame, SandboxForms)) {
478 // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
479 m_frame.document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Blocked form submission to '" + submission->action().stringCenterEllipsizedToLength() + "' because the form's frame is sandboxed and the 'allow-forms' permission is not set.");
480 return;
481 }
482
483 URL formAction = submission->action();
484 if (!m_frame.document()->contentSecurityPolicy()->allowFormAction(formAction))
485 return;
486
487 Frame* targetFrame = findFrameForNavigation(submission->target(), &submission->state().sourceDocument());
488 if (!targetFrame) {
489 if (!DOMWindow::allowPopUp(m_frame) && !UserGestureIndicator::processingUserGesture())
490 return;
491
492 // FIXME: targetFrame can be null for two distinct reasons:
493 // 1. The frame was not found by name, so we should try opening a new window.
494 // 2. The frame was found, but navigating it was not allowed, e.g. by HTML5 sandbox or by origin checks.
495 // Continuing form submission makes no sense in the latter case.
496 // There is a repeat check after timer fires, so this is not a correctness issue.
497
498 targetFrame = &m_frame;
499 } else
500 submission->clearTarget();
501
502 if (!targetFrame->page())
503 return;
504
505 if (m_frame.tree().isDescendantOf(targetFrame))
506 m_submittedFormURL = submission->requestURL();
507
508 submission->setReferrer(outgoingReferrer());
509 submission->setOrigin(SecurityPolicy::generateOriginHeader(m_frame.document()->referrerPolicy(), submission->requestURL(), m_frame.document()->securityOrigin()));
510
511 targetFrame->navigationScheduler().scheduleFormSubmission(WTFMove(submission));
512}
513
514void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy)
515{
516 if (m_frame.document() && m_frame.document()->parser())
517 m_frame.document()->parser()->stopParsing();
518
519 if (unloadEventPolicy != UnloadEventPolicy::None)
520 dispatchUnloadEvents(unloadEventPolicy);
521
522 m_isComplete = true; // to avoid calling completed() in finishedParsing()
523 m_didCallImplicitClose = true; // don't want that one either
524
525 if (m_frame.document() && m_frame.document()->parsing()) {
526 finishedParsing();
527 m_frame.document()->setParsing(false);
528 }
529
530 if (auto* document = m_frame.document()) {
531 // FIXME: Should the DatabaseManager watch for something like ActiveDOMObject::stop() rather than being special-cased here?
532 DatabaseManager::singleton().stopDatabases(*document, nullptr);
533 }
534
535 policyChecker().stopCheck();
536
537 // FIXME: This will cancel redirection timer, which really needs to be restarted when restoring the frame from b/f cache.
538 m_frame.navigationScheduler().cancel();
539}
540
541void FrameLoader::stop()
542{
543 // http://bugs.webkit.org/show_bug.cgi?id=10854
544 // The frame's last ref may be removed and it will be deleted by checkCompleted().
545 Ref<Frame> protect(m_frame);
546
547 if (DocumentParser* parser = m_frame.document()->parser()) {
548 parser->stopParsing();
549 parser->finish();
550 }
551}
552
553void FrameLoader::closeURL()
554{
555 history().saveDocumentState();
556
557 RefPtr<Document> currentDocument = m_frame.document();
558 UnloadEventPolicy unloadEventPolicy;
559 if (m_frame.page() && m_frame.page()->chrome().client().isSVGImageChromeClient()) {
560 // If this is the SVGDocument of an SVGImage, no need to dispatch events or recalcStyle.
561 unloadEventPolicy = UnloadEventPolicy::None;
562 } else {
563 // Should only send the pagehide event here if the current document exists and has not been placed in the back/forward cache.
564 unloadEventPolicy = currentDocument && currentDocument->backForwardCacheState() == Document::NotInBackForwardCache ? UnloadEventPolicy::UnloadAndPageHide : UnloadEventPolicy::UnloadOnly;
565 }
566
567 stopLoading(unloadEventPolicy);
568
569 if (currentDocument)
570 currentDocument->editor().clearUndoRedoOperations();
571}
572
573bool FrameLoader::didOpenURL()
574{
575 if (m_frame.navigationScheduler().redirectScheduledDuringLoad()) {
576 // A redirect was scheduled before the document was created.
577 // This can happen when one frame changes another frame's location.
578 return false;
579 }
580
581 m_frame.navigationScheduler().cancel();
582
583 m_isComplete = false;
584 m_didCallImplicitClose = false;
585
586 // If we are still in the process of initializing an empty document then
587 // its frame is not in a consistent state for rendering, so avoid setJSStatusBarText
588 // since it may cause clients to attempt to render the frame.
589 if (!m_stateMachine.creatingInitialEmptyDocument()) {
590 DOMWindow* window = m_frame.document()->domWindow();
591 window->setStatus(String());
592 window->setDefaultStatus(String());
593 }
594
595 started();
596
597 return true;
598}
599
600void FrameLoader::didExplicitOpen()
601{
602 m_isComplete = false;
603 m_didCallImplicitClose = false;
604
605 // Calling document.open counts as committing the first real document load.
606 if (!m_stateMachine.committedFirstRealDocumentLoad())
607 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
608
609 if (auto* document = m_frame.document())
610 m_client->dispatchDidExplicitOpen(document->url(), document->contentType());
611
612 // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
613 // from a subsequent window.document.open / window.document.write call.
614 // Canceling redirection here works for all cases because document.open
615 // implicitly precedes document.write.
616 m_frame.navigationScheduler().cancel();
617}
618
619static inline bool shouldClearWindowName(const Frame& frame, const Document& newDocument)
620{
621 if (!frame.isMainFrame())
622 return false;
623
624 if (frame.loader().opener())
625 return false;
626
627 return !newDocument.securityOrigin().isSameOriginAs(frame.document()->securityOrigin());
628}
629
630void FrameLoader::clear(RefPtr<Document>&& newDocument, bool clearWindowProperties, bool clearScriptObjects, bool clearFrameView, Function<void()>&& handleDOMWindowCreation)
631{
632 bool neededClear = m_needsClear;
633 m_needsClear = false;
634
635 if (neededClear && m_frame.document()->backForwardCacheState() != Document::InBackForwardCache) {
636 Ref document { *m_frame.document() };
637 document->cancelParsing();
638 document->stopActiveDOMObjects();
639 bool hadLivingRenderTree = document->hasLivingRenderTree();
640 document->willBeRemovedFromFrame();
641 if (hadLivingRenderTree)
642 document->adjustFocusedNodeOnNodeRemoval(document);
643 }
644
645 if (handleDOMWindowCreation)
646 handleDOMWindowCreation();
647
648 if (!neededClear)
649 return;
650
651 // Do this after detaching the document so that the unload event works.
652 if (clearWindowProperties) {
653 InspectorInstrumentation::frameWindowDiscarded(m_frame, m_frame.document()->domWindow());
654 m_frame.document()->domWindow()->resetUnlessSuspendedForDocumentSuspension();
655 m_frame.windowProxy().clearJSWindowProxiesNotMatchingDOMWindow(newDocument->domWindow(), m_frame.document()->backForwardCacheState() == Document::AboutToEnterBackForwardCache);
656
657 if (shouldClearWindowName(m_frame, *newDocument))
658 m_frame.tree().setName(nullAtom());
659 }
660
661 m_frame.eventHandler().clear();
662
663 if (clearFrameView && m_frame.view())
664 m_frame.view()->clear();
665
666 // Do not drop the document before the ScriptController and view are cleared
667 // as some destructors might still try to access the document.
668 m_frame.setDocument(nullptr);
669
670 subframeLoader().clear();
671
672 if (clearWindowProperties)
673 m_frame.windowProxy().setDOMWindow(newDocument->domWindow());
674
675 if (clearScriptObjects)
676 m_frame.script().clearScriptObjects();
677
678 if (newDocument->contentSecurityPolicy()) {
679 bool enableEvalValue = newDocument->contentSecurityPolicy()->evalErrorMessage().isNull();
680 bool enableWASMValue = newDocument->contentSecurityPolicy()->webAssemblyErrorMessage().isNull();
681 m_frame.script().setEvalEnabled(enableEvalValue, newDocument->contentSecurityPolicy()->evalErrorMessage());
682 m_frame.script().setWebAssemblyEnabled(enableWASMValue, newDocument->contentSecurityPolicy()->webAssemblyErrorMessage());
683 }
684
685 m_frame.navigationScheduler().clear();
686
687 m_checkTimer.stop();
688 m_shouldCallCheckCompleted = false;
689 m_shouldCallCheckLoadComplete = false;
690
691 if (m_stateMachine.isDisplayingInitialEmptyDocument() && m_stateMachine.committedFirstRealDocumentLoad())
692 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
693}
694
695void FrameLoader::receivedFirstData()
696{
697 Ref protectedFrame { m_frame };
698
699 dispatchDidCommitLoad(std::nullopt, std::nullopt);
700 dispatchDidClearWindowObjectsInAllWorlds();
701 dispatchGlobalObjectAvailableInAllWorlds();
702
703 if (!m_documentLoader)
704 return;
705
706 auto& documentLoader = *m_documentLoader;
707 auto& title = documentLoader.title();
708 if (!title.string.isNull())
709 m_client->dispatchDidReceiveTitle(title);
710
711 ASSERT(m_frame.document());
712 auto& document = *m_frame.document();
713
714 LinkLoader::loadLinksFromHeader(documentLoader.response().httpHeaderField(HTTPHeaderName::Link), document.url(), document, LinkLoader::MediaAttributeCheck::MediaAttributeEmpty);
715
716 scheduleRefreshIfNeeded(document, documentLoader.response().httpHeaderField(HTTPHeaderName::Refresh), IsMetaRefresh::No);
717}
718
719void FrameLoader::setOutgoingReferrer(const URL& url)
720{
721 m_outgoingReferrer = url.strippedForUseAsReferrer();
722}
723
724static AtomString extractContentLanguageFromHeader(const String& header)
725{
726 auto commaIndex = header.find(',');
727 if (commaIndex == notFound)
728 return AtomString { stripLeadingAndTrailingHTMLSpaces(header) };
729 return StringView(header).left(commaIndex).stripLeadingAndTrailingMatchedCharacters(isHTMLSpace<UChar>).toAtomString();
730}
731
732void FrameLoader::didBeginDocument(bool dispatch)
733{
734 m_needsClear = true;
735 m_isComplete = false;
736 m_didCallImplicitClose = false;
737 m_frame.document()->setReadyState(Document::Loading);
738
739 if (m_pendingStateObject) {
740 m_frame.document()->statePopped(*m_pendingStateObject);
741 m_pendingStateObject = nullptr;
742 }
743
744 if (dispatch)
745 dispatchDidClearWindowObjectsInAllWorlds();
746
747 updateFirstPartyForCookies();
748 m_frame.document()->initContentSecurityPolicy();
749
750 const Settings& settings = m_frame.settings();
751 m_frame.document()->cachedResourceLoader().setImagesEnabled(settings.areImagesEnabled());
752 m_frame.document()->cachedResourceLoader().setAutoLoadImages(settings.loadsImagesAutomatically());
753
754 if (m_documentLoader) {
755 String dnsPrefetchControl = m_documentLoader->response().httpHeaderField(HTTPHeaderName::XDNSPrefetchControl);
756 if (!dnsPrefetchControl.isEmpty())
757 m_frame.document()->parseDNSPrefetchControlHeader(dnsPrefetchControl);
758
759 // The DocumentLoader may have already parsed the CSP header to do some checks. If so, reuse the already parsed version instead of parsing again.
760 if (auto* contentSecurityPolicy = m_documentLoader->contentSecurityPolicy())
761 m_frame.document()->contentSecurityPolicy()->didReceiveHeaders(*contentSecurityPolicy, ContentSecurityPolicy::ReportParsingErrors::No);
762 else
763 m_frame.document()->contentSecurityPolicy()->didReceiveHeaders(ContentSecurityPolicyResponseHeaders(m_documentLoader->response()), referrer(), ContentSecurityPolicy::ReportParsingErrors::No);
764
765 if (m_frame.document()->url().protocolIsInHTTPFamily() || m_frame.document()->url().protocolIsBlob())
766 m_frame.document()->setCrossOriginEmbedderPolicy(obtainCrossOriginEmbedderPolicy(m_documentLoader->response(), m_frame.document()));
767
768 String referrerPolicy = m_documentLoader->response().httpHeaderField(HTTPHeaderName::ReferrerPolicy);
769 if (!referrerPolicy.isNull())
770 m_frame.document()->processReferrerPolicy(referrerPolicy, ReferrerPolicySource::HTTPHeader);
771
772 String headerContentLanguage = m_documentLoader->response().httpHeaderField(HTTPHeaderName::ContentLanguage);
773 if (!headerContentLanguage.isEmpty()) {
774 auto contentLanguage = extractContentLanguageFromHeader(headerContentLanguage);
775 if (!contentLanguage.isEmpty())
776 m_frame.document()->setContentLanguage(WTFMove(contentLanguage));
777 }
778
779 // https://html.spec.whatwg.org/multipage/browsing-the-web.html#initialise-the-document-object (Step 7)
780 if (m_frame.isMainFrame()) {
781 if (auto crossOriginOpenerPolicy = m_documentLoader->crossOriginOpenerPolicy())
782 m_frame.document()->setCrossOriginOpenerPolicy(WTFMove(*crossOriginOpenerPolicy));
783 }
784 }
785
786 history().restoreDocumentState();
787}
788
789void FrameLoader::finishedParsing()
790{
791 LOG(Loading, "WebCoreLoading %s: Finished parsing", m_frame.tree().uniqueName().string().utf8().data());
792
793 m_frame.injectUserScripts(UserScriptInjectionTime::DocumentEnd);
794
795 if (m_stateMachine.creatingInitialEmptyDocument())
796 return;
797
798 // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves
799 // because doing so will cause us to re-enter the destructor when protector goes out of scope.
800 // Null-checking the FrameView indicates whether or not we're in the destructor.
801 RefPtr<Frame> protector = m_frame.view() ? &m_frame : 0;
802
803 m_client->dispatchDidFinishDocumentLoad();
804
805 scrollToFragmentWithParentBoundary(m_frame.document()->url());
806
807 checkCompleted();
808
809 if (!m_frame.view())
810 return; // We are being destroyed by something checkCompleted called.
811
812 // Check if the scrollbars are really needed for the content.
813 // If not, remove them, relayout, and repaint.
814 m_frame.view()->restoreScrollbar();
815}
816
817void FrameLoader::loadDone(LoadCompletionType type)
818{
819 if (type == LoadCompletionType::Finish)
820 checkCompleted();
821 else
822 scheduleCheckCompleted();
823}
824
825void FrameLoader::subresourceLoadDone(LoadCompletionType type)
826{
827 if (type == LoadCompletionType::Finish)
828 checkLoadComplete();
829 else
830 scheduleCheckLoadComplete();
831}
832
833bool FrameLoader::preventsParentFromBeingComplete(const Frame& frame) const
834{
835 return !frame.loader().m_isComplete && (!frame.ownerElement() || !frame.ownerElement()->isLazyLoadObserverActive());
836}
837
838bool FrameLoader::allChildrenAreComplete() const
839{
840 for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling()) {
841 if (preventsParentFromBeingComplete(*child))
842 return false;
843 }
844 return true;
845}
846
847bool FrameLoader::allAncestorsAreComplete() const
848{
849 for (Frame* ancestor = &m_frame; ancestor; ancestor = ancestor->tree().parent()) {
850 if (!ancestor->loader().m_isComplete)
851 return false;
852 }
853 return true;
854}
855
856void FrameLoader::checkCompleted()
857{
858 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed());
859 m_shouldCallCheckCompleted = false;
860
861 // Have we completed before?
862 if (m_isComplete)
863 return;
864
865 // FIXME: It would be better if resource loads were kicked off after render tree update (or didn't complete synchronously).
866 // https://bugs.webkit.org/show_bug.cgi?id=171729
867 if (m_frame.document()->inRenderTreeUpdate()) {
868 scheduleCheckCompleted();
869 return;
870 }
871
872 // Are we still parsing?
873 if (m_frame.document()->parsing())
874 return;
875
876 // Still waiting for images/scripts?
877 if (m_frame.document()->cachedResourceLoader().requestCount())
878 return;
879
880 // Still waiting for elements that don't go through a FrameLoader?
881 if (m_frame.document()->isDelayingLoadEvent())
882 return;
883
884 auto* scriptableParser = m_frame.document()->scriptableDocumentParser();
885 if (scriptableParser && scriptableParser->hasScriptsWaitingForStylesheets())
886 return;
887
888 // Any frame that hasn't completed yet?
889 if (!allChildrenAreComplete())
890 return;
891
892 // Important not to protect earlier in this function, because earlier parts
893 // of this function can be called in the frame's destructor, and it's not legal
894 // to ref an object while it's being destroyed.
895 Ref<Frame> protect(m_frame);
896
897 // OK, completed.
898 m_isComplete = true;
899 m_requestedHistoryItem = nullptr;
900 m_frame.document()->setReadyState(Document::Complete);
901
902 checkCallImplicitClose(); // if we didn't do it before
903
904 m_frame.navigationScheduler().startTimer();
905
906 completed();
907 if (m_frame.page())
908 checkLoadComplete();
909}
910
911void FrameLoader::checkTimerFired()
912{
913 checkCompletenessNow();
914}
915
916void FrameLoader::checkCompletenessNow()
917{
918 Ref<Frame> protect(m_frame);
919
920 if (Page* page = m_frame.page()) {
921 if (page->defersLoading())
922 return;
923 }
924 if (m_shouldCallCheckCompleted)
925 checkCompleted();
926 if (m_shouldCallCheckLoadComplete)
927 checkLoadComplete();
928}
929
930void FrameLoader::startCheckCompleteTimer()
931{
932 if (!(m_shouldCallCheckCompleted || m_shouldCallCheckLoadComplete))
933 return;
934 if (m_checkTimer.isActive())
935 return;
936 m_checkTimer.startOneShot(0_s);
937}
938
939void FrameLoader::scheduleCheckCompleted()
940{
941 m_shouldCallCheckCompleted = true;
942 startCheckCompleteTimer();
943}
944
945void FrameLoader::scheduleCheckLoadComplete()
946{
947 m_shouldCallCheckLoadComplete = true;
948 startCheckCompleteTimer();
949}
950
951void FrameLoader::checkCallImplicitClose()
952{
953 if (m_didCallImplicitClose || m_frame.document()->parsing() || m_frame.document()->isDelayingLoadEvent())
954 return;
955
956 if (!allChildrenAreComplete())
957 return; // still got a frame running -> too early
958
959 m_didCallImplicitClose = true;
960 m_wasUnloadEventEmitted = false;
961 m_frame.document()->implicitClose();
962}
963
964void FrameLoader::loadURLIntoChildFrame(const URL& url, const String& referer, Frame* childFrame)
965{
966 FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadURLIntoChildFrame: frame load started");
967
968 ASSERT(childFrame);
969
970#if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
971 if (auto activeLoader = activeDocumentLoader()) {
972 if (auto subframeArchive = activeLoader->popArchiveForSubframe(childFrame->tree().uniqueName(), url)) {
973 childFrame->loader().loadArchive(RefPtr<Archive> { subframeArchive }.releaseNonNull());
974 return;
975 }
976 }
977#endif
978
979 // If we're moving in the back/forward list, we might want to replace the content
980 // of this child frame with whatever was there at that point.
981 auto* parentItem = history().currentItem();
982 if (parentItem && parentItem->children().size() && isBackForwardLoadType(loadType()) && !m_frame.document()->loadEventFinished()) {
983 if (auto* childItem = parentItem->childItemWithTarget(childFrame->tree().uniqueName())) {
984 childFrame->loader().m_requestedHistoryItem = childItem;
985 childFrame->loader().loadDifferentDocumentItem(*childItem, nullptr, loadType(), MayAttemptCacheOnlyLoadForFormSubmissionItem, ShouldTreatAsContinuingLoad::No);
986 return;
987 }
988 }
989
990 auto* lexicalFrame = lexicalFrameFromCommonVM();
991 auto initiatedByMainFrame = lexicalFrame && lexicalFrame->isMainFrame() ? InitiatedByMainFrame::Yes : InitiatedByMainFrame::Unknown;
992
993 FrameLoadRequest frameLoadRequest { *m_frame.document(), m_frame.document()->securityOrigin(), { url }, selfTargetFrameName(), initiatedByMainFrame };
994 frameLoadRequest.setNewFrameOpenerPolicy(NewFrameOpenerPolicy::Suppress);
995 frameLoadRequest.setLockBackForwardList(LockBackForwardList::Yes);
996 childFrame->loader().loadURL(WTFMove(frameLoadRequest), referer, FrameLoadType::RedirectWithLockedBackForwardList, nullptr, { }, std::nullopt, [] { });
997}
998
999#if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
1000
1001void FrameLoader::loadArchive(Ref<Archive>&& archive)
1002{
1003 FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadArchive: frame load started");
1004
1005 ArchiveResource* mainResource = archive->mainResource();
1006 ASSERT(mainResource);
1007 if (!mainResource)
1008 return;
1009
1010 ResourceResponse response(URL(), mainResource->mimeType(), mainResource->data().size(), mainResource->textEncoding());
1011 SubstituteData substituteData(&mainResource->data(), URL(), response, SubstituteData::SessionHistoryVisibility::Hidden);
1012
1013 ResourceRequest request(mainResource->url());
1014
1015 auto documentLoader = m_client->createDocumentLoader(request, substituteData);
1016 documentLoader->setArchive(WTFMove(archive));
1017 load(documentLoader.get());
1018}
1019
1020#endif // ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
1021
1022String FrameLoader::outgoingReferrer() const
1023{
1024 // See http://www.whatwg.org/specs/web-apps/current-work/#fetching-resources
1025 // for why we walk the parent chain for srcdoc documents.
1026 Frame* frame = &m_frame;
1027 while (frame && frame->document()->isSrcdocDocument()) {
1028 frame = frame->tree().parent();
1029 // Srcdoc documents cannot be top-level documents, by definition,
1030 // because they need to be contained in iframes with the srcdoc.
1031 ASSERT(frame);
1032 }
1033 if (!frame)
1034 return emptyString();
1035 return frame->loader().m_outgoingReferrer;
1036}
1037
1038String FrameLoader::outgoingOrigin() const
1039{
1040 return m_frame.document()->securityOrigin().toString();
1041}
1042
1043bool FrameLoader::checkIfFormActionAllowedByCSP(const URL& url, bool didReceiveRedirectResponse, const URL& preRedirectURL) const
1044{
1045 if (m_submittedFormURL.isEmpty())
1046 return true;
1047
1048 auto redirectResponseReceived = didReceiveRedirectResponse ? ContentSecurityPolicy::RedirectResponseReceived::Yes : ContentSecurityPolicy::RedirectResponseReceived::No;
1049 return m_frame.document()->contentSecurityPolicy()->allowFormAction(url, redirectResponseReceived, preRedirectURL);
1050}
1051
1052void FrameLoader::setOpener(Frame* opener)
1053{
1054 if (m_opener && !opener)
1055 m_client->didDisownOpener();
1056
1057 if (m_opener) {
1058 // When setOpener is called in ~FrameLoader, opener's m_frameLoader is already cleared.
1059 auto& openerFrameLoader = m_opener == &m_frame ? *this : m_opener->loader();
1060 openerFrameLoader.m_openedFrames.remove(m_frame);
1061 }
1062 if (opener) {
1063 opener->loader().m_openedFrames.add(m_frame);
1064 if (auto* page = m_frame.page())
1065 page->setOpenedByDOMWithOpener(true);
1066 }
1067 m_opener = opener;
1068
1069 if (m_frame.document())
1070 m_frame.document()->initSecurityContext();
1071}
1072
1073void FrameLoader::provisionalLoadStarted()
1074{
1075 if (m_stateMachine.firstLayoutDone())
1076 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
1077 m_frame.navigationScheduler().cancel(NewLoadInProgress::Yes);
1078 m_client->provisionalLoadStarted();
1079
1080 if (m_frame.isMainFrame()) {
1081 tracePoint(MainResourceLoadDidStartProvisional, PAGE_ID);
1082
1083 if (auto* page = m_frame.page())
1084 page->didStartProvisionalLoad();
1085 }
1086}
1087
1088void FrameLoader::resetMultipleFormSubmissionProtection()
1089{
1090 m_submittedFormURL = URL();
1091}
1092
1093void FrameLoader::updateFirstPartyForCookies()
1094{
1095 if (m_frame.tree().parent())
1096 setFirstPartyForCookies(m_frame.tree().parent()->document()->firstPartyForCookies());
1097 else
1098 setFirstPartyForCookies(m_frame.document()->url());
1099}
1100
1101void FrameLoader::setFirstPartyForCookies(const URL& url)
1102{
1103 for (Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext(&m_frame))
1104 frame->document()->setFirstPartyForCookies(url);
1105
1106 RegistrableDomain registrableDomain(url);
1107 for (Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext(&m_frame)) {
1108 if (SecurityPolicy::shouldInheritSecurityOriginFromOwner(frame->document()->url()) || registrableDomain.matches(frame->document()->url()))
1109 frame->document()->setSiteForCookies(url);
1110 }
1111}
1112
1113// This does the same kind of work that didOpenURL does, except it relies on the fact
1114// that a higher level already checked that the URLs match and the scrolling is the right thing to do.
1115void FrameLoader::loadInSameDocument(URL url, RefPtr<SerializedScriptValue> stateObject, bool isNewNavigation)
1116{
1117 FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadInSameDocument: frame load started");
1118
1119 // If we have a state object, we cannot also be a new navigation.
1120 ASSERT(!stateObject || (stateObject && !isNewNavigation));
1121
1122 // Update the data source's request with the new URL to fake the URL change
1123 URL oldURL = m_frame.document()->url();
1124 m_frame.document()->setURL(url);
1125 setOutgoingReferrer(url);
1126 documentLoader()->replaceRequestURLForSameDocumentNavigation(url);
1127 if (isNewNavigation && !shouldTreatURLAsSameAsCurrent(url) && !stateObject) {
1128 // NB: must happen after replaceRequestURLForSameDocumentNavigation(), since we add
1129 // based on the current request. Must also happen before we openURL and displace the
1130 // scroll position, since adding the BF item will save away scroll state.
1131
1132 // NB2: If we were loading a long, slow doc, and the user fragment navigated before
1133 // it was done, currItem is now set the that slow doc, and prevItem is whatever was
1134 // before it. Adding the b/f item will bump the slow doc down to prevItem, even
1135 // though its load is not yet done. I think this all works out OK, for one because
1136 // we have already saved away the scroll and doc state for the long slow load,
1137 // but it's not an obvious case.
1138
1139 history().updateBackForwardListForFragmentScroll();
1140 }
1141
1142 bool hashChange = equalIgnoringFragmentIdentifier(url, oldURL) && !equalRespectingNullity(url.fragmentIdentifier(), oldURL.fragmentIdentifier());
1143
1144 history().updateForSameDocumentNavigation();
1145
1146 // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor
1147 if (hashChange)
1148 m_frame.eventHandler().stopAutoscrollTimer();
1149
1150 // It's important to model this as a load that starts and immediately finishes.
1151 // Otherwise, the parent frame may think we never finished loading.
1152 started();
1153
1154 if (auto* ownerElement = m_frame.ownerElement()) {
1155 auto* ownerRenderer = ownerElement->renderer();
1156 auto* view = m_frame.view();
1157 if (is<RenderWidget>(ownerRenderer) && view)
1158 downcast<RenderWidget>(*ownerRenderer).setWidget(view);
1159 }
1160
1161 // We need to scroll to the fragment whether or not a hash change occurred, since
1162 // the user might have scrolled since the previous navigation.
1163 scrollToFragmentWithParentBoundary(url, isNewNavigation);
1164
1165 m_isComplete = false;
1166 checkCompleted();
1167
1168 if (isNewNavigation) {
1169 // This will clear previousItem from the rest of the frame tree that didn't
1170 // doing any loading. We need to make a pass on this now, since for fragment
1171 // navigation we'll not go through a real load and reach Completed state.
1172 checkLoadComplete();
1173 }
1174
1175 m_client->dispatchDidNavigateWithinPage();
1176
1177 m_frame.document()->statePopped(stateObject ? stateObject.releaseNonNull() : SerializedScriptValue::nullValue());
1178 m_client->dispatchDidPopStateWithinPage();
1179
1180 if (hashChange) {
1181 m_frame.document()->enqueueHashchangeEvent(oldURL.string(), url.string());
1182 m_client->dispatchDidChangeLocationWithinPage();
1183 }
1184
1185 // FrameLoaderClient::didFinishLoad() tells the internal load delegate the load finished with no error
1186 m_client->didFinishLoad();
1187}
1188
1189bool FrameLoader::isComplete() const
1190{
1191 return m_isComplete;
1192}
1193
1194void FrameLoader::completed()
1195{
1196 Ref<Frame> protect(m_frame);
1197
1198 for (Frame* descendant = m_frame.tree().traverseNext(&m_frame); descendant; descendant = descendant->tree().traverseNext(&m_frame))
1199 descendant->navigationScheduler().startTimer();
1200
1201 if (Frame* parent = m_frame.tree().parent())
1202 parent->loader().checkCompleted();
1203
1204 if (m_frame.view())
1205 m_frame.view()->maintainScrollPositionAtAnchor(nullptr);
1206}
1207
1208void FrameLoader::started()
1209{
1210 for (Frame* frame = &m_frame; frame; frame = frame->tree().parent())
1211 frame->loader().m_isComplete = false;
1212}
1213
1214void FrameLoader::prepareForLoadStart()
1215{
1216 FRAMELOADER_RELEASE_LOG(ResourceLoading, "prepareForLoadStart: Starting frame load");
1217
1218 m_progressTracker->progressStarted();
1219 m_client->dispatchDidStartProvisionalLoad();
1220
1221 if (AXObjectCache::accessibilityEnabled()) {
1222 if (AXObjectCache* cache = m_frame.document()->existingAXObjectCache()) {
1223 AXObjectCache::AXLoadingEvent loadingEvent = loadType() == FrameLoadType::Reload ? AXObjectCache::AXLoadingReloaded : AXObjectCache::AXLoadingStarted;
1224 cache->frameLoadingEventNotification(&m_frame, loadingEvent);
1225 }
1226 }
1227}
1228
1229void FrameLoader::setupForReplace()
1230{
1231 m_client->revertToProvisionalState(m_documentLoader.get());
1232 setState(FrameState::Provisional);
1233 m_provisionalDocumentLoader = m_documentLoader;
1234 FRAMELOADER_RELEASE_LOG(ResourceLoading, "setupForReplace: Setting provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
1235 m_documentLoader = nullptr;
1236 detachChildren();
1237}
1238
1239void FrameLoader::loadFrameRequest(FrameLoadRequest&& request, Event* event, RefPtr<FormState>&& formState, std::optional<PrivateClickMeasurement>&& privateClickMeasurement)
1240{
1241 FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadFrameRequest: frame load started");
1242
1243 // Protect frame from getting blown away inside dispatchBeforeLoadEvent in loadWithDocumentLoader.
1244 Ref protectedFrame { m_frame };
1245
1246 URL url = request.resourceRequest().url();
1247
1248 ASSERT(m_frame.document());
1249 if (!request.requesterSecurityOrigin().canDisplay(url)) {
1250 FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadFrameRequest: canceling - Not allowed to load local resource");
1251 reportLocalLoadFailed(&m_frame, url.stringCenterEllipsizedToLength());
1252 return;
1253 }
1254
1255 if (!portAllowed(url)) {
1256 FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadFrameRequest: canceling - port not allowed");
1257 reportBlockedLoadFailed(m_frame, url);
1258 return;
1259 }
1260
1261 String argsReferrer = request.resourceRequest().httpReferrer();
1262 if (argsReferrer.isEmpty())
1263 argsReferrer = outgoingReferrer();
1264
1265 ReferrerPolicy referrerPolicy = request.referrerPolicy();
1266 if (referrerPolicy == ReferrerPolicy::EmptyString)
1267 referrerPolicy = m_frame.document()->referrerPolicy();
1268 String referrer = SecurityPolicy::generateReferrerHeader(referrerPolicy, url, argsReferrer);
1269
1270 FrameLoadType loadType;
1271 if (request.resourceRequest().cachePolicy() == ResourceRequestCachePolicy::ReloadIgnoringCacheData)
1272 loadType = FrameLoadType::Reload;
1273 else if (request.lockBackForwardList() == LockBackForwardList::Yes)
1274 loadType = FrameLoadType::RedirectWithLockedBackForwardList;
1275 else
1276 loadType = FrameLoadType::Standard;
1277
1278 auto completionHandler = [this, protectedFrame = Ref { m_frame }, formState = WeakPtr { formState }, frameName = request.frameName()] {
1279 // FIXME: It's possible this targetFrame will not be the same frame that was targeted by the actual
1280 // load if frame names have changed.
1281 Frame* sourceFrame = formState ? formState->sourceDocument().frame() : &m_frame;
1282 if (!sourceFrame)
1283 sourceFrame = &m_frame;
1284 Frame* targetFrame = sourceFrame->loader().findFrameForNavigation(frameName);
1285 if (targetFrame && targetFrame != sourceFrame) {
1286 if (auto* page = targetFrame->page(); page && isInVisibleAndActivePage(*sourceFrame))
1287 page->chrome().focus();
1288 }
1289 };
1290
1291 if (request.resourceRequest().httpMethod() == "POST"_s)
1292 loadPostRequest(WTFMove(request), referrer, loadType, event, WTFMove(formState), WTFMove(completionHandler));
1293 else
1294 loadURL(WTFMove(request), referrer, loadType, event, WTFMove(formState), WTFMove(privateClickMeasurement), WTFMove(completionHandler));
1295}
1296
1297static ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicyToApply(Frame& currentFrame, InitiatedByMainFrame initiatedByMainFrame, ShouldOpenExternalURLsPolicy propagatedPolicy)
1298{
1299 if (UserGestureIndicator::processingUserGesture())
1300 return ShouldOpenExternalURLsPolicy::ShouldAllow;
1301
1302 if (initiatedByMainFrame == InitiatedByMainFrame::Yes)
1303 return propagatedPolicy;
1304
1305 if (!currentFrame.isMainFrame())
1306 return ShouldOpenExternalURLsPolicy::ShouldNotAllow;
1307
1308 return propagatedPolicy;
1309}
1310
1311static ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicyToApply(Frame& currentFrame, const FrameLoadRequest& frameLoadRequest)
1312{
1313 return shouldOpenExternalURLsPolicyToApply(currentFrame, frameLoadRequest.initiatedByMainFrame(), frameLoadRequest.shouldOpenExternalURLsPolicy());
1314}
1315
1316static void applyShouldOpenExternalURLsPolicyToNewDocumentLoader(Frame& frame, DocumentLoader& documentLoader, InitiatedByMainFrame initiatedByMainFrame, ShouldOpenExternalURLsPolicy propagatedPolicy)
1317{
1318 documentLoader.setShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(frame, initiatedByMainFrame, propagatedPolicy));
1319}
1320
1321static void applyShouldOpenExternalURLsPolicyToNewDocumentLoader(Frame& frame, DocumentLoader& documentLoader, const FrameLoadRequest& frameLoadRequest)
1322{
1323 documentLoader.setShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(frame, frameLoadRequest));
1324}
1325
1326bool FrameLoader::isNavigationAllowed() const
1327{
1328 return m_pageDismissalEventBeingDispatched == PageDismissalType::None && !m_frame.script().willReplaceWithResultOfExecutingJavascriptURL() && NavigationDisabler::isNavigationAllowed(m_frame);
1329}
1330
1331bool FrameLoader::isStopLoadingAllowed() const
1332{
1333 return m_pageDismissalEventBeingDispatched == PageDismissalType::None;
1334}
1335
1336void FrameLoader::loadURL(FrameLoadRequest&& frameLoadRequest, const String& referrer, FrameLoadType newLoadType, Event* event, RefPtr<FormState>&& formState, std::optional<PrivateClickMeasurement>&& privateClickMeasurement, CompletionHandler<void()>&& completionHandler)
1337{
1338 FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadURL: frame load started");
1339 ASSERT(frameLoadRequest.resourceRequest().httpMethod() == "GET"_s);
1340
1341 CompletionHandlerCallingScope completionHandlerCaller(WTFMove(completionHandler));
1342 if (m_inStopAllLoaders || m_inClearProvisionalLoadForPolicyCheck)
1343 return;
1344
1345 Ref<Frame> protect(m_frame);
1346
1347 // Anchor target is ignored when the download attribute is set since it will download the hyperlink rather than follow it.
1348 auto effectiveFrameName = frameLoadRequest.downloadAttribute().isNull() ? frameLoadRequest.frameName() : nullAtom();
1349 bool isFormSubmission = formState;
1350
1351 // The search for a target frame is done earlier in the case of form submission.
1352 auto targetFrame = isFormSubmission ? nullptr : RefPtr { findFrameForNavigation(effectiveFrameName) };
1353 if (targetFrame && targetFrame != &m_frame) {
1354 frameLoadRequest.setFrameName(selfTargetFrameName());
1355 targetFrame->loader().loadURL(WTFMove(frameLoadRequest), referrer, newLoadType, event, WTFMove(formState), WTFMove(privateClickMeasurement), completionHandlerCaller.release());
1356 return;
1357 }
1358
1359 const URL& newURL = frameLoadRequest.resourceRequest().url();
1360 ResourceRequest request(newURL);
1361 if (!referrer.isEmpty())
1362 request.setHTTPReferrer(referrer);
1363
1364 updateRequestAndAddExtraFields(request, IsMainResource::Yes, newLoadType, ShouldUpdateAppInitiatedValue::Yes, FrameLoader::IsServiceWorkerNavigationLoad::No, &frameLoadRequest.requester());
1365
1366 ASSERT(newLoadType != FrameLoadType::Same);
1367
1368 if (!isNavigationAllowed())
1369 return;
1370
1371 NavigationAction action { frameLoadRequest.requester(), request, frameLoadRequest.initiatedByMainFrame(), newLoadType, isFormSubmission, event, frameLoadRequest.shouldOpenExternalURLsPolicy(), frameLoadRequest.downloadAttribute() };
1372 action.setLockHistory(frameLoadRequest.lockHistory());
1373 action.setLockBackForwardList(frameLoadRequest.lockBackForwardList());
1374 action.setShouldReplaceDocumentIfJavaScriptURL(frameLoadRequest.shouldReplaceDocumentIfJavaScriptURL());
1375 if (privateClickMeasurement && m_frame.isMainFrame())
1376 action.setPrivateClickMeasurement(WTFMove(*privateClickMeasurement));
1377
1378 NewFrameOpenerPolicy openerPolicy = frameLoadRequest.newFrameOpenerPolicy();
1379 AllowNavigationToInvalidURL allowNavigationToInvalidURL = frameLoadRequest.allowNavigationToInvalidURL();
1380 if (!targetFrame && !effectiveFrameName.isEmpty()) {
1381 action = action.copyWithShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(m_frame, frameLoadRequest));
1382
1383 // https://html.spec.whatwg.org/#the-rules-for-choosing-a-browsing-context-given-a-browsing-context-name (Step 8.2)
1384 if (frameLoadRequest.requester().shouldForceNoOpenerBasedOnCOOP()) {
1385 effectiveFrameName = blankTargetFrameName();
1386 openerPolicy = NewFrameOpenerPolicy::Suppress;
1387 }
1388
1389 policyChecker().checkNewWindowPolicy(WTFMove(action), WTFMove(request), WTFMove(formState), effectiveFrameName, [this, allowNavigationToInvalidURL, openerPolicy, completionHandler = completionHandlerCaller.release()] (const ResourceRequest& request, WeakPtr<FormState>&& formState, const AtomString& frameName, const NavigationAction& action, ShouldContinuePolicyCheck shouldContinue) mutable {
1390 continueLoadAfterNewWindowPolicy(request, formState.get(), frameName, action, shouldContinue, allowNavigationToInvalidURL, openerPolicy);
1391 completionHandler();
1392 });
1393 return;
1394 }
1395
1396 RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
1397
1398 bool sameURL = shouldTreatURLAsSameAsCurrent(newURL);
1399 const String& httpMethod = request.httpMethod();
1400
1401 // Make sure to do scroll to fragment processing even if the URL is
1402 // exactly the same so pages with '#' links and DHTML side effects
1403 // work properly.
1404 if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, newLoadType, newURL)) {
1405 oldDocumentLoader->setTriggeringAction(WTFMove(action));
1406 oldDocumentLoader->setLastCheckedRequest(ResourceRequest());
1407 policyChecker().stopCheck();
1408 policyChecker().setLoadType(newLoadType);
1409 RELEASE_ASSERT(!isBackForwardLoadType(newLoadType) || history().provisionalItem());
1410 policyChecker().checkNavigationPolicy(WTFMove(request), ResourceResponse { } /* redirectResponse */, oldDocumentLoader.get(), WTFMove(formState), [this, protectedFrame = Ref { m_frame }] (const ResourceRequest& request, WeakPtr<FormState>&&, NavigationPolicyDecision navigationPolicyDecision) {
1411 continueFragmentScrollAfterNavigationPolicy(request, navigationPolicyDecision == NavigationPolicyDecision::ContinueLoad);
1412 }, PolicyDecisionMode::Synchronous);
1413 return;
1414 }
1415
1416 // Must grab this now, since this load may stop the previous load and clear this flag.
1417 bool isRedirect = m_quickRedirectComing;
1418#if USE(SYSTEM_PREVIEW)
1419 bool isSystemPreview = frameLoadRequest.isSystemPreview();
1420 if (isSystemPreview)
1421 request.setSystemPreviewInfo(frameLoadRequest.systemPreviewInfo());
1422#endif
1423 loadWithNavigationAction(request, WTFMove(action), newLoadType, WTFMove(formState), allowNavigationToInvalidURL, frameLoadRequest.shouldTreatAsContinuingLoad(), [this, isRedirect, sameURL, newLoadType, protectedFrame = Ref { m_frame }, completionHandler = completionHandlerCaller.release()] () mutable {
1424 if (isRedirect) {
1425 m_quickRedirectComing = false;
1426 if (m_provisionalDocumentLoader)
1427 m_provisionalDocumentLoader->setIsClientRedirect(true);
1428 else if (m_policyDocumentLoader)
1429 m_policyDocumentLoader->setIsClientRedirect(true);
1430 } else if (sameURL && !isReload(newLoadType)) {
1431 // Example of this case are sites that reload the same URL with a different cookie
1432 // driving the generated content, or a master frame with links that drive a target
1433 // frame, where the user has clicked on the same link repeatedly.
1434 m_loadType = FrameLoadType::Same;
1435 }
1436 completionHandler();
1437 });
1438}
1439
1440SubstituteData FrameLoader::defaultSubstituteDataForURL(const URL& url)
1441{
1442 if (!shouldTreatURLAsSrcdocDocument(url))
1443 return SubstituteData();
1444 auto& srcdoc = m_frame.ownerElement()->attributeWithoutSynchronization(srcdocAttr);
1445 ASSERT(!srcdoc.isNull());
1446 CString encodedSrcdoc = srcdoc.string().utf8();
1447
1448 ResourceResponse response(URL(), "text/html"_s, encodedSrcdoc.length(), "UTF-8"_s);
1449 return SubstituteData(SharedBuffer::create(encodedSrcdoc.data(), encodedSrcdoc.length()), URL(), response, SubstituteData::SessionHistoryVisibility::Hidden);
1450}
1451
1452void FrameLoader::load(FrameLoadRequest&& request)
1453{
1454 FRAMELOADER_RELEASE_LOG(ResourceLoading, "load (FrameLoadRequest): frame load started");
1455
1456 if (m_inStopAllLoaders || m_inClearProvisionalLoadForPolicyCheck)
1457 return;
1458
1459 if (!request.frameName().isEmpty()) {
1460 Frame* frame = findFrameForNavigation(request.frameName());
1461 if (frame) {
1462 request.setShouldCheckNewWindowPolicy(false);
1463 if (&frame->loader() != this) {
1464 frame->loader().load(WTFMove(request));
1465 return;
1466 }
1467 }
1468 }
1469
1470 if (request.shouldCheckNewWindowPolicy()) {
1471 NavigationAction action { request.requester(), request.resourceRequest(), InitiatedByMainFrame::Unknown, NavigationType::Other, request.shouldOpenExternalURLsPolicy() };
1472 policyChecker().checkNewWindowPolicy(WTFMove(action), WTFMove(request.resourceRequest()), { }, request.frameName(), [this] (const ResourceRequest& request, WeakPtr<FormState>&& formState, const AtomString& frameName, const NavigationAction& action, ShouldContinuePolicyCheck shouldContinue) {
1473 continueLoadAfterNewWindowPolicy(request, formState.get(), frameName, action, shouldContinue, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Suppress);
1474 });
1475
1476 return;
1477 }
1478
1479 if (!request.hasSubstituteData())
1480 request.setSubstituteData(defaultSubstituteDataForURL(request.resourceRequest().url()));
1481
1482 Ref<DocumentLoader> loader = m_client->createDocumentLoader(request.resourceRequest(), request.substituteData());
1483 loader->setAllowsWebArchiveForMainFrame(request.isRequestFromClientOrUserInput());
1484 loader->setAllowsDataURLsForMainFrame(request.isRequestFromClientOrUserInput());
1485 loader->setIsContinuingLoadAfterProvisionalLoadStarted(request.shouldTreatAsContinuingLoad() == ShouldTreatAsContinuingLoad::YesAfterProvisionalLoadStarted);
1486 addSameSiteInfoToRequestIfNeeded(loader->request());
1487 applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, request);
1488
1489 if (request.shouldTreatAsContinuingLoad() != ShouldTreatAsContinuingLoad::No) {
1490 loader->setClientRedirectSourceForHistory(request.clientRedirectSourceForHistory());
1491 if (request.lockBackForwardList() == LockBackForwardList::Yes) {
1492 loader->setIsClientRedirect(true);
1493 m_loadType = FrameLoadType::RedirectWithLockedBackForwardList;
1494 }
1495 }
1496
1497 SetForScope continuingLoadGuard(m_currentLoadContinuingState, request.shouldTreatAsContinuingLoad() != ShouldTreatAsContinuingLoad::No ? LoadContinuingState::ContinuingWithRequest : LoadContinuingState::NotContinuing);
1498 load(loader.get());
1499}
1500
1501void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, NavigationAction&& action, FrameLoadType type, RefPtr<FormState>&& formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, CompletionHandler<void()>&& completionHandler)
1502{
1503 FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadWithNavigationAction: frame load started");
1504
1505 if (request.url().protocolIsJavaScript()) {
1506 m_frame.script().executeJavaScriptURL(request.url(), action.requester() ? action.requester()->securityOrigin.ptr() : nullptr, action.shouldReplaceDocumentIfJavaScriptURL());
1507 m_quickRedirectComing = false;
1508 return completionHandler();
1509 }
1510
1511 Ref<DocumentLoader> loader = m_client->createDocumentLoader(request, defaultSubstituteDataForURL(request.url()));
1512 applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, action.initiatedByMainFrame(), action.shouldOpenExternalURLsPolicy());
1513 loader->setIsContinuingLoadAfterProvisionalLoadStarted(shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::YesAfterProvisionalLoadStarted);
1514
1515 if (action.lockHistory() == LockHistory::Yes && m_documentLoader)
1516 loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory().string() : m_documentLoader->clientRedirectSourceForHistory());
1517
1518 loader->setTriggeringAction(WTFMove(action));
1519 if (m_documentLoader)
1520 loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1521
1522 loadWithDocumentLoader(loader.ptr(), type, WTFMove(formState), allowNavigationToInvalidURL, WTFMove(completionHandler));
1523}
1524
1525void FrameLoader::load(DocumentLoader& newDocumentLoader)
1526{
1527 FRAMELOADER_RELEASE_LOG(ResourceLoading, "load (DocumentLoader): frame load started");
1528
1529 ResourceRequest& r = newDocumentLoader.request();
1530 // FIXME: Using m_loadType seems wrong here.
1531 // If we are only preparing to load the main resource, that is previous load's load type!
1532 updateRequestAndAddExtraFields(r, IsMainResource::Yes, m_loadType, ShouldUpdateAppInitiatedValue::No);
1533 FrameLoadType type;
1534
1535 if (shouldTreatURLAsSameAsCurrent(newDocumentLoader.originalRequest().url())) {
1536 r.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
1537 type = FrameLoadType::Same;
1538 } else if (shouldTreatURLAsSameAsCurrent(newDocumentLoader.unreachableURL()) && isReload(m_loadType))
1539 type = m_loadType;
1540 else if (m_loadType == FrameLoadType::RedirectWithLockedBackForwardList && ((!newDocumentLoader.unreachableURL().isEmpty() && newDocumentLoader.substituteData().isValid()) || shouldTreatCurrentLoadAsContinuingLoad()))
1541 type = FrameLoadType::RedirectWithLockedBackForwardList;
1542 else
1543 type = FrameLoadType::Standard;
1544
1545 if (m_documentLoader)
1546 newDocumentLoader.setOverrideEncoding(m_documentLoader->overrideEncoding());
1547
1548 // When we loading alternate content for an unreachable URL that we're
1549 // visiting in the history list, we treat it as a reload so the history list
1550 // is appropriately maintained.
1551 //
1552 // FIXME: This seems like a dangerous overloading of the meaning of "FrameLoadType::Reload" ...
1553 // shouldn't a more explicit type of reload be defined, that means roughly
1554 // "load without affecting history" ?
1555 if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {
1556 // shouldReloadToHandleUnreachableURL returns true only when the original load type is back-forward.
1557 // In this case we should save the document state now. Otherwise the state can be lost because load type is
1558 // changed and updateForBackForwardNavigation() will not be called when loading is committed.
1559 history().saveDocumentAndScrollState();
1560
1561 ASSERT(type == FrameLoadType::Standard);
1562 type = FrameLoadType::Reload;
1563 }
1564
1565 loadWithDocumentLoader(&newDocumentLoader, type, nullptr, AllowNavigationToInvalidURL::Yes);
1566}
1567
1568void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, RefPtr<FormState>&& formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, CompletionHandler<void()>&& completionHandler)
1569{
1570 FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadWithDocumentLoader: frame load started");
1571
1572 Ref protectedFrame = m_frame;
1573
1574 CompletionHandlerCallingScope completionHandlerCaller(WTFMove(completionHandler));
1575
1576 ASSERT(m_client->hasWebView());
1577
1578 // Unfortunately the view must be non-nil, this is ultimately due
1579 // to parser requiring a FrameView. We should fix this dependency.
1580
1581 ASSERT(m_frame.view());
1582
1583 if (!isNavigationAllowed())
1584 return;
1585
1586 if (m_frame.document())
1587 m_previousURL = m_frame.document()->url();
1588
1589 const URL& newURL = loader->request().url();
1590
1591 // Only the first iframe navigation or the first iframe navigation after about:blank should be reported.
1592 // https://www.w3.org/TR/resource-timing-2/#resources-included-in-the-performanceresourcetiming-interface
1593 if (m_shouldReportResourceTimingToParentFrame && !m_previousURL.isNull() && m_previousURL != aboutBlankURL())
1594 m_shouldReportResourceTimingToParentFrame = false;
1595
1596 // Log main frame navigation types.
1597 if (m_frame.isMainFrame()) {
1598 if (auto* page = m_frame.page()) {
1599 FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadWithDocumentLoader: main frame load started");
1600 page->mainFrameLoadStarted(newURL, type);
1601 page->performanceLogging().didReachPointOfInterest(PerformanceLogging::MainFrameLoadStarted);
1602 }
1603 }
1604
1605 policyChecker().setLoadType(type);
1606 RELEASE_ASSERT(!isBackForwardLoadType(type) || history().provisionalItem());
1607 bool isFormSubmission = formState;
1608
1609 const String& httpMethod = loader->request().httpMethod();
1610
1611 if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, policyChecker().loadType(), newURL)) {
1612 RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
1613 NavigationAction action { *m_frame.document(), loader->request(), InitiatedByMainFrame::Unknown, policyChecker().loadType(), isFormSubmission };
1614
1615 oldDocumentLoader->setTriggeringAction(WTFMove(action));
1616 oldDocumentLoader->setLastCheckedRequest(ResourceRequest());
1617 policyChecker().stopCheck();
1618 RELEASE_ASSERT(!isBackForwardLoadType(policyChecker().loadType()) || history().provisionalItem());
1619 policyChecker().checkNavigationPolicy(ResourceRequest(loader->request()), ResourceResponse { } /* redirectResponse */, oldDocumentLoader.get(), WTFMove(formState), [this, protectedFrame = Ref { m_frame }] (const ResourceRequest& request, WeakPtr<FormState>&&, NavigationPolicyDecision navigationPolicyDecision) {
1620 continueFragmentScrollAfterNavigationPolicy(request, navigationPolicyDecision == NavigationPolicyDecision::ContinueLoad);
1621 }, PolicyDecisionMode::Synchronous);
1622 return;
1623 }
1624
1625 if (Frame* parent = m_frame.tree().parent())
1626 loader->setOverrideEncoding(parent->loader().documentLoader()->overrideEncoding());
1627
1628 policyChecker().stopCheck();
1629 setPolicyDocumentLoader(loader);
1630 if (loader->triggeringAction().isEmpty())
1631 loader->setTriggeringAction({ *m_frame.document(), loader->request(), InitiatedByMainFrame::Unknown, policyChecker().loadType(), isFormSubmission });
1632
1633 m_frame.navigationScheduler().cancel(NewLoadInProgress::Yes);
1634
1635 if (shouldTreatCurrentLoadAsContinuingLoad()) {
1636 continueLoadAfterNavigationPolicy(loader->request(), formState.get(), NavigationPolicyDecision::ContinueLoad, allowNavigationToInvalidURL);
1637 return;
1638 }
1639
1640 RELEASE_ASSERT(!isBackForwardLoadType(policyChecker().loadType()) || history().provisionalItem());
1641 policyChecker().checkNavigationPolicy(ResourceRequest(loader->request()), ResourceResponse { } /* redirectResponse */, loader, WTFMove(formState), [this, protectedFrame = Ref { m_frame }, allowNavigationToInvalidURL, completionHandler = completionHandlerCaller.release()] (const ResourceRequest& request, WeakPtr<FormState>&& formState, NavigationPolicyDecision navigationPolicyDecision) mutable {
1642 continueLoadAfterNavigationPolicy(request, formState.get(), navigationPolicyDecision, allowNavigationToInvalidURL);
1643 completionHandler();
1644 }, PolicyDecisionMode::Asynchronous);
1645}
1646
1647void FrameLoader::clearProvisionalLoadForPolicyCheck()
1648{
1649 if (!m_policyDocumentLoader || !m_provisionalDocumentLoader || m_inClearProvisionalLoadForPolicyCheck)
1650 return;
1651
1652 SetForScope change(m_inClearProvisionalLoadForPolicyCheck, true);
1653 m_provisionalDocumentLoader->stopLoading();
1654 FRAMELOADER_RELEASE_LOG(ResourceLoading, "clearProvisionalLoadForPolicyCheck: Clearing provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
1655 setProvisionalDocumentLoader(nullptr);
1656}
1657
1658bool FrameLoader::hasOpenedFrames() const
1659{
1660 return !m_openedFrames.computesEmpty();
1661}
1662
1663void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
1664{
1665 ASSERT(!url.isEmpty());
1666 if (!frame)
1667 return;
1668
1669 frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Not allowed to load local resource: " + url);
1670}
1671
1672void FrameLoader::reportBlockedLoadFailed(Frame& frame, const URL& url)
1673{
1674 ASSERT(!url.isEmpty());
1675 auto message = makeString("Not allowed to use restricted network port ", url.port().value(), ": ", url.stringCenterEllipsizedToLength());
1676 frame.document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, message);
1677}
1678
1679bool FrameLoader::willLoadMediaElementURL(URL& url, Node& initiatorNode)
1680{
1681#if PLATFORM(IOS_FAMILY)
1682 // MobileStore depends on the iOS 4.0 era client delegate method because webView:resource:willSendRequest:redirectResponse:fromDataSource
1683 // doesn't let them tell when a load request is coming from a media element. See <rdar://problem/8266916> for more details.
1684 if (IOSApplication::isMobileStore())
1685 return m_client->shouldLoadMediaElementURL(url);
1686#endif
1687
1688 ResourceRequest request(url);
1689 request.setInspectorInitiatorNodeIdentifier(InspectorInstrumentation::identifierForNode(initiatorNode));
1690 if (m_documentLoader)
1691 request.setIsAppInitiated(m_documentLoader->lastNavigationWasAppInitiated());
1692
1693 ResourceLoaderIdentifier identifier;
1694 ResourceError error;
1695 requestFromDelegate(request, identifier, error);
1696 notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, ResourceResponse(url, String(), -1, String()), nullptr, -1, -1, error);
1697
1698 url = request.url();
1699
1700 return error.isNull();
1701}
1702
1703bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader& docLoader)
1704{
1705 URL unreachableURL = docLoader.unreachableURL();
1706
1707 if (unreachableURL.isEmpty())
1708 return false;
1709
1710 if (!isBackForwardLoadType(policyChecker().loadType()))
1711 return false;
1712
1713 // We only treat unreachableURLs specially during the delegate callbacks
1714 // for provisional load errors and navigation policy decisions. The former
1715 // case handles well-formed URLs that can't be loaded, and the latter
1716 // case handles malformed URLs and unknown schemes. Loading alternate content
1717 // at other times behaves like a standard load.
1718 if (policyChecker().delegateIsDecidingNavigationPolicy() || policyChecker().delegateIsHandlingUnimplementablePolicy())
1719 return m_policyDocumentLoader && unreachableURL == m_policyDocumentLoader->request().url();
1720
1721 return unreachableURL == m_provisionalLoadErrorBeingHandledURL;
1722}
1723
1724void FrameLoader::reloadWithOverrideEncoding(const String& encoding)
1725{
1726 if (!m_documentLoader)
1727 return;
1728
1729 FRAMELOADER_RELEASE_LOG(ResourceLoading, "reloadWithOverrideEncoding: frame load started");
1730
1731 ResourceRequest request = m_documentLoader->request();
1732 URL unreachableURL = m_documentLoader->unreachableURL();
1733 if (!unreachableURL.isEmpty())
1734 request.setURL(unreachableURL);
1735
1736 // FIXME: If the resource is a result of form submission and is not cached, the form will be silently resubmitted.
1737 // We should ask the user for confirmation in this case.
1738 request.setCachePolicy(ResourceRequestCachePolicy::ReturnCacheDataElseLoad);
1739
1740 Ref<DocumentLoader> loader = m_client->createDocumentLoader(request, defaultSubstituteDataForURL(request.url()));
1741 applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, InitiatedByMainFrame::Unknown, m_documentLoader->shouldOpenExternalURLsPolicyToPropagate());
1742
1743 setPolicyDocumentLoader(loader.ptr());
1744
1745 loader->setOverrideEncoding(encoding);
1746
1747 loadWithDocumentLoader(loader.ptr(), FrameLoadType::Reload, { }, AllowNavigationToInvalidURL::Yes);
1748}
1749
1750void FrameLoader::reload(OptionSet<ReloadOption> options)
1751{
1752 if (!m_documentLoader)
1753 return;
1754
1755 // If a window is created by javascript, its main frame can have an empty but non-nil URL.
1756 // Reloading in this case will lose the current contents (see 4151001).
1757 if (m_documentLoader->request().url().isEmpty())
1758 return;
1759
1760 FRAMELOADER_RELEASE_LOG(ResourceLoading, "reload: frame load started");
1761
1762 // Replace error-page URL with the URL we were trying to reach.
1763 ResourceRequest initialRequest = m_documentLoader->request();
1764 URL unreachableURL = m_documentLoader->unreachableURL();
1765 if (!unreachableURL.isEmpty())
1766 initialRequest.setURL(unreachableURL);
1767
1768 // Create a new document loader for the reload, this will become m_documentLoader eventually,
1769 // but first it has to be the "policy" document loader, and then the "provisional" document loader.
1770 Ref<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest, defaultSubstituteDataForURL(initialRequest.url()));
1771 loader->setAllowsWebArchiveForMainFrame(m_documentLoader->allowsWebArchiveForMainFrame());
1772 loader->setAllowsDataURLsForMainFrame(m_documentLoader->allowsDataURLsForMainFrame());
1773 applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, InitiatedByMainFrame::Unknown, m_documentLoader->shouldOpenExternalURLsPolicyToPropagate());
1774
1775 loader->setUserContentExtensionsEnabled(!options.contains(ReloadOption::DisableContentBlockers));
1776
1777 ResourceRequest& request = loader->request();
1778
1779 // FIXME: We don't have a mechanism to revalidate the main resource without reloading at the moment.
1780 request.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
1781
1782 addSameSiteInfoToRequestIfNeeded(request);
1783
1784 // If we're about to re-post, set up action so the application can warn the user.
1785 if (request.httpMethod() == "POST"_s)
1786 loader->setTriggeringAction({ *m_frame.document(), request, InitiatedByMainFrame::Unknown, NavigationType::FormResubmitted });
1787
1788 loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1789
1790 auto frameLoadTypeForReloadOptions = [] (auto options) {
1791 if (options & ReloadOption::FromOrigin)
1792 return FrameLoadType::ReloadFromOrigin;
1793 if (options & ReloadOption::ExpiredOnly)
1794 return FrameLoadType::ReloadExpiredOnly;
1795 return FrameLoadType::Reload;
1796 };
1797
1798 loadWithDocumentLoader(loader.ptr(), frameLoadTypeForReloadOptions(options), { }, AllowNavigationToInvalidURL::Yes);
1799}
1800
1801void FrameLoader::stopAllLoaders(ClearProvisionalItem clearProvisionalItem, StopLoadingPolicy stopLoadingPolicy)
1802{
1803 if (m_frame.document() && m_frame.document()->backForwardCacheState() == Document::InBackForwardCache)
1804 return;
1805
1806 if (stopLoadingPolicy == StopLoadingPolicy::PreventDuringUnloadEvents && !isStopLoadingAllowed())
1807 return;
1808
1809 // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
1810 if (m_inStopAllLoaders)
1811 return;
1812
1813 // This method might dispatch events.
1814 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed());
1815
1816 // Calling stopLoading() on the provisional document loader can blow away
1817 // the frame from underneath.
1818 Ref<Frame> protect(m_frame);
1819
1820 m_inStopAllLoaders = true;
1821
1822 policyChecker().stopCheck();
1823
1824 // If no new load is in progress, we should clear the provisional item from history
1825 // before we call stopLoading.
1826 if (clearProvisionalItem == ClearProvisionalItem::Yes)
1827 history().setProvisionalItem(nullptr);
1828
1829 for (RefPtr<Frame> child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
1830 child->loader().stopAllLoaders(clearProvisionalItem);
1831
1832 FRAMELOADER_RELEASE_LOG(ResourceLoading, "stopAllLoaders: m_provisionalDocumentLoader=%p, m_documentLoader=%p", m_provisionalDocumentLoader.get(), m_documentLoader.get());
1833
1834 if (m_provisionalDocumentLoader)
1835 m_provisionalDocumentLoader->stopLoading();
1836 if (m_documentLoader)
1837 m_documentLoader->stopLoading();
1838 if (m_frame.page() && !m_frame.page()->chrome().client().isSVGImageChromeClient())
1839 platformStrategies()->loaderStrategy()->browsingContextRemoved(frame());
1840
1841 FRAMELOADER_RELEASE_LOG(ResourceLoading, "stopAllLoaders: Clearing provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
1842 setProvisionalDocumentLoader(nullptr);
1843
1844 m_inStopAllLoaders = false;
1845}
1846
1847void FrameLoader::stopForBackForwardCache()
1848{
1849 ASSERT(!m_inStopForBackForwardCache);
1850 SetForScope<bool> inStopForBackForwardCache { m_inStopForBackForwardCache, true };
1851 // Stop provisional loads in subframes (The one in the main frame is about to be committed).
1852 if (!m_frame.isMainFrame()) {
1853 if (m_provisionalDocumentLoader)
1854 m_provisionalDocumentLoader->stopLoading();
1855 FRAMELOADER_RELEASE_LOG(ResourceLoading, "stopForBackForwardCache: Clearing provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
1856 setProvisionalDocumentLoader(nullptr);
1857 }
1858
1859 // Stop current loads.
1860 if (m_documentLoader)
1861 m_documentLoader->stopLoading();
1862
1863 for (RefPtr<Frame> child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
1864 child->loader().stopForBackForwardCache();
1865
1866 // We cancel pending navigations & policy checks *after* cancelling loads because cancelling loads might end up
1867 // running script, which could schedule new navigations.
1868 policyChecker().stopCheck();
1869 m_frame.navigationScheduler().cancel();
1870}
1871
1872void FrameLoader::stopAllLoadersAndCheckCompleteness()
1873{
1874 stopAllLoaders();
1875
1876 if (!m_checkTimer.isActive())
1877 return;
1878
1879 m_checkTimer.stop();
1880 m_checkingLoadCompleteForDetachment = true;
1881 checkCompletenessNow();
1882 m_checkingLoadCompleteForDetachment = false;
1883}
1884
1885void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
1886{
1887 if (m_inStopForBackForwardCache)
1888 return;
1889 // Calling stopAllLoaders can cause the frame to be deallocated, including the frame loader.
1890 Ref<Frame> protectedFrame(m_frame);
1891
1892 stopAllLoaders();
1893
1894#if PLATFORM(IOS_FAMILY)
1895 // Lay out immediately when stopping to immediately clear the old page if we just committed this one
1896 // but haven't laid out/painted yet.
1897 // FIXME: Is this behavior specific to iOS? Or should we expose a setting to toggle this behavior?
1898 if (m_frame.view() && !m_frame.view()->didFirstLayout())
1899 m_frame.view()->layoutContext().layout();
1900#endif
1901
1902 if (deferCheckLoadComplete)
1903 scheduleCheckLoadComplete();
1904 else if (m_frame.page())
1905 checkLoadComplete();
1906}
1907
1908DocumentLoader* FrameLoader::activeDocumentLoader() const
1909{
1910 if (m_state == FrameState::Provisional)
1911 return m_provisionalDocumentLoader.get();
1912 return m_documentLoader.get();
1913}
1914
1915bool FrameLoader::isLoading() const
1916{
1917 DocumentLoader* docLoader = activeDocumentLoader();
1918 if (!docLoader)
1919 return false;
1920 return docLoader->isLoading();
1921}
1922
1923bool FrameLoader::frameHasLoaded() const
1924{
1925 return m_stateMachine.committedFirstRealDocumentLoad() || (m_provisionalDocumentLoader && !m_stateMachine.creatingInitialEmptyDocument());
1926}
1927
1928void FrameLoader::setDocumentLoader(DocumentLoader* loader)
1929{
1930 if (loader == m_documentLoader)
1931 return;
1932
1933 FRAMELOADER_RELEASE_LOG(ResourceLoading, "setDocumentLoader: Setting document loader to %p (was %p)", loader, m_documentLoader.get());
1934
1935 RELEASE_ASSERT(!loader || loader->frameLoader() == this);
1936
1937 m_client->prepareForDataSourceReplacement();
1938 detachChildren();
1939
1940 // detachChildren() can trigger this frame's unload event, and therefore
1941 // script can run and do just about anything. For example, an unload event that calls
1942 // document.write("") on its parent frame can lead to a recursive detachChildren()
1943 // invocation for this frame. In that case, we can end up at this point with a
1944 // loader that hasn't been deleted but has been detached from its frame. Such a
1945 // DocumentLoader has been sufficiently detached that we'll end up in an inconsistent
1946 // state if we try to use it.
1947 if (loader && !loader->frame())
1948 return;
1949
1950 if (m_documentLoader)
1951 m_documentLoader->detachFromFrame();
1952
1953 m_documentLoader = loader;
1954}
1955
1956void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
1957{
1958 if (m_policyDocumentLoader == loader)
1959 return;
1960
1961 FRAMELOADER_RELEASE_LOG(ResourceLoading, "setPolicyDocumentLoader: Setting policy document loader to %p (was %p)", loader, m_policyDocumentLoader.get());
1962
1963 if (loader)
1964 loader->attachToFrame(m_frame);
1965 if (m_policyDocumentLoader
1966 && m_policyDocumentLoader != m_provisionalDocumentLoader
1967 && m_policyDocumentLoader != m_documentLoader)
1968 m_policyDocumentLoader->detachFromFrame();
1969
1970 m_policyDocumentLoader = loader;
1971}
1972
1973void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
1974{
1975 if (m_provisionalDocumentLoader == loader)
1976 return;
1977
1978 FRAMELOADER_RELEASE_LOG(ResourceLoading, "setProvisionalDocumentLoader: Setting provisional document loader to %p (was %p)", loader, m_provisionalDocumentLoader.get());
1979
1980 ASSERT(!loader || !m_provisionalDocumentLoader);
1981 RELEASE_ASSERT(!loader || loader->frameLoader() == this);
1982
1983 if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
1984 m_provisionalDocumentLoader->detachFromFrame();
1985
1986 m_provisionalDocumentLoader = loader;
1987}
1988
1989void FrameLoader::setState(FrameState newState)
1990{
1991 FrameState oldState = m_state;
1992 m_state = newState;
1993
1994 if (newState == FrameState::Provisional)
1995 provisionalLoadStarted();
1996 else if (newState == FrameState::Complete) {
1997 frameLoadCompleted();
1998 if (m_documentLoader)
1999 m_documentLoader->stopRecordingResponses();
2000 if (m_frame.isMainFrame() && oldState != newState) {
2001 FRAMELOADER_RELEASE_LOG(ResourceLoading, "setState: main frame load completed");
2002 m_frame.page()->performanceLogging().didReachPointOfInterest(PerformanceLogging::MainFrameLoadCompleted);
2003 }
2004 }
2005}
2006
2007void FrameLoader::clearProvisionalLoad()
2008{
2009 FRAMELOADER_RELEASE_LOG(ResourceLoading, "clearProvisionalLoad: Clearing provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
2010 setProvisionalDocumentLoader(nullptr);
2011 if (m_progressTracker)
2012 m_progressTracker->progressCompleted();
2013 setState(FrameState::Complete);
2014}
2015
2016void FrameLoader::commitProvisionalLoad()
2017{
2018 RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2019 Ref<Frame> protect(m_frame);
2020
2021 std::unique_ptr<CachedPage> cachedPage;
2022 if (m_loadingFromCachedPage && history().provisionalItem())
2023 cachedPage = BackForwardCache::singleton().take(*history().provisionalItem(), m_frame.page());
2024
2025 LOG(BackForwardCache, "WebCoreLoading %s: About to commit provisional load from previous URL '%s' to new URL '%s' with cached page %p", m_frame.tree().uniqueName().string().utf8().data(),
2026 m_frame.document() ? m_frame.document()->url().stringCenterEllipsizedToLength().utf8().data() : "",
2027 pdl ? pdl->url().stringCenterEllipsizedToLength().utf8().data() : "<no provisional DocumentLoader>", cachedPage.get());
2028
2029 if (RefPtr document = m_frame.document()) {
2030 // In the case where we're restoring from a cached page, our document will not
2031 // be connected to its frame yet, so the following call with be a no-op. We will
2032 // attempt to confirm any active composition once again in this scenario after we
2033 // finish restoring from the cached page.
2034 document->editor().confirmOrCancelCompositionAndNotifyClient();
2035 }
2036
2037 if (!m_frame.tree().parent() && history().currentItem() && history().currentItem() != history().provisionalItem()) {
2038 // Check to see if we need to cache the page we are navigating away from into the back/forward cache.
2039 // We are doing this here because we know for sure that a new page is about to be loaded.
2040 BackForwardCache::singleton().addIfCacheable(*history().currentItem(), m_frame.page());
2041
2042 WebCore::jettisonExpensiveObjectsOnTopLevelNavigation();
2043 }
2044
2045 if (m_loadType != FrameLoadType::Replace)
2046 closeOldDataSources();
2047
2048 if (!cachedPage && !m_stateMachine.creatingInitialEmptyDocument())
2049 m_client->makeRepresentation(pdl.get());
2050
2051 transitionToCommitted(cachedPage.get());
2052
2053 if (pdl && m_documentLoader) {
2054 // Check if the destination page is allowed to access the previous page's timing information.
2055 Ref<SecurityOrigin> securityOrigin(SecurityOrigin::create(pdl->request().url()));
2056 m_documentLoader->timing().setHasSameOriginAsPreviousDocument(securityOrigin.get().canRequest(m_previousURL));
2057 }
2058
2059 // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
2060 // status has changed, if there was a redirect. The frame load delegate may have saved some state about
2061 // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are
2062 // just about to commit a new page, there cannot possibly be a pending redirect at this point.
2063 if (m_sentRedirectNotification)
2064 clientRedirectCancelledOrFinished(NewLoadInProgress::No);
2065
2066 if (cachedPage && cachedPage->document()) {
2067#if PLATFORM(IOS_FAMILY)
2068 // FIXME: CachedPage::restore() would dispatch viewport change notification. However UIKit expects load
2069 // commit to happen before any changes to viewport arguments and dealing with this there is difficult.
2070 m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(true);
2071#endif
2072 willRestoreFromCachedPage();
2073
2074 // Start request for the main resource and dispatch didReceiveResponse before the load is committed for
2075 // consistency with all other loads. See https://bugs.webkit.org/show_bug.cgi?id=150927.
2076 ResourceError mainResouceError;
2077 ResourceLoaderIdentifier mainResourceIdentifier;
2078 ResourceRequest mainResourceRequest(cachedPage->documentLoader()->request());
2079 requestFromDelegate(mainResourceRequest, mainResourceIdentifier, mainResouceError);
2080 notifier().dispatchDidReceiveResponse(cachedPage->documentLoader(), mainResourceIdentifier, cachedPage->documentLoader()->response());
2081
2082 auto hasInsecureContent = cachedPage->cachedMainFrame()->hasInsecureContent();
2083 auto usedLegacyTLS = cachedPage->cachedMainFrame()->usedLegacyTLS();
2084
2085 dispatchDidCommitLoad(hasInsecureContent, usedLegacyTLS);
2086
2087 // FIXME: This API should be turned around so that we ground CachedPage into the Page.
2088 cachedPage->restore(*m_frame.page());
2089
2090#if PLATFORM(IOS_FAMILY)
2091 m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(false);
2092 m_frame.page()->chrome().dispatchViewportPropertiesDidChange(m_frame.page()->viewportArguments());
2093#endif
2094 m_frame.page()->chrome().dispatchDisabledAdaptationsDidChange(m_frame.page()->disabledAdaptations());
2095
2096 auto& title = m_documentLoader->title();
2097 if (!title.string.isNull())
2098 m_client->dispatchDidReceiveTitle(title);
2099
2100 // Send remaining notifications for the main resource.
2101 notifier().sendRemainingDelegateMessages(m_documentLoader.get(), mainResourceIdentifier, mainResourceRequest, ResourceResponse(), nullptr, static_cast<int>(m_documentLoader->response().expectedContentLength()), 0, mainResouceError);
2102
2103 Vector<Ref<Frame>> targetFrames;
2104 targetFrames.append(m_frame);
2105 for (auto* child = m_frame.tree().firstChild(); child; child = child->tree().traverseNext(&m_frame))
2106 targetFrames.append(*child);
2107
2108 for (auto& frame : targetFrames)
2109 frame->loader().checkCompleted();
2110 } else
2111 didOpenURL();
2112
2113 if (RefPtr document = m_frame.document())
2114 document->editor().confirmOrCancelCompositionAndNotifyClient();
2115
2116 LOG(Loading, "WebCoreLoading %s: Finished committing provisional load to URL %s", m_frame.tree().uniqueName().string().utf8().data(),
2117 m_frame.document() ? m_frame.document()->url().stringCenterEllipsizedToLength().utf8().data() : "");
2118
2119 if (m_loadType == FrameLoadType::Standard && m_documentLoader && m_documentLoader->isClientRedirect())
2120 history().updateForClientRedirect();
2121
2122 if (m_loadingFromCachedPage) {
2123 // Note, didReceiveDocType is expected to be called for cached pages. See <rdar://problem/5906758> for more details.
2124 if (auto* page = m_frame.page())
2125 page->chrome().didReceiveDocType(m_frame);
2126 m_frame.document()->resume(ReasonForSuspension::BackForwardCache);
2127
2128 // Force a layout to update view size and thereby update scrollbars.
2129#if PLATFORM(IOS_FAMILY)
2130 if (!m_client->forceLayoutOnRestoreFromBackForwardCache())
2131 m_frame.view()->forceLayout();
2132#else
2133 m_frame.view()->forceLayout();
2134#endif
2135
2136 // Main resource delegates were already sent, so we skip the first response here.
2137 for (unsigned i = 1; i < m_documentLoader->responses().size(); ++i) {
2138 const auto& response = m_documentLoader->responses()[i];
2139 // FIXME: If the WebKit client changes or cancels the request, this is not respected.
2140 ResourceError error;
2141 ResourceLoaderIdentifier identifier;
2142 ResourceRequest request(response.url());
2143 if (m_documentLoader)
2144 request.setIsAppInitiated(m_documentLoader->lastNavigationWasAppInitiated());
2145 requestFromDelegate(request, identifier, error);
2146 // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
2147 // However, with today's computers and networking speeds, this won't happen in practice.
2148 // Could be an issue with a giant local file.
2149 notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, response, nullptr, static_cast<int>(response.expectedContentLength()), 0, error);
2150 }
2151
2152 // FIXME: Why only this frame and not parent frames?
2153 checkLoadCompleteForThisFrame();
2154 }
2155}
2156
2157void FrameLoader::transitionToCommitted(CachedPage* cachedPage)
2158{
2159 ASSERT(m_client->hasWebView());
2160 ASSERT(m_state == FrameState::Provisional);
2161
2162 if (m_state != FrameState::Provisional)
2163 return;
2164
2165 if (FrameView* view = m_frame.view()) {
2166 if (ScrollAnimator* scrollAnimator = view->existingScrollAnimator())
2167 scrollAnimator->cancelAnimations();
2168 }
2169
2170 m_client->setCopiesOnScroll();
2171 history().updateForCommit();
2172
2173 // The call to closeURL() invokes the unload event handler, which can execute arbitrary
2174 // JavaScript. If the script initiates a new load, we need to abandon the current load,
2175 // or the two will stomp each other.
2176 auto originalProvisionalDocumentLoader = m_provisionalDocumentLoader;
2177 if (m_documentLoader)
2178 closeURL();
2179 if (originalProvisionalDocumentLoader != m_provisionalDocumentLoader)
2180 return;
2181
2182 if (m_documentLoader)
2183 m_documentLoader->stopLoadingSubresources();
2184 if (m_documentLoader)
2185 m_documentLoader->stopLoadingPlugIns();
2186
2187 // Setting our document loader invokes the unload event handler of our child frames.
2188 // Script can do anything. If the script initiates a new load, we need to abandon the
2189 // current load or the two will stomp each other.
2190 setDocumentLoader(m_provisionalDocumentLoader.get());
2191 if (originalProvisionalDocumentLoader != m_provisionalDocumentLoader)
2192 return;
2193 FRAMELOADER_RELEASE_LOG(ResourceLoading, "transitionToCommitted: Clearing provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
2194 setProvisionalDocumentLoader(nullptr);
2195
2196 // Nothing else can interrupt this commit - set the Provisional->Committed transition in stone
2197 setState(FrameState::CommittedPage);
2198
2199 // Handle adding the URL to the back/forward list.
2200 auto documentLoader = m_documentLoader;
2201
2202 switch (m_loadType) {
2203 case FrameLoadType::Forward:
2204 case FrameLoadType::Back:
2205 case FrameLoadType::IndexedBackForward:
2206 if (m_frame.page()) {
2207 // If the first load within a frame is a navigation within a back/forward list that was attached
2208 // without any of the items being loaded then we need to update the history in a similar manner as
2209 // for a standard load with the exception of updating the back/forward list (<rdar://problem/8091103>).
2210 if (!m_stateMachine.committedFirstRealDocumentLoad() && m_frame.isMainFrame())
2211 history().updateForStandardLoad(HistoryController::UpdateAllExceptBackForwardList);
2212
2213 history().updateForBackForwardNavigation();
2214
2215 // For cached pages, CachedFrame::restore will take care of firing the popstate event with the history item's state object
2216 if (history().currentItem() && !cachedPage)
2217 m_pendingStateObject = history().currentItem()->stateObject();
2218
2219 // Create a document view for this document, or used the cached view.
2220 if (cachedPage) {
2221 ASSERT(cachedPage->documentLoader());
2222 cachedPage->documentLoader()->attachToFrame(m_frame);
2223 m_client->transitionToCommittedFromCachedFrame(cachedPage->cachedMainFrame());
2224 } else
2225 m_client->transitionToCommittedForNewPage();
2226 }
2227 break;
2228
2229 case FrameLoadType::Reload:
2230 case FrameLoadType::ReloadFromOrigin:
2231 case FrameLoadType::ReloadExpiredOnly:
2232 case FrameLoadType::Same:
2233 case FrameLoadType::Replace:
2234 history().updateForReload();
2235 m_client->transitionToCommittedForNewPage();
2236 break;
2237
2238 case FrameLoadType::Standard:
2239 history().updateForStandardLoad();
2240 if (m_frame.view())
2241 m_frame.view()->setScrollbarsSuppressed(true);
2242 m_client->transitionToCommittedForNewPage();
2243 break;
2244
2245 case FrameLoadType::RedirectWithLockedBackForwardList:
2246 history().updateForRedirectWithLockedBackForwardList();
2247 m_client->transitionToCommittedForNewPage();
2248 break;
2249 }
2250
2251 if (documentLoader)
2252 documentLoader->writer().setMIMEType(documentLoader->responseMIMEType());
2253
2254 if (m_stateMachine.creatingInitialEmptyDocument())
2255 return;
2256
2257 if (!m_stateMachine.committedFirstRealDocumentLoad())
2258 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
2259}
2260
2261void FrameLoader::clientRedirectCancelledOrFinished(NewLoadInProgress newLoadInProgress)
2262{
2263 // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
2264 // the redirect succeeded. We should either rename this API, or add a new method, like
2265 // -webView:didFinishClientRedirectForFrame:
2266 m_client->dispatchDidCancelClientRedirect();
2267
2268 if (newLoadInProgress == NewLoadInProgress::No)
2269 m_quickRedirectComing = false;
2270
2271 m_sentRedirectNotification = false;
2272}
2273
2274void FrameLoader::clientRedirected(const URL& url, double seconds, WallTime fireDate, LockBackForwardList lockBackForwardList)
2275{
2276 m_client->dispatchWillPerformClientRedirect(url, seconds, fireDate, lockBackForwardList);
2277
2278 // Remember that we sent a redirect notification to the frame load delegate so that when we commit
2279 // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
2280 m_sentRedirectNotification = true;
2281
2282 // If a "quick" redirect comes in, we set a special mode so we treat the next
2283 // load as part of the original navigation. If we don't have a document loader, we have
2284 // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
2285 // Loads triggered by JavaScript form submissions never count as quick redirects.
2286 m_quickRedirectComing = (lockBackForwardList == LockBackForwardList::Yes || history().currentItemShouldBeReplaced()) && m_documentLoader && !m_isExecutingJavaScriptFormAction;
2287}
2288
2289bool FrameLoader::shouldReload(const URL& currentURL, const URL& destinationURL)
2290{
2291 // This function implements the rule: "Don't reload if navigating by fragment within
2292 // the same URL, but do reload if going to a new URL or to the same URL with no
2293 // fragment identifier at all."
2294 if (!destinationURL.hasFragmentIdentifier())
2295 return true;
2296 return !equalIgnoringFragmentIdentifier(currentURL, destinationURL);
2297}
2298
2299void FrameLoader::closeOldDataSources()
2300{
2301 // FIXME: Is it important for this traversal to be postorder instead of preorder?
2302 // If so, add helpers for postorder traversal, and use them. If not, then lets not
2303 // use a recursive algorithm here.
2304 for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
2305 child->loader().closeOldDataSources();
2306
2307 if (m_documentLoader)
2308 m_client->dispatchWillClose();
2309
2310 m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
2311}
2312
2313void FrameLoader::willRestoreFromCachedPage()
2314{
2315 ASSERT(!m_frame.tree().parent());
2316 ASSERT(m_frame.page());
2317 ASSERT(m_frame.isMainFrame());
2318
2319 m_frame.navigationScheduler().cancel();
2320
2321 // We still have to close the previous part page.
2322 closeURL();
2323
2324 // Delete old status bar messages (if it _was_ activated on last URL).
2325 if (m_frame.script().canExecuteScripts(NotAboutToExecuteScript)) {
2326 DOMWindow* window = m_frame.document()->domWindow();
2327 window->setStatus(String());
2328 window->setDefaultStatus(String());
2329 }
2330}
2331
2332void FrameLoader::open(CachedFrameBase& cachedFrame)
2333{
2334 // Don't re-emit the load event.
2335 m_didCallImplicitClose = true;
2336
2337 URL url = cachedFrame.url();
2338
2339 // FIXME: I suspect this block of code doesn't do anything.
2340 if (url.protocolIsInHTTPFamily() && !url.host().isEmpty() && url.path().isEmpty())
2341 url.setPath("/"_s);
2342
2343 started();
2344 Ref document = *cachedFrame.document();
2345 ASSERT(document->domWindow());
2346
2347 clear(document.ptr(), true, true, cachedFrame.isMainFrame());
2348
2349 document->attachToCachedFrame(cachedFrame);
2350 document->setBackForwardCacheState(Document::NotInBackForwardCache);
2351
2352 m_needsClear = true;
2353 m_isComplete = false;
2354 m_didCallImplicitClose = false;
2355 setOutgoingReferrer(url);
2356
2357 FrameView* view = cachedFrame.view();
2358
2359 // When navigating to a CachedFrame its FrameView should never be null. If it is we'll crash in creative ways downstream.
2360 ASSERT(view);
2361 view->setWasScrolledByUser(false);
2362
2363 std::optional<IntRect> previousViewFrameRect = m_frame.view() ? m_frame.view()->frameRect() : std::optional<IntRect>(std::nullopt);
2364 m_frame.setView(view);
2365
2366 // Use the previous ScrollView's frame rect.
2367 if (previousViewFrameRect)
2368 view->setFrameRect(previousViewFrameRect.value());
2369
2370
2371 // Setting the document builds the render tree and runs post style resolution callbacks that can do anything,
2372 // including loading a child frame before its been re-attached to the frame tree as part of this restore.
2373 // For example, the HTML object element may load its content into a frame in a post style resolution callback.
2374 Style::PostResolutionCallbackDisabler disabler(document.get());
2375 WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
2376 NavigationDisabler disableNavigation { &m_frame };
2377
2378 m_frame.setDocument(document.copyRef());
2379
2380 document->domWindow()->resumeFromBackForwardCache();
2381
2382 updateFirstPartyForCookies();
2383
2384 cachedFrame.restore();
2385}
2386
2387bool FrameLoader::isReplacing() const
2388{
2389 return m_loadType == FrameLoadType::Replace;
2390}
2391
2392void FrameLoader::setReplacing()
2393{
2394 m_loadType = FrameLoadType::Replace;
2395}
2396
2397bool FrameLoader::subframeIsLoading() const
2398{
2399 // It's most likely that the last added frame is the last to load so we walk backwards.
2400 for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling()) {
2401 FrameLoader& childLoader = child->loader();
2402 DocumentLoader* documentLoader = childLoader.documentLoader();
2403 if (documentLoader && documentLoader->isLoadingInAPISense())
2404 return true;
2405 documentLoader = childLoader.provisionalDocumentLoader();
2406 if (documentLoader && documentLoader->isLoadingInAPISense())
2407 return true;
2408 documentLoader = childLoader.policyDocumentLoader();
2409 if (documentLoader)
2410 return true;
2411 }
2412 return false;
2413}
2414
2415void FrameLoader::willChangeTitle(DocumentLoader* loader)
2416{
2417 m_client->willChangeTitle(loader);
2418}
2419
2420FrameLoadType FrameLoader::loadType() const
2421{
2422 return m_loadType;
2423}
2424
2425CachePolicy FrameLoader::subresourceCachePolicy(const URL& url) const
2426{
2427 if (Page* page = m_frame.page()) {
2428 if (page->isResourceCachingDisabledByWebInspector())
2429 return CachePolicy::Reload;
2430 }
2431
2432 if (m_isComplete)
2433 return CachePolicy::Verify;
2434
2435 if (m_loadType == FrameLoadType::ReloadFromOrigin)
2436 return CachePolicy::Reload;
2437
2438 if (Frame* parentFrame = m_frame.tree().parent()) {
2439 CachePolicy parentCachePolicy = parentFrame->loader().subresourceCachePolicy(url);
2440 if (parentCachePolicy != CachePolicy::Verify)
2441 return parentCachePolicy;
2442 }
2443
2444 switch (m_loadType) {
2445 case FrameLoadType::Reload:
2446 return CachePolicy::Revalidate;
2447 case FrameLoadType::Back:
2448 case FrameLoadType::Forward:
2449 case FrameLoadType::IndexedBackForward:
2450 return CachePolicy::HistoryBuffer;
2451 case FrameLoadType::ReloadFromOrigin:
2452 ASSERT_NOT_REACHED(); // Already handled above.
2453 return CachePolicy::Reload;
2454 case FrameLoadType::RedirectWithLockedBackForwardList:
2455 case FrameLoadType::Replace:
2456 case FrameLoadType::Same:
2457 case FrameLoadType::Standard:
2458 return CachePolicy::Verify;
2459 case FrameLoadType::ReloadExpiredOnly:
2460 // We know about expiration for HTTP and data. Do a normal reload otherwise.
2461 if (!url.protocolIsInHTTPFamily() && !url.protocolIsData())
2462 return CachePolicy::Reload;
2463 return CachePolicy::Verify;
2464 }
2465
2466 RELEASE_ASSERT_NOT_REACHED();
2467 return CachePolicy::Verify;
2468}
2469
2470void FrameLoader::dispatchDidFailProvisionalLoad(DocumentLoader& provisionalDocumentLoader, const ResourceError& error)
2471{
2472 m_provisionalLoadErrorBeingHandledURL = provisionalDocumentLoader.url();
2473
2474#if ENABLE(CONTENT_FILTERING)
2475 auto contentFilterWillContinueLoading = false;
2476#endif
2477
2478 auto willContinueLoading = WillContinueLoading::No;
2479 if (history().provisionalItem())
2480 willContinueLoading = WillContinueLoading::Yes;
2481#if ENABLE(CONTENT_FILTERING)
2482 if (provisionalDocumentLoader.contentFilterWillHandleProvisionalLoadFailure(error)) {
2483 willContinueLoading = WillContinueLoading::Yes;
2484 contentFilterWillContinueLoading = true;
2485 }
2486#endif
2487
2488 m_client->dispatchDidFailProvisionalLoad(error, willContinueLoading);
2489
2490#if ENABLE(CONTENT_FILTERING)
2491 if (contentFilterWillContinueLoading)
2492 provisionalDocumentLoader.contentFilterHandleProvisionalLoadFailure(error);
2493#endif
2494
2495 m_provisionalLoadErrorBeingHandledURL = { };
2496}
2497
2498void FrameLoader::checkLoadCompleteForThisFrame()
2499{
2500 ASSERT(m_client->hasWebView());
2501
2502 // FIXME: Should this check be done in checkLoadComplete instead of here?
2503 // FIXME: Why does this one check need to be repeated here, and not the many others from checkCompleted?
2504 if (m_frame.document()->isDelayingLoadEvent())
2505 return;
2506
2507 switch (m_state) {
2508 case FrameState::Provisional: {
2509 // FIXME: Prohibiting any provisional load failures from being sent to clients
2510 // while handling provisional load failures is too heavy. For example, the current
2511 // load will fail to cancel another ongoing load. That might prevent clients' page
2512 // load state being handled properly.
2513 if (!m_provisionalLoadErrorBeingHandledURL.isEmpty())
2514 return;
2515
2516 RefPtr<DocumentLoader> protector = m_provisionalDocumentLoader;
2517 if (!protector)
2518 return;
2519
2520 // If we've received any errors we may be stuck in the provisional state and actually complete.
2521 const ResourceError& error = protector->mainDocumentError();
2522 if (error.isNull())
2523 return;
2524
2525 // Check all children first.
2526 RefPtr<HistoryItem> item;
2527 if (Page* page = m_frame.page()) {
2528 if (isBackForwardLoadType(loadType())) {
2529 // Reset the back forward list to the last committed history item at the top level.
2530 item = page->mainFrame().loader().history().currentItem();
2531 }
2532 }
2533
2534 // Only reset if we aren't already going to a new provisional item.
2535 bool shouldReset = !history().provisionalItem();
2536 if (!protector->isLoadingInAPISense() || protector->isStopping()) {
2537 FRAMELOADER_RELEASE_LOG(ResourceLoading, "checkLoadCompleteForThisFrame: Failed provisional load (isTimeout = %d, isCancellation = %d, errorCode = %d)", error.isTimeout(), error.isCancellation(), error.errorCode());
2538
2539 dispatchDidFailProvisionalLoad(*protector, error);
2540 ASSERT(!protector->isLoading());
2541
2542 // If we're in the middle of loading multipart data, we need to restore the document loader.
2543 if (isReplacing() && !m_documentLoader.get())
2544 setDocumentLoader(m_provisionalDocumentLoader.get());
2545
2546 // Finish resetting the load state, but only if another load hasn't been started by the
2547 // delegate callback.
2548 if (protector == m_provisionalDocumentLoader)
2549 clearProvisionalLoad();
2550 else if (activeDocumentLoader()) {
2551 URL unreachableURL = activeDocumentLoader()->unreachableURL();
2552 if (!unreachableURL.isEmpty() && unreachableURL == protector->request().url())
2553 shouldReset = false;
2554 }
2555 }
2556 if (shouldReset && item) {
2557 if (Page* page = m_frame.page())
2558 page->backForward().setCurrentItem(*item);
2559 }
2560 return;
2561 }
2562
2563 case FrameState::CommittedPage: {
2564 if (!m_documentLoader)
2565 return;
2566 if (m_documentLoader->isLoadingInAPISense() && !m_documentLoader->isStopping() && !m_checkingLoadCompleteForDetachment)
2567 return;
2568
2569 setState(FrameState::Complete);
2570
2571 // FIXME: Is this subsequent work important if we already navigated away?
2572 // Maybe there are bugs because of that, or extra work we can skip because
2573 // the new page is ready.
2574
2575 m_client->forceLayoutForNonHTML();
2576
2577 // If the user had a scroll point, scroll to it, overriding the anchor point if any.
2578 if (m_frame.page()) {
2579 if (isBackForwardLoadType(m_loadType) || isReload(m_loadType))
2580 history().restoreScrollPositionAndViewState();
2581 }
2582
2583 if (m_stateMachine.creatingInitialEmptyDocument() || !m_stateMachine.committedFirstRealDocumentLoad())
2584 return;
2585
2586 m_progressTracker->progressCompleted();
2587 Page* page = m_frame.page();
2588 if (page) {
2589 if (m_frame.isMainFrame()) {
2590 tracePoint(MainResourceLoadDidEnd, PAGE_ID);
2591 page->didFinishLoad();
2592 }
2593 }
2594
2595 if (RefPtr domWindow = m_frame.document() ? m_frame.document()->domWindow() : nullptr)
2596 domWindow->performance().scheduleNavigationObservationTaskIfNeeded();
2597
2598 Ref protector = *m_documentLoader;
2599 const ResourceError& error = protector->mainDocumentError();
2600
2601 AXObjectCache::AXLoadingEvent loadingEvent;
2602 if (!error.isNull()) {
2603 FRAMELOADER_RELEASE_LOG(ResourceLoading, "checkLoadCompleteForThisFrame: Finished frame load with error (isTimeout = %d, isCancellation = %d, errorCode = %d)", error.isTimeout(), error.isCancellation(), error.errorCode());
2604 m_client->dispatchDidFailLoad(error);
2605 loadingEvent = AXObjectCache::AXLoadingFailed;
2606 } else {
2607 FRAMELOADER_RELEASE_LOG(ResourceLoading, "checkLoadCompleteForThisFrame: Finished frame load");
2608#if ENABLE(DATA_DETECTION)
2609 auto document = m_frame.document();
2610 auto types = OptionSet<DataDetectorType> { m_frame.settings().dataDetectorTypes() };
2611 if (document && types) {
2612 auto documentLevelResults = retainPtr(DataDetection::detectContentInRange(makeRangeSelectingNodeContents(*document), types, m_client->dataDetectionContext()));
2613 m_frame.dataDetectionResults().setDocumentLevelResults(documentLevelResults.get());
2614 if (m_frame.isMainFrame())
2615 m_client->dispatchDidFinishDataDetection(documentLevelResults.get());
2616 }
2617#endif
2618 m_client->dispatchDidFinishLoad();
2619 loadingEvent = AXObjectCache::AXLoadingFinished;
2620 }
2621
2622 // Notify accessibility.
2623 if (auto* document = m_frame.document()) {
2624 if (AXObjectCache* cache = document->existingAXObjectCache())
2625 cache->frameLoadingEventNotification(&m_frame, loadingEvent);
2626 }
2627
2628 // The above calls to dispatchDidFinishLoad() might have detached the Frame
2629 // from its Page and also might have caused Page to be deleted.
2630 // Don't assume 'page' is still available to use.
2631 if (m_frame.isMainFrame() && m_frame.page()) {
2632 ASSERT(&m_frame.page()->mainFrame() == &m_frame);
2633 m_frame.page()->diagnosticLoggingClient().logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageLoadedKey(), emptyString(), error.isNull() ? DiagnosticLoggingResultPass : DiagnosticLoggingResultFail, ShouldSample::Yes);
2634 }
2635
2636 return;
2637 }
2638
2639 case FrameState::Complete:
2640 m_loadType = FrameLoadType::Standard;
2641 frameLoadCompleted();
2642 return;
2643 }
2644
2645 ASSERT_NOT_REACHED();
2646}
2647
2648void FrameLoader::setOriginalURLForDownloadRequest(ResourceRequest& request)
2649{
2650 // FIXME: Rename firstPartyForCookies back to mainDocumentURL. It was a mistake to think that it was only used for cookies.
2651 // The originalURL is defined as the URL of the page where the download was initiated.
2652 URL originalURL;
2653 auto* initiator = m_frame.document();
2654 if (initiator) {
2655 originalURL = initiator->firstPartyForCookies();
2656 // If there is no main document URL, it means that this document is newly opened and just for download purpose.
2657 // In this case, we need to set the originalURL to this document's opener's main document URL.
2658 if (originalURL.isEmpty() && opener() && opener()->document()) {
2659 originalURL = opener()->document()->firstPartyForCookies();
2660 initiator = opener()->document();
2661 }
2662 }
2663 // If the originalURL is the same as the requested URL, we are processing a download
2664 // initiated directly without a page and do not need to specify the originalURL.
2665 if (originalURL == request.url())
2666 request.setFirstPartyForCookies(URL());
2667 else
2668 request.setFirstPartyForCookies(originalURL);
2669 addSameSiteInfoToRequestIfNeeded(request, initiator);
2670}
2671
2672void FrameLoader::didReachLayoutMilestone(OptionSet<LayoutMilestone> milestones)
2673{
2674 ASSERT(m_frame.isMainFrame());
2675
2676 m_client->dispatchDidReachLayoutMilestone(milestones);
2677}
2678
2679void FrameLoader::didFirstLayout()
2680{
2681#if PLATFORM(IOS_FAMILY)
2682 // Only send layout-related delegate callbacks synchronously for the main frame to
2683 // avoid reentering layout for the main frame while delivering a layout-related delegate
2684 // callback for a subframe.
2685 if (&m_frame != &m_frame.page()->mainFrame())
2686 return;
2687#endif
2688 if (m_frame.page() && isBackForwardLoadType(m_loadType))
2689 history().restoreScrollPositionAndViewState();
2690
2691 if (m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
2692 m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
2693}
2694
2695void FrameLoader::didReachVisuallyNonEmptyState()
2696{
2697 ASSERT(m_frame.isMainFrame());
2698 m_client->dispatchDidReachVisuallyNonEmptyState();
2699}
2700
2701void FrameLoader::frameLoadCompleted()
2702{
2703 // Note: Can be called multiple times.
2704
2705 m_client->frameLoadCompleted();
2706
2707 history().updateForFrameLoadCompleted();
2708
2709 // After a canceled provisional load, firstLayoutDone is false.
2710 // Reset it to true if we're displaying a page.
2711 if (m_documentLoader && m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
2712 m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
2713}
2714
2715void FrameLoader::detachChildren()
2716{
2717 // detachChildren() will fire the unload event in each subframe and the
2718 // HTML specification states that the parent document's ignore-opens-during-unload counter while
2719 // this event is being fired in its subframes:
2720 // https://html.spec.whatwg.org/multipage/browsers.html#unload-a-document
2721 IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(m_frame.document());
2722
2723 // detachChildren() will fire the unload event in each subframe and the
2724 // HTML specification states that navigations should be prevented during the prompt to unload algorithm:
2725 // https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate
2726 std::unique_ptr<NavigationDisabler> navigationDisabler;
2727 if (m_frame.isMainFrame())
2728 navigationDisabler = makeUnique<NavigationDisabler>(&m_frame);
2729
2730 // Any subframe inserted by unload event handlers executed in the loop below will not get unloaded
2731 // because we create a copy of the subframes list before looping. Therefore, it would be unsafe to
2732 // allow loading of subframes at this point.
2733 SubframeLoadingDisabler subframeLoadingDisabler(m_frame.document());
2734
2735 Vector<Ref<Frame>, 16> childrenToDetach;
2736 childrenToDetach.reserveInitialCapacity(m_frame.tree().childCount());
2737 for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling())
2738 childrenToDetach.uncheckedAppend(*child);
2739 for (auto& child : childrenToDetach)
2740 child->loader().detachFromParent();
2741}
2742
2743void FrameLoader::closeAndRemoveChild(Frame& child)
2744{
2745 child.tree().detachFromParent();
2746
2747 child.setView(nullptr);
2748 child.willDetachPage();
2749 child.detachFromPage();
2750
2751 m_frame.tree().removeChild(child);
2752}
2753
2754// Called every time a resource is completely loaded or an error is received.
2755void FrameLoader::checkLoadComplete()
2756{
2757 m_shouldCallCheckLoadComplete = false;
2758
2759 if (!m_frame.page())
2760 return;
2761
2762 ASSERT(m_client->hasWebView());
2763
2764 // FIXME: Always traversing the entire frame tree is a bit inefficient, but
2765 // is currently needed in order to null out the previous history item for all frames.
2766 Vector<Ref<Frame>, 16> frames;
2767 for (Frame* frame = &m_frame.mainFrame(); frame; frame = frame->tree().traverseNext())
2768 frames.append(*frame);
2769
2770 // To process children before their parents, iterate the vector backwards.
2771 for (auto frame = frames.rbegin(); frame != frames.rend(); ++frame) {
2772 if ((*frame)->page())
2773 (*frame)->loader().checkLoadCompleteForThisFrame();
2774 }
2775}
2776
2777int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
2778{
2779 if (!recurse)
2780 return m_frame.document()->cachedResourceLoader().requestCount();
2781
2782 int count = 0;
2783 for (Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext(&m_frame))
2784 count += frame->document()->cachedResourceLoader().requestCount();
2785 return count;
2786}
2787
2788String FrameLoader::userAgent(const URL& url) const
2789{
2790 String userAgent;
2791
2792 if (auto* documentLoader = m_frame.mainFrame().loader().activeDocumentLoader()) {
2793 if (m_frame.settings().needsSiteSpecificQuirks())
2794 userAgent = documentLoader->customUserAgentAsSiteSpecificQuirks();
2795 if (userAgent.isEmpty())
2796 userAgent = documentLoader->customUserAgent();
2797 }
2798
2799 InspectorInstrumentation::applyUserAgentOverride(m_frame, userAgent);
2800
2801 if (!userAgent.isEmpty())
2802 return userAgent;
2803
2804 return m_client->userAgent(url);
2805}
2806
2807String FrameLoader::navigatorPlatform() const
2808{
2809 if (auto* documentLoader = m_frame.mainFrame().loader().activeDocumentLoader()) {
2810 auto& customNavigatorPlatform = documentLoader->customNavigatorPlatform();
2811 if (!customNavigatorPlatform.isEmpty())
2812 return customNavigatorPlatform;
2813 }
2814 return String();
2815}
2816
2817void FrameLoader::dispatchOnloadEvents()
2818{
2819 m_client->dispatchDidDispatchOnloadEvents();
2820
2821 if (documentLoader())
2822 documentLoader()->dispatchOnloadEvents();
2823}
2824
2825void FrameLoader::frameDetached()
2826{
2827 // Calling stopAllLoadersAndCheckCompleteness() can cause the frame to be deallocated, including the frame loader.
2828 Ref<Frame> protectedFrame(m_frame);
2829
2830 if (m_checkTimer.isActive()) {
2831 m_checkTimer.stop();
2832 checkCompletenessNow();
2833 }
2834
2835 if (m_frame.document()->backForwardCacheState() != Document::InBackForwardCache)
2836 stopAllLoadersAndCheckCompleteness();
2837
2838 detachFromParent();
2839
2840 if (m_frame.document()->backForwardCacheState() != Document::InBackForwardCache)
2841 m_frame.document()->stopActiveDOMObjects();
2842}
2843
2844void FrameLoader::detachFromParent()
2845{
2846 // Calling stopAllLoaders() can cause the frame to be deallocated, including the frame loader.
2847 Ref<Frame> protect(m_frame);
2848
2849 closeURL();
2850 history().saveScrollPositionAndViewStateToItem(history().currentItem());
2851 detachChildren();
2852 if (m_frame.document()->backForwardCacheState() != Document::InBackForwardCache) {
2853 // stopAllLoaders() needs to be called after detachChildren() if the document is not in the back/forward cache,
2854 // because detachedChildren() will trigger the unload event handlers of any child frames, and those event
2855 // handlers might start a new subresource load in this frame.
2856 stopAllLoaders(ClearProvisionalItem::Yes, StopLoadingPolicy::AlwaysStopLoading);
2857 }
2858
2859 InspectorInstrumentation::frameDetachedFromParent(m_frame);
2860
2861 detachViewsAndDocumentLoader();
2862
2863 m_progressTracker = nullptr;
2864
2865 if (Frame* parent = m_frame.tree().parent()) {
2866 parent->loader().closeAndRemoveChild(m_frame);
2867 parent->loader().scheduleCheckCompleted();
2868 parent->loader().scheduleCheckLoadComplete();
2869 } else {
2870 m_frame.setView(nullptr);
2871 m_frame.willDetachPage();
2872 m_frame.detachFromPage();
2873 }
2874}
2875
2876void FrameLoader::detachViewsAndDocumentLoader()
2877{
2878 m_client->detachedFromParent2();
2879 setDocumentLoader(nullptr);
2880 m_client->detachedFromParent3();
2881}
2882
2883ResourceRequestCachePolicy FrameLoader::defaultRequestCachingPolicy(const ResourceRequest& request, FrameLoadType loadType, bool isMainResource)
2884{
2885 if (m_overrideCachePolicyForTesting)
2886 return m_overrideCachePolicyForTesting.value();
2887
2888 if (isMainResource) {
2889 if (isReload(loadType) || request.isConditional())
2890 return ResourceRequestCachePolicy::ReloadIgnoringCacheData;
2891
2892 return ResourceRequestCachePolicy::UseProtocolCachePolicy;
2893 }
2894
2895 if (request.isConditional())
2896 return ResourceRequestCachePolicy::ReloadIgnoringCacheData;
2897
2898 auto* documentLoader = this->documentLoader();
2899 if (documentLoader && documentLoader->isLoadingInAPISense()) {
2900 // If we inherit cache policy from a main resource, we use the DocumentLoader's
2901 // original request cache policy for two reasons:
2902 // 1. For POST requests, we mutate the cache policy for the main resource,
2903 // but we do not want this to apply to subresources
2904 // 2. Delegates that modify the cache policy using willSendRequest: should
2905 // not affect any other resources. Such changes need to be done
2906 // per request.
2907 ResourceRequestCachePolicy mainDocumentOriginalCachePolicy = documentLoader->originalRequest().cachePolicy();
2908 // Back-forward navigations try to load main resource from cache only to avoid re-submitting form data, and start over (with a warning dialog) if that fails.
2909 // This policy is set on initial request too, but should not be inherited.
2910 return (mainDocumentOriginalCachePolicy == ResourceRequestCachePolicy::ReturnCacheDataDontLoad) ? ResourceRequestCachePolicy::ReturnCacheDataElseLoad : mainDocumentOriginalCachePolicy;
2911 }
2912
2913 return ResourceRequestCachePolicy::UseProtocolCachePolicy;
2914}
2915
2916void FrameLoader::updateRequestAndAddExtraFields(ResourceRequest& request, IsMainResource mainResource, FrameLoadType loadType, ShouldUpdateAppInitiatedValue shouldUpdate, IsServiceWorkerNavigationLoad isServiceWorkerNavigationLoad, Document* initiator)
2917{
2918 ASSERT(isServiceWorkerNavigationLoad == IsServiceWorkerNavigationLoad::No || mainResource != IsMainResource::Yes);
2919
2920 // If the request came from a previous process due to process-swap-on-navigation then we should not modify the request.
2921 if (m_currentLoadContinuingState == LoadContinuingState::ContinuingWithRequest)
2922 return;
2923
2924 // Don't set the cookie policy URL if it's already been set.
2925 // But make sure to set it on all requests regardless of protocol, as it has significance beyond the cookie policy (<rdar://problem/6616664>).
2926 bool isMainResource = mainResource == IsMainResource::Yes;
2927 bool isMainFrameMainResource = isMainResource && m_frame.isMainFrame();
2928 if (request.firstPartyForCookies().isEmpty()) {
2929 if (isMainFrameMainResource)
2930 request.setFirstPartyForCookies(request.url());
2931 else if (Document* document = m_frame.document())
2932 request.setFirstPartyForCookies(document->firstPartyForCookies());
2933 }
2934
2935 if (request.isSameSiteUnspecified()) {
2936 if (!initiator) {
2937 initiator = m_frame.document();
2938 if (isMainResource) {
2939 auto* ownerFrame = m_frame.tree().parent();
2940 if (!ownerFrame && m_stateMachine.isDisplayingInitialEmptyDocument())
2941 ownerFrame = m_opener.get();
2942 if (ownerFrame)
2943 initiator = ownerFrame->document();
2944 ASSERT(ownerFrame || m_frame.isMainFrame());
2945 }
2946 }
2947 addSameSiteInfoToRequestIfNeeded(request, initiator);
2948 }
2949
2950 // In case of service worker navigation load, we inherit isTopSite from the FetchEvent request directly.
2951 if (isServiceWorkerNavigationLoad == IsServiceWorkerNavigationLoad::No)
2952 request.setIsTopSite(isMainFrameMainResource);
2953
2954 Page* page = frame().page();
2955 bool hasSpecificCachePolicy = request.cachePolicy() != ResourceRequestCachePolicy::UseProtocolCachePolicy;
2956
2957 if (page && page->isResourceCachingDisabledByWebInspector()) {
2958 request.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
2959 loadType = FrameLoadType::ReloadFromOrigin;
2960 } else if (!hasSpecificCachePolicy)
2961 request.setCachePolicy(defaultRequestCachingPolicy(request, loadType, isMainResource));
2962
2963 // The remaining modifications are only necessary for HTTP and HTTPS.
2964 if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily())
2965 return;
2966
2967 if (!hasSpecificCachePolicy && request.cachePolicy() == ResourceRequestCachePolicy::ReloadIgnoringCacheData) {
2968 if (loadType == FrameLoadType::Reload)
2969 request.setHTTPHeaderField(HTTPHeaderName::CacheControl, HTTPHeaderValues::maxAge0());
2970 else if (loadType == FrameLoadType::ReloadFromOrigin) {
2971 request.setHTTPHeaderField(HTTPHeaderName::CacheControl, HTTPHeaderValues::noCache());
2972 request.setHTTPHeaderField(HTTPHeaderName::Pragma, HTTPHeaderValues::noCache());
2973 }
2974 }
2975
2976 if (m_overrideResourceLoadPriorityForTesting)
2977 request.setPriority(m_overrideResourceLoadPriorityForTesting.value());
2978
2979 // Make sure we send the Origin header.
2980 addHTTPOriginIfNeeded(request, String());
2981
2982 applyUserAgentIfNeeded(request);
2983
2984 if (isMainResource)
2985 request.setHTTPHeaderField(HTTPHeaderName::Accept, CachedResourceRequest::acceptHeaderValueFromType(CachedResource::Type::MainResource));
2986
2987 // Only set fallback array if it's still empty (later attempts may be incorrect, see bug 117818).
2988 if (request.responseContentDispositionEncodingFallbackArray().isEmpty()) {
2989 // Always try UTF-8. If that fails, try frame encoding (if any) and then the default.
2990 request.setResponseContentDispositionEncodingFallbackArray("UTF-8"_s, m_frame.document()->encoding(), m_frame.settings().defaultTextEncodingName());
2991 }
2992
2993 if (shouldUpdate == ShouldUpdateAppInitiatedValue::Yes && m_frame.mainFrame().loader().documentLoader())
2994 request.setIsAppInitiated(m_frame.mainFrame().loader().documentLoader()->lastNavigationWasAppInitiated());
2995}
2996
2997void FrameLoader::scheduleRefreshIfNeeded(Document& document, const String& content, IsMetaRefresh isMetaRefresh)
2998{
2999 double delay = 0;
3000 String urlString;
3001 if (parseMetaHTTPEquivRefresh(content, delay, urlString)) {
3002 auto completedURL = urlString.isEmpty() ? document.url() : document.completeURL(urlString);
3003 if (!completedURL.protocolIsJavaScript())
3004 m_frame.navigationScheduler().scheduleRedirect(document, delay, completedURL, isMetaRefresh);
3005 else {
3006 String message = "Refused to refresh " + document.url().stringCenterEllipsizedToLength() + " to a javascript: URL";
3007 document.addConsoleMessage(MessageSource::Security, MessageLevel::Error, message);
3008 }
3009 }
3010}
3011
3012void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, const String& origin)
3013{
3014 if (!request.httpOrigin().isEmpty())
3015 return; // Request already has an Origin header.
3016
3017 // Don't send an Origin header for GET or HEAD to avoid privacy issues.
3018 // For example, if an intranet page has a hyperlink to an external web
3019 // site, we don't want to include the Origin of the request because it
3020 // will leak the internal host name. Similar privacy concerns have lead
3021 // to the widespread suppression of the Referer header at the network
3022 // layer.
3023 if (request.httpMethod() == "GET"_s || request.httpMethod() == "HEAD"_s)
3024 return;
3025
3026 // FIXME: take referrer-policy into account.
3027 // https://bugs.webkit.org/show_bug.cgi?id=209066
3028
3029 // For non-GET and non-HEAD methods, always send an Origin header so the
3030 // server knows we support this feature.
3031
3032 if (origin.isEmpty()) {
3033 // If we don't know what origin header to attach, we attach the value
3034 // for an empty origin.
3035 request.setHTTPOrigin(SecurityOrigin::createUnique()->toString());
3036 return;
3037 }
3038
3039 request.setHTTPOrigin(origin);
3040}
3041
3042// Implements the "'Same-site' and 'cross-site' Requests" algorithm from <https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00#section-2.1>.
3043// The algorithm is ammended to treat URLs that inherit their security origin from their owner (e.g. about:blank)
3044// as same-site. This matches the behavior of Chrome and Firefox.
3045void FrameLoader::addSameSiteInfoToRequestIfNeeded(ResourceRequest& request, const Document* initiator)
3046{
3047 if (!request.isSameSiteUnspecified())
3048 return;
3049 if (!initiator) {
3050 request.setIsSameSite(true);
3051 return;
3052 }
3053 if (SecurityPolicy::shouldInheritSecurityOriginFromOwner(request.url())) {
3054 request.setIsSameSite(true);
3055 return;
3056 }
3057
3058 request.setIsSameSite(initiator->isSameSiteForCookies(request.url()));
3059}
3060
3061void FrameLoader::loadPostRequest(FrameLoadRequest&& request, const String& referrer, FrameLoadType loadType, Event* event, RefPtr<FormState>&& formState, CompletionHandler<void()>&& completionHandler)
3062{
3063 FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadPostRequest: frame load started");
3064
3065 auto frameName = request.frameName();
3066 LockHistory lockHistory = request.lockHistory();
3067 AllowNavigationToInvalidURL allowNavigationToInvalidURL = request.allowNavigationToInvalidURL();
3068 NewFrameOpenerPolicy openerPolicy = request.newFrameOpenerPolicy();
3069
3070 const ResourceRequest& inRequest = request.resourceRequest();
3071 const URL& url = inRequest.url();
3072 const String& contentType = inRequest.httpContentType();
3073 String origin = inRequest.httpOrigin();
3074
3075 ResourceRequest workingResourceRequest(url);
3076
3077 if (!referrer.isEmpty())
3078 workingResourceRequest.setHTTPReferrer(referrer);
3079 workingResourceRequest.setHTTPOrigin(origin);
3080 workingResourceRequest.setHTTPMethod("POST"_s);
3081 workingResourceRequest.setHTTPBody(inRequest.httpBody());
3082 workingResourceRequest.setHTTPContentType(contentType);
3083 updateRequestAndAddExtraFields(workingResourceRequest, IsMainResource::Yes, loadType, ShouldUpdateAppInitiatedValue::Yes, FrameLoader::IsServiceWorkerNavigationLoad::No, &request.requester());
3084
3085 if (Document* document = m_frame.document())
3086 document->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(workingResourceRequest, ContentSecurityPolicy::InsecureRequestType::Load);
3087
3088 NavigationAction action { request.requester(), workingResourceRequest, request.initiatedByMainFrame(), loadType, true, event, request.shouldOpenExternalURLsPolicy(), { } };
3089 action.setLockHistory(lockHistory);
3090 action.setShouldReplaceDocumentIfJavaScriptURL(request.shouldReplaceDocumentIfJavaScriptURL());
3091
3092 if (!frameName.isEmpty()) {
3093 // The search for a target frame is done earlier in the case of form submission.
3094 if (auto* targetFrame = formState ? nullptr : findFrameForNavigation(frameName)) {
3095 targetFrame->loader().loadWithNavigationAction(workingResourceRequest, WTFMove(action), loadType, WTFMove(formState), allowNavigationToInvalidURL, request.shouldTreatAsContinuingLoad(), WTFMove(completionHandler));
3096 return;
3097 }
3098
3099 // https://html.spec.whatwg.org/#the-rules-for-choosing-a-browsing-context-given-a-browsing-context-name (Step 8.2)
3100 if (request.requester().shouldForceNoOpenerBasedOnCOOP()) {
3101 frameName = blankTargetFrameName();
3102 openerPolicy = NewFrameOpenerPolicy::Suppress;
3103 }
3104
3105 policyChecker().checkNewWindowPolicy(WTFMove(action), WTFMove(workingResourceRequest), WTFMove(formState), frameName, [this, allowNavigationToInvalidURL, openerPolicy, completionHandler = WTFMove(completionHandler)] (const ResourceRequest& request, WeakPtr<FormState>&& formState, const AtomString& frameName, const NavigationAction& action, ShouldContinuePolicyCheck shouldContinue) mutable {
3106 continueLoadAfterNewWindowPolicy(request, formState.get(), frameName, action, shouldContinue, allowNavigationToInvalidURL, openerPolicy);
3107 completionHandler();
3108 });
3109 return;
3110 }
3111
3112 // must grab this now, since this load may stop the previous load and clear this flag
3113 bool isRedirect = m_quickRedirectComing;
3114 loadWithNavigationAction(workingResourceRequest, WTFMove(action), loadType, WTFMove(formState), allowNavigationToInvalidURL, request.shouldTreatAsContinuingLoad(), [this, isRedirect, protectedFrame = Ref { m_frame }, completionHandler = WTFMove(completionHandler)] () mutable {
3115 if (isRedirect) {
3116 m_quickRedirectComing = false;
3117 if (m_provisionalDocumentLoader)
3118 m_provisionalDocumentLoader->setIsClientRedirect(true);
3119 else if (m_policyDocumentLoader)
3120 m_policyDocumentLoader->setIsClientRedirect(true);
3121 }
3122 completionHandler();
3123 });
3124}
3125
3126ResourceLoaderIdentifier FrameLoader::loadResourceSynchronously(const ResourceRequest& request, ClientCredentialPolicy clientCredentialPolicy, const FetchOptions& options, const HTTPHeaderMap& originalRequestHeaders, ResourceError& error, ResourceResponse& response, RefPtr<SharedBuffer>& data)
3127{
3128 ASSERT(m_frame.document());
3129 String referrer = SecurityPolicy::generateReferrerHeader(m_frame.document()->referrerPolicy(), request.url(), outgoingReferrer());
3130
3131 ResourceRequest initialRequest = request;
3132 initialRequest.setTimeoutInterval(10);
3133
3134 if (!referrer.isEmpty())
3135 initialRequest.setHTTPReferrer(referrer);
3136 addHTTPOriginIfNeeded(initialRequest, outgoingOrigin());
3137
3138 initialRequest.setFirstPartyForCookies(m_frame.mainFrame().loader().documentLoader()->request().url());
3139
3140 updateRequestAndAddExtraFields(initialRequest, IsMainResource::No);
3141
3142 applyUserAgentIfNeeded(initialRequest);
3143
3144 ResourceLoaderIdentifier identifier;
3145 ResourceRequest newRequest(initialRequest);
3146 requestFromDelegate(newRequest, identifier, error);
3147
3148#if ENABLE(CONTENT_EXTENSIONS)
3149 if (error.isNull()) {
3150 if (auto* page = m_frame.page()) {
3151 if (m_documentLoader) {
3152 auto results = page->userContentProvider().processContentRuleListsForLoad(*page, newRequest.url(), ContentExtensions::ResourceType::Fetch, *m_documentLoader);
3153 bool blockedLoad = results.summary.blockedLoad;
3154 ContentExtensions::applyResultsToRequest(WTFMove(results), page, newRequest);
3155 if (blockedLoad) {
3156 newRequest = { };
3157 error = ResourceError(errorDomainWebKitInternal, 0, initialRequest.url(), emptyString());
3158 response = { };
3159 data = nullptr;
3160 }
3161 }
3162 }
3163 }
3164#endif
3165
3166 m_frame.document()->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(newRequest, ContentSecurityPolicy::InsecureRequestType::Load);
3167
3168 if (error.isNull()) {
3169 ASSERT(!newRequest.isNull());
3170
3171 if (!documentLoader()->applicationCacheHost().maybeLoadSynchronously(newRequest, error, response, data)) {
3172 Vector<uint8_t> buffer;
3173 platformStrategies()->loaderStrategy()->loadResourceSynchronously(*this, identifier, newRequest, clientCredentialPolicy, options, originalRequestHeaders, error, response, buffer);
3174 data = SharedBuffer::create(WTFMove(buffer));
3175 documentLoader()->applicationCacheHost().maybeLoadFallbackSynchronously(newRequest, error, response, data);
3176 ResourceLoadObserver::shared().logSubresourceLoading(&m_frame, newRequest, response,
3177 (isScriptLikeDestination(options.destination) ? ResourceLoadObserver::FetchDestinationIsScriptLike::Yes : ResourceLoadObserver::FetchDestinationIsScriptLike::No));
3178 }
3179 }
3180
3181 notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, response, data.get(), data ? data->size() : 0, -1, error);
3182 return identifier;
3183}
3184
3185void FrameLoader::receivedMainResourceError(const ResourceError& error)
3186{
3187 // Retain because the stop may release the last reference to it.
3188 Ref<Frame> protect(m_frame);
3189
3190 RefPtr<DocumentLoader> loader = activeDocumentLoader();
3191 // FIXME: Don't want to do this if an entirely new load is going, so should check
3192 // that both data sources on the frame are either this or nil.
3193 stop();
3194 if (m_client->shouldFallBack(error)) {
3195 HTMLFrameOwnerElement* owner = m_frame.ownerElement();
3196 if (is<HTMLObjectElement>(owner))
3197 downcast<HTMLObjectElement>(*owner).renderFallbackContent();
3198 }
3199
3200 if (m_state == FrameState::Provisional && m_provisionalDocumentLoader) {
3201 if (m_submittedFormURL == m_provisionalDocumentLoader->originalRequestCopy().url())
3202 m_submittedFormURL = URL();
3203
3204 // We might have made a back/forward cache item, but now we're bailing out due to an error before we ever
3205 // transitioned to the new page (before WebFrameState == commit). The goal here is to restore any state
3206 // so that the existing view (that wenever got far enough to replace) can continue being used.
3207 history().invalidateCurrentItemCachedPage();
3208
3209 // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
3210 // status has changed, if there was a redirect. The frame load delegate may have saved some state about
3211 // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
3212 // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
3213 // has ended.
3214 if (m_sentRedirectNotification)
3215 clientRedirectCancelledOrFinished(NewLoadInProgress::No);
3216 }
3217
3218 checkCompleted();
3219 if (m_frame.page())
3220 checkLoadComplete();
3221}
3222
3223void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
3224{
3225 m_quickRedirectComing = false;
3226
3227 if (!shouldContinue)
3228 return;
3229
3230 // Calling stopLoading() on the provisional document loader can cause the underlying
3231 // frame to be deallocated.
3232 Ref<Frame> protectedFrame(m_frame);
3233
3234 // If we have a provisional request for a different document, a fragment scroll should cancel it.
3235 if (m_provisionalDocumentLoader && !equalIgnoringFragmentIdentifier(m_provisionalDocumentLoader->request().url(), request.url())) {
3236 m_provisionalDocumentLoader->stopLoading();
3237 FRAMELOADER_RELEASE_LOG(ResourceLoading, "continueFragmentScrollAfterNavigationPolicy: Clearing provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
3238 setProvisionalDocumentLoader(nullptr);
3239 }
3240
3241 bool isRedirect = m_quickRedirectComing || policyChecker().loadType() == FrameLoadType::RedirectWithLockedBackForwardList;
3242 loadInSameDocument(request.url(), nullptr, !isRedirect);
3243}
3244
3245bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const URL& url)
3246{
3247 // We don't do this if we are submitting a form with method other than "GET", explicitly reloading,
3248 // currently displaying a frameset, or if the URL does not have a fragment.
3249 // These rules were originally based on what KHTML was doing in KHTMLPart::openURL.
3250
3251 // FIXME: What about load types other than Standard and Reload?
3252
3253 return (!isFormSubmission || equalLettersIgnoringASCIICase(httpMethod, "get"_s))
3254 && !isReload(loadType)
3255 && loadType != FrameLoadType::Same
3256 && m_frame.document()->backForwardCacheState() != Document::InBackForwardCache
3257 && !shouldReload(m_frame.document()->url(), url)
3258 // We don't want to just scroll if a link from within a
3259 // frameset is trying to reload the frameset into _top.
3260 && !m_frame.document()->isFrameSet()
3261 && !stateMachine().isDisplayingInitialEmptyDocument();
3262}
3263
3264static bool itemAllowsScrollRestoration(HistoryItem* historyItem)
3265{
3266 return !historyItem || historyItem->shouldRestoreScrollPosition();
3267}
3268
3269static bool isSameDocumentReload(bool isNewNavigation, FrameLoadType loadType)
3270{
3271 return !isNewNavigation && !isBackForwardLoadType(loadType);
3272}
3273
3274void FrameLoader::scrollToFragmentWithParentBoundary(const URL& url, bool isNewNavigation)
3275{
3276 RefPtr view = m_frame.view();
3277 RefPtr document = m_frame.document();
3278 if (!view || !document)
3279 return;
3280
3281 if (isSameDocumentReload(isNewNavigation, m_loadType) || itemAllowsScrollRestoration(history().currentItem())) {
3282 // https://html.spec.whatwg.org/multipage/browsing-the-web.html#try-to-scroll-to-the-fragment
3283 if (!document->haveStylesheetsLoaded())
3284 document->setGotoAnchorNeededAfterStylesheetsLoad(true);
3285 else
3286 view->scrollToFragment(url);
3287 }
3288
3289}
3290
3291bool FrameLoader::shouldClose()
3292{
3293 Page* page = m_frame.page();
3294 if (!page)
3295 return true;
3296 if (!page->chrome().canRunBeforeUnloadConfirmPanel())
3297 return true;
3298
3299 // Store all references to each subframe in advance since beforeunload's event handler may modify frame
3300 Vector<Ref<Frame>, 16> targetFrames;
3301 targetFrames.append(m_frame);
3302 for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().traverseNext(&m_frame))
3303 targetFrames.append(*child);
3304
3305 bool shouldClose = false;
3306 {
3307 NavigationDisabler navigationDisabler(&m_frame);
3308 IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(m_frame.document());
3309 size_t i;
3310
3311 for (i = 0; i < targetFrames.size(); i++) {
3312 if (!targetFrames[i]->tree().isDescendantOf(&m_frame))
3313 continue;
3314 if (!targetFrames[i]->loader().dispatchBeforeUnloadEvent(page->chrome(), this))
3315 break;
3316 }
3317
3318 if (i == targetFrames.size())
3319 shouldClose = true;
3320 }
3321
3322 if (!shouldClose)
3323 m_submittedFormURL = URL();
3324
3325 m_currentNavigationHasShownBeforeUnloadConfirmPanel = false;
3326 return shouldClose;
3327}
3328
3329void FrameLoader::dispatchUnloadEvents(UnloadEventPolicy unloadEventPolicy)
3330{
3331 if (!m_frame.document())
3332 return;
3333
3334 if (m_pageDismissalEventBeingDispatched != PageDismissalType::None)
3335 return;
3336
3337 // We store the frame's page in a local variable because the frame might get detached inside dispatchEvent.
3338 ForbidPromptsScope forbidPrompts(m_frame.page());
3339 ForbidSynchronousLoadsScope forbidSynchronousLoads(m_frame.page());
3340 IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(m_frame.document());
3341
3342 if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) {
3343 auto* currentFocusedElement = m_frame.document()->focusedElement();
3344 if (is<HTMLInputElement>(currentFocusedElement))
3345 downcast<HTMLInputElement>(*currentFocusedElement).endEditing();
3346 if (m_pageDismissalEventBeingDispatched == PageDismissalType::None) {
3347 if (unloadEventPolicy == UnloadEventPolicy::UnloadAndPageHide) {
3348 m_pageDismissalEventBeingDispatched = PageDismissalType::PageHide;
3349 m_frame.document()->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame.document()->backForwardCacheState() == Document::AboutToEnterBackForwardCache), m_frame.document());
3350 }
3351
3352 // This takes care of firing the visibilitychange event and making sure the document is reported as hidden.
3353 m_frame.document()->setVisibilityHiddenDueToDismissal(true);
3354
3355 if (m_frame.document()->backForwardCacheState() == Document::NotInBackForwardCache) {
3356 Ref<Event> unloadEvent(Event::create(eventNames().unloadEvent, Event::CanBubble::No, Event::IsCancelable::No));
3357 // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed
3358 // while dispatching the event, so protect it to prevent writing the end
3359 // time into freed memory.
3360 RefPtr<DocumentLoader> documentLoader = m_provisionalDocumentLoader;
3361 auto* timing = documentLoader ? &documentLoader->timing() : nullptr;
3362 m_pageDismissalEventBeingDispatched = PageDismissalType::Unload;
3363 if (timing && !timing->unloadEventStart())
3364 timing->markUnloadEventStart();
3365 m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
3366 if (timing && !timing->unloadEventEnd())
3367 timing->markUnloadEventEnd();
3368 }
3369 }
3370 m_pageDismissalEventBeingDispatched = PageDismissalType::None;
3371 m_wasUnloadEventEmitted = true;
3372 }
3373
3374 // Dispatching the unload event could have made m_frame.document() null.
3375 if (!m_frame.document())
3376 return;
3377
3378 if (m_frame.document()->backForwardCacheState() != Document::NotInBackForwardCache)
3379 return;
3380
3381 // Don't remove event listeners from a transitional empty document (see bug 28716 for more information).
3382 bool keepEventListeners = m_stateMachine.isDisplayingInitialEmptyDocument() && m_provisionalDocumentLoader
3383 && m_frame.document()->isSecureTransitionTo(m_provisionalDocumentLoader->url());
3384
3385 if (!keepEventListeners)
3386 m_frame.document()->removeAllEventListeners();
3387}
3388
3389static bool shouldAskForNavigationConfirmation(Document& document, const BeforeUnloadEvent& event)
3390{
3391 // Confirmation dialog should not be displayed when the allow-modals flag is not set.
3392 if (document.isSandboxed(SandboxModals))
3393 return false;
3394
3395 bool userDidInteractWithPage = document.topDocument().userDidInteractWithPage();
3396 // Web pages can request we ask for confirmation before navigating by:
3397 // - Cancelling the BeforeUnloadEvent (modern way)
3398 // - Setting the returnValue attribute on the BeforeUnloadEvent to a non-empty string.
3399 // - Returning a non-empty string from the event handler, which is then set as returnValue
3400 // attribute on the BeforeUnloadEvent.
3401 return userDidInteractWithPage && (event.defaultPrevented() || !event.returnValue().isEmpty());
3402}
3403
3404bool FrameLoader::dispatchBeforeUnloadEvent(Chrome& chrome, FrameLoader* frameLoaderBeingNavigated)
3405{
3406 DOMWindow* domWindow = m_frame.document()->domWindow();
3407 if (!domWindow)
3408 return true;
3409
3410 RefPtr<Document> document = m_frame.document();
3411 if (!document->bodyOrFrameset())
3412 return true;
3413
3414 Ref<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create();
3415
3416 {
3417 SetForScope change(m_pageDismissalEventBeingDispatched, PageDismissalType::BeforeUnload);
3418 ForbidPromptsScope forbidPrompts(m_frame.page());
3419 ForbidSynchronousLoadsScope forbidSynchronousLoads(m_frame.page());
3420 domWindow->dispatchEvent(beforeUnloadEvent, domWindow->document());
3421 }
3422
3423 if (!beforeUnloadEvent->defaultPrevented())
3424 document->defaultEventHandler(beforeUnloadEvent.get());
3425
3426 if (!shouldAskForNavigationConfirmation(*document, beforeUnloadEvent))
3427 return true;
3428
3429 // If the navigating FrameLoader has already shown a beforeunload confirmation panel for the current navigation attempt,
3430 // this frame is not allowed to cause another one to be shown.
3431 if (frameLoaderBeingNavigated->m_currentNavigationHasShownBeforeUnloadConfirmPanel) {
3432 document->addConsoleMessage(MessageSource::JS, MessageLevel::Error, "Blocked attempt to show multiple beforeunload confirmation dialogs for the same navigation."_s);
3433 return true;
3434 }
3435
3436 // We should only display the beforeunload dialog for an iframe if its SecurityOrigin matches all
3437 // ancestor frame SecurityOrigins up through the navigating FrameLoader.
3438 if (frameLoaderBeingNavigated != this) {
3439 Frame* parentFrame = m_frame.tree().parent();
3440 while (parentFrame) {
3441 Document* parentDocument = parentFrame->document();
3442 if (!parentDocument)
3443 return true;
3444 if (!m_frame.document() || !m_frame.document()->securityOrigin().isSameOriginDomain(parentDocument->securityOrigin())) {
3445 document->addConsoleMessage(MessageSource::JS, MessageLevel::Error, "Blocked attempt to show beforeunload confirmation dialog on behalf of a frame with different security origin. Protocols, domains, and ports must match."_s);
3446 return true;
3447 }
3448
3449 if (&parentFrame->loader() == frameLoaderBeingNavigated)
3450 break;
3451
3452 parentFrame = parentFrame->tree().parent();
3453 }
3454
3455 // The navigatingFrameLoader should always be in our ancestory.
3456 ASSERT(parentFrame);
3457 ASSERT(&parentFrame->loader() == frameLoaderBeingNavigated);
3458 }
3459
3460 frameLoaderBeingNavigated->m_currentNavigationHasShownBeforeUnloadConfirmPanel = true;
3461
3462 String text = document->displayStringModifiedByEncoding(beforeUnloadEvent->returnValue());
3463 return chrome.runBeforeUnloadConfirmPanel(text, m_frame);
3464}
3465
3466void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& request, FormState* formState, NavigationPolicyDecision navigationPolicyDecision, AllowNavigationToInvalidURL allowNavigationToInvalidURL)
3467{
3468 // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
3469 // nil policyDataSource because loading the alternate page will have passed
3470 // through this method already, nested; otherwise, policyDataSource should still be set.
3471 ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
3472
3473 bool isTargetItem = history().provisionalItem() ? history().provisionalItem()->isTargetItem() : false;
3474
3475 bool urlIsDisallowed = allowNavigationToInvalidURL == AllowNavigationToInvalidURL::No && !request.url().isValid();
3476 bool canContinue = navigationPolicyDecision == NavigationPolicyDecision::ContinueLoad && shouldClose() && !urlIsDisallowed;
3477
3478 if (!canContinue) {
3479 FRAMELOADER_RELEASE_LOG(ResourceLoading, "continueLoadAfterNavigationPolicy: can't continue loading frame due to the following reasons ("
3480 "allowNavigationToInvalidURL = %d, "
3481 "requestURLIsValid = %d, "
3482 "navigationPolicyDecision = %d)",
3483 static_cast<int>(allowNavigationToInvalidURL),
3484 request.url().isValid(),
3485 static_cast<int>(navigationPolicyDecision));
3486
3487 // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we
3488 // need to report that the client redirect was cancelled.
3489 // FIXME: The client should be told about ignored non-quick redirects, too.
3490 if (m_quickRedirectComing)
3491 clientRedirectCancelledOrFinished(NewLoadInProgress::No);
3492
3493 if (navigationPolicyDecision == NavigationPolicyDecision::StopAllLoads) {
3494 stopAllLoaders();
3495 m_checkTimer.stop();
3496 }
3497
3498 setPolicyDocumentLoader(nullptr);
3499 checkCompleted();
3500
3501 if (navigationPolicyDecision != NavigationPolicyDecision::StopAllLoads)
3502 checkLoadComplete();
3503
3504 // If the navigation request came from the back/forward menu, and we punt on it, we have the
3505 // problem that we have optimistically moved the b/f cursor already, so move it back. For sanity,
3506 // we only do this when punting a navigation for the target frame or top-level frame.
3507 if ((isTargetItem || m_frame.isMainFrame()) && isBackForwardLoadType(policyChecker().loadType())) {
3508 if (Page* page = m_frame.page()) {
3509 if (HistoryItem* resetItem = m_frame.mainFrame().loader().history().currentItem())
3510 page->backForward().setCurrentItem(*resetItem);
3511 }
3512 }
3513 return;
3514 }
3515
3516 FrameLoadType type = policyChecker().loadType();
3517 // A new navigation is in progress, so don't clear the history's provisional item.
3518 stopAllLoaders(ClearProvisionalItem::No);
3519
3520 // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
3521 // might detach the current FrameLoader, in which case we should bail on this newly defunct load.
3522 if (!m_frame.page()) {
3523 FRAMELOADER_RELEASE_LOG(ResourceLoading, "continueLoadAfterNavigationPolicy: can't continue loading frame because it became defunct");
3524 return;
3525 }
3526
3527 setProvisionalDocumentLoader(m_policyDocumentLoader.get());
3528 FRAMELOADER_RELEASE_LOG(ResourceLoading, "continueLoadAfterNavigationPolicy: Setting provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
3529 m_loadType = type;
3530 setState(FrameState::Provisional);
3531
3532 setPolicyDocumentLoader(nullptr);
3533
3534 if (isBackForwardLoadType(type)) {
3535 auto& diagnosticLoggingClient = m_frame.page()->diagnosticLoggingClient();
3536 if (history().provisionalItem() && history().provisionalItem()->isInBackForwardCache()) {
3537 diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::backForwardCacheKey(), DiagnosticLoggingKeys::retrievalKey(), DiagnosticLoggingResultPass, ShouldSample::Yes);
3538 loadProvisionalItemFromCachedPage();
3539 FRAMELOADER_RELEASE_LOG(ResourceLoading, "continueLoadAfterNavigationPolicy: can't continue loading frame because it will be loaded from cache");
3540 return;
3541 }
3542 diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::backForwardCacheKey(), DiagnosticLoggingKeys::retrievalKey(), DiagnosticLoggingResultFail, ShouldSample::Yes);
3543 }
3544
3545 CompletionHandler<void()> completionHandler = [this, protectedFrame = Ref { m_frame }] () mutable {
3546 if (!m_provisionalDocumentLoader) {
3547 FRAMELOADER_RELEASE_LOG(ResourceLoading, "continueLoadAfterNavigationPolicy (completionHandler): Frame load canceled - no provisional document loader before prepareForLoadStart");
3548 return;
3549 }
3550
3551 prepareForLoadStart();
3552
3553 // The load might be cancelled inside of prepareForLoadStart(), nulling out the m_provisionalDocumentLoader,
3554 // so we need to null check it again.
3555 if (!m_provisionalDocumentLoader) {
3556 FRAMELOADER_RELEASE_LOG(ResourceLoading, "continueLoadAfterNavigationPolicy (completionHandler): Frame load canceled - no provisional document loader after prepareForLoadStart");
3557 return;
3558 }
3559
3560 DocumentLoader* activeDocLoader = activeDocumentLoader();
3561 if (activeDocLoader && activeDocLoader->isLoadingMainResource()) {
3562 FRAMELOADER_RELEASE_LOG(ResourceLoading, "continueLoadAfterNavigationPolicy (completionHandler): Main frame already being loaded");
3563 return;
3564 }
3565
3566 m_loadingFromCachedPage = false;
3567
3568 m_provisionalDocumentLoader->startLoadingMainResource();
3569 };
3570
3571 if (!formState) {
3572 completionHandler();
3573 return;
3574 }
3575
3576 m_client->dispatchWillSubmitForm(*formState, WTFMove(completionHandler));
3577}
3578
3579void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
3580 FormState* formState, const AtomString& frameName, const NavigationAction& action, ShouldContinuePolicyCheck shouldContinue, AllowNavigationToInvalidURL allowNavigationToInvalidURL, NewFrameOpenerPolicy openerPolicy)
3581{
3582 if (shouldContinue != ShouldContinuePolicyCheck::Yes)
3583 return;
3584
3585 Ref<Frame> frame(m_frame);
3586
3587 if (request.url().protocolIsJavaScript() && !frame->document()->contentSecurityPolicy()->allowJavaScriptURLs(frame->document()->url().string(), { }, request.url().string(), nullptr))
3588 return;
3589
3590 RefPtr<Frame> mainFrame = m_client->dispatchCreatePage(action, openerPolicy);
3591 if (!mainFrame)
3592 return;
3593
3594 SandboxFlags sandboxFlags = frame->loader().effectiveSandboxFlags();
3595 if (sandboxFlags & SandboxPropagatesToAuxiliaryBrowsingContexts)
3596 mainFrame->loader().forceSandboxFlags(sandboxFlags);
3597
3598 if (!isBlankTargetFrameName(frameName))
3599 mainFrame->tree().setName(frameName);
3600
3601 mainFrame->page()->setOpenedByDOM();
3602 mainFrame->loader().m_client->dispatchShow();
3603 if (openerPolicy == NewFrameOpenerPolicy::Allow) {
3604 mainFrame->loader().setOpener(frame.ptr());
3605 mainFrame->document()->setReferrerPolicy(frame->document()->referrerPolicy());
3606 }
3607
3608 NavigationAction newAction { *frame->document(), request, InitiatedByMainFrame::Unknown, NavigationType::Other, action.shouldOpenExternalURLsPolicy(), nullptr, action.downloadAttribute() };
3609 newAction.setShouldReplaceDocumentIfJavaScriptURL(action.shouldReplaceDocumentIfJavaScriptURL());
3610 mainFrame->loader().loadWithNavigationAction(request, WTFMove(newAction), FrameLoadType::Standard, formState, allowNavigationToInvalidURL, ShouldTreatAsContinuingLoad::No);
3611}
3612
3613void FrameLoader::requestFromDelegate(ResourceRequest& request, ResourceLoaderIdentifier& identifier, ResourceError& error)
3614{
3615 ASSERT(!request.isNull());
3616
3617 identifier = ResourceLoaderIdentifier::generate();
3618 notifier().assignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
3619
3620 ResourceRequest newRequest(request);
3621 notifier().dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse(), nullptr);
3622
3623 if (newRequest.isNull())
3624 error = cancelledError(request);
3625 else
3626 error = ResourceError();
3627
3628 request = newRequest;
3629}
3630
3631void FrameLoader::loadedResourceFromMemoryCache(CachedResource& resource, ResourceRequest& newRequest, ResourceError& error)
3632{
3633 Page* page = m_frame.page();
3634 if (!page)
3635 return;
3636
3637 if (!resource.shouldSendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource.url().string()))
3638 return;
3639
3640 // Main resource delegate messages are synthesized in MainResourceLoader, so we must not send them here.
3641 if (resource.type() == CachedResource::Type::MainResource)
3642 return;
3643
3644 if (!page->areMemoryCacheClientCallsEnabled()) {
3645 InspectorInstrumentation::didLoadResourceFromMemoryCache(*page, m_documentLoader.get(), &resource);
3646 m_documentLoader->recordMemoryCacheLoadForFutureClientNotification(resource.resourceRequest());
3647 m_documentLoader->didTellClientAboutLoad(resource.url().string());
3648 return;
3649 }
3650
3651 if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), newRequest, resource.response(), resource.encodedSize())) {
3652 InspectorInstrumentation::didLoadResourceFromMemoryCache(*page, m_documentLoader.get(), &resource);
3653 m_documentLoader->didTellClientAboutLoad(resource.url().string());
3654 return;
3655 }
3656
3657 ResourceLoaderIdentifier identifier;
3658 requestFromDelegate(newRequest, identifier, error);
3659
3660 ResourceResponse response = resource.response();
3661 response.setSource(ResourceResponse::Source::MemoryCache);
3662 notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, newRequest, response, nullptr, resource.encodedSize(), 0, error);
3663}
3664
3665void FrameLoader::applyUserAgentIfNeeded(ResourceRequest& request)
3666{
3667 if (!request.hasHTTPHeaderField(HTTPHeaderName::UserAgent)) {
3668 String userAgent = this->userAgent(request.url());
3669 ASSERT(!userAgent.isNull());
3670 request.setHTTPUserAgent(userAgent);
3671 }
3672}
3673
3674bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const URL& url, ResourceLoaderIdentifier requestIdentifier)
3675{
3676 Frame& topFrame = m_frame.tree().top();
3677 if (&m_frame == &topFrame)
3678 return false;
3679
3680 XFrameOptionsDisposition disposition = parseXFrameOptionsHeader(content);
3681
3682 switch (disposition) {
3683 case XFrameOptionsDisposition::SameOrigin: {
3684 auto origin = SecurityOrigin::create(url);
3685 if (!origin->isSameSchemeHostPort(topFrame.document()->securityOrigin()))
3686 return true;
3687 for (Frame* frame = m_frame.tree().parent(); frame; frame = frame->tree().parent()) {
3688 if (!origin->isSameSchemeHostPort(frame->document()->securityOrigin()))
3689 return true;
3690 }
3691 return false;
3692 }
3693 case XFrameOptionsDisposition::Deny:
3694 return true;
3695 case XFrameOptionsDisposition::AllowAll:
3696 return false;
3697 case XFrameOptionsDisposition::Conflict:
3698 m_frame.document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, "Multiple 'X-Frame-Options' headers with conflicting values ('" + content + "') encountered when loading '" + url.stringCenterEllipsizedToLength() + "'. Falling back to 'DENY'.", requestIdentifier.toUInt64());
3699 return true;
3700 case XFrameOptionsDisposition::Invalid:
3701 m_frame.document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, "Invalid 'X-Frame-Options' header encountered when loading '" + url.stringCenterEllipsizedToLength() + "': '" + content + "' is not a recognized directive. The header will be ignored.", requestIdentifier.toUInt64());
3702 return false;
3703 case XFrameOptionsDisposition::None:
3704 return false;
3705 }
3706 ASSERT_NOT_REACHED();
3707 return false;
3708}
3709
3710void FrameLoader::loadProvisionalItemFromCachedPage()
3711{
3712 DocumentLoader* provisionalLoader = provisionalDocumentLoader();
3713 LOG(BackForwardCache, "FrameLoader::loadProvisionalItemFromCachedPage Loading provisional DocumentLoader %p with URL '%s' from CachedPage", provisionalDocumentLoader(), provisionalDocumentLoader()->url().stringCenterEllipsizedToLength().utf8().data());
3714
3715 prepareForLoadStart();
3716
3717 m_loadingFromCachedPage = true;
3718
3719 // Should have timing data from previous time(s) the page was shown.
3720 ASSERT(provisionalLoader->timing().startTime());
3721 provisionalLoader->resetTiming();
3722 provisionalLoader->timing().markStartTime();
3723
3724 provisionalLoader->setCommitted(true);
3725 commitProvisionalLoad();
3726}
3727
3728bool FrameLoader::shouldTreatURLAsSameAsCurrent(const URL& url) const
3729{
3730 if (!history().currentItem())
3731 return false;
3732 return url == history().currentItem()->url() || url == history().currentItem()->originalURL();
3733}
3734
3735bool FrameLoader::shouldTreatURLAsSrcdocDocument(const URL& url) const
3736{
3737 if (!url.isAboutSrcDoc())
3738 return false;
3739 HTMLFrameOwnerElement* ownerElement = m_frame.ownerElement();
3740 if (!ownerElement)
3741 return false;
3742 if (!ownerElement->hasTagName(iframeTag))
3743 return false;
3744 return ownerElement->hasAttributeWithoutSynchronization(srcdocAttr);
3745}
3746
3747Frame* FrameLoader::findFrameForNavigation(const AtomString& name, Document* activeDocument)
3748{
3749 // FIXME: Eventually all callers should supply the actual activeDocument so we can call canNavigate with the right document.
3750 if (!activeDocument)
3751 activeDocument = m_frame.document();
3752
3753 if (!activeDocument)
3754 return nullptr;
3755
3756 auto* frame = m_frame.tree().find(name, activeDocument->frame() ? *activeDocument->frame() : m_frame);
3757
3758 if (!activeDocument->canNavigate(frame))
3759 return nullptr;
3760
3761 return frame;
3762}
3763
3764void FrameLoader::loadSameDocumentItem(HistoryItem& item)
3765{
3766 ASSERT(item.documentSequenceNumber() == history().currentItem()->documentSequenceNumber());
3767
3768 Ref<Frame> protect(m_frame);
3769
3770 // Save user view state to the current history item here since we don't do a normal load.
3771 // FIXME: Does form state need to be saved here too?
3772 history().saveScrollPositionAndViewStateToItem(history().currentItem());
3773 if (FrameView* view = m_frame.view())
3774 view->setWasScrolledByUser(false);
3775
3776 history().setCurrentItem(item);
3777
3778 // loadInSameDocument() actually changes the URL and notifies load delegates of a "fake" load
3779 loadInSameDocument(item.url(), item.stateObject(), false);
3780
3781 // Restore user view state from the current history item here since we don't do a normal load.
3782 history().restoreScrollPositionAndViewState();
3783}
3784
3785// FIXME: This function should really be split into a couple pieces, some of
3786// which should be methods of HistoryController and some of which should be
3787// methods of FrameLoader.
3788void FrameLoader::loadDifferentDocumentItem(HistoryItem& item, HistoryItem* fromItem, FrameLoadType loadType, FormSubmissionCacheLoadPolicy cacheLoadPolicy, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad)
3789{
3790 FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadDifferentDocumentItem: frame load started");
3791
3792 Ref<Frame> protectedFrame(m_frame);
3793
3794 // History items should not be reported to the parent.
3795 m_shouldReportResourceTimingToParentFrame = false;
3796
3797 // Remember this item so we can traverse any child items as child frames load
3798 history().setProvisionalItem(&item);
3799
3800 auto initiatedByMainFrame = InitiatedByMainFrame::Unknown;
3801
3802 SetForScope continuingLoadGuard(m_currentLoadContinuingState, shouldTreatAsContinuingLoad != ShouldTreatAsContinuingLoad::No ? LoadContinuingState::ContinuingWithHistoryItem : LoadContinuingState::NotContinuing);
3803
3804 if (CachedPage* cachedPage = BackForwardCache::singleton().get(item, m_frame.page())) {
3805 auto documentLoader = cachedPage->documentLoader();
3806 m_client->updateCachedDocumentLoader(*documentLoader);
3807
3808 auto action = NavigationAction { *m_frame.document(), documentLoader->request(), initiatedByMainFrame, loadType, false };
3809 action.setTargetBackForwardItem(item);
3810 action.setSourceBackForwardItem(fromItem);
3811 documentLoader->setTriggeringAction(WTFMove(action));
3812
3813 documentLoader->setLastCheckedRequest(ResourceRequest());
3814 loadWithDocumentLoader(documentLoader, loadType, { }, AllowNavigationToInvalidURL::Yes);
3815 return;
3816 }
3817
3818 URL itemURL = item.url();
3819 URL itemOriginalURL = item.originalURL();
3820 URL currentURL;
3821 if (documentLoader())
3822 currentURL = documentLoader()->url();
3823 RefPtr<FormData> formData = item.formData();
3824
3825 ResourceRequest request(itemURL);
3826
3827 if (!item.referrer().isNull())
3828 request.setHTTPReferrer(item.referrer());
3829
3830 ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy = shouldOpenExternalURLsPolicyToApply(m_frame, initiatedByMainFrame, item.shouldOpenExternalURLsPolicy());
3831 bool isFormSubmission = false;
3832 Event* event = nullptr;
3833
3834 if (auto* documentLoader = m_frame.mainFrame().loader().documentLoader())
3835 request.setIsAppInitiated(documentLoader->lastNavigationWasAppInitiated());
3836
3837 // If this was a repost that failed the page cache, we might try to repost the form.
3838 NavigationAction action;
3839 if (formData) {
3840 request.setHTTPMethod("POST"_s);
3841 request.setHTTPBody(WTFMove(formData));
3842 request.setHTTPContentType(item.formContentType());
3843 auto securityOrigin = SecurityOrigin::createFromString(item.referrer());
3844 addHTTPOriginIfNeeded(request, securityOrigin->toString());
3845
3846 updateRequestAndAddExtraFields(request, IsMainResource::Yes, loadType);
3847
3848 // FIXME: Slight hack to test if the NSURL cache contains the page we're going to.
3849 // We want to know this before talking to the policy delegate, since it affects whether
3850 // we show the DoYouReallyWantToRepost nag.
3851 //
3852 // This trick has a small bug (3123893) where we might find a cache hit, but then
3853 // have the item vanish when we try to use it in the ensuing nav. This should be
3854 // extremely rare, but in that case the user will get an error on the navigation.
3855
3856 if (cacheLoadPolicy == MayAttemptCacheOnlyLoadForFormSubmissionItem) {
3857 request.setCachePolicy(ResourceRequestCachePolicy::ReturnCacheDataDontLoad);
3858 action = { *m_frame.document(), request, initiatedByMainFrame, loadType, isFormSubmission, event, shouldOpenExternalURLsPolicy };
3859 } else {
3860 request.setCachePolicy(ResourceRequestCachePolicy::ReturnCacheDataElseLoad);
3861 action = { *m_frame.document(), request, initiatedByMainFrame, NavigationType::FormResubmitted, shouldOpenExternalURLsPolicy, event };
3862 }
3863 } else {
3864 switch (loadType) {
3865 case FrameLoadType::Reload:
3866 case FrameLoadType::ReloadFromOrigin:
3867 case FrameLoadType::ReloadExpiredOnly:
3868 request.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
3869 break;
3870 case FrameLoadType::Back:
3871 case FrameLoadType::Forward:
3872 case FrameLoadType::IndexedBackForward: {
3873#if PLATFORM(COCOA)
3874 bool allowStaleData = true;
3875#else
3876 bool allowStaleData = !item.wasRestoredFromSession();
3877#endif
3878 if (allowStaleData)
3879 request.setCachePolicy(ResourceRequestCachePolicy::ReturnCacheDataElseLoad);
3880 item.setWasRestoredFromSession(false);
3881 break;
3882 }
3883 case FrameLoadType::Standard:
3884 case FrameLoadType::RedirectWithLockedBackForwardList:
3885 break;
3886 case FrameLoadType::Same:
3887 case FrameLoadType::Replace:
3888 ASSERT_NOT_REACHED();
3889 }
3890
3891 updateRequestAndAddExtraFields(request, IsMainResource::Yes, loadType);
3892
3893 ResourceRequest requestForOriginalURL(request);
3894 requestForOriginalURL.setURL(itemOriginalURL);
3895 action = { *m_frame.document(), requestForOriginalURL, initiatedByMainFrame, loadType, isFormSubmission, event, shouldOpenExternalURLsPolicy };
3896 }
3897
3898 action.setTargetBackForwardItem(item);
3899 action.setSourceBackForwardItem(fromItem);
3900
3901 loadWithNavigationAction(request, WTFMove(action), loadType, { }, AllowNavigationToInvalidURL::Yes, shouldTreatAsContinuingLoad);
3902}
3903
3904// Loads content into this frame, as specified by history item
3905void FrameLoader::loadItem(HistoryItem& item, HistoryItem* fromItem, FrameLoadType loadType, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad)
3906{
3907 m_requestedHistoryItem = &item;
3908 HistoryItem* currentItem = history().currentItem();
3909 bool sameDocumentNavigation = currentItem && item.shouldDoSameDocumentNavigationTo(*currentItem);
3910
3911 // If we're continuing this history navigation in a new process, then doing a same document navigation never makes sense.
3912 ASSERT(!sameDocumentNavigation || shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::No);
3913
3914 if (sameDocumentNavigation)
3915 loadSameDocumentItem(item);
3916 else
3917 loadDifferentDocumentItem(item, fromItem, loadType, MayAttemptCacheOnlyLoadForFormSubmissionItem, shouldTreatAsContinuingLoad);
3918}
3919
3920void FrameLoader::retryAfterFailedCacheOnlyMainResourceLoad()
3921{
3922 ASSERT(m_state == FrameState::Provisional);
3923 ASSERT(!m_loadingFromCachedPage);
3924 ASSERT(history().provisionalItem());
3925 ASSERT(history().provisionalItem()->formData());
3926 ASSERT(history().provisionalItem() == m_requestedHistoryItem.get());
3927
3928 FrameLoadType loadType = m_loadType;
3929 HistoryItem* item = history().provisionalItem();
3930
3931 stopAllLoaders(ClearProvisionalItem::No);
3932 if (item)
3933 loadDifferentDocumentItem(*item, history().currentItem(), loadType, MayNotAttemptCacheOnlyLoadForFormSubmissionItem, ShouldTreatAsContinuingLoad::No);
3934 else {
3935 ASSERT_NOT_REACHED();
3936 FRAMELOADER_RELEASE_LOG_ERROR(ResourceLoading, "retryAfterFailedCacheOnlyMainResourceLoad: Retrying load after failed cache-only main resource load failed because there is no provisional history item.");
3937 }
3938}
3939
3940ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const
3941{
3942 ResourceError error = m_client->cancelledError(request);
3943 error.setType(ResourceError::Type::Cancellation);
3944 return error;
3945}
3946
3947ResourceError FrameLoader::blockedByContentBlockerError(const ResourceRequest& request) const
3948{
3949 return m_client->blockedByContentBlockerError(request);
3950}
3951
3952ResourceError FrameLoader::blockedError(const ResourceRequest& request) const
3953{
3954 ResourceError error = m_client->blockedError(request);
3955 error.setType(ResourceError::Type::Cancellation);
3956 return error;
3957}
3958
3959#if ENABLE(CONTENT_FILTERING)
3960ResourceError FrameLoader::blockedByContentFilterError(const ResourceRequest& request) const
3961{
3962 ResourceError error = m_client->blockedByContentFilterError(request);
3963 error.setType(ResourceError::Type::General);
3964 return error;
3965}
3966#endif
3967
3968#if PLATFORM(IOS_FAMILY)
3969RetainPtr<CFDictionaryRef> FrameLoader::connectionProperties(ResourceLoader* loader)
3970{
3971 return m_client->connectionProperties(loader->documentLoader(), loader->identifier());
3972}
3973#endif
3974
3975ReferrerPolicy FrameLoader::effectiveReferrerPolicy() const
3976{
3977 if (auto* parentFrame = m_frame.tree().parent())
3978 return parentFrame->document()->referrerPolicy();
3979 if (m_opener)
3980 return m_opener->document()->referrerPolicy();
3981 return ReferrerPolicy::Default;
3982}
3983
3984String FrameLoader::referrer() const
3985{
3986 return m_documentLoader ? m_documentLoader->request().httpReferrer() : emptyString();
3987}
3988
3989void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
3990{
3991 if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript))
3992 return;
3993
3994 Vector<Ref<DOMWrapperWorld>> worlds;
3995 ScriptController::getAllWorlds(worlds);
3996 for (auto& world : worlds)
3997 dispatchDidClearWindowObjectInWorld(world);
3998}
3999
4000void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
4001{
4002 if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript) || !m_frame.windowProxy().existingJSWindowProxy(world))
4003 return;
4004
4005 m_client->dispatchDidClearWindowObjectInWorld(world);
4006
4007 if (Page* page = m_frame.page())
4008 page->inspectorController().didClearWindowObjectInWorld(m_frame, world);
4009
4010 InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world);
4011}
4012
4013void FrameLoader::dispatchGlobalObjectAvailableInAllWorlds()
4014{
4015 Vector<Ref<DOMWrapperWorld>> worlds;
4016 ScriptController::getAllWorlds(worlds);
4017 for (auto& world : worlds)
4018 m_client->dispatchGlobalObjectAvailable(world);
4019}
4020
4021SandboxFlags FrameLoader::effectiveSandboxFlags() const
4022{
4023 SandboxFlags flags = m_forcedSandboxFlags;
4024 if (Frame* parentFrame = m_frame.tree().parent())
4025 flags |= parentFrame->document()->sandboxFlags();
4026 if (HTMLFrameOwnerElement* ownerElement = m_frame.ownerElement())
4027 flags |= ownerElement->sandboxFlags();
4028 return flags;
4029}
4030
4031void FrameLoader::didChangeTitle(DocumentLoader* loader)
4032{
4033 m_client->didChangeTitle(loader);
4034
4035 if (loader == m_documentLoader) {
4036 // Must update the entries in the back-forward list too.
4037 history().setCurrentItemTitle(loader->title());
4038 // This must go through the WebFrame because it has the right notion of the current b/f item.
4039 m_client->setTitle(loader->title(), loader->urlForHistory());
4040 m_client->setMainFrameDocumentReady(true); // update observers with new DOMDocument
4041 m_client->dispatchDidReceiveTitle(loader->title());
4042 }
4043
4044#if ENABLE(REMOTE_INSPECTOR)
4045 if (m_frame.isMainFrame())
4046 m_frame.page()->remoteInspectorInformationDidChange();
4047#endif
4048}
4049
4050void FrameLoader::dispatchDidCommitLoad(std::optional<HasInsecureContent> initialHasInsecureContent, std::optional<UsedLegacyTLS> initialUsedLegacyTLS)
4051{
4052 if (m_stateMachine.creatingInitialEmptyDocument())
4053 return;
4054
4055 m_client->dispatchDidCommitLoad(initialHasInsecureContent, initialUsedLegacyTLS);
4056
4057 if (auto* page = m_frame.page(); page && m_frame.isMainFrame())
4058 page->didCommitLoad();
4059
4060 InspectorInstrumentation::didCommitLoad(m_frame, m_documentLoader.get());
4061
4062#if ENABLE(REMOTE_INSPECTOR)
4063 if (auto* page = m_frame.page(); page && m_frame.isMainFrame())
4064 page->remoteInspectorInformationDidChange();
4065#endif
4066}
4067
4068void FrameLoader::tellClientAboutPastMemoryCacheLoads()
4069{
4070 ASSERT(m_frame.page());
4071 ASSERT(m_frame.page()->areMemoryCacheClientCallsEnabled());
4072
4073 if (!m_documentLoader)
4074 return;
4075
4076 Vector<ResourceRequest> pastLoads;
4077 m_documentLoader->takeMemoryCacheLoadsForClientNotification(pastLoads);
4078
4079 for (auto& pastLoad : pastLoads) {
4080 CachedResource* resource = MemoryCache::singleton().resourceForRequest(pastLoad, m_frame.page()->sessionID());
4081
4082 // FIXME: These loads, loaded from cache, but now gone from the cache by the time
4083 // Page::setMemoryCacheClientCallsEnabled(true) is called, will not be seen by the client.
4084 // Consider if there's some efficient way of remembering enough to deliver this client call.
4085 // We have the URL, but not the rest of the response or the length.
4086 if (!resource)
4087 continue;
4088
4089 ResourceRequest request(resource->url());
4090 m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize());
4091 }
4092}
4093
4094NetworkingContext* FrameLoader::networkingContext() const
4095{
4096 return m_networkingContext.get();
4097}
4098
4099void FrameLoader::loadProgressingStatusChanged()
4100{
4101 if (auto* view = m_frame.mainFrame().view())
4102 view->loadProgressingStatusChanged();
4103}
4104
4105void FrameLoader::completePageTransitionIfNeeded()
4106{
4107 m_client->completePageTransitionIfNeeded();
4108}
4109
4110void FrameLoader::clearTestingOverrides()
4111{
4112 m_overrideCachePolicyForTesting = std::nullopt;
4113 m_overrideResourceLoadPriorityForTesting = std::nullopt;
4114 m_isStrictRawResourceValidationPolicyDisabledForTesting = false;
4115}
4116
4117bool FrameLoaderClient::hasHTMLView() const
4118{
4119 return true;
4120}
4121
4122RefPtr<Frame> createWindow(Frame& openerFrame, Frame& lookupFrame, FrameLoadRequest&& request, WindowFeatures& features, bool& created)
4123{
4124 ASSERT(!features.dialog || request.frameName().isEmpty());
4125 ASSERT(request.resourceRequest().httpMethod() == "GET"_s);
4126
4127 created = false;
4128
4129 // FIXME: Provide line number information with respect to the opener's document.
4130 if (request.resourceRequest().url().protocolIsJavaScript() && !openerFrame.document()->contentSecurityPolicy()->allowJavaScriptURLs(openerFrame.document()->url().string(), { }, request.resourceRequest().url().string(), nullptr))
4131 return nullptr;
4132
4133 if (!request.frameName().isEmpty() && !isBlankTargetFrameName(request.frameName())) {
4134 if (RefPtr<Frame> frame = lookupFrame.loader().findFrameForNavigation(request.frameName(), openerFrame.document())) {
4135 if (!isSelfTargetFrameName(request.frameName())) {
4136 if (auto* page = frame->page(); page && isInVisibleAndActivePage(openerFrame))
4137 page->chrome().focus();
4138 }
4139 return frame;
4140 }
4141 }
4142
4143 // https://html.spec.whatwg.org/#the-rules-for-choosing-a-browsing-context-given-a-browsing-context-name (Step 8.2)
4144 if (openerFrame.document()->shouldForceNoOpenerBasedOnCOOP()) {
4145 request.setFrameName(blankTargetFrameName());
4146 features.noopener = true;
4147 }
4148
4149 // Sandboxed frames cannot open new auxiliary browsing contexts.
4150 if (isDocumentSandboxed(openerFrame, SandboxPopups)) {
4151 // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
4152 openerFrame.document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Blocked opening '" + request.resourceRequest().url().stringCenterEllipsizedToLength() + "' in a new window because the request was made in a sandboxed frame whose 'allow-popups' permission is not set.");
4153 return nullptr;
4154 }
4155
4156 // FIXME: Setting the referrer should be the caller's responsibility.
4157 String referrer = SecurityPolicy::generateReferrerHeader(openerFrame.document()->referrerPolicy(), request.resourceRequest().url(), openerFrame.loader().outgoingReferrer());
4158 if (!referrer.isEmpty())
4159 request.resourceRequest().setHTTPReferrer(referrer);
4160 FrameLoader::addSameSiteInfoToRequestIfNeeded(request.resourceRequest(), openerFrame.document());
4161
4162 Page* oldPage = openerFrame.page();
4163 if (!oldPage)
4164 return nullptr;
4165
4166 ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy = shouldOpenExternalURLsPolicyToApply(openerFrame, request);
4167 NavigationAction action { request.requester(), request.resourceRequest(), request.initiatedByMainFrame(), NavigationType::Other, shouldOpenExternalURLsPolicy };
4168 Page* page = oldPage->chrome().createWindow(openerFrame, features, action);
4169 if (!page)
4170 return nullptr;
4171
4172 RefPtr<Frame> frame = &page->mainFrame();
4173
4174 if (isDocumentSandboxed(openerFrame, SandboxPropagatesToAuxiliaryBrowsingContexts))
4175 frame->loader().forceSandboxFlags(openerFrame.document()->sandboxFlags());
4176
4177 if (!isBlankTargetFrameName(request.frameName()))
4178 frame->tree().setName(request.frameName());
4179
4180 page->chrome().setToolbarsVisible(features.toolBarVisible || features.locationBarVisible);
4181
4182 if (!frame->page())
4183 return nullptr;
4184 page->chrome().setStatusbarVisible(features.statusBarVisible);
4185
4186 if (!frame->page())
4187 return nullptr;
4188 page->chrome().setScrollbarsVisible(features.scrollbarsVisible);
4189
4190 if (!frame->page())
4191 return nullptr;
4192 page->chrome().setMenubarVisible(features.menuBarVisible);
4193
4194 if (!frame->page())
4195 return nullptr;
4196 page->chrome().setResizable(features.resizable);
4197
4198 // 'x' and 'y' specify the location of the window, while 'width' and 'height'
4199 // specify the size of the viewport. We can only resize the window, so adjust
4200 // for the difference between the window size and the viewport size.
4201
4202 // FIXME: We should reconcile the initialization of viewport arguments between iOS and non-IOS.
4203#if !PLATFORM(IOS_FAMILY)
4204 FloatSize viewportSize = page->chrome().pageRect().size();
4205 FloatRect windowRect = page->chrome().windowRect();
4206 if (features.x)
4207 windowRect.setX(*features.x);
4208 if (features.y)
4209 windowRect.setY(*features.y);
4210 // Zero width and height mean using default size, not minimum one.
4211 if (features.width && *features.width)
4212 windowRect.setWidth(*features.width + (windowRect.width() - viewportSize.width()));
4213 if (features.height && *features.height)
4214 windowRect.setHeight(*features.height + (windowRect.height() - viewportSize.height()));
4215
4216#if PLATFORM(GTK)
4217 FloatRect oldWindowRect = oldPage->chrome().windowRect();
4218 // Use the size of the previous window if there is no default size.
4219 if (!windowRect.width())
4220 windowRect.setWidth(oldWindowRect.width());
4221 if (!windowRect.height())
4222 windowRect.setHeight(oldWindowRect.height());
4223#endif
4224
4225 // Ensure non-NaN values, minimum size as well as being within valid screen area.
4226 FloatRect newWindowRect = DOMWindow::adjustWindowRect(*page, windowRect);
4227
4228 if (!frame->page())
4229 return nullptr;
4230 page->chrome().setWindowRect(newWindowRect);
4231#else
4232 // On iOS, width and height refer to the viewport dimensions.
4233 ViewportArguments arguments;
4234 // Zero width and height mean using default size, not minimum one.
4235 if (features.width && *features.width)
4236 arguments.width = *features.width;
4237 if (features.height && *features.height)
4238 arguments.height = *features.height;
4239 frame->setViewportArguments(arguments);
4240#endif
4241
4242 if (!frame->page())
4243 return nullptr;
4244 page->chrome().show();
4245
4246 created = true;
4247 return frame;
4248}
4249
4250// At the moment, we do not actually create a new browsing context / frame. We merely make it so that existing windowProxy for the
4251// current browsing context lose their browsing context. We also clear properties of the frame (opener, openees, name), so that it
4252// appears the same as a new browsing context.
4253void FrameLoader::switchBrowsingContextsGroup()
4254{
4255 // Disown opener.
4256 setOpener(nullptr);
4257 if (auto* page = m_frame.page())
4258 page->setOpenedByDOMWithOpener(false);
4259
4260 detachFromAllOpenedFrames();
4261
4262 m_frame.tree().clearName();
4263
4264 // Make sure we use fresh Window proxies. The old window proxies will keep pointing to the old window which will be frameless when
4265 // a new window is created for this frame.
4266 m_frame.resetScript();
4267
4268 // On same-origin navigation from the initial empty document, we normally reuse the window for the new document. We need to prevent
4269 // this when we want to isolate so old window proxies will indeed start pointing to a frameless window and appear closed.
4270 if (auto* window = m_frame.window())
4271 window->setMayReuseForNavigation(false);
4272}
4273
4274bool FrameLoader::shouldSuppressTextInputFromEditing() const
4275{
4276 return m_frame.settings().shouldSuppressTextInputFromEditingDuringProvisionalNavigation() && m_state == FrameState::Provisional;
4277}
4278
4279} // namespace WebCore
4280
4281#undef PAGE_ID
4282#undef FRAME_ID
Note: See TracBrowser for help on using the repository browser.