void ContentExtensionsBackend::processContentExtensionRulesForLoad(ResourceRequest& request, ResourceType resourceType, DocumentLoader& initiatingDocumentLoader) { Document* currentDocument = nullptr; URL mainDocumentURL; if (initiatingDocumentLoader.frame()) { currentDocument = initiatingDocumentLoader.frame()->document(); if (Document* mainDocument = initiatingDocumentLoader.frame()->mainFrame().document()) mainDocumentURL = mainDocument->url(); } ResourceLoadInfo resourceLoadInfo = { request.url(), mainDocumentURL, resourceType }; Vector<ContentExtensions::Action> actions = actionsForResourceLoad(resourceLoadInfo); StringBuilder css; bool willBlockLoad = false; for (const auto& action : actions) { switch (action.type()) { case ContentExtensions::ActionType::BlockLoad: willBlockLoad = true; break; case ContentExtensions::ActionType::BlockCookies: request.setAllowCookies(false); break; case ContentExtensions::ActionType::CSSDisplayNoneSelector: if (resourceType == ResourceType::Document) initiatingDocumentLoader.addPendingContentExtensionDisplayNoneSelector(action.extensionIdentifier(), action.stringArgument(), action.actionID()); else if (currentDocument) currentDocument->styleSheetCollection().addDisplayNoneSelector(action.extensionIdentifier(), action.stringArgument(), action.actionID()); break; case ContentExtensions::ActionType::CSSDisplayNoneStyleSheet: { StyleSheetContents* styleSheetContents = globalDisplayNoneStyleSheet(action.stringArgument()); if (styleSheetContents) { if (resourceType == ResourceType::Document) initiatingDocumentLoader.addPendingContentExtensionSheet(action.stringArgument(), *styleSheetContents); else if (currentDocument) currentDocument->styleSheetCollection().maybeAddContentExtensionSheet(action.stringArgument(), *styleSheetContents); } break; } case ContentExtensions::ActionType::IgnorePreviousRules: case ContentExtensions::ActionType::InvalidAction: RELEASE_ASSERT_NOT_REACHED(); } } if (willBlockLoad) { if (currentDocument) currentDocument->addConsoleMessage(MessageSource::ContentBlocker, MessageLevel::Info, makeString("Content blocker prevented frame displaying ", mainDocumentURL.string(), " from loading a resource from ", request.url().string())); request = ResourceRequest(); } }
void InspectorNetworkAgent::didLoadResourceFromMemoryCache(DocumentLoader& loader, CachedResource& resource) { String loaderId = m_pageAgent->loaderId(&loader); String frameId = m_pageAgent->frameId(loader.frame()); unsigned long identifier = loader.frame()->page()->progress().createUniqueIdentifier(); String requestId = IdentifiersFactory::requestId(identifier); m_resourcesData->resourceCreated(requestId, loaderId); m_resourcesData->addCachedResource(requestId, &resource); RefPtr<Inspector::Protocol::Network::Initiator> initiatorObject = buildInitiatorObject(loader.frame() ? loader.frame()->document() : nullptr); m_frontendDispatcher->requestServedFromMemoryCache(requestId, frameId, loaderId, loader.url().string(), timestamp(), initiatorObject, buildObjectForCachedResource(&resource, &loader)); }
static bool contentExtensionsEnabled(const DocumentLoader& documentLoader) { if (auto frame = documentLoader.frame()) { if (frame->isMainFrame()) return documentLoader.userContentExtensionsEnabled(); if (auto mainDocumentLoader = frame->mainFrame().loader().documentLoader()) return mainDocumentLoader->userContentExtensionsEnabled(); } return true; }
void InspectorNetworkAgent::didReceiveResponse(unsigned long identifier, DocumentLoader& loader, const ResourceResponse& response, ResourceLoader* resourceLoader) { if (m_hiddenRequestIdentifiers.contains(identifier)) return; String requestId = IdentifiersFactory::requestId(identifier); RefPtr<Inspector::Protocol::Network::Response> resourceResponse = buildObjectForResourceResponse(response, &loader); bool isNotModified = response.httpStatusCode() == 304; CachedResource* cachedResource = nullptr; if (resourceLoader && resourceLoader->isSubresourceLoader() && !isNotModified) cachedResource = static_cast<SubresourceLoader*>(resourceLoader)->cachedResource(); if (!cachedResource) cachedResource = InspectorPageAgent::cachedResource(loader.frame(), response.url()); if (cachedResource) { // Use mime type from cached resource in case the one in response is empty. if (resourceResponse && response.mimeType().isEmpty()) resourceResponse->setString(Inspector::Protocol::Network::Response::MimeType, cachedResource->response().mimeType()); m_resourcesData->addCachedResource(requestId, cachedResource); } InspectorPageAgent::ResourceType type = m_resourcesData->resourceType(requestId); InspectorPageAgent::ResourceType newType = cachedResource ? InspectorPageAgent::cachedResourceType(*cachedResource) : type; // FIXME: XHRResource is returned for CachedResource::RawResource, it should be OtherResource unless it truly is an XHR. // RawResource is used for loading worker scripts, and those should stay as ScriptResource and not change to XHRResource. if (type != newType && newType != InspectorPageAgent::XHRResource && newType != InspectorPageAgent::OtherResource) type = newType; m_resourcesData->responseReceived(requestId, m_pageAgent->frameId(loader.frame()), response); m_resourcesData->setResourceType(requestId, type); m_frontendDispatcher->responseReceived(requestId, m_pageAgent->frameId(loader.frame()), m_pageAgent->loaderId(&loader), timestamp(), InspectorPageAgent::resourceTypeJson(type), resourceResponse); // If we revalidated the resource and got Not modified, send content length following didReceiveResponse // as there will be no calls to didReceiveData from the network stack. if (isNotModified && cachedResource && cachedResource->encodedSize()) didReceiveData(identifier, nullptr, cachedResource->encodedSize(), 0); }
void InspectorNetworkAgent::willSendRequest(unsigned long identifier, DocumentLoader& loader, ResourceRequest& request, const ResourceResponse& redirectResponse) { if (request.hiddenFromInspector()) { m_hiddenRequestIdentifiers.add(identifier); return; } String requestId = IdentifiersFactory::requestId(identifier); m_resourcesData->resourceCreated(requestId, m_pageAgent->loaderId(&loader)); CachedResource* cachedResource = InspectorPageAgent::cachedResource(loader.frame(), request.url()); InspectorPageAgent::ResourceType type = cachedResource ? InspectorPageAgent::cachedResourceType(*cachedResource) : m_resourcesData->resourceType(requestId); if (type == InspectorPageAgent::OtherResource) { if (m_loadingXHRSynchronously) type = InspectorPageAgent::XHRResource; else if (equalIgnoringFragmentIdentifier(request.url(), loader.frameLoader()->icon().url())) type = InspectorPageAgent::ImageResource; else if (equalIgnoringFragmentIdentifier(request.url(), loader.url()) && !loader.isCommitted()) type = InspectorPageAgent::DocumentResource; } m_resourcesData->setResourceType(requestId, type); for (auto& entry : m_extraRequestHeaders) request.setHTTPHeaderField(entry.key, entry.value); request.setReportLoadTiming(true); request.setReportRawHeaders(true); if (m_cacheDisabled) { request.setHTTPHeaderField(HTTPHeaderName::Pragma, "no-cache"); request.setCachePolicy(ReloadIgnoringCacheData); request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "no-cache"); } Inspector::Protocol::Page::ResourceType resourceType = InspectorPageAgent::resourceTypeJson(type); RefPtr<Inspector::Protocol::Network::Initiator> initiatorObject = buildInitiatorObject(loader.frame() ? loader.frame()->document() : nullptr); m_frontendDispatcher->requestWillBeSent(requestId, m_pageAgent->frameId(loader.frame()), m_pageAgent->loaderId(&loader), loader.url().string(), buildObjectForResourceRequest(request), timestamp(), initiatorObject, buildObjectForResourceResponse(redirectResponse, &loader), type != InspectorPageAgent::OtherResource ? &resourceType : nullptr); }
void InspectorInstrumentation::loadEventFiredImpl(InstrumentingAgents* instrumentingAgents, Frame* frame, const KURL& url) { DocumentLoader* documentLoader = frame->loader()->documentLoader(); ASSERT(documentLoader); if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent()) domAgent->loadEventFired(documentLoader->frame()->document()); if (frame->page()->mainFrame() != frame || url != documentLoader->requestURL()) return; if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent()) timelineAgent->didMarkLoadEvent(); if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent()) pageAgent->loadEventFired(); }
void InspectorNetworkAgent::didFailLoading(unsigned long identifier, DocumentLoader& loader, const ResourceError& error) { if (m_hiddenRequestIdentifiers.remove(identifier)) return; String requestId = IdentifiersFactory::requestId(identifier); if (m_resourcesData->resourceType(requestId) == InspectorPageAgent::DocumentResource) { Frame* frame = loader.frame(); if (frame && frame->loader().documentLoader() && frame->document()) { m_resourcesData->addResourceSharedBuffer(requestId, frame->loader().documentLoader()->mainResourceData(), frame->document()->encoding()); } } bool canceled = error.isCancellation(); m_frontendDispatcher->loadingFailed(requestId, timestamp(), error.localizedDescription(), canceled ? &canceled : nullptr); }
void InspectorNetworkAgent::didFinishLoading(unsigned long identifier, DocumentLoader& loader, double finishTime) { if (m_hiddenRequestIdentifiers.remove(identifier)) return; String requestId = IdentifiersFactory::requestId(identifier); if (m_resourcesData->resourceType(requestId) == InspectorPageAgent::DocumentResource) m_resourcesData->addResourceSharedBuffer(requestId, loader.frameLoader()->documentLoader()->mainResourceData(), loader.frame()->document()->encoding()); m_resourcesData->maybeDecodeDataToContent(requestId); // FIXME: The finishTime that is passed in is from the NetworkProcess and is more accurate. // However, all other times passed to the Inspector are generated from the web process. Mixing // times from different processes can cause the finish time to be earlier than the response // received time due to inter-process communication lag. finishTime = timestamp(); String sourceMappingURL; NetworkResourcesData::ResourceData const* resourceData = m_resourcesData->data(requestId); if (resourceData && resourceData->cachedResource()) sourceMappingURL = InspectorPageAgent::sourceMapURLForResource(resourceData->cachedResource()); m_frontendDispatcher->loadingFinished(requestId, finishTime, !sourceMappingURL.isEmpty() ? &sourceMappingURL : nullptr); }
BlockedStatus ContentExtensionsBackend::processContentExtensionRulesForLoad(const URL& url, ResourceType resourceType, DocumentLoader& initiatingDocumentLoader) { if (m_contentExtensions.isEmpty()) return { }; Document* currentDocument = nullptr; URL mainDocumentURL; if (Frame* frame = initiatingDocumentLoader.frame()) { currentDocument = frame->document(); if (initiatingDocumentLoader.isLoadingMainResource() && frame->isMainFrame() && resourceType == ResourceType::Document) mainDocumentURL = url; else if (Document* mainDocument = frame->mainFrame().document()) mainDocumentURL = mainDocument->url(); } ResourceLoadInfo resourceLoadInfo = { url, mainDocumentURL, resourceType }; Vector<ContentExtensions::Action> actions = actionsForResourceLoad(resourceLoadInfo); bool willBlockLoad = false; bool willBlockCookies = false; bool willMakeHTTPS = false; for (const auto& action : actions) { switch (action.type()) { case ContentExtensions::ActionType::BlockLoad: willBlockLoad = true; break; case ContentExtensions::ActionType::BlockCookies: willBlockCookies = true; break; case ContentExtensions::ActionType::CSSDisplayNoneSelector: if (resourceType == ResourceType::Document) initiatingDocumentLoader.addPendingContentExtensionDisplayNoneSelector(action.extensionIdentifier(), action.stringArgument(), action.actionID()); else if (currentDocument) currentDocument->extensionStyleSheets().addDisplayNoneSelector(action.extensionIdentifier(), action.stringArgument(), action.actionID()); break; case ContentExtensions::ActionType::CSSDisplayNoneStyleSheet: { StyleSheetContents* styleSheetContents = globalDisplayNoneStyleSheet(action.stringArgument()); if (styleSheetContents) { if (resourceType == ResourceType::Document) initiatingDocumentLoader.addPendingContentExtensionSheet(action.stringArgument(), *styleSheetContents); else if (currentDocument) currentDocument->extensionStyleSheets().maybeAddContentExtensionSheet(action.stringArgument(), *styleSheetContents); } break; } case ContentExtensions::ActionType::MakeHTTPS: { if ((url.protocolIs("http") || url.protocolIs("ws")) && (!url.port() || isDefaultPortForProtocol(url.port().value(), url.protocol()))) willMakeHTTPS = true; break; } case ContentExtensions::ActionType::IgnorePreviousRules: case ContentExtensions::ActionType::InvalidAction: RELEASE_ASSERT_NOT_REACHED(); } } if (currentDocument) { if (willMakeHTTPS) { ASSERT(url.protocolIs("http") || url.protocolIs("ws")); String newProtocol = url.protocolIs("http") ? ASCIILiteral("https") : ASCIILiteral("wss"); currentDocument->addConsoleMessage(MessageSource::ContentBlocker, MessageLevel::Info, makeString("Content blocker promoted URL from ", url.string(), " to ", newProtocol)); } if (willBlockLoad) currentDocument->addConsoleMessage(MessageSource::ContentBlocker, MessageLevel::Info, makeString("Content blocker prevented frame displaying ", mainDocumentURL.string(), " from loading a resource from ", url.string())); } return { willBlockLoad, willBlockCookies, willMakeHTTPS }; }
BlockedStatus ContentExtensionsBackend::processContentExtensionRulesForLoad(ResourceRequest& request, ResourceType resourceType, DocumentLoader& initiatingDocumentLoader) { Document* currentDocument = nullptr; URL mainDocumentURL; if (Frame* frame = initiatingDocumentLoader.frame()) { currentDocument = frame->document(); if (initiatingDocumentLoader.isLoadingMainResource() && frame->isMainFrame() && resourceType == ResourceType::Document) mainDocumentURL = request.url(); else if (Document* mainDocument = frame->mainFrame().document()) mainDocumentURL = mainDocument->url(); } ResourceLoadInfo resourceLoadInfo = { request.url(), mainDocumentURL, resourceType }; Vector<ContentExtensions::Action> actions = actionsForResourceLoad(resourceLoadInfo); bool willBlockLoad = false; for (const auto& action : actions) { switch (action.type()) { case ContentExtensions::ActionType::BlockLoad: willBlockLoad = true; break; case ContentExtensions::ActionType::BlockCookies: request.setAllowCookies(false); break; case ContentExtensions::ActionType::CSSDisplayNoneSelector: if (resourceType == ResourceType::Document) initiatingDocumentLoader.addPendingContentExtensionDisplayNoneSelector(action.extensionIdentifier(), action.stringArgument(), action.actionID()); else if (currentDocument) currentDocument->extensionStyleSheets().addDisplayNoneSelector(action.extensionIdentifier(), action.stringArgument(), action.actionID()); break; case ContentExtensions::ActionType::CSSDisplayNoneStyleSheet: { StyleSheetContents* styleSheetContents = globalDisplayNoneStyleSheet(action.stringArgument()); if (styleSheetContents) { if (resourceType == ResourceType::Document) initiatingDocumentLoader.addPendingContentExtensionSheet(action.stringArgument(), *styleSheetContents); else if (currentDocument) currentDocument->extensionStyleSheets().maybeAddContentExtensionSheet(action.stringArgument(), *styleSheetContents); } break; } case ContentExtensions::ActionType::MakeHTTPS: { const URL originalURL = request.url(); if (originalURL.protocolIs("http") && (!originalURL.hasPort() || isDefaultPortForProtocol(originalURL.port(), originalURL.protocol()))) { URL newURL = originalURL; newURL.setProtocol("https"); if (originalURL.hasPort()) newURL.setPort(defaultPortForProtocol("https")); request.setURL(newURL); if (resourceType == ResourceType::Document && initiatingDocumentLoader.isLoadingMainResource()) { // This is to make sure the correct 'new' URL shows in the location bar. initiatingDocumentLoader.request().setURL(newURL); initiatingDocumentLoader.frameLoader()->client().dispatchDidChangeProvisionalURL(); } if (currentDocument) currentDocument->addConsoleMessage(MessageSource::ContentBlocker, MessageLevel::Info, makeString("Content blocker promoted URL from ", originalURL.string(), " to ", newURL.string())); } break; } case ContentExtensions::ActionType::IgnorePreviousRules: case ContentExtensions::ActionType::InvalidAction: RELEASE_ASSERT_NOT_REACHED(); } } if (willBlockLoad) { if (currentDocument) currentDocument->addConsoleMessage(MessageSource::ContentBlocker, MessageLevel::Info, makeString("Content blocker prevented frame displaying ", mainDocumentURL.string(), " from loading a resource from ", request.url().string())); return BlockedStatus::Blocked; } return BlockedStatus::NotBlocked; }