Unreviewed, temporarily disable the data interaction unit tests.
[WebKit.git] / Tools / TestWebKitAPI / ios / DataInteractionSimulator.mm
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 "DataInteractionSimulator.h"
28
29 #if 0
30
31 #import "InstanceMethodSwizzler.h"
32 #import "PlatformUtilities.h"
33 #import <UIKit/UIItemProvider_Private.h>
34 #import <WebCore/SoftLinking.h>
35 #import <WebKit/WKWebViewPrivate.h>
36 #import <wtf/RetainPtr.h>
37
38 SOFT_LINK_FRAMEWORK(UIKit)
39 SOFT_LINK(UIKit, UIApplicationInstantiateSingleton, void, (Class singletonClass), (singletonClass))
40
41 using namespace TestWebKitAPI;
42
43 #if USE(APPLE_INTERNAL_SDK) && __has_include(<WebKitAdditions/DataInteractionSimulatorAdditions.mm>)
44 #include <WebKitAdditions/DataInteractionSimulatorAdditions.mm>
45 #endif
46
47 static double progressIncrementStep = 0.033;
48 static double progressTimeStep = 0.016;
49 static NSString *TestWebKitAPISimulateCancelAllTouchesNotificationName = @"TestWebKitAPISimulateCancelAllTouchesNotificationName";
50
51 static NSArray *dataInteractionEventNames()
52 {
53     static NSArray *eventNames = nil;
54     static dispatch_once_t onceToken;
55     dispatch_once(&onceToken, ^() {
56         eventNames = @[ DataInteractionEnterEventName, DataInteractionOverEventName, DataInteractionPerformOperationEventName, DataInteractionLeaveEventName, DataInteractionStartEventName ];
57     });
58     return eventNames;
59 }
60
61 @interface DataInteractionSimulatorApplication : UIApplication
62 @end
63
64 @implementation DataInteractionSimulatorApplication
65 - (void)_cancelAllTouches
66 {
67     [[NSNotificationCenter defaultCenter] postNotificationName:TestWebKitAPISimulateCancelAllTouchesNotificationName object:nil];
68 }
69 @end
70
71 @implementation DataInteractionSimulator
72
73 - (instancetype)initWithWebView:(TestWKWebView *)webView
74 {
75     if (self = [super init]) {
76         _webView = webView;
77         _shouldEnsureUIApplication = NO;
78         [_webView setUIDelegate:self];
79     }
80     return self;
81 }
82
83 - (void)dealloc
84 {
85     if ([_webView UIDelegate] == self)
86         [_webView setUIDelegate:nil];
87
88     [super dealloc];
89 }
90
91 - (void)_resetSimulatedState
92 {
93     _phase = DataInteractionBeginning;
94     _currentProgress = 0;
95     _isDoneWithCurrentRun = false;
96     _observedEventNames = adoptNS([[NSMutableArray alloc] init]);
97     _finalSelectionRects = @[ ];
98     _dataInteractionSession = nil;
99     _dataOperationSession = nil;
100     _shouldPerformOperation = NO;
101 }
102
103 - (NSArray *)observedEventNames
104 {
105     return _observedEventNames.get();
106 }
107
108 - (void)simulateAllTouchesCanceled:(NSNotification *)notification
109 {
110     [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_advanceProgress) object:nil];
111     _phase = DataInteractionCancelled;
112     _currentProgress = 1;
113     _isDoneWithCurrentRun = true;
114     if (_dataInteractionSession)
115         [_webView _simulateDataInteractionSessionDidEnd:_dataInteractionSession.get()];
116 }
117
118 - (void)runFrom:(CGPoint)startLocation to:(CGPoint)endLocation
119 {
120     NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
121     [defaultCenter addObserver:self selector:@selector(simulateAllTouchesCanceled:) name:TestWebKitAPISimulateCancelAllTouchesNotificationName object:nil];
122
123     if (_shouldEnsureUIApplication)
124         UIApplicationInstantiateSingleton([DataInteractionSimulatorApplication class]);
125
126     [self _resetSimulatedState];
127
128     RetainPtr<DataInteractionSimulator> strongSelf = self;
129     for (NSString *eventName in dataInteractionEventNames()) {
130         DataInteractionSimulator *weakSelf = strongSelf.get();
131         [weakSelf->_webView performAfterReceivingMessage:eventName action:^() {
132             [weakSelf->_observedEventNames addObject:eventName];
133         }];
134     }
135
136     _startLocation = startLocation;
137     _endLocation = endLocation;
138
139     if (self.externalItemProviders.count) {
140         _dataOperationSession = adoptNS([[MockDataOperationSession alloc] initWithProviders:self.externalItemProviders location:_startLocation window:[_webView window]]);
141         _phase = DataInteractionBegan;
142         [self _advanceProgress];
143     } else {
144         _dataInteractionSession = adoptNS([[MockDataInteractionSession alloc] initWithWindow:[_webView window]]);
145         [_dataInteractionSession setMockLocationInWindow:_startLocation];
146         [_webView _simulatePrepareForDataInteractionSession:_dataInteractionSession.get() completion:^() {
147             DataInteractionSimulator *weakSelf = strongSelf.get();
148             if (weakSelf->_phase == DataInteractionCancelled)
149                 return;
150
151             weakSelf->_phase = DataInteractionBeginning;
152             [weakSelf _advanceProgress];
153         }];
154     }
155
156     Util::run(&_isDoneWithCurrentRun);
157     [_webView clearMessageHandlers:dataInteractionEventNames()];
158     _finalSelectionRects = [_webView selectionRectsAfterPresentationUpdate];
159
160     [defaultCenter removeObserver:self];
161 }
162
163 - (NSArray *)finalSelectionRects
164 {
165     return _finalSelectionRects.get();
166 }
167
168 - (void)_concludeDataInteractionAndPerformOperationIfNecessary
169 {
170     if (_shouldPerformOperation) {
171         [_webView _simulateDataInteractionPerformOperation:_dataOperationSession.get()];
172         _phase = DataInteractionPerforming;
173     } else {
174         _isDoneWithCurrentRun = YES;
175         _phase = DataInteractionCancelled;
176     }
177
178     [_webView _simulateDataInteractionEnded:_dataOperationSession.get()];
179
180     if (_dataInteractionSession)
181         [_webView _simulateDataInteractionSessionDidEnd:_dataInteractionSession.get()];
182 }
183
184 - (void)_advanceProgress
185 {
186     _currentProgress += progressIncrementStep;
187     CGPoint locationInWindow = self._currentLocation;
188     [_dataInteractionSession setMockLocationInWindow:locationInWindow];
189     [_dataOperationSession setMockLocationInWindow:locationInWindow];
190
191     if (_currentProgress >= 1) {
192         _currentProgress = 1;
193         [self _concludeDataInteractionAndPerformOperationIfNecessary];
194         return;
195     }
196
197     switch (_phase) {
198     case DataInteractionBeginning: {
199         NSMutableArray<UIItemProvider *> *itemProviders = [NSMutableArray array];
200         NSArray *items = [_webView _simulatedItemsForSession:_dataInteractionSession.get()];
201         if (!items.count) {
202             _phase = DataInteractionCancelled;
203             _currentProgress = 1;
204             _isDoneWithCurrentRun = true;
205             return;
206         }
207
208         for (WKDataInteractionItem *item in items)
209             [itemProviders addObject:item.itemProvider];
210
211         _dataOperationSession = adoptNS([[MockDataOperationSession alloc] initWithProviders:itemProviders location:self._currentLocation window:[_webView window]]);
212         [_dataInteractionSession setItems:items];
213         _sourceItemProviders = itemProviders;
214         if (self.showCustomActionSheetBlock) {
215             // Defer progress until the custom action sheet is dismissed.
216             return;
217         }
218
219         [_webView _simulateWillBeginDataInteractionWithSession:_dataInteractionSession.get()];
220         _phase = DataInteractionBegan;
221         break;
222     }
223     case DataInteractionBegan:
224         [_webView _simulateDataInteractionEntered:_dataOperationSession.get()];
225         _phase = DataInteractionEntered;
226         break;
227     case DataInteractionEntered:
228         _shouldPerformOperation = [_webView _simulateDataInteractionUpdated:_dataOperationSession.get()];
229         break;
230     default:
231         break;
232     }
233
234     [self _scheduleAdvanceProgress];
235 }
236
237 - (CGPoint)_currentLocation
238 {
239     CGFloat distanceX = _endLocation.x - _startLocation.x;
240     CGFloat distanceY = _endLocation.y - _startLocation.y;
241     return CGPointMake(_startLocation.x + _currentProgress * distanceX, _startLocation.y + _currentProgress * distanceY);
242 }
243
244 - (void)_scheduleAdvanceProgress
245 {
246     [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_advanceProgress) object:nil];
247     [self performSelector:@selector(_advanceProgress) withObject:nil afterDelay:progressTimeStep];
248 }
249
250 - (NSArray *)sourceItemProviders
251 {
252     return _sourceItemProviders.get();
253 }
254
255 - (NSArray *)externalItemProviders
256 {
257     return _externalItemProviders.get();
258 }
259
260 - (void)setExternalItemProviders:(NSArray *)externalItemProviders
261 {
262     _externalItemProviders = adoptNS([externalItemProviders copy]);
263 }
264
265 - (DataInteractionPhase)phase
266 {
267     return _phase;
268 }
269
270 #pragma mark - WKUIDelegatePrivate
271
272 - (void)_webView:(WKWebView *)webView dataInteractionOperationWasHandled:(BOOL)handled forSession:(id)session itemProviders:(NSArray<UIItemProvider *> *)itemProviders
273 {
274     _isDoneWithCurrentRun = true;
275
276     if (self.dataInteractionOperationCompletionBlock)
277         self.dataInteractionOperationCompletionBlock(handled, itemProviders);
278 }
279
280 - (NSUInteger)_webView:(WKWebView *)webView willUpdateDataInteractionOperationToOperation:(NSUInteger)operation forSession:(id)session
281 {
282     return self.overrideDataInteractionOperationBlock ? self.overrideDataInteractionOperationBlock(operation, session) : operation;
283 }
284
285 - (NSArray<UIItemProvider *>*)_webView:(WKWebView *)webView adjustedDataInteractionItemProviders:(NSArray<UIItemProvider *>*)originalItemProviders
286 {
287     return self.convertItemProvidersBlock ? self.convertItemProvidersBlock(originalItemProviders) : originalItemProviders;
288 }
289
290 - (BOOL)_webView:(WKWebView *)webView showCustomSheetForElement:(_WKActivatedElementInfo *)element
291 {
292     if (!self.showCustomActionSheetBlock)
293         return NO;
294
295     RetainPtr<DataInteractionSimulator> strongSelf = self;
296     dispatch_async(dispatch_get_main_queue(), ^() {
297         DataInteractionSimulator *weakSelf = strongSelf.get();
298         [weakSelf->_webView _simulateWillBeginDataInteractionWithSession:weakSelf->_dataInteractionSession.get()];
299         weakSelf->_phase = DataInteractionBegan;
300         [weakSelf _scheduleAdvanceProgress];
301     });
302
303     return self.showCustomActionSheetBlock(element);
304 }
305
306 @end
307
308 #endif // ENABLE(DATA_INTERACTION)