Delay WebProcess launch until a load is triggered in a Web view
[WebKit-https.git] / Source / WebKit / UIProcess / Cocoa / WebPageProxyCocoa.mm
1 /*
2  * Copyright (C) 2014-2019 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 #import "config.h"
27 #import "WebPageProxy.h"
28
29 #import "APIAttachment.h"
30 #import "APIUIClient.h"
31 #import "DataDetectionResult.h"
32 #import "LoadParameters.h"
33 #import "PageClient.h"
34 #import "SafeBrowsingSPI.h"
35 #import "SafeBrowsingWarning.h"
36 #import "WebPageMessages.h"
37 #import "WebProcessProxy.h"
38 #import "WebsiteDataStore.h"
39 #import <WebCore/DragItem.h>
40 #import <WebCore/NotImplemented.h>
41 #import <WebCore/SearchPopupMenuCocoa.h>
42 #import <WebCore/ValidationBubble.h>
43 #import <wtf/BlockPtr.h>
44 #import <wtf/cf/TypeCastsCF.h>
45
46 namespace WebKit {
47 using namespace WebCore;
48
49 #if ENABLE(DATA_DETECTION)
50 void WebPageProxy::setDataDetectionResult(const DataDetectionResult& dataDetectionResult)
51 {
52     m_dataDetectionResults = dataDetectionResult.results;
53 }
54 #endif
55
56 void WebPageProxy::saveRecentSearches(const String& name, const Vector<WebCore::RecentSearch>& searchItems)
57 {
58     if (!name) {
59         // FIXME: This should be a message check.
60         return;
61     }
62
63     WebCore::saveRecentSearches(name, searchItems);
64 }
65
66 void WebPageProxy::loadRecentSearches(const String& name, Vector<WebCore::RecentSearch>& searchItems)
67 {
68     if (!name) {
69         // FIXME: This should be a message check.
70         return;
71     }
72
73     searchItems = WebCore::loadRecentSearches(name);
74 }
75
76 void WebPageProxy::beginSafeBrowsingCheck(const URL& url, bool forMainFrameNavigation, WebFramePolicyListenerProxy& listener)
77 {
78 #if HAVE(SAFE_BROWSING)
79     SSBLookupContext *context = [SSBLookupContext sharedLookupContext];
80     if (!context)
81         return listener.didReceiveSafeBrowsingResults({ });
82     [context lookUpURL:url completionHandler:makeBlockPtr([listener = makeRef(listener), forMainFrameNavigation, url = url] (SSBLookupResult *result, NSError *error) mutable {
83         RunLoop::main().dispatch([listener = WTFMove(listener), result = retainPtr(result), error = retainPtr(error), forMainFrameNavigation, url = WTFMove(url)] {
84             if (error) {
85                 listener->didReceiveSafeBrowsingResults({ });
86                 return;
87             }
88
89             for (SSBServiceLookupResult *lookupResult in [result serviceLookupResults]) {
90                 if (lookupResult.isPhishing || lookupResult.isMalware || lookupResult.isUnwantedSoftware) {
91                     listener->didReceiveSafeBrowsingResults(SafeBrowsingWarning::create(url, forMainFrameNavigation, lookupResult));
92                     return;
93                 }
94             }
95             listener->didReceiveSafeBrowsingResults({ });
96         });
97     }).get()];
98 #else
99     listener.didReceiveSafeBrowsingResults({ });
100 #endif
101 }
102
103 #if ENABLE(CONTENT_FILTERING)
104 void WebPageProxy::contentFilterDidBlockLoadForFrame(const WebCore::ContentFilterUnblockHandler& unblockHandler, uint64_t frameID)
105 {
106     if (WebFrameProxy* frame = m_process->webFrame(frameID))
107         frame->contentFilterDidBlockLoad(unblockHandler);
108 }
109 #endif
110
111 void WebPageProxy::addPlatformLoadParameters(LoadParameters& loadParameters)
112 {
113     loadParameters.dataDetectionContext = m_uiClient->dataDetectionContext();
114 }
115
116 void WebPageProxy::createSandboxExtensionsIfNeeded(const Vector<String>& files, SandboxExtension::Handle& fileReadHandle, SandboxExtension::HandleArray& fileUploadHandles)
117 {
118     if (!files.size())
119         return;
120
121     if (files.size() == 1) {
122         BOOL isDirectory;
123         if ([[NSFileManager defaultManager] fileExistsAtPath:files[0] isDirectory:&isDirectory] && !isDirectory) {
124             SandboxExtension::createHandle("/", SandboxExtension::Type::ReadOnly, fileReadHandle);
125             willAcquireUniversalFileReadSandboxExtension(m_process);
126         }
127     }
128
129     fileUploadHandles.allocate(files.size());
130     for (size_t i = 0; i< files.size(); i++) {
131         NSString *file = files[i];
132         if (![[NSFileManager defaultManager] fileExistsAtPath:file])
133             continue;
134         SandboxExtension::createHandle(file, SandboxExtension::Type::ReadOnly, fileUploadHandles[i]);
135     }
136 }
137
138 bool WebPageProxy::scrollingUpdatesDisabledForTesting()
139 {
140     return pageClient().scrollingUpdatesDisabledForTesting();
141 }
142
143 #if ENABLE(DRAG_SUPPORT)
144
145 void WebPageProxy::startDrag(const DragItem& dragItem, const ShareableBitmap::Handle& dragImageHandle)
146 {
147     pageClient().startDrag(dragItem, dragImageHandle);
148 }
149
150 #if PLATFORM(IOS_FAMILY)
151
152 void WebPageProxy::setPromisedDataForImage(const String&, const SharedMemory::Handle&, uint64_t, const String&, const String&, const String&, const String&, const String&, const SharedMemory::Handle&, uint64_t)
153 {
154     notImplemented();
155 }
156
157 void WebPageProxy::setDragCaretRect(const IntRect& dragCaretRect)
158 {
159     if (m_currentDragCaretRect == dragCaretRect)
160         return;
161
162     auto previousRect = m_currentDragCaretRect;
163     m_currentDragCaretRect = dragCaretRect;
164     pageClient().didChangeDragCaretRect(previousRect, dragCaretRect);
165 }
166
167 #endif // PLATFORM(IOS_FAMILY)
168
169 #endif // ENABLE(DRAG_SUPPORT)
170
171 #if ENABLE(ATTACHMENT_ELEMENT)
172
173 void WebPageProxy::platformRegisterAttachment(Ref<API::Attachment>&& attachment, const String& preferredFileName, const IPC::DataReference& dataReference)
174 {
175     if (dataReference.isEmpty())
176         return;
177
178     auto buffer = SharedBuffer::create(dataReference.data(), dataReference.size());
179     auto fileWrapper = adoptNS([pageClient().allocFileWrapperInstance() initRegularFileWithContents:buffer->createNSData().autorelease()]);
180     [fileWrapper setPreferredFilename:preferredFileName];
181     attachment->setFileWrapper(fileWrapper.get());
182 }
183
184 void WebPageProxy::platformRegisterAttachment(Ref<API::Attachment>&& attachment, const String& filePath)
185 {
186     if (!filePath)
187         return;
188
189     auto fileWrapper = adoptNS([pageClient().allocFileWrapperInstance() initWithURL:[NSURL fileURLWithPath:filePath] options:0 error:nil]);
190     attachment->setFileWrapper(fileWrapper.get());
191 }
192
193 void WebPageProxy::platformCloneAttachment(Ref<API::Attachment>&& fromAttachment, Ref<API::Attachment>&& toAttachment)
194 {
195     toAttachment->setFileWrapper(fromAttachment->fileWrapper());
196 }
197
198 #endif // ENABLE(ATTACHMENT_ELEMENT)
199     
200 void WebPageProxy::performDictionaryLookupAtLocation(const WebCore::FloatPoint& point)
201 {
202     if (!hasRunningProcess())
203         return;
204     
205     process().send(Messages::WebPage::PerformDictionaryLookupAtLocation(point), m_pageID);
206 }
207
208 void WebPageProxy::performDictionaryLookupOfCurrentSelection()
209 {
210     if (!hasRunningProcess())
211         return;
212     
213     process().send(Messages::WebPage::PerformDictionaryLookupOfCurrentSelection(), m_pageID);
214 }
215     
216 #if ENABLE(APPLE_PAY)
217
218 IPC::Connection* WebPageProxy::paymentCoordinatorConnection(const WebPaymentCoordinatorProxy&)
219 {
220     return messageSenderConnection();
221 }
222
223 const String& WebPageProxy::paymentCoordinatorSourceApplicationBundleIdentifier(const WebPaymentCoordinatorProxy&, PAL::SessionID sessionID)
224 {
225     ASSERT_UNUSED(sessionID, sessionID == websiteDataStore().sessionID());
226     return websiteDataStore().sourceApplicationBundleIdentifier();
227 }
228
229 const String& WebPageProxy::paymentCoordinatorSourceApplicationSecondaryIdentifier(const WebPaymentCoordinatorProxy&, PAL::SessionID sessionID)
230 {
231     ASSERT_UNUSED(sessionID, sessionID == websiteDataStore().sessionID());
232     return websiteDataStore().sourceApplicationSecondaryIdentifier();
233 }
234
235 void WebPageProxy::paymentCoordinatorAddMessageReceiver(WebPaymentCoordinatorProxy&, const IPC::StringReference& messageReceiverName, IPC::MessageReceiver& messageReceiver)
236 {
237     process().addMessageReceiver(messageReceiverName, m_pageID, messageReceiver);
238 }
239
240 void WebPageProxy::paymentCoordinatorRemoveMessageReceiver(WebPaymentCoordinatorProxy&, const IPC::StringReference& messageReceiverName)
241 {
242     process().removeMessageReceiver(messageReceiverName, m_pageID);
243 }
244
245 #endif
246
247 #if ENABLE(SPEECH_SYNTHESIS)
248 void WebPageProxy::didStartSpeaking(WebCore::PlatformSpeechSynthesisUtterance&)
249 {
250 }
251
252 void WebPageProxy::didFinishSpeaking(WebCore::PlatformSpeechSynthesisUtterance&)
253 {
254     m_speechSynthesisData->speakingFinishedCompletionHandler();
255 }
256
257 void WebPageProxy::didPauseSpeaking(WebCore::PlatformSpeechSynthesisUtterance&)
258 {
259     m_speechSynthesisData->speakingPausedCompletionHandler();
260 }
261
262 void WebPageProxy::didResumeSpeaking(WebCore::PlatformSpeechSynthesisUtterance&)
263 {
264     m_speechSynthesisData->speakingResumedCompletionHandler();
265 }
266
267 void WebPageProxy::speakingErrorOccurred(WebCore::PlatformSpeechSynthesisUtterance&)
268 {
269     process().send(Messages::WebPage::SpeakingErrorOccurred(), m_pageID);
270 }
271
272 void WebPageProxy::boundaryEventOccurred(WebCore::PlatformSpeechSynthesisUtterance&, WebCore::SpeechBoundary speechBoundary, unsigned charIndex)
273 {
274     process().send(Messages::WebPage::BoundaryEventOccurred(speechBoundary == WebCore::SpeechBoundary::SpeechWordBoundary, charIndex), m_pageID);
275 }
276
277 void WebPageProxy::voicesDidChange()
278 {
279     process().send(Messages::WebPage::VoicesDidChange(), m_pageID);
280 }
281 #endif // ENABLE(SPEECH_SYNTHESIS)
282
283 } // namespace WebKit