Take referrer policy into account when clearing the referrer header
[WebKit-https.git] / Source / WebKit2 / WebProcess / Network / WebResourceLoadScheduler.cpp
1 /*
2  * Copyright (C) 2012 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WebResourceLoadScheduler.h"
28
29 #include "Logging.h"
30 #include "NetworkConnectionToWebProcessMessages.h"
31 #include "NetworkProcessConnection.h"
32 #include "NetworkResourceLoadParameters.h"
33 #include "WebCoreArgumentCoders.h"
34 #include "WebErrors.h"
35 #include "WebFrame.h"
36 #include "WebFrameLoaderClient.h"
37 #include "WebPage.h"
38 #include "WebProcess.h"
39 #include "WebResourceLoader.h"
40 #include <WebCore/Document.h>
41 #include <WebCore/DocumentLoader.h>
42 #include <WebCore/Frame.h>
43 #include <WebCore/FrameLoader.h>
44 #include <WebCore/NetscapePlugInStreamLoader.h>
45 #include <WebCore/ReferrerPolicy.h>
46 #include <WebCore/ResourceBuffer.h>
47 #include <WebCore/ResourceLoader.h>
48 #include <WebCore/Settings.h>
49 #include <WebCore/SubresourceLoader.h>
50 #include <wtf/text/CString.h>
51
52 #if ENABLE(NETWORK_PROCESS)
53
54 using namespace WebCore;
55
56 namespace WebKit {
57
58 WebResourceLoadScheduler::WebResourceLoadScheduler()
59     : m_internallyFailedLoadTimer(RunLoop::main(), this, &WebResourceLoadScheduler::internallyFailedLoadTimerFired)
60     , m_suspendPendingRequestsCount(0)
61 {
62 }
63
64 WebResourceLoadScheduler::~WebResourceLoadScheduler()
65 {
66 }
67
68 PassRefPtr<SubresourceLoader> WebResourceLoadScheduler::scheduleSubresourceLoad(Frame* frame, CachedResource* resource, const ResourceRequest& request, ResourceLoadPriority priority, const ResourceLoaderOptions& options)
69 {
70     RefPtr<SubresourceLoader> loader = SubresourceLoader::create(frame, resource, request, options);
71     if (loader)
72         scheduleLoad(loader.get(), priority, frame->document()->referrerPolicy() == ReferrerPolicyDefault);
73     return loader.release();
74 }
75
76 PassRefPtr<NetscapePlugInStreamLoader> WebResourceLoadScheduler::schedulePluginStreamLoad(Frame* frame, NetscapePlugInStreamLoaderClient* client, const ResourceRequest& request)
77 {
78     RefPtr<NetscapePlugInStreamLoader> loader = NetscapePlugInStreamLoader::create(frame, client, request);
79     if (loader)
80         scheduleLoad(loader.get(), ResourceLoadPriorityLow, frame->document()->referrerPolicy() == ReferrerPolicyDefault);
81     return loader.release();
82 }
83
84 void WebResourceLoadScheduler::scheduleLoad(ResourceLoader* resourceLoader, ResourceLoadPriority priority, bool shouldClearReferrerOnHTTPSToHTTPRedirect)
85 {
86     ASSERT(resourceLoader);
87     ASSERT(priority != ResourceLoadPriorityUnresolved);
88     priority = ResourceLoadPriorityHighest;
89
90     ResourceLoadIdentifier identifier = resourceLoader->identifier();
91     ASSERT(identifier);
92
93     // If the DocumentLoader schedules this as an archive resource load,
94     // then we should remember the ResourceLoader in our records but not schedule it in the NetworkProcess.
95     if (resourceLoader->documentLoader()->scheduleArchiveLoad(resourceLoader, resourceLoader->request())) {
96         LOG(NetworkScheduling, "(WebProcess) WebResourceLoadScheduler::scheduleLoad, url '%s' will be handled as an archive resource.", resourceLoader->url().string().utf8().data());
97         m_webResourceLoaders.set(identifier, WebResourceLoader::create(resourceLoader));
98         return;
99     }
100     
101     LOG(NetworkScheduling, "(WebProcess) WebResourceLoadScheduler::scheduleLoad, url '%s' will be scheduled with the NetworkProcess with priority %i", resourceLoader->url().string().utf8().data(), priority);
102
103     ContentSniffingPolicy contentSniffingPolicy = resourceLoader->shouldSniffContent() ? SniffContent : DoNotSniffContent;
104     StoredCredentials allowStoredCredentials = resourceLoader->shouldUseCredentialStorage() ? AllowStoredCredentials : DoNotAllowStoredCredentials;
105     bool privateBrowsingEnabled = resourceLoader->frameLoader()->frame()->settings()->privateBrowsingEnabled();
106
107     WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(resourceLoader->frameLoader()->client())->webFrame();
108     WebPage* webPage = webFrame->page();
109
110     NetworkResourceLoadParameters loadParameters(identifier, webPage->pageID(), webFrame->frameID(), resourceLoader->request(), priority, contentSniffingPolicy, allowStoredCredentials, privateBrowsingEnabled, shouldClearReferrerOnHTTPSToHTTPRedirect);
111     if (!WebProcess::shared().networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::ScheduleResourceLoad(loadParameters), 0)) {
112         // We probably failed to schedule this load with the NetworkProcess because it had crashed.
113         // This load will never succeed so we will schedule it to fail asynchronously.
114         scheduleInternallyFailedLoad(resourceLoader);
115         return;
116     }
117     
118     m_webResourceLoaders.set(identifier, WebResourceLoader::create(resourceLoader));
119     
120     notifyDidScheduleResourceRequest(resourceLoader);
121 }
122
123 void WebResourceLoadScheduler::scheduleInternallyFailedLoad(WebCore::ResourceLoader* resourceLoader)
124 {
125     m_internallyFailedResourceLoaders.add(resourceLoader);
126     m_internallyFailedLoadTimer.startOneShot(0);
127 }
128
129 void WebResourceLoadScheduler::internallyFailedLoadTimerFired()
130 {
131     Vector<RefPtr<ResourceLoader> > internallyFailedResourceLoaders;
132     copyToVector(m_internallyFailedResourceLoaders, internallyFailedResourceLoaders);
133     
134     for (size_t i = 0; i < internallyFailedResourceLoaders.size(); ++i)
135         internallyFailedResourceLoaders[i]->didFail(internalError(internallyFailedResourceLoaders[i]->url()));
136 }
137
138 void WebResourceLoadScheduler::remove(ResourceLoader* resourceLoader)
139 {
140     ASSERT(resourceLoader);
141     LOG(NetworkScheduling, "(WebProcess) WebResourceLoadScheduler::remove, url '%s'", resourceLoader->url().string().utf8().data());
142
143     if (m_internallyFailedResourceLoaders.contains(resourceLoader)) {
144         m_internallyFailedResourceLoaders.remove(resourceLoader);
145         return;
146     }
147     
148     ResourceLoadIdentifier identifier = resourceLoader->identifier();
149     if (!identifier) {
150         LOG_ERROR("WebResourceLoadScheduler removing a ResourceLoader that has no identifier.");
151         return;
152     }
153     
154     // FIXME (NetworkProcess): We should only tell the NetworkProcess to remove load identifiers for ResourceLoaders that were never started.
155     // If a resource load was actually started within the NetworkProcess then the NetworkProcess handles clearing out the identifier.
156     WebProcess::shared().networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::RemoveLoadIdentifier(identifier), 0);
157     
158     ASSERT(m_webResourceLoaders.contains(identifier));
159     m_webResourceLoaders.remove(identifier);
160 }
161
162 void WebResourceLoadScheduler::crossOriginRedirectReceived(ResourceLoader*, const KURL&)
163 {
164     // We handle cross origin redirects entirely within the NetworkProcess.
165     // We override this call in the WebProcess to make it a no-op.
166 }
167
168 void WebResourceLoadScheduler::servePendingRequests(ResourceLoadPriority minimumPriority)
169 {
170     LOG(NetworkScheduling, "(WebProcess) WebResourceLoadScheduler::servePendingRequests");
171     
172     // The NetworkProcess scheduler is good at making sure loads are serviced until there are no more pending requests.
173     // If this WebProcess isn't expecting requests to be served then we can ignore messaging the NetworkProcess right now.
174     if (m_suspendPendingRequestsCount)
175         return;
176
177     WebProcess::shared().networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::ServePendingRequests(minimumPriority), 0);
178 }
179
180 void WebResourceLoadScheduler::suspendPendingRequests()
181 {
182     ++m_suspendPendingRequestsCount;
183 }
184
185 void WebResourceLoadScheduler::resumePendingRequests()
186 {
187     ASSERT(m_suspendPendingRequestsCount);
188     --m_suspendPendingRequestsCount;
189 }
190
191 void WebResourceLoadScheduler::setSerialLoadingEnabled(bool enabled)
192 {
193     WebProcess::shared().networkConnection()->connection()->sendSync(Messages::NetworkConnectionToWebProcess::SetSerialLoadingEnabled(enabled), Messages::NetworkConnectionToWebProcess::SetSerialLoadingEnabled::Reply(), 0);
194 }
195
196 void WebResourceLoadScheduler::networkProcessCrashed()
197 {
198     HashMap<unsigned long, RefPtr<WebResourceLoader> >::iterator end = m_webResourceLoaders.end();
199     for (HashMap<unsigned long, RefPtr<WebResourceLoader> >::iterator i = m_webResourceLoaders.begin(); i != end; ++i)
200         scheduleInternallyFailedLoad(i->value.get()->resourceLoader());
201
202     m_webResourceLoaders.clear();
203 }
204
205 } // namespace WebKit
206
207 #endif // ENABLE(NETWORK_PROCESS)