Changeset 213988 in webkit
- Timestamp:
- Mar 15, 2017 10:59:08 AM (7 years ago)
- Location:
- trunk
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r213987 r213988 1 2017-03-15 Alex Christensen <achristensen@webkit.org> 2 3 Compiled content extensions should include the JSON source 4 https://bugs.webkit.org/show_bug.cgi?id=169643 5 6 Reviewed by Geoffrey Garen. 7 8 Serializing the JSON string from which a content extension was compiled 9 to disk with the compiled content extension will allow us to validate content 10 extensions and automatically migrate older content extensions to new versions. 11 It less than doubles the size of the compiled content extension on disk, and when 12 interpreting the bytecode that memory is never read, so it doesn't increase our 13 dirty memory usage. 14 15 Covered by new API tests. 16 17 * contentextensions/ContentExtensionCompiler.cpp: 18 (WebCore::ContentExtensions::compileRuleList): 19 * contentextensions/ContentExtensionCompiler.h: 20 1 21 2017-03-15 Antoine Quint <graouts@apple.com> 2 22 -
trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp
r213669 r213988 307 307 double patternPartitioningStart = monotonicallyIncreasingTime(); 308 308 #endif 309 310 client.writeSource(ruleJSON); 309 311 310 312 Vector<SerializedActionByte> actions; -
trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.h
r213669 r213988 41 41 42 42 // Functions should be called in this order. All except writeActions and finalize can be called multiple times, though. 43 virtual void writeSource(const String&) = 0; 43 44 virtual void writeActions(Vector<SerializedActionByte>&&, bool conditionsApplyOnlyToDomain) = 0; 44 45 virtual void writeFiltersWithoutConditionsBytecode(Vector<DFABytecode>&&) = 0; -
trunk/Source/WebKit2/ChangeLog
r213978 r213988 1 2017-03-15 Alex Christensen <achristensen@webkit.org> 2 3 Compiled content extensions should include the JSON source 4 https://bugs.webkit.org/show_bug.cgi?id=169643 5 6 Reviewed by Geoffrey Garen. 7 8 * UIProcess/API/APIContentExtensionStore.cpp: 9 (API::ContentExtensionStore::ContentExtensionStore): 10 (API::ContentExtensionMetaData::fileSize): 11 (API::encodeContentExtensionMetaData): 12 (API::decodeContentExtensionMetaData): 13 (API::compiledToFile): 14 (API::createExtension): 15 (API::ContentExtensionStore::getContentExtensionSource): 16 * UIProcess/API/APIContentExtensionStore.h: 17 * UIProcess/API/Cocoa/WKContentExtensionStore.mm: 18 (toWKErrorCode): 19 (-[WKContentExtensionStore lookupContentExtensionForIdentifier:completionHandler:]): 20 (-[WKContentExtensionStore removeContentExtensionForIdentifier:completionHandler:]): 21 (-[WKContentExtensionStore _getContentExtensionSourceForIdentifier:completionHandler:]): 22 * UIProcess/API/Cocoa/WKContentExtensionStorePrivate.h: 23 * UIProcess/API/Cocoa/WKError.h: 24 * UIProcess/API/Cocoa/_WKUserContentExtensionStore.h: 25 * UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm: 26 (toUserContentExtensionStoreError): 27 (-[_WKUserContentExtensionStore compileContentExtensionForIdentifier:encodedContentExtension:completionHandler:]): 28 (-[_WKUserContentExtensionStore lookupContentExtensionForIdentifier:completionHandler:]): 29 (-[_WKUserContentExtensionStore removeContentExtensionForIdentifier:completionHandler:]): 30 1 31 2017-03-15 Dean Jackson <dino@apple.com> 2 32 -
trunk/Source/WebKit2/UIProcess/API/APIContentExtensionStore.cpp
r213696 r213988 69 69 , m_removeQueue(WorkQueue::create("ContentExtensionStore Remove Queue")) 70 70 { 71 WebCore::makeAllDirectories(storePath); 71 72 } 72 73 … … 82 83 // The size and offset of the densely packed bytes in the file, not sizeof and offsetof, which would 83 84 // represent the size and offset of the structure in memory, possibly with compiler-added padding. 84 const size_t ContentExtensionFileHeaderSize = 2 * sizeof(uint32_t) + 4* sizeof(uint64_t);85 const size_t ConditionsApplyOnlyToDomainOffset = sizeof(uint32_t) + 4* sizeof(uint64_t);85 const size_t ContentExtensionFileHeaderSize = 2 * sizeof(uint32_t) + 5 * sizeof(uint64_t); 86 const size_t ConditionsApplyOnlyToDomainOffset = sizeof(uint32_t) + 5 * sizeof(uint64_t); 86 87 87 88 struct ContentExtensionMetaData { 88 89 uint32_t version { ContentExtensionStore::CurrentContentExtensionFileVersion }; 90 uint64_t sourceSize { 0 }; 89 91 uint64_t actionsSize { 0 }; 90 92 uint64_t filtersWithoutConditionsBytecodeSize { 0 }; … … 96 98 { 97 99 return ContentExtensionFileHeaderSize 100 + sourceSize 98 101 + actionsSize 99 102 + filtersWithoutConditionsBytecodeSize … … 108 111 109 112 encoder << metaData.version; 113 encoder << metaData.sourceSize; 110 114 encoder << metaData.actionsSize; 111 115 encoder << metaData.filtersWithoutConditionsBytecodeSize; … … 130 134 if (!decoder.decode(metaData.version)) 131 135 return false; 136 if (!decoder.decode(metaData.sourceSize)) 137 return false; 132 138 if (!decoder.decode(metaData.actionsSize)) 133 139 return false; … … 182 188 , m_metaData(metaData) 183 189 { 190 ASSERT(!metaData.sourceSize); 184 191 ASSERT(!metaData.actionsSize); 185 192 ASSERT(!metaData.filtersWithoutConditionsBytecodeSize); … … 187 194 ASSERT(!metaData.conditionedFiltersBytecodeSize); 188 195 ASSERT(!metaData.conditionsApplyOnlyToDomain); 196 } 197 198 void writeSource(const String& sourceJSON) final { 199 ASSERT(!m_filtersWithoutConditionsBytecodeWritten); 200 ASSERT(!m_filtersWithConditionBytecodeWritten); 201 ASSERT(!m_conditionFiltersBytecodeWritten); 202 ASSERT(!m_actionsWritten); 203 ASSERT(!m_sourceWritten); 204 writeToFile(sourceJSON.is8Bit()); 205 m_sourceWritten += sizeof(bool); 206 if (sourceJSON.is8Bit()) { 207 size_t serializedLength = sourceJSON.length() * sizeof(LChar); 208 writeToFile(Data(sourceJSON.characters8(), serializedLength)); 209 m_sourceWritten += serializedLength; 210 } else { 211 size_t serializedLength = sourceJSON.length() * sizeof(UChar); 212 writeToFile(Data(reinterpret_cast<const uint8_t*>(sourceJSON.characters16()), serializedLength)); 213 m_sourceWritten += serializedLength; 214 } 189 215 } 190 216 … … 223 249 void finalize() final 224 250 { 251 m_metaData.sourceSize = m_sourceWritten; 225 252 m_metaData.actionsSize = m_actionsWritten; 226 253 m_metaData.filtersWithoutConditionsBytecodeSize = m_filtersWithoutConditionsBytecodeWritten; … … 240 267 241 268 private: 269 void writeToFile(bool value) 270 { 271 writeToFile(Data(reinterpret_cast<const uint8_t*>(&value), sizeof(value))); 272 } 242 273 void writeToFile(const Data& data) 243 274 { … … 254 285 size_t m_conditionFiltersBytecodeWritten { 0 }; 255 286 size_t m_actionsWritten { 0 }; 287 size_t m_sourceWritten { 0 }; 256 288 bool m_conditionsApplyOnlyToDomain { false }; 257 289 bool m_fileError { false }; … … 295 327 { 296 328 auto sharedMemory = WebKit::SharedMemory::create(const_cast<uint8_t*>(fileData.data()), fileData.size(), WebKit::SharedMemory::Protection::ReadOnly); 329 const size_t headerAndSourceSize = ContentExtensionFileHeaderSize + metaData.sourceSize; 297 330 auto compiledContentExtensionData = WebKit::WebCompiledContentExtensionData( 298 331 WTFMove(sharedMemory), 299 332 fileData, 300 333 ConditionsApplyOnlyToDomainOffset, 301 ContentExtensionFileHeaderSize,334 headerAndSourceSize, 302 335 metaData.actionsSize, 303 ContentExtensionFileHeaderSize336 headerAndSourceSize 304 337 + metaData.actionsSize, 305 338 metaData.filtersWithoutConditionsBytecodeSize, 306 ContentExtensionFileHeaderSize339 headerAndSourceSize 307 340 + metaData.actionsSize 308 341 + metaData.filtersWithoutConditionsBytecodeSize, 309 342 metaData.filtersWithConditionsBytecodeSize, 310 ContentExtensionFileHeaderSize343 headerAndSourceSize 311 344 + metaData.actionsSize 312 345 + metaData.filtersWithoutConditionsBytecodeSize … … 402 435 WebCore::closeFile(file); 403 436 } 404 437 438 void ContentExtensionStore::getContentExtensionSource(const WTF::String& identifier, Function<void(WTF::String)> completionHandler) 439 { 440 m_readQueue->dispatch([protectedThis = makeRef(*this), identifier = identifier.isolatedCopy(), storePath = m_storePath.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable { 441 auto path = constructedPath(storePath, identifier); 442 443 auto complete = [protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler)](String source) mutable { 444 RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler), source = source.isolatedCopy()] { 445 completionHandler(source); 446 }); 447 }; 448 449 ContentExtensionMetaData metaData; 450 Data fileData; 451 if (!openAndMapContentExtension(path, metaData, fileData)) { 452 complete({ }); 453 return; 454 } 455 456 switch (metaData.version) { 457 case 9: 458 if (!metaData.sourceSize) { 459 complete({ }); 460 return; 461 } 462 bool is8Bit = fileData.data()[ContentExtensionFileHeaderSize]; 463 size_t start = ContentExtensionFileHeaderSize + sizeof(bool); 464 size_t length = metaData.sourceSize - sizeof(bool); 465 if (is8Bit) 466 complete(String(fileData.data() + start, length)); 467 else { 468 ASSERT(!(length % sizeof(UChar))); 469 complete(String(reinterpret_cast<const UChar*>(fileData.data() + start), length / sizeof(UChar))); 470 } 471 return; 472 } 473 474 // Older versions cannot recover the original JSON source from disk. 475 complete({ }); 476 }); 477 } 478 405 479 const std::error_category& contentExtensionStoreErrorCategory() 406 480 { -
trunk/Source/WebKit2/UIProcess/API/APIContentExtensionStore.h
r213696 r213988 43 43 public: 44 44 enum class Error { 45 LookupFailed = 6, // Mirrors value of WKErrorContentExtensionStoreLookupFailed45 LookupFailed = 1, 46 46 VersionMismatch, 47 47 CompileFailed, … … 51 51 // This should be incremented every time a functional change is made to the bytecode, file format, etc. 52 52 // to prevent crashing while loading old data. 53 const static uint32_t CurrentContentExtensionFileVersion = 8; 53 // Also update ContentExtensionStore::getContentExtensionSource to be able to find the original JSON 54 // source from old versions. 55 const static uint32_t CurrentContentExtensionFileVersion = 9; 54 56 55 57 static ContentExtensionStore& defaultStore(); … … 67 69 void synchronousRemoveAllContentExtensions(); 68 70 void invalidateContentExtensionVersion(const WTF::String& identifier); 71 void getContentExtensionSource(const WTF::String& identifier, Function<void(WTF::String)>); 69 72 70 73 private: -
trunk/Source/WebKit2/UIProcess/API/Cocoa/WKContentExtensionStore.mm
r213696 r213988 30 30 #if WK_API_ENABLED 31 31 32 #import "APIContentExtensionStore.h" 32 33 #import "WKErrorInternal.h" 34 35 static WKErrorCode toWKErrorCode(const std::error_code& error) 36 { 37 ASSERT(error.category() == API::contentExtensionStoreErrorCategory()); 38 switch (static_cast<API::ContentExtensionStore::Error>(error.value())) { 39 case API::ContentExtensionStore::Error::LookupFailed: 40 return WKErrorContentExtensionStoreLookupFailed; 41 case API::ContentExtensionStore::Error::VersionMismatch: 42 return WKErrorContentExtensionStoreVersionMismatch; 43 case API::ContentExtensionStore::Error::CompileFailed: 44 return WKErrorContentExtensionStoreCompileFailed; 45 case API::ContentExtensionStore::Error::RemoveFailed: 46 return WKErrorContentExtensionStoreRemoveFailed; 47 } 48 ASSERT_NOT_REACHED(); 49 return WKErrorUnknown; 50 } 33 51 34 52 @implementation WKContentExtensionStore … … 93 111 94 112 auto userInfo = @{NSHelpAnchorErrorKey: [NSString stringWithFormat:@"Extension lookup failed: %s", error.message().c_str()]}; 95 ASSERT(error.value() == WKErrorContentExtensionStoreLookupFailed || error.value() == WKErrorContentExtensionStoreVersionMismatch); 96 rawHandler(nil, [NSError errorWithDomain:WKErrorDomain code:error.value() userInfo:userInfo]); 113 auto wkError = toWKErrorCode(error); 114 ASSERT(wkError == WKErrorContentExtensionStoreLookupFailed || wkError == WKErrorContentExtensionStoreVersionMismatch); 115 rawHandler(nil, [NSError errorWithDomain:WKErrorDomain code:wkError userInfo:userInfo]); 97 116 return; 98 117 } … … 112 131 113 132 auto userInfo = @{NSHelpAnchorErrorKey: [NSString stringWithFormat:@"Extension removal failed: %s", error.message().c_str()]}; 114 ASSERT( error.value() == WKErrorContentExtensionStoreRemoveFailed);133 ASSERT(toWKErrorCode(error) == WKErrorContentExtensionStoreRemoveFailed); 115 134 rawHandler([NSError errorWithDomain:WKErrorDomain code:WKErrorContentExtensionStoreRemoveFailed userInfo:userInfo]); 116 135 return; … … 145 164 } 146 165 166 - (void)_getContentExtensionSourceForIdentifier:(NSString *)identifier completionHandler:(void (^)(NSString*))completionHandler 167 { 168 auto handler = adoptNS([completionHandler copy]); 169 _contentExtensionStore->getContentExtensionSource(identifier, [handler](String source) { 170 auto rawHandler = (void (^)(NSString *))handler.get(); 171 if (source.isNull()) 172 rawHandler(nil); 173 else 174 rawHandler(source); 175 }); 176 } 177 147 178 // NS_RELEASES_ARGUMENT to keep peak memory usage low. 148 179 -
trunk/Source/WebKit2/UIProcess/API/Cocoa/WKContentExtensionStorePrivate.h
r213696 r213988 33 33 - (void)_removeAllContentExtensions; 34 34 - (void)_invalidateContentExtensionVersionForIdentifier:(NSString *)identifier; 35 - (void)_getContentExtensionSourceForIdentifier:(NSString *)identifier completionHandler:(void (^)(NSString*))completionHandler; 35 36 36 37 // NS_RELEASES_ARGUMENT to keep peak memory usage low. -
trunk/Source/WebKit2/UIProcess/API/Cocoa/WKError.h
r213696 r213988 43 43 @constant WKErrorJavaScriptResultTypeIsUnsupported Indicates that the result of JavaScript execution could not be returned. 44 44 @constant WKErrorContentExtensionStoreLookupFailed Indicates that looking up a WKUserContentExtension failed. 45 @constant WKErrorContentExtensionStoreVersionMismatch Indicates that looking up a WKUserContentExtension found an extension with an incompatible binary version.45 @constant WKErrorContentExtensionStoreVersionMismatch Indicates that the WKUserContentExtension version did not match the latest. 46 46 @constant WKErrorContentExtensionStoreCompileFailed Indicates that compiling a WKUserContentExtension failed. 47 47 @constant WKErrorContentExtensionStoreRemoveFailed Indicates that removing a WKUserContentExtension failed. -
trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.h
r213696 r213988 45 45 46 46 typedef NS_ENUM(NSInteger, _WKUserContentExtensionStoreErrorCode) { 47 _WKUserContentExtensionStoreErrorLookupFailed = 6, // Mirrors value of WKErrorContentExtensionStoreLookupFailed47 _WKUserContentExtensionStoreErrorLookupFailed, 48 48 _WKUserContentExtensionStoreErrorVersionMismatch, 49 49 _WKUserContentExtensionStoreErrorCompileFailed, -
trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm
r213696 r213988 39 39 NSString * const _WKUserContentExtensionsDomain = @"WKErrorDomain"; 40 40 41 static NSError *toUserContentExtensionStoreError(const NSError *error) 42 { 43 if (!error) 44 return nil; 45 46 ASSERT(error.domain == WKErrorDomain); 47 switch (error.code) { 48 case WKErrorContentExtensionStoreLookupFailed: 49 return [NSError errorWithDomain:_WKUserContentExtensionsDomain code:_WKUserContentExtensionStoreErrorLookupFailed userInfo:error.userInfo]; 50 case WKErrorContentExtensionStoreVersionMismatch: 51 return [NSError errorWithDomain:_WKUserContentExtensionsDomain code:_WKUserContentExtensionStoreErrorVersionMismatch userInfo:error.userInfo]; 52 case WKErrorContentExtensionStoreCompileFailed: 53 return [NSError errorWithDomain:_WKUserContentExtensionsDomain code:_WKUserContentExtensionStoreErrorCompileFailed userInfo:error.userInfo]; 54 case WKErrorContentExtensionStoreRemoveFailed: 55 return [NSError errorWithDomain:_WKUserContentExtensionsDomain code:_WKUserContentExtensionStoreErrorRemoveFailed userInfo:error.userInfo]; 56 default: 57 RELEASE_ASSERT_NOT_REACHED(); 58 } 59 } 60 41 61 @implementation _WKUserContentExtensionStore 42 62 … … 55 75 [_contentExtensionStore _compileContentExtensionForIdentifier:identifier encodedContentExtension:encodedContentExtension completionHandler:^(WKContentExtension *contentExtension, NSError *error) { 56 76 _WKUserContentFilter *contentFilter = contentExtension ? [[[_WKUserContentFilter alloc] _initWithWKContentExtension:contentExtension] autorelease] : nil; 57 completionHandler(contentFilter, error);77 completionHandler(contentFilter, toUserContentExtensionStoreError(error)); 58 78 }]; 59 79 } … … 63 83 [_contentExtensionStore lookupContentExtensionForIdentifier:identifier completionHandler:^(WKContentExtension *contentExtension, NSError *error) { 64 84 _WKUserContentFilter *contentFilter = contentExtension ? [[[_WKUserContentFilter alloc] _initWithWKContentExtension:contentExtension] autorelease] : nil; 65 completionHandler(contentFilter, error);85 completionHandler(contentFilter, toUserContentExtensionStoreError(error)); 66 86 }]; 67 87 } … … 69 89 - (void)removeContentExtensionForIdentifier:(NSString *)identifier completionHandler:(void (^)(NSError *))completionHandler 70 90 { 71 [_contentExtensionStore removeContentExtensionForIdentifier:identifier completionHandler:completionHandler]; 91 [_contentExtensionStore removeContentExtensionForIdentifier:identifier completionHandler:^(NSError *error) { 92 completionHandler(toUserContentExtensionStoreError(error)); 93 }]; 72 94 } 73 95 -
trunk/Tools/ChangeLog
r213986 r213988 1 2017-03-15 Alex Christensen <achristensen@webkit.org> 2 3 Compiled content extensions should include the JSON source 4 https://bugs.webkit.org/show_bug.cgi?id=169643 5 6 Reviewed by Geoffrey Garen. 7 8 * TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp: 9 * TestWebKitAPI/Tests/WebKit2Cocoa/WKUserContentExtensionStore.mm: 10 (TEST_F): 11 1 12 2017-03-15 Kocsen Chung <kocsen_chung@apple.com> 2 13 -
trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp
r213669 r213988 100 100 EXPECT_EQ(data.topURLFilters.size(), 0ull); 101 101 } 102 103 void writeSource(const String&) final { } 102 104 103 105 void writeActions(Vector<ContentExtensions::SerializedActionByte>&& actions, bool conditionsApplyOnlyToDomain) final -
trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WKUserContentExtensionStore.mm
r213696 r213988 147 147 }]; 148 148 TestWebKitAPI::Util::run(&doneLookingUp); 149 150 __block bool doneGettingSource = false; 151 [[WKContentExtensionStore defaultStore] _getContentExtensionSourceForIdentifier:@"TestExtension" completionHandler:^(NSString* source) { 152 EXPECT_NULL(source); 153 doneGettingSource = true; 154 }]; 155 TestWebKitAPI::Util::run(&doneGettingSource); 149 156 } 150 157 … … 184 191 } 185 192 193 TEST_F(WKContentExtensionStoreTest, NonDefaultStore) 194 { 195 NSURL *tempDir = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"ContentExtensionTest"] isDirectory:YES]; 196 WKContentExtensionStore *store = [WKContentExtensionStore storeWithURL:tempDir]; 197 NSString *identifier = @"TestExtension"; 198 NSString *fileName = @"ContentExtension-TestExtension"; 199 200 __block bool doneCompiling = false; 201 [store compileContentExtensionForIdentifier:identifier encodedContentExtension:basicFilter completionHandler:^(WKContentExtension *filter, NSError *error) { 202 EXPECT_NOT_NULL(filter); 203 EXPECT_NULL(error); 204 doneCompiling = true; 205 }]; 206 TestWebKitAPI::Util::run(&doneCompiling); 207 208 NSData *data = [NSData dataWithContentsOfURL:[tempDir URLByAppendingPathComponent:fileName]]; 209 EXPECT_NOT_NULL(data); 210 EXPECT_EQ(data.length, 228u); 211 212 __block bool doneCheckingSource = false; 213 [store _getContentExtensionSourceForIdentifier:identifier completionHandler:^(NSString *source) { 214 EXPECT_NOT_NULL(source); 215 EXPECT_STREQ(basicFilter.UTF8String, source.UTF8String); 216 doneCheckingSource = true; 217 }]; 218 TestWebKitAPI::Util::run(&doneCheckingSource); 219 220 __block bool doneRemoving = false; 221 [store removeContentExtensionForIdentifier:identifier completionHandler:^(NSError *error) { 222 EXPECT_NULL(error); 223 doneRemoving = true; 224 }]; 225 TestWebKitAPI::Util::run(&doneRemoving); 226 227 NSData *dataAfterRemoving = [NSData dataWithContentsOfURL:[tempDir URLByAppendingPathComponent:fileName]]; 228 EXPECT_NULL(dataAfterRemoving); 229 } 230 231 TEST_F(WKContentExtensionStoreTest, NonASCIISource) 232 { 233 static NSString *nonASCIIFilter = @"[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*webkit.org\"}, \"unused\":\"💩\"}]"; 234 NSURL *tempDir = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"ContentExtensionTest"] isDirectory:YES]; 235 WKContentExtensionStore *store = [WKContentExtensionStore storeWithURL:tempDir]; 236 NSString *identifier = @"TestExtension"; 237 NSString *fileName = @"ContentExtension-TestExtension"; 238 239 __block bool done = false; 240 [store compileContentExtensionForIdentifier:identifier encodedContentExtension:nonASCIIFilter completionHandler:^(WKContentExtension *filter, NSError *error) { 241 EXPECT_NOT_NULL(filter); 242 EXPECT_NULL(error); 243 244 [store _getContentExtensionSourceForIdentifier:identifier completionHandler:^(NSString *source) { 245 EXPECT_NOT_NULL(source); 246 EXPECT_STREQ(nonASCIIFilter.UTF8String, source.UTF8String); 247 248 [store _removeAllContentExtensions]; 249 NSData *dataAfterRemoving = [NSData dataWithContentsOfURL:[tempDir URLByAppendingPathComponent:fileName]]; 250 EXPECT_NULL(dataAfterRemoving); 251 252 done = true; 253 }]; 254 }]; 255 TestWebKitAPI::Util::run(&done); 256 } 257 186 258 #endif
Note: See TracChangeset
for help on using the changeset viewer.