[iOS WebKit2] Add support for text autosizing
[WebKit-https.git] / Source / WebKit2 / UIProcess / ios / WebPageProxyIOS.mm
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 #import "config.h"
27 #import "WebPageProxy.h"
28
29 #if PLATFORM(IOS)
30
31 #import "DataReference.h"
32 #import "EditingRange.h"
33 #import "NativeWebKeyboardEvent.h"
34 #import "PageClient.h"
35 #import "RemoteLayerTreeTransaction.h"
36 #import "ViewUpdateDispatcherMessages.h"
37 #import "WKBrowsingContextControllerInternal.h"
38 #import "WebContextUserMessageCoders.h"
39 #import "WebKitSystemInterfaceIOS.h"
40 #import "WebPageMessages.h"
41 #import "WebProcessProxy.h"
42 #import "WebVideoFullscreenManagerProxy.h"
43 #import <WebCore/NotImplemented.h>
44 #import <WebCore/SharedBuffer.h>
45 #import <WebCore/UserAgent.h>
46
47 using namespace WebCore;
48
49 namespace WebKit {
50
51 void WebPageProxy::platformInitialize()
52 {
53 }
54
55 static String userVisibleWebKitVersionString()
56 {
57     // If the version is longer than 3 digits then the leading digits represent the version of the OS. Our user agent
58     // string should not include the leading digits, so strip them off and report the rest as the version. <rdar://problem/4997547>
59     NSString *fullVersion = [[NSBundle bundleForClass:NSClassFromString(@"WKView")] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
60     NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
61     if (nonDigitRange.location == NSNotFound && fullVersion.length > 3)
62         return [fullVersion substringFromIndex:fullVersion.length - 3];
63     if (nonDigitRange.location != NSNotFound && nonDigitRange.location > 3)
64         return [fullVersion substringFromIndex:nonDigitRange.location - 3];
65     return fullVersion;
66 }
67
68 String WebPageProxy::standardUserAgent(const String& applicationName)
69 {
70     return standardUserAgentWithApplicationName(applicationName, userVisibleWebKitVersionString());
71 }
72
73 void WebPageProxy::getIsSpeaking(bool&)
74 {
75     notImplemented();
76 }
77
78 void WebPageProxy::speak(const String&)
79 {
80     notImplemented();
81 }
82
83 void WebPageProxy::stopSpeaking()
84 {
85     notImplemented();
86 }
87
88 void WebPageProxy::searchWithSpotlight(const String&)
89 {
90     notImplemented();
91 }
92
93 void WebPageProxy::searchTheWeb(const String&)
94 {
95     notImplemented();
96 }
97
98 void WebPageProxy::windowAndViewFramesChanged(const FloatRect&, const FloatPoint&)
99 {
100     notImplemented();
101 }
102
103 String WebPageProxy::stringSelectionForPasteboard()
104 {
105     notImplemented();
106     return String();
107 }
108
109 PassRefPtr<WebCore::SharedBuffer> WebPageProxy::dataSelectionForPasteboard(const String&)
110 {
111     notImplemented();
112     return 0;
113 }
114
115 bool WebPageProxy::readSelectionFromPasteboard(const String&)
116 {
117     notImplemented();
118     return false;
119 }
120
121 void WebPageProxy::performDictionaryLookupAtLocation(const WebCore::FloatPoint&)
122 {
123     notImplemented();
124 }
125
126 void WebPageProxy::gestureCallback(const WebCore::IntPoint& point, uint32_t gestureType, uint32_t gestureState, uint32_t flags, uint64_t callbackID)
127 {
128     RefPtr<GestureCallback> callback = m_gestureCallbacks.take(callbackID);
129     if (!callback) {
130         ASSERT_NOT_REACHED();
131         return;
132     }
133     
134     callback->performCallbackWithReturnValue(point, gestureType, gestureState, flags);
135 }
136
137 void WebPageProxy::touchesCallback(const WebCore::IntPoint& point, uint32_t touches, uint64_t callbackID)
138 {
139     RefPtr<TouchesCallback> callback = m_touchesCallbacks.take(callbackID);
140     if (!callback) {
141         ASSERT_NOT_REACHED();
142         return;
143     }
144
145     callback->performCallbackWithReturnValue(point, touches);
146 }
147
148 void WebPageProxy::autocorrectionDataCallback(const Vector<WebCore::FloatRect>& rects, const String& fontName, float fontSize, uint64_t fontTraits, uint64_t callbackID)
149 {
150     RefPtr<AutocorrectionDataCallback> callback = m_autocorrectionCallbacks.take(callbackID);
151     if (!callback) {
152         ASSERT_NOT_REACHED();
153         return;
154     }
155
156     callback->performCallbackWithReturnValue(rects, fontName, fontSize, fontTraits);
157 }
158
159 void WebPageProxy::dictationContextCallback(const String& selectedText, const String& beforeText, const String& afterText, uint64_t callbackID)
160 {
161     RefPtr<DictationContextCallback> callback = m_dictationContextCallbacks.take(callbackID);
162     if (!callback) {
163         ASSERT_NOT_REACHED();
164         return;
165     }
166
167     callback->performCallbackWithReturnValue(selectedText, beforeText, afterText);
168 }
169
170 void WebPageProxy::autocorrectionContextCallback(const String& beforeText, const String& markedText, const String& selectedText, const String& afterText, uint64_t location, uint64_t length, uint64_t callbackID)
171 {
172     RefPtr<AutocorrectionContextCallback> callback = m_autocorrectionContextCallbacks.take(callbackID);
173     if (!callback) {
174         ASSERT_NOT_REACHED();
175         return;
176     }
177
178     callback->performCallbackWithReturnValue(beforeText, markedText, selectedText, afterText, location, length);
179 }
180
181 bool WebPageProxy::updateVisibleContentRects(const VisibleContentRectUpdateInfo& visibleContentRectUpdateInfo)
182 {
183     if (visibleContentRectUpdateInfo == m_lastVisibleContentRectUpdate)
184         return false;
185
186     m_lastVisibleContentRectUpdate = visibleContentRectUpdateInfo;
187     m_process->send(Messages::ViewUpdateDispatcher::VisibleContentRectUpdate(m_pageID, visibleContentRectUpdateInfo), 0);
188     return true;
189 }
190
191 void WebPageProxy::dynamicViewportSizeUpdate(const FloatSize& minimumLayoutSize, const FloatRect& targetExposedContentRect, const FloatRect& targetUnobscuredRect, double targetScale)
192 {
193     m_process->send(Messages::WebPage::DynamicViewportSizeUpdate(minimumLayoutSize, targetExposedContentRect, targetUnobscuredRect, targetScale), m_pageID);
194 }
195
196 void WebPageProxy::setViewportConfigurationMinimumLayoutSize(const WebCore::FloatSize& size)
197 {
198     m_process->send(Messages::WebPage::SetViewportConfigurationMinimumLayoutSize(size), m_pageID);
199 }
200
201 void WebPageProxy::setMinimumLayoutSizeForMinimalUI(const WebCore::FloatSize& size)
202 {
203     m_process->send(Messages::WebPage::SetMinimumLayoutSizeForMinimalUI(size), m_pageID);
204 }
205
206 void WebPageProxy::didCommitLayerTree(const WebKit::RemoteLayerTreeTransaction& layerTreeTransaction)
207 {
208     m_pageExtendedBackgroundColor = layerTreeTransaction.pageExtendedBackgroundColor();
209
210     m_pageClient.didCommitLayerTree(layerTreeTransaction);
211 }
212
213 void WebPageProxy::selectWithGesture(const WebCore::IntPoint point, WebCore::TextGranularity granularity, uint32_t gestureType, uint32_t gestureState, PassRefPtr<GestureCallback> callback)
214 {
215     if (!isValid()) {
216         callback->invalidate();
217         return;
218     }
219     
220     uint64_t callbackID = callback->callbackID();
221     m_gestureCallbacks.set(callbackID, callback);
222     m_process->send(Messages::WebPage::SelectWithGesture(point, (uint32_t)granularity, gestureType, gestureState, callbackID), m_pageID);
223 }
224
225 void WebPageProxy::updateSelectionWithTouches(const WebCore::IntPoint point, uint32_t touches, bool baseIsStart, PassRefPtr<TouchesCallback> callback)
226 {
227     if (!isValid()) {
228         callback->invalidate();
229         return;
230     }
231
232     uint64_t callbackID = callback->callbackID();
233     m_touchesCallbacks.set(callbackID, callback);
234     m_process->send(Messages::WebPage::UpdateSelectionWithTouches(point, touches, baseIsStart, callbackID), m_pageID);
235 }
236     
237 void WebPageProxy::replaceDictatedText(const String& oldText, const String& newText)
238 {
239     m_process->send(Messages::WebPage::ReplaceDictatedText(oldText, newText), m_pageID);
240 }
241
242 void WebPageProxy::replaceSelectedText(const String& oldText, const String& newText)
243 {
244     m_process->send(Messages::WebPage::ReplaceSelectedText(oldText, newText), m_pageID);
245 }
246
247 void WebPageProxy::requestAutocorrectionData(const String& textForAutocorrection, PassRefPtr<AutocorrectionDataCallback> callback)
248 {
249     if (!isValid()) {
250         callback->invalidate();
251         return;
252     }
253
254     uint64_t callbackID = callback->callbackID();
255     m_autocorrectionCallbacks.set(callbackID, callback);
256     m_process->send(Messages::WebPage::RequestAutocorrectionData(textForAutocorrection, callbackID), m_pageID);
257 }
258
259 void WebPageProxy::applyAutocorrection(const String& correction, const String& originalText, PassRefPtr<StringCallback> callback)
260 {
261     if (!isValid()) {
262         callback->invalidate();
263         return;
264     }
265
266     uint64_t callbackID = callback->callbackID();
267     m_stringCallbacks.set(callbackID, callback);
268     m_process->send(Messages::WebPage::ApplyAutocorrection(correction, originalText, callbackID), m_pageID);
269 }
270
271 bool WebPageProxy::applyAutocorrection(const String& correction, const String& originalText)
272 {
273     bool autocorrectionApplied = false;
274     m_process->sendSync(Messages::WebPage::SyncApplyAutocorrection(correction, originalText), Messages::WebPage::SyncApplyAutocorrection::Reply(autocorrectionApplied), m_pageID);
275     return autocorrectionApplied;
276 }
277
278 void WebPageProxy::requestDictationContext(PassRefPtr<DictationContextCallback> callback)
279 {
280     if (!isValid()) {
281         callback->invalidate();
282         return;
283     }
284
285     uint64_t callbackID = callback->callbackID();
286     m_dictationContextCallbacks.set(callbackID, callback);
287     m_process->send(Messages::WebPage::RequestDictationContext(callbackID), m_pageID);
288 }
289
290 void WebPageProxy::requestAutocorrectionContext(PassRefPtr<AutocorrectionContextCallback> callback)
291 {
292     if (!isValid()) {
293         callback->invalidate();
294         return;
295     }
296
297     uint64_t callbackID = callback->callbackID();
298     m_autocorrectionContextCallbacks.set(callbackID, callback);
299     m_process->send(Messages::WebPage::RequestAutocorrectionContext(callbackID), m_pageID);
300 }
301
302 void WebPageProxy::getAutocorrectionContext(String& beforeContext, String& markedText, String& selectedText, String& afterContext, uint64_t& location, uint64_t& length)
303 {
304     m_process->sendSync(Messages::WebPage::GetAutocorrectionContext(), Messages::WebPage::GetAutocorrectionContext::Reply(beforeContext, markedText, selectedText, afterContext, location, length), m_pageID);
305 }
306
307 void WebPageProxy::selectWithTwoTouches(const WebCore::IntPoint from, const WebCore::IntPoint to, uint32_t gestureType, uint32_t gestureState, PassRefPtr<GestureCallback> callback)
308 {
309     if (!isValid()) {
310         callback->invalidate();
311         return;
312     }
313
314     uint64_t callbackID = callback->callbackID();
315     m_gestureCallbacks.set(callbackID, callback);
316     m_process->send(Messages::WebPage::SelectWithTwoTouches(from, to, gestureType, gestureState, callbackID), m_pageID);
317 }
318
319 void WebPageProxy::updateBlockSelectionWithTouch(const WebCore::IntPoint point, uint32_t touch, uint32_t handlePosition)
320 {
321     m_process->send(Messages::WebPage::UpdateBlockSelectionWithTouch(point, touch, handlePosition), m_pageID);
322 }
323
324 void WebPageProxy::didReceivePositionInformation(const InteractionInformationAtPosition& info)
325 {
326     m_pageClient.positionInformationDidChange(info);
327 }
328
329 void WebPageProxy::getPositionInformation(const WebCore::IntPoint& point, InteractionInformationAtPosition& info)
330 {
331     m_process->sendSync(Messages::WebPage::GetPositionInformation(point), Messages::WebPage::GetPositionInformation::Reply(info), m_pageID);
332 }
333
334 void WebPageProxy::requestPositionInformation(const WebCore::IntPoint& point)
335 {
336     m_process->send(Messages::WebPage::RequestPositionInformation(point), m_pageID);
337 }
338
339 void WebPageProxy::startInteractionWithElementAtPosition(const WebCore::IntPoint& point)
340 {
341     m_process->send(Messages::WebPage::StartInteractionWithElementAtPosition(point), m_pageID);
342 }
343
344 void WebPageProxy::stopInteraction()
345 {
346     m_process->send(Messages::WebPage::StopInteraction(), m_pageID);
347 }
348
349 void WebPageProxy::performActionOnElement(uint32_t action)
350 {
351     m_process->send(Messages::WebPage::PerformActionOnElement(action), m_pageID);
352 }
353
354 void WebPageProxy::saveImageToLibrary(const SharedMemory::Handle& imageHandle, uint64_t imageSize)
355 {
356     RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::create(imageHandle, SharedMemory::ReadOnly);
357     RefPtr<SharedBuffer> buffer = SharedBuffer::create(static_cast<unsigned char*>(sharedMemoryBuffer->data()), imageSize);
358     m_pageClient.saveImageToLibrary(buffer);
359 }
360
361 void WebPageProxy::didUpdateBlockSelectionWithTouch(uint32_t touch, uint32_t flags, float growThreshold, float shrinkThreshold)
362 {
363     m_pageClient.didUpdateBlockSelectionWithTouch(touch, flags, growThreshold, shrinkThreshold);
364 }
365
366 void WebPageProxy::applicationWillEnterForeground()
367 {
368     m_process->send(Messages::WebPage::ApplicationWillEnterForeground(), m_pageID);
369 }
370
371 void WebPageProxy::applicationWillResignActive()
372 {
373     m_process->send(Messages::WebPage::ApplicationWillResignActive(), m_pageID);
374 }
375
376 void WebPageProxy::applicationDidBecomeActive()
377 {
378     m_process->send(Messages::WebPage::ApplicationDidBecomeActive(), m_pageID);
379 }
380
381 void WebPageProxy::notifyRevealedSelection()
382 {
383     m_pageClient.selectionDidChange();
384 }
385
386 void WebPageProxy::extendSelection(WebCore::TextGranularity granularity)
387 {
388     m_process->send(Messages::WebPage::ExtendSelection(static_cast<uint32_t>(granularity)), m_pageID);
389 }
390
391 void WebPageProxy::interpretKeyEvent(const EditorState& state, bool isCharEvent, bool& handled)
392 {
393     m_editorState = state;
394     handled = m_pageClient.interpretKeyEvent(m_keyEventQueue.first(), isCharEvent);
395 }
396
397 // Complex text input support for plug-ins.
398 void WebPageProxy::sendComplexTextInputToPlugin(uint64_t, const String&)
399 {
400     notImplemented();
401 }
402
403 void WebPageProxy::setSmartInsertDeleteEnabled(bool)
404 {
405     notImplemented();
406 }
407
408 void WebPageProxy::registerWebProcessAccessibilityToken(const IPC::DataReference& data)
409 {
410     m_pageClient.accessibilityWebProcessTokenReceived(data);
411 }    
412
413 void WebPageProxy::makeFirstResponder()
414 {
415     notImplemented();
416 }
417
418 void WebPageProxy::registerUIProcessAccessibilityTokens(const IPC::DataReference& elementToken, const IPC::DataReference& windowToken)
419 {
420     if (!isValid())
421         return;
422     
423     process().send(Messages::WebPage::RegisterUIProcessAccessibilityTokens(elementToken, windowToken), m_pageID);
424 }
425
426 void WebPageProxy::pluginFocusOrWindowFocusChanged(uint64_t, bool)
427 {
428     notImplemented();
429 }
430
431 void WebPageProxy::setPluginComplexTextInputState(uint64_t, uint64_t)
432 {
433     notImplemented();
434 }
435
436 void WebPageProxy::executeSavedCommandBySelector(const String&, bool&)
437 {
438     notImplemented();
439 }
440
441 bool WebPageProxy::shouldDelayWindowOrderingForEvent(const WebKit::WebMouseEvent&)
442 {
443     notImplemented();
444     return false;
445 }
446
447 bool WebPageProxy::acceptsFirstMouse(int, const WebKit::WebMouseEvent&)
448 {
449     notImplemented();
450     return false;
451 }
452
453 void WebPageProxy::willStartUserTriggeredZooming()
454 {
455     process().send(Messages::WebPage::WillStartUserTriggeredZooming(), m_pageID);
456 }
457
458 void WebPageProxy::tapHighlightAtPosition(const WebCore::FloatPoint& position, uint64_t& requestID)
459 {
460     static uint64_t uniqueRequestID = 0;
461     requestID = ++uniqueRequestID;
462
463     process().send(Messages::WebPage::TapHighlightAtPosition(requestID, position), m_pageID);
464 }
465
466 void WebPageProxy::blurAssistedNode()
467 {
468     process().send(Messages::WebPage::BlurAssistedNode(), m_pageID);
469 }
470
471 FloatSize WebPageProxy::screenSize()
472 {
473     return FloatSize(WKGetScreenSize());
474 }
475
476 FloatSize WebPageProxy::availableScreenSize()
477 {
478     return FloatSize(WKGetAvailableScreenSize());
479 }
480     
481 float WebPageProxy::textAutosizingWidth()
482 {
483     return WKGetScreenSize().width;
484 }
485     
486 void WebPageProxy::dynamicViewportUpdateChangedTarget(double newScale, const WebCore::FloatPoint& newScrollPosition)
487 {
488     m_pageClient.dynamicViewportUpdateChangedTarget(newScale, newScrollPosition);
489 }
490
491 void WebPageProxy::didGetTapHighlightGeometries(uint64_t requestID, const WebCore::Color& color, const Vector<WebCore::FloatQuad>& highlightedQuads, const WebCore::IntSize& topLeftRadius, const WebCore::IntSize& topRightRadius, const WebCore::IntSize& bottomLeftRadius, const WebCore::IntSize& bottomRightRadius)
492 {
493     m_pageClient.didGetTapHighlightGeometries(requestID, color, highlightedQuads, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
494 }
495
496 void WebPageProxy::startAssistingNode(const AssistedNodeInformation& information, bool userIsInteracting, IPC::MessageDecoder& decoder)
497 {
498     RefPtr<API::Object> userData;
499     WebContextUserMessageDecoder messageDecoder(userData, process());
500     if (!decoder.decode(messageDecoder))
501         return;
502
503     m_pageClient.startAssistingNode(information, userIsInteracting, userData.get());
504 }
505
506 void WebPageProxy::stopAssistingNode()
507 {
508     m_pageClient.stopAssistingNode();
509 }
510
511 #if ENABLE(INSPECTOR)
512 void WebPageProxy::showInspectorIndication()
513 {
514     m_pageClient.showInspectorIndication();
515 }
516
517 void WebPageProxy::hideInspectorIndication()
518 {
519     m_pageClient.hideInspectorIndication();
520 }
521 #endif
522
523 void WebPageProxy::focusNextAssistedNode(bool isForward)
524 {
525     process().send(Messages::WebPage::FocusNextAssistedNode(isForward), m_pageID);
526 }
527
528 void WebPageProxy::setAssistedNodeValue(const String& value)
529 {
530     process().send(Messages::WebPage::SetAssistedNodeValue(value), m_pageID);
531 }
532
533 void WebPageProxy::setAssistedNodeValueAsNumber(double value)
534 {
535     process().send(Messages::WebPage::SetAssistedNodeValueAsNumber(value), m_pageID);
536 }
537
538 void WebPageProxy::setAssistedNodeSelectedIndex(uint32_t index, bool allowMultipleSelection)
539 {
540     process().send(Messages::WebPage::SetAssistedNodeSelectedIndex(index, allowMultipleSelection), m_pageID);
541 }
542
543 void WebPageProxy::didPerformDictionaryLookup(const AttributedString&, const DictionaryPopupInfo&)
544 {
545     notImplemented();
546 }
547
548 void WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplication(const String&, const String&, const IPC::DataReference&, const String&)
549 {
550     notImplemented();
551 }
552
553 void WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplicationRaw(const String&, const String&, const uint8_t*, unsigned long, const String&)
554 {
555     notImplemented();
556 }
557
558 void WebPageProxy::openPDFFromTemporaryFolderWithNativeApplication(const String&)
559 {
560     notImplemented();
561 }
562
563 void WebPageProxy::setAcceleratedCompositingRootLayer(LayerOrView* rootLayer)
564 {
565     m_pageClient.setAcceleratedCompositingRootLayer(rootLayer);
566 }
567
568 void WebPageProxy::showPlaybackTargetPicker(bool hasVideo, const IntRect& elementRect)
569 {
570     m_pageClient.showPlaybackTargetPicker(hasVideo, elementRect);
571 }
572
573 void WebPageProxy::zoomToRect(FloatRect rect, double minimumScale, double maximumScale)
574 {
575     m_pageClient.zoomToRect(rect, minimumScale, maximumScale);
576 }
577
578 } // namespace WebKit
579
580 #endif // PLATFORM(IOS)