[Cocoa] WKCustomProtocolLoader should store a WeakPtr to its LegacyCustomProtocolMana...
[WebKit-https.git] / Source / WebKit / UIProcess / WebURLSchemeTask.cpp
1 /*
2  * Copyright (C) 2017 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 "WebURLSchemeTask.h"
28
29 #include "DataReference.h"
30 #include "SharedBufferDataReference.h"
31 #include "WebErrors.h"
32 #include "WebPageMessages.h"
33 #include "WebPageProxy.h"
34 #include "WebURLSchemeHandler.h"
35
36 namespace WebKit {
37 using namespace WebCore;
38
39 Ref<WebURLSchemeTask> WebURLSchemeTask::create(WebURLSchemeHandler& handler, WebPageProxy& page, WebProcessProxy& process, uint64_t resourceIdentifier, ResourceRequest&& request, SyncLoadCompletionHandler&& syncCompletionHandler)
40 {
41     return adoptRef(*new WebURLSchemeTask(handler, page, process, resourceIdentifier, WTFMove(request), WTFMove(syncCompletionHandler)));
42 }
43
44 WebURLSchemeTask::WebURLSchemeTask(WebURLSchemeHandler& handler, WebPageProxy& page, WebProcessProxy& process, uint64_t resourceIdentifier, ResourceRequest&& request, SyncLoadCompletionHandler&& syncCompletionHandler)
45     : m_urlSchemeHandler(handler)
46     , m_page(&page)
47     , m_process(makeRef(process))
48     , m_identifier(resourceIdentifier)
49     , m_pageIdentifier(page.pageID())
50     , m_request(WTFMove(request))
51     , m_syncCompletionHandler(WTFMove(syncCompletionHandler))
52 {
53 }
54
55 auto WebURLSchemeTask::didPerformRedirection(WebCore::ResourceResponse&& response, WebCore::ResourceRequest&& request) -> ExceptionType
56 {
57     if (m_stopped)
58         return ExceptionType::TaskAlreadyStopped;
59     
60     if (m_completed)
61         return ExceptionType::CompleteAlreadyCalled;
62     
63     if (m_dataSent)
64         return ExceptionType::DataAlreadySent;
65     
66     if (m_responseSent)
67         return ExceptionType::RedirectAfterResponse;
68     
69     if (isSync())
70         m_syncResponse = response;
71
72     m_request = request;
73     m_process->send(Messages::WebPage::URLSchemeTaskDidPerformRedirection(m_urlSchemeHandler->identifier(), m_identifier, response, request), m_page->pageID());
74
75     return ExceptionType::None;
76 }
77
78 auto WebURLSchemeTask::didReceiveResponse(const ResourceResponse& response) -> ExceptionType
79 {
80     if (m_stopped)
81         return ExceptionType::TaskAlreadyStopped;
82
83     if (m_completed)
84         return ExceptionType::CompleteAlreadyCalled;
85
86     if (m_dataSent)
87         return ExceptionType::DataAlreadySent;
88
89     m_responseSent = true;
90
91     response.includeCertificateInfo();
92
93     if (isSync())
94         m_syncResponse = response;
95
96     m_process->send(Messages::WebPage::URLSchemeTaskDidReceiveResponse(m_urlSchemeHandler->identifier(), m_identifier, response), m_page->pageID());
97     return ExceptionType::None;
98 }
99
100 auto WebURLSchemeTask::didReceiveData(Ref<SharedBuffer>&& buffer) -> ExceptionType
101 {
102     if (m_stopped)
103         return ExceptionType::TaskAlreadyStopped;
104
105     if (m_completed)
106         return ExceptionType::CompleteAlreadyCalled;
107
108     if (!m_responseSent)
109         return ExceptionType::NoResponseSent;
110
111     m_dataSent = true;
112
113     if (isSync()) {
114         if (m_syncData)
115             m_syncData->append(WTFMove(buffer));
116         else
117             m_syncData = WTFMove(buffer);
118         return ExceptionType::None;
119     }
120
121     m_process->send(Messages::WebPage::URLSchemeTaskDidReceiveData(m_urlSchemeHandler->identifier(), m_identifier, { buffer }), m_page->pageID());
122     return ExceptionType::None;
123 }
124
125 auto WebURLSchemeTask::didComplete(const ResourceError& error) -> ExceptionType
126 {
127     if (m_stopped)
128         return ExceptionType::TaskAlreadyStopped;
129
130     if (m_completed)
131         return ExceptionType::CompleteAlreadyCalled;
132
133     if (!m_responseSent && error.isNull())
134         return ExceptionType::NoResponseSent;
135
136     m_completed = true;
137     
138     if (isSync()) {
139         IPC::DataReference data;
140         if (m_syncData)
141             data = { reinterpret_cast<const uint8_t*>(m_syncData->data()), m_syncData->size() };
142         m_syncCompletionHandler(m_syncResponse, error, data);
143         m_syncData = nullptr;
144     }
145
146     m_process->send(Messages::WebPage::URLSchemeTaskDidComplete(m_urlSchemeHandler->identifier(), m_identifier, error), m_page->pageID());
147     m_urlSchemeHandler->taskCompleted(*this);
148
149     return ExceptionType::None;
150 }
151
152 void WebURLSchemeTask::pageDestroyed()
153 {
154     ASSERT(m_page);
155     m_page = nullptr;
156     m_process = nullptr;
157     m_stopped = true;
158     
159     if (isSync())
160         m_syncCompletionHandler({ }, failedCustomProtocolSyncLoad(m_request), { });
161 }
162
163 void WebURLSchemeTask::stop()
164 {
165     ASSERT(!m_stopped);
166     m_stopped = true;
167
168     if (isSync())
169         m_syncCompletionHandler({ }, failedCustomProtocolSyncLoad(m_request), { });
170 }
171
172 } // namespace WebKit