1/* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "config.h" 32#include "core/loader/FrameFetchContext.h" 33 34#include "core/dom/Document.h" 35#include "core/frame/FrameConsole.h" 36#include "core/frame/LocalFrame.h" 37#include "core/inspector/InspectorInstrumentation.h" 38#include "core/inspector/InspectorTraceEvents.h" 39#include "core/loader/DocumentLoader.h" 40#include "core/loader/FrameLoader.h" 41#include "core/loader/FrameLoaderClient.h" 42#include "core/loader/ProgressTracker.h" 43#include "core/page/Page.h" 44#include "core/frame/Settings.h" 45#include "platform/weborigin/SecurityPolicy.h" 46 47namespace blink { 48 49FrameFetchContext::FrameFetchContext(LocalFrame* frame) 50 : m_frame(frame) 51{ 52} 53 54void FrameFetchContext::reportLocalLoadFailed(const KURL& url) 55{ 56 FrameLoader::reportLocalLoadFailed(m_frame, url.elidedString()); 57} 58 59void FrameFetchContext::addAdditionalRequestHeaders(Document* document, ResourceRequest& request, FetchResourceType type) 60{ 61 bool isMainResource = type == FetchMainResource; 62 if (!isMainResource) { 63 String outgoingReferrer; 64 ReferrerPolicy referrerPolicy; 65 String outgoingOrigin; 66 if (request.httpReferrer().isNull()) { 67 outgoingReferrer = document->outgoingReferrer(); 68 referrerPolicy = document->referrerPolicy(); 69 outgoingOrigin = document->outgoingOrigin(); 70 } else { 71 outgoingReferrer = request.httpReferrer(); 72 referrerPolicy = request.referrerPolicy(); 73 outgoingOrigin = SecurityOrigin::createFromString(outgoingReferrer)->toString(); 74 } 75 76 outgoingReferrer = SecurityPolicy::generateReferrerHeader(referrerPolicy, request.url(), outgoingReferrer); 77 if (outgoingReferrer.isEmpty()) 78 request.clearHTTPReferrer(); 79 else 80 request.setHTTPReferrer(Referrer(outgoingReferrer, referrerPolicy)); 81 82 request.addHTTPOriginIfNeeded(AtomicString(outgoingOrigin)); 83 } 84 85 // The remaining modifications are only necessary for HTTP and HTTPS. 86 if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily()) 87 return; 88 89 m_frame->loader().applyUserAgent(request); 90} 91 92void FrameFetchContext::setFirstPartyForCookies(ResourceRequest& request) 93{ 94 if (m_frame->tree().top()->isLocalFrame()) 95 request.setFirstPartyForCookies(toLocalFrame(m_frame->tree().top())->document()->firstPartyForCookies()); 96} 97 98CachePolicy FrameFetchContext::cachePolicy(Document* document) const 99{ 100 if (document && document->loadEventFinished()) 101 return CachePolicyVerify; 102 103 FrameLoadType loadType = m_frame->loader().loadType(); 104 if (loadType == FrameLoadTypeReloadFromOrigin) 105 return CachePolicyReload; 106 107 Frame* parentFrame = m_frame->tree().parent(); 108 if (parentFrame && parentFrame->isLocalFrame()) { 109 CachePolicy parentCachePolicy = toLocalFrame(parentFrame)->loader().fetchContext().cachePolicy(toLocalFrame(parentFrame)->document()); 110 if (parentCachePolicy != CachePolicyVerify) 111 return parentCachePolicy; 112 } 113 114 if (loadType == FrameLoadTypeReload) 115 return CachePolicyRevalidate; 116 117 DocumentLoader* loader = document ? document->loader() : 0; 118 if (loader && loader->request().cachePolicy() == ReturnCacheDataElseLoad) 119 return CachePolicyHistoryBuffer; 120 return CachePolicyVerify; 121 122} 123 124// FIXME(http://crbug.com/274173): 125// |loader| can be null if the resource is loaded from imported document. 126// This means inspector, which uses DocumentLoader as an grouping entity, 127// cannot see imported documents. 128inline DocumentLoader* FrameFetchContext::ensureLoader(DocumentLoader* loader) 129{ 130 return loader ? loader : m_frame->loader().documentLoader(); 131} 132 133void FrameFetchContext::dispatchDidChangeResourcePriority(unsigned long identifier, ResourceLoadPriority loadPriority, int intraPriorityValue) 134{ 135 m_frame->loader().client()->dispatchDidChangeResourcePriority(identifier, loadPriority, intraPriorityValue); 136} 137 138void FrameFetchContext::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse, const FetchInitiatorInfo& initiatorInfo) 139{ 140 m_frame->loader().applyUserAgent(request); 141 m_frame->loader().client()->dispatchWillSendRequest(loader, identifier, request, redirectResponse); 142 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ResourceSendRequest", "data", InspectorSendRequestEvent::data(identifier, m_frame, request)); 143 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); 144 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 145 InspectorInstrumentation::willSendRequest(m_frame, identifier, ensureLoader(loader), request, redirectResponse, initiatorInfo); 146} 147 148void FrameFetchContext::dispatchDidLoadResourceFromMemoryCache(const ResourceRequest& request, const ResourceResponse& response) 149{ 150 m_frame->loader().client()->dispatchDidLoadResourceFromMemoryCache(request, response); 151} 152 153void FrameFetchContext::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r, ResourceLoader* resourceLoader) 154{ 155 m_frame->loader().progress().incrementProgress(identifier, r); 156 m_frame->loader().client()->dispatchDidReceiveResponse(loader, identifier, r); 157 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ResourceReceiveResponse", "data", InspectorReceiveResponseEvent::data(identifier, m_frame, r)); 158 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 159 DocumentLoader* documentLoader = ensureLoader(loader); 160 InspectorInstrumentation::didReceiveResourceResponse(m_frame, identifier, documentLoader, r, resourceLoader); 161 // It is essential that inspector gets resource response BEFORE console. 162 m_frame->console().reportResourceResponseReceived(documentLoader, identifier, r); 163} 164 165void FrameFetchContext::dispatchDidReceiveData(DocumentLoader*, unsigned long identifier, const char* data, int dataLength, int encodedDataLength) 166{ 167 m_frame->loader().progress().incrementProgress(identifier, data, dataLength); 168 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ResourceReceivedData", "data", InspectorReceiveDataEvent::data(identifier, m_frame, encodedDataLength)); 169 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 170 InspectorInstrumentation::didReceiveData(m_frame, identifier, data, dataLength, encodedDataLength); 171} 172 173void FrameFetchContext::dispatchDidDownloadData(DocumentLoader*, unsigned long identifier, int dataLength, int encodedDataLength) 174{ 175 m_frame->loader().progress().incrementProgress(identifier, 0, dataLength); 176 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ResourceReceivedData", "data", InspectorReceiveDataEvent::data(identifier, m_frame, encodedDataLength)); 177 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 178 InspectorInstrumentation::didReceiveData(m_frame, identifier, 0, dataLength, encodedDataLength); 179} 180 181void FrameFetchContext::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier, double finishTime, int64_t encodedDataLength) 182{ 183 m_frame->loader().progress().completeProgress(identifier); 184 m_frame->loader().client()->dispatchDidFinishLoading(loader, identifier); 185 186 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ResourceFinish", "data", InspectorResourceFinishEvent::data(identifier, finishTime, false)); 187 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 188 InspectorInstrumentation::didFinishLoading(m_frame, identifier, ensureLoader(loader), finishTime, encodedDataLength); 189} 190 191void FrameFetchContext::dispatchDidFail(DocumentLoader* loader, unsigned long identifier, const ResourceError& error) 192{ 193 m_frame->loader().progress().completeProgress(identifier); 194 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ResourceFinish", "data", InspectorResourceFinishEvent::data(identifier, 0, true)); 195 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 196 InspectorInstrumentation::didFailLoading(m_frame, identifier, error); 197} 198 199void FrameFetchContext::sendRemainingDelegateMessages(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response, int dataLength) 200{ 201 if (!response.isNull()) 202 dispatchDidReceiveResponse(ensureLoader(loader), identifier, response); 203 204 if (dataLength > 0) 205 dispatchDidReceiveData(ensureLoader(loader), identifier, 0, dataLength, 0); 206 207 dispatchDidFinishLoading(ensureLoader(loader), identifier, 0, 0); 208} 209 210void FrameFetchContext::trace(Visitor* visitor) 211{ 212 visitor->trace(m_frame); 213 FetchContext::trace(visitor); 214} 215 216} // namespace blink 217