Changeset 212974 in webkit
- Timestamp:
- Feb 24, 2017 4:05:45 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit2/ChangeLog
r212973 r212974 1 2017-02-20 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 Refactor data interaction to use new WKDataInteraction SPI 4 https://bugs.webkit.org/show_bug.cgi?id=168602 5 Work towards <rdar://problem/30313681> 6 7 Reviewed by Tim Horton. 8 9 Adjust testing SPI to match new data interaction interfaces. 10 11 * Platform/spi/ios/UIKitSPI.h: 12 * UIProcess/API/Cocoa/WKWebView.mm: 13 (-[WKWebView _simulateDataInteractionEntered:]): 14 (-[WKWebView _simulateDataInteractionUpdated:]): 15 (-[WKWebView _simulateDataInteractionPerformOperation:]): 16 (-[WKWebView _simulateDataInteractionEnded:]): 17 (-[WKWebView _simulateDataInteractionSessionDidEnd:]): 18 (-[WKWebView _simulateWillBeginDataInteractionWithSession:]): 19 (-[WKWebView _simulatedItemsForSession:]): 20 (-[WKWebView _simulatePrepareForDataInteractionSession:completion:]): 21 (-[WKWebView _simulateDataInteractionSessionDidEnd:withOperation:]): Deleted. 22 (-[WKWebView _simulateFailedDataInteractionWithIndex:]): Deleted. 23 (-[WKWebView _simulateWillBeginDataInteractionWithIndex:withSession:]): Deleted. 24 (-[WKWebView _simulatedItemsForDataInteractionWithIndex:]): Deleted. 25 * UIProcess/API/Cocoa/WKWebViewPrivate.h: 26 * UIProcess/ios/WKContentViewInteraction.h: 27 * UIProcess/ios/WKContentViewInteraction.mm: 28 (-[WKContentView _positionInformationDidChange:]): 29 * UIProcess/ios/WKScrollView.h: 30 * UIProcess/ios/WKScrollView.mm: 31 1 32 2017-02-20 Wenson Hsieh <wenson_hsieh@apple.com> 2 33 -
trunk/Source/WebKit2/Platform/spi/ios/UIKitSPI.h
r212211 r212974 55 55 #import <UIKit/UITableViewCell_Private.h> 56 56 #import <UIKit/UITapGestureRecognizer_Private.h> 57 #import <UIKit/UITextEffectsWindow.h> 57 58 #import <UIKit/UITextInput_Private.h> 58 59 #import <UIKit/UITextInteractionAssistant_Private.h> -
trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm
r212973 r212974 5236 5236 - (void)_simulateDataInteractionEntered:(id)info 5237 5237 { 5238 #if ENABLE(DATA_INTERACTION) 5239 [_contentView _simulateDataInteractionEntered:info]; 5240 #endif 5238 5241 } 5239 5242 5240 5243 - (void)_simulateDataInteractionUpdated:(id)info 5241 5244 { 5245 #if ENABLE(DATA_INTERACTION) 5246 [_contentView _simulateDataInteractionUpdated:info]; 5247 #endif 5242 5248 } 5243 5249 5244 5250 - (void)_simulateDataInteractionPerformOperation:(id)info 5245 5251 { 5252 #if ENABLE(DATA_INTERACTION) 5253 [_contentView _simulateDataInteractionPerformOperation:info]; 5254 #endif 5246 5255 } 5247 5256 5248 5257 - (void)_simulateDataInteractionEnded:(id)info 5249 5258 { 5250 } 5251 5252 - (void)_simulateDataInteractionSessionDidEnd:(id)session withOperation:(NSUInteger)operation 5253 { 5254 } 5255 5256 - (void)_simulateFailedDataInteractionWithIndex:(NSInteger)sourceIndex 5257 { 5258 } 5259 5260 - (void)_simulateWillBeginDataInteractionWithIndex:(NSInteger)sourceIndex withSession:(id)session 5261 { 5262 } 5263 5264 - (NSArray *)_simulatedItemsForDataInteractionWithIndex:(NSInteger)sourceIndex 5265 { 5259 #if ENABLE(DATA_INTERACTION) 5260 [_contentView _simulateDataInteractionEnded:info]; 5261 #endif 5262 } 5263 5264 - (void)_simulateDataInteractionSessionDidEnd:(id)session 5265 { 5266 #if ENABLE(DATA_INTERACTION) 5267 [_contentView _simulateDataInteractionSessionDidEnd:session]; 5268 #endif 5269 } 5270 5271 - (void)_simulateWillBeginDataInteractionWithSession:(id)session 5272 { 5273 #if ENABLE(DATA_INTERACTION) 5274 [_contentView _simulateWillBeginDataInteractionWithSession:session]; 5275 #endif 5276 } 5277 5278 - (NSArray *)_simulatedItemsForSession:(id)session 5279 { 5280 #if ENABLE(DATA_INTERACTION) 5281 return [_contentView _simulatedItemsForSession:session]; 5282 #else 5266 5283 return @[ ]; 5284 #endif 5285 } 5286 5287 - (void)_simulatePrepareForDataInteractionSession:(id)session completion:(dispatch_block_t)completion 5288 { 5289 #if ENABLE(DATA_INTERACTION) 5290 [_contentView _simulatePrepareForDataInteractionSession:session completion:completion]; 5291 #endif 5267 5292 } 5268 5293 -
trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h
r212973 r212974 311 311 - (void)_simulateDataInteractionPerformOperation:(id)info WK_API_AVAILABLE(ios(WK_IOS_TBA)); 312 312 - (void)_simulateDataInteractionEnded:(id)info WK_API_AVAILABLE(ios(WK_IOS_TBA)); 313 - (void)_simulateDataInteractionSessionDidEnd:(id)session withOperation:(NSUInteger)operationWK_API_AVAILABLE(ios(WK_IOS_TBA));314 - (void)_simulate FailedDataInteractionWithIndex:(NSInteger)sourceIndexWK_API_AVAILABLE(ios(WK_IOS_TBA));315 - ( void)_simulateWillBeginDataInteractionWithIndex:(NSInteger)sourceIndex withSession:(id)session WK_API_AVAILABLE(ios(WK_IOS_TBA));316 - ( NSArray *)_simulatedItemsForDataInteractionWithIndex:(NSInteger)sourceIndexWK_API_AVAILABLE(ios(WK_IOS_TBA));313 - (void)_simulateDataInteractionSessionDidEnd:(id)session WK_API_AVAILABLE(ios(WK_IOS_TBA)); 314 - (void)_simulateWillBeginDataInteractionWithSession:(id)session WK_API_AVAILABLE(ios(WK_IOS_TBA)); 315 - (NSArray *)_simulatedItemsForSession:(id)session WK_API_AVAILABLE(ios(WK_IOS_TBA)); 316 - (void)_simulatePrepareForDataInteractionSession:(id)session completion:(dispatch_block_t)completion WK_API_AVAILABLE(ios(WK_IOS_TBA)); 317 317 318 318 #endif // TARGET_OS_IPHONE -
trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h
r212973 r212974 189 189 WebKit::WKDataInteractionState _dataInteractionState; 190 190 BOOL _isPerformingDataInteractionOperation; 191 RetainPtr<WKDataInteraction> _dataInteraction; 192 CGPoint _deferredActionSheetRequestLocation; 191 193 #endif 192 194 } … … 196 198 @interface WKContentView (WKInteraction) <UIGestureRecognizerDelegate, UIWebTouchEventsGestureRecognizerDelegate, UITextInputPrivate, UIWebFormAccessoryDelegate, UIWKInteractionViewProtocol, WKFileUploadPanelDelegate, WKActionSheetAssistantDelegate 197 199 #if ENABLE(DATA_INTERACTION) 198 , WK ViewDataInteractionSourceDelegate, WKDataInteractionSessionDelegate, WKViewDataInteractionDestinationDelegate, WKDataInteractionItemVisualTarget200 , WKDataInteractionItemVisualTarget, WKDataInteractionDelegate, WKViewDataInteractionDestinationDelegate 199 201 #endif 200 202 > … … 270 272 - (void)_didHandleStartDataInteractionRequest:(BOOL)started; 271 273 - (void)_startDataInteractionWithImage:(RetainPtr<CGImageRef>)image withIndicatorData:(std::optional<WebCore::TextIndicatorData>)indicatorData atClientPosition:(CGPoint)clientPosition anchorPoint:(CGPoint)anchorPoint action:(uint64_t)action; 272 - (void)_simulateDataInteractionEntered:(id)info WK_API_AVAILABLE(ios(WK_IOS_TBA));273 - (void)_simulateDataInteractionUpdated:(id)info WK_API_AVAILABLE(ios(WK_IOS_TBA));274 - (void)_simulateDataInteractionPerformOperation:(id)info WK_API_AVAILABLE(ios(WK_IOS_TBA));275 - (void)_simulateDataInteractionEnded:(id)info WK_API_AVAILABLE(ios(WK_IOS_TBA));276 - (void)_simulateDataInteractionSessionDidEnd:(id)session withOperation:(NSUInteger)operation WK_API_AVAILABLE(ios(WK_IOS_TBA));277 - (void)_simulate FailedDataInteractionWithIndex:(NSInteger)sourceIndex WK_API_AVAILABLE(ios(WK_IOS_TBA));278 - ( void)_simulateWillBeginDataInteractionWithIndex:(NSInteger)sourceIndex withSession:(id)session WK_API_AVAILABLE(ios(WK_IOS_TBA));279 - ( NSArray *)_simulatedItemsForDataInteractionWithIndex:(NSInteger)sourceIndex WK_API_AVAILABLE(ios(WK_IOS_TBA));274 - (void)_simulateDataInteractionEntered:(id)info; 275 - (void)_simulateDataInteractionUpdated:(id)info; 276 - (void)_simulateDataInteractionPerformOperation:(id)info; 277 - (void)_simulateDataInteractionEnded:(id)info; 278 - (void)_simulateDataInteractionSessionDidEnd:(id)session; 279 - (void)_simulateWillBeginDataInteractionWithSession:(id)session; 280 - (NSArray *)_simulatedItemsForSession:(id)session; 281 - (void)_simulatePrepareForDataInteractionSession:(id)session completion:(dispatch_block_t)completion; 280 282 #endif 281 283 -
trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm
r212973 r212974 1721 1721 if (_actionSheetAssistant) 1722 1722 [_actionSheetAssistant updateSheetPosition]; 1723 1724 #if ENABLE(DATA_INTERACTION)1725 [self _updateDataInteractionPreviewSnapshotIfPossible];1726 #endif1727 1723 } 1728 1724 -
trunk/Source/WebKit2/UIProcess/ios/WKScrollView.mm
r212459 r212974 130 130 } 131 131 132 #if USE(APPLE_INTERNAL_SDK) && __has_include(<WebKitAdditions/WKScrollViewAdditions.mm>) 133 #import <WebKitAdditions/WKScrollViewAdditions.mm> 134 #endif 135 132 136 - (void)setInternalDelegate:(WKWebView <UIScrollViewDelegate> *)internalDelegate 133 137 { -
trunk/Tools/ChangeLog
r212973 r212974 1 2017-02-20 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 Refactor data interaction to use new WKDataInteraction SPI 4 https://bugs.webkit.org/show_bug.cgi?id=168602 5 Work towards <rdar://problem/30313681> 6 7 Reviewed by Tim Horton. 8 9 Update DataInteractionSimulator to simulate data interaction using updated SPI. See changes in WebKit2 for more details. 10 11 * TestWebKitAPI/Tests/ios/DataInteractionTests.mm: 12 (TestWebKitAPI::TEST): 13 * TestWebKitAPI/ios/DataInteractionSimulator.h: 14 * TestWebKitAPI/ios/DataInteractionSimulator.mm: 15 (-[DataInteractionSimulator _resetSimulatedState]): 16 (-[DataInteractionSimulator runFrom:to:]): 17 (-[DataInteractionSimulator _advanceProgress]): 18 (-[DataInteractionSimulator _currentLocation]): 19 (-[DataInteractionSimulator _finishDataInteraction]): Deleted. 20 (-[DataInteractionSimulator webViewDidSendDataInteractionStartRequest:]): Deleted. 21 (-[DataInteractionSimulator webView:didReceiveDataInteractionStartResponse:]): Deleted. 22 1 23 2017-02-20 Wenson Hsieh <wenson_hsieh@apple.com> 2 24 -
trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm
r212901 r212974 26 26 #include "config.h" 27 27 28 #if 028 #if ENABLE(DATA_INTERACTION) 29 29 30 30 #import "DataInteractionSimulator.h" … … 82 82 NSURL *imageURL = [NSURL fileURLWithPath:[webView editorValue]]; 83 83 EXPECT_WK_STREQ("icon.png", imageURL.lastPathComponent); 84 EXPECT_TRUE([dataInteractionSimulator didTryToBeginDataInteraction]);85 84 86 85 NSArray *observedEventNames = [dataInteractionSimulator observedEventNames]; … … 103 102 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"source.textContent"].length, 0UL); 104 103 EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"editor.textContent"].UTF8String); 105 EXPECT_TRUE([dataInteractionSimulator didTryToBeginDataInteraction]);106 104 107 105 NSArray *observedEventNames = [dataInteractionSimulator observedEventNames]; … … 122 120 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"source.textContent"].length, 0UL); 123 121 EXPECT_WK_STREQ("Hello world", [webView editorValue].UTF8String); 124 EXPECT_TRUE([dataInteractionSimulator didTryToBeginDataInteraction]);125 122 126 123 NSArray *observedEventNames = [dataInteractionSimulator observedEventNames]; … … 140 137 141 138 EXPECT_WK_STREQ("https://www.daringfireball.net/", [webView editorValue].UTF8String); 142 EXPECT_TRUE([dataInteractionSimulator didTryToBeginDataInteraction]);143 139 144 140 NSArray *observedEventNames = [dataInteractionSimulator observedEventNames]; … … 158 154 159 155 EXPECT_WK_STREQ("https://www.daringfireball.net/", [webView editorValue].UTF8String); 160 EXPECT_TRUE([dataInteractionSimulator didTryToBeginDataInteraction]);161 156 162 157 NSArray *observedEventNames = [dataInteractionSimulator observedEventNames]; … … 176 171 177 172 EXPECT_FALSE([webView editorContainsImageElement]); 178 EXPECT_FALSE([dataInteractionSimulator didTryToBeginDataInteraction]);179 173 180 174 NSArray *observedEventNames = [dataInteractionSimulator observedEventNames]; … … 193 187 194 188 EXPECT_FALSE([webView editorContainsImageElement]); 195 EXPECT_TRUE([dataInteractionSimulator didTryToBeginDataInteraction]);196 189 197 190 NSArray *observedEventNames = [dataInteractionSimulator observedEventNames]; … … 210 203 211 204 EXPECT_WK_STREQ("", [webView editorValue].UTF8String); 212 EXPECT_TRUE([dataInteractionSimulator didTryToBeginDataInteraction]);213 205 214 206 NSArray *observedEventNames = [dataInteractionSimulator observedEventNames]; … … 218 210 EXPECT_FALSE([observedEventNames containsObject:DataInteractionPerformOperationEventName]); 219 211 EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:@[ ]]); 220 }221 222 TEST(DataInteractionTests, HandlesDataInteractionFailureGracefully)223 {224 RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);225 [webView synchronouslyLoadTestPageNamed:@"link-and-input"];226 227 RetainPtr<DataInteractionSimulator> dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);228 [dataInteractionSimulator setForceRequestToFail:YES];229 [dataInteractionSimulator runFrom:CGPointMake(100, 50) to:CGPointMake(100, 300)];230 EXPECT_WK_STREQ("", [webView editorValue].UTF8String);231 232 // Before r212266, starting a subsequent gesture would have caused a debug assertion in the web process.233 [dataInteractionSimulator setForceRequestToFail:NO];234 [dataInteractionSimulator runFrom:CGPointMake(100, 50) to:CGPointMake(100, 300)];235 EXPECT_WK_STREQ("https://www.daringfireball.net/", [webView editorValue].UTF8String);236 212 } 237 213 -
trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h
r212973 r212974 33 33 34 34 @class MockDataInteractionInfo; 35 @class MockDataInteractionSession; 35 36 36 37 extern NSString * const DataInteractionEnterEventName; … … 41 42 42 43 typedef NS_ENUM(NSInteger, DataInteractionPhase) { 43 DataInteractionUnrecognized = 1, 44 DataInteractionCancelled = 0, 45 DataInteractionBeginning = 1, 44 46 DataInteractionBegan = 2, 45 47 DataInteractionEntered = 3, … … 49 51 @interface DataInteractionSimulator : NSObject<_WKTestingDelegate> { 50 52 RetainPtr<TestWKWebView> _webView; 53 RetainPtr<MockDataInteractionSession> _dataInteractionSession; 51 54 RetainPtr<MockDataInteractionInfo> _dataInteractionInfo; 52 55 RetainPtr<NSMutableArray> _observedEventNames; … … 56 59 CGPoint _endLocation; 57 60 58 double _ gestureProgress;61 double _currentProgress; 59 62 bool _isDoneWithCurrentRun; 60 63 DataInteractionPhase _phase; … … 64 67 - (void)runFrom:(CGPoint)startLocation to:(CGPoint)endLocation; 65 68 66 @property (nonatomic) BOOL forceRequestToFail;67 69 @property (nonatomic, strong) UIItemProvider *externalItemProvider; 68 @property (nonatomic, readonly) BOOL didTryToBeginDataInteraction;69 70 @property (nonatomic, readonly) NSArray *observedEventNames; 70 71 @property (nonatomic, readonly) NSArray *finalSelectionRects; -
trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm
r212973 r212974 74 74 - (void)_resetSimulatedState 75 75 { 76 _ gestureProgress = 0;77 _ phase = DataInteractionUnrecognized;76 _phase = DataInteractionBeginning; 77 _currentProgress = 0; 78 78 _isDoneWithCurrentRun = false; 79 _didTryToBeginDataInteraction = NO;80 79 _observedEventNames = adoptNS([[NSMutableArray alloc] init]); 81 80 _finalSelectionRects = @[ ]; 81 _dataInteractionSession = nil; 82 _dataInteractionInfo = nil; 82 83 } 83 84 … … 103 104 104 105 if (self.externalItemProvider) { 106 _dataInteractionInfo = adoptNS([[MockDataInteractionInfo alloc] initWithProvider:self.externalItemProvider location:_startLocation window:[_webView window]]); 105 107 _phase = DataInteractionBegan; 106 _dataInteractionInfo = adoptNS([[MockDataInteractionInfo alloc] initWithProvider:self.externalItemProvider location:startLocation window:[_webView window]]); 107 } 108 109 [self _scheduleAdvanceProgress]; 108 [self _advanceProgress]; 109 } else { 110 _dataInteractionSession = adoptNS([[MockDataInteractionSession alloc] initWithWindow:[_webView window]]); 111 [_dataInteractionSession setMockLocationInWindow:_startLocation]; 112 [_webView _simulatePrepareForDataInteractionSession:_dataInteractionSession.get() completion:^() { 113 DataInteractionSimulator *weakSelf = strongSelf.get(); 114 weakSelf->_phase = DataInteractionBeginning; 115 [weakSelf _advanceProgress]; 116 }]; 117 } 110 118 111 119 Util::run(&_isDoneWithCurrentRun); … … 121 129 - (void)_advanceProgress 122 130 { 123 _gestureProgress = std::min(1.0, std::max(0.0, progressIncrementStep + _gestureProgress)); 124 [_dataInteractionInfo setMockLocationInWindow:self._currentLocation]; 125 if (_gestureProgress >= 1) { 126 [self _finishDataInteraction]; 131 _currentProgress += progressIncrementStep; 132 CGPoint locationInWindow = self._currentLocation; 133 [_dataInteractionSession setMockLocationInWindow:locationInWindow]; 134 [_dataInteractionInfo setMockLocationInWindow:locationInWindow]; 135 136 if (_currentProgress >= 1) { 137 [_webView _simulateDataInteractionPerformOperation:_dataInteractionInfo.get()]; 138 [_webView _simulateDataInteractionEnded:_dataInteractionInfo.get()]; 139 if (_dataInteractionSession) 140 [_webView _simulateDataInteractionSessionDidEnd:_dataInteractionSession.get()]; 141 142 _phase = DataInteractionPerforming; 143 _currentProgress = 1; 127 144 return; 128 145 } 129 146 130 147 switch (_phase) { 131 case DataInteractionUnrecognized: 132 [self _scheduleAdvanceProgress]; 133 break; 148 case DataInteractionBeginning: { 149 NSMutableArray<UIItemProvider *> *itemProviders = [NSMutableArray array]; 150 NSArray<WKDataInteractionItem *> *items = [_webView _simulatedItemsForSession:_dataInteractionSession.get()]; 151 if (!items.count) { 152 _phase = DataInteractionCancelled; 153 _currentProgress = 1; 154 _isDoneWithCurrentRun = true; 155 return; 156 } 157 158 for (WKDataInteractionItem *item in items) 159 [itemProviders addObject:item.itemProvider]; 160 161 _dataInteractionInfo = adoptNS([[MockDataInteractionInfo alloc] initWithProvider:itemProviders.firstObject location:self._currentLocation window:[_webView window]]); 162 [_dataInteractionSession setItems:items]; 163 [_webView _simulateWillBeginDataInteractionWithSession:_dataInteractionSession.get()]; 164 _phase = DataInteractionBegan; 165 break; 166 } 134 167 case DataInteractionBegan: 135 168 [_webView _simulateDataInteractionEntered:_dataInteractionInfo.get()]; 136 169 _phase = DataInteractionEntered; 137 [self _scheduleAdvanceProgress];138 170 break; 139 171 case DataInteractionEntered: 140 172 [_webView _simulateDataInteractionUpdated:_dataInteractionInfo.get()]; 141 [self _scheduleAdvanceProgress];142 173 break; 143 174 default: 144 175 break; 145 176 } 146 } 147 148 - (void)_finishDataInteraction 149 { 150 if (_phase == DataInteractionUnrecognized) { 151 _isDoneWithCurrentRun = true; 152 return; 153 } 154 155 _phase = DataInteractionPerforming; 156 [_webView _simulateDataInteractionPerformOperation:_dataInteractionInfo.get()]; 157 [_webView _simulateDataInteractionEnded:_dataInteractionInfo.get()]; 158 [_webView _simulateDataInteractionSessionDidEnd:nil withOperation:0]; 177 178 [self _scheduleAdvanceProgress]; 159 179 } 160 180 … … 163 183 CGFloat distanceX = _endLocation.x - _startLocation.x; 164 184 CGFloat distanceY = _endLocation.y - _startLocation.y; 165 return CGPointMake(_startLocation.x + _ gestureProgress * distanceX, _startLocation.y + _gestureProgress * distanceY);185 return CGPointMake(_startLocation.x + _currentProgress * distanceX, _startLocation.y + _currentProgress * distanceY); 166 186 } 167 187 … … 189 209 } 190 210 191 - (void)webViewDidSendDataInteractionStartRequest:(WKWebView *)webView192 {193 // This addresses a race condition in the testing harness wherein the web process might take longer than usual to process the194 // request to start data interaction, and in the meantime, DataInteractionSimulator would end up completing the rest of the test195 // before a response from the web process is received. We instead defer test progress until after the web process has indicated196 // whether or not data interaction should commence.197 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_advanceProgress) object:nil];198 }199 200 - (void)webView:(WKWebView *)webView didReceiveDataInteractionStartResponse:(BOOL)started201 {202 [self _scheduleAdvanceProgress];203 }204 205 211 @end 206 212
Note: See TracChangeset
for help on using the changeset viewer.