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/LocalFrame.h" 36 #include "core/inspector/InspectorInstrumentation.h" 37 #include "core/inspector/InspectorTraceEvents.h" 38 #include "core/loader/DocumentLoader.h" 39 #include "core/loader/FrameLoader.h" 40 #include "core/loader/FrameLoaderClient.h" 41 #include "core/loader/ProgressTracker.h" 42 #include "core/page/Page.h" 43 #include "core/frame/Settings.h" 44 #include "platform/weborigin/SecurityPolicy.h" 45 46 namespace WebCore { 47 48 FrameFetchContext::FrameFetchContext(LocalFrame* frame) 49 : m_frame(frame) 50 { 51 } 52 53 void FrameFetchContext::reportLocalLoadFailed(const KURL& url) 54 { 55 FrameLoader::reportLocalLoadFailed(m_frame, url.elidedString()); 56 } 57 58 void FrameFetchContext::addAdditionalRequestHeaders(Document* document, ResourceRequest& request, FetchResourceType type) 59 { 60 bool isMainResource = type == FetchMainResource; 61 if (!isMainResource) { 62 String outgoingReferrer; 63 String outgoingOrigin; 64 if (request.httpReferrer().isNull()) { 65 outgoingReferrer = document->outgoingReferrer(); 66 outgoingOrigin = document->outgoingOrigin(); 67 } else { 68 outgoingReferrer = request.httpReferrer(); 69 outgoingOrigin = SecurityOrigin::createFromString(outgoingReferrer)->toString(); 70 } 71 72 outgoingReferrer = SecurityPolicy::generateReferrerHeader(document->referrerPolicy(), request.url(), outgoingReferrer); 73 if (outgoingReferrer.isEmpty()) 74 request.clearHTTPReferrer(); 75 else if (!request.httpReferrer()) 76 request.setHTTPReferrer(Referrer(outgoingReferrer, document->referrerPolicy())); 77 78 FrameLoader::addHTTPOriginIfNeeded(request, AtomicString(outgoingOrigin)); 79 } 80 81 // The remaining modifications are only necessary for HTTP and HTTPS. 82 if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily()) 83 return; 84 85 m_frame->loader().applyUserAgent(request); 86 87 // Default to sending an empty Origin header if one hasn't been set yet. 88 FrameLoader::addHTTPOriginIfNeeded(request, nullAtom); 89 } 90 91 void FrameFetchContext::setFirstPartyForCookies(ResourceRequest& request) 92 { 93 if (m_frame->tree().top()->isLocalFrame()) 94 request.setFirstPartyForCookies(toLocalFrame(m_frame->tree().top())->document()->firstPartyForCookies()); 95 } 96 97 CachePolicy FrameFetchContext::cachePolicy(Document* document) const 98 { 99 if (document && document->loadEventFinished()) 100 return CachePolicyVerify; 101 102 FrameLoadType loadType = m_frame->loader().loadType(); 103 if (loadType == FrameLoadTypeReloadFromOrigin) 104 return CachePolicyReload; 105 106 Frame* parentFrame = m_frame->tree().parent(); 107 if (parentFrame && parentFrame->isLocalFrame()) { 108 CachePolicy parentCachePolicy = toLocalFrame(parentFrame)->loader().fetchContext().cachePolicy(toLocalFrame(parentFrame)->document()); 109 if (parentCachePolicy != CachePolicyVerify) 110 return parentCachePolicy; 111 } 112 113 if (loadType == FrameLoadTypeReload) 114 return CachePolicyRevalidate; 115 116 DocumentLoader* loader = document ? document->loader() : 0; 117 if (loader && loader->request().cachePolicy() == ReturnCacheDataElseLoad) 118 return CachePolicyHistoryBuffer; 119 return CachePolicyVerify; 120 121 } 122 123 // FIXME(http://crbug.com/274173): 124 // |loader| can be null if the resource is loaded from imported document. 125 // This means inspector, which uses DocumentLoader as an grouping entity, 126 // cannot see imported documents. 127 inline DocumentLoader* FrameFetchContext::ensureLoader(DocumentLoader* loader) 128 { 129 return loader ? loader : m_frame->loader().documentLoader(); 130 } 131 132 void FrameFetchContext::dispatchDidChangeResourcePriority(unsigned long identifier, ResourceLoadPriority loadPriority, int intraPriorityValue) 133 { 134 m_frame->loader().client()->dispatchDidChangeResourcePriority(identifier, loadPriority, intraPriorityValue); 135 } 136 137 void FrameFetchContext::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse, const FetchInitiatorInfo& initiatorInfo) 138 { 139 m_frame->loader().applyUserAgent(request); 140 m_frame->loader().client()->dispatchWillSendRequest(loader, identifier, request, redirectResponse); 141 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ResourceSendRequest", "data", InspectorSendRequestEvent::data(identifier, m_frame, request)); 142 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); 143 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 144 InspectorInstrumentation::willSendRequest(m_frame, identifier, ensureLoader(loader), request, redirectResponse, initiatorInfo); 145 } 146 147 void FrameFetchContext::dispatchDidLoadResourceFromMemoryCache(const ResourceRequest& request, const ResourceResponse& response) 148 { 149 m_frame->loader().client()->dispatchDidLoadResourceFromMemoryCache(request, response); 150 } 151 152 void FrameFetchContext::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r, ResourceLoader* resourceLoader) 153 { 154 m_frame->loader().progress().incrementProgress(identifier, r); 155 m_frame->loader().client()->dispatchDidReceiveResponse(loader, identifier, r); 156 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ResourceReceiveResponse", "data", InspectorReceiveResponseEvent::data(identifier, m_frame, r)); 157 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 158 InspectorInstrumentation::didReceiveResourceResponse(m_frame, identifier, ensureLoader(loader), r, resourceLoader); 159 } 160 161 void FrameFetchContext::dispatchDidReceiveData(DocumentLoader*, unsigned long identifier, const char* data, int dataLength, int encodedDataLength) 162 { 163 m_frame->loader().progress().incrementProgress(identifier, data, dataLength); 164 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ResourceReceivedData", "data", InspectorReceiveDataEvent::data(identifier, m_frame, encodedDataLength)); 165 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 166 InspectorInstrumentation::didReceiveData(m_frame, identifier, data, dataLength, encodedDataLength); 167 } 168 169 void FrameFetchContext::dispatchDidDownloadData(DocumentLoader*, unsigned long identifier, int dataLength, int encodedDataLength) 170 { 171 m_frame->loader().progress().incrementProgress(identifier, 0, dataLength); 172 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ResourceReceivedData", "data", InspectorReceiveDataEvent::data(identifier, m_frame, encodedDataLength)); 173 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 174 InspectorInstrumentation::didReceiveData(m_frame, identifier, 0, dataLength, encodedDataLength); 175 } 176 177 void FrameFetchContext::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier, double finishTime, int64_t encodedDataLength) 178 { 179 m_frame->loader().progress().completeProgress(identifier); 180 m_frame->loader().client()->dispatchDidFinishLoading(loader, identifier); 181 182 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ResourceFinish", "data", InspectorResourceFinishEvent::data(identifier, finishTime, false)); 183 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 184 InspectorInstrumentation::didFinishLoading(m_frame, identifier, ensureLoader(loader), finishTime, encodedDataLength); 185 } 186 187 void FrameFetchContext::dispatchDidFail(DocumentLoader* loader, unsigned long identifier, const ResourceError& error) 188 { 189 m_frame->loader().progress().completeProgress(identifier); 190 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ResourceFinish", "data", InspectorResourceFinishEvent::data(identifier, 0, true)); 191 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 192 InspectorInstrumentation::didFailLoading(m_frame, identifier, error); 193 } 194 195 void FrameFetchContext::sendRemainingDelegateMessages(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response, int dataLength) 196 { 197 if (!response.isNull()) 198 dispatchDidReceiveResponse(ensureLoader(loader), identifier, response); 199 200 if (dataLength > 0) 201 dispatchDidReceiveData(ensureLoader(loader), identifier, 0, dataLength, 0); 202 203 dispatchDidFinishLoading(ensureLoader(loader), identifier, 0, 0); 204 } 205 206 } // namespace WebCore 207