Title: [213988] trunk
Revision
213988
Author
[email protected]
Date
2017-03-15 10:59:08 -0700 (Wed, 15 Mar 2017)

Log Message

Compiled content extensions should include the JSON source
https://bugs.webkit.org/show_bug.cgi?id=169643

Reviewed by Geoffrey Garen.

Source/WebCore:

Serializing the JSON string from which a content extension was compiled
to disk with the compiled content extension will allow us to validate content
extensions and automatically migrate older content extensions to new versions.
It less than doubles the size of the compiled content extension on disk, and when
interpreting the bytecode that memory is never read, so it doesn't increase our
dirty memory usage.

Covered by new API tests.

* contentextensions/ContentExtensionCompiler.cpp:
(WebCore::ContentExtensions::compileRuleList):
* contentextensions/ContentExtensionCompiler.h:

Source/WebKit2:

* UIProcess/API/APIContentExtensionStore.cpp:
(API::ContentExtensionStore::ContentExtensionStore):
(API::ContentExtensionMetaData::fileSize):
(API::encodeContentExtensionMetaData):
(API::decodeContentExtensionMetaData):
(API::compiledToFile):
(API::createExtension):
(API::ContentExtensionStore::getContentExtensionSource):
* UIProcess/API/APIContentExtensionStore.h:
* UIProcess/API/Cocoa/WKContentExtensionStore.mm:
(toWKErrorCode):
(-[WKContentExtensionStore lookupContentExtensionForIdentifier:completionHandler:]):
(-[WKContentExtensionStore removeContentExtensionForIdentifier:completionHandler:]):
(-[WKContentExtensionStore _getContentExtensionSourceForIdentifier:completionHandler:]):
* UIProcess/API/Cocoa/WKContentExtensionStorePrivate.h:
* UIProcess/API/Cocoa/WKError.h:
* UIProcess/API/Cocoa/_WKUserContentExtensionStore.h:
* UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm:
(toUserContentExtensionStoreError):
(-[_WKUserContentExtensionStore compileContentExtensionForIdentifier:encodedContentExtension:completionHandler:]):
(-[_WKUserContentExtensionStore lookupContentExtensionForIdentifier:completionHandler:]):
(-[_WKUserContentExtensionStore removeContentExtensionForIdentifier:completionHandler:]):

Tools:

* TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:
* TestWebKitAPI/Tests/WebKit2Cocoa/WKUserContentExtensionStore.mm:
(TEST_F):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (213987 => 213988)


--- trunk/Source/WebCore/ChangeLog	2017-03-15 17:40:59 UTC (rev 213987)
+++ trunk/Source/WebCore/ChangeLog	2017-03-15 17:59:08 UTC (rev 213988)
@@ -1,3 +1,23 @@
+2017-03-15  Alex Christensen  <[email protected]>
+
+        Compiled content extensions should include the JSON source
+        https://bugs.webkit.org/show_bug.cgi?id=169643
+
+        Reviewed by Geoffrey Garen.
+
+        Serializing the JSON string from which a content extension was compiled
+        to disk with the compiled content extension will allow us to validate content
+        extensions and automatically migrate older content extensions to new versions.
+        It less than doubles the size of the compiled content extension on disk, and when
+        interpreting the bytecode that memory is never read, so it doesn't increase our
+        dirty memory usage.
+
+        Covered by new API tests.
+
+        * contentextensions/ContentExtensionCompiler.cpp:
+        (WebCore::ContentExtensions::compileRuleList):
+        * contentextensions/ContentExtensionCompiler.h:
+
 2017-03-15  Antoine Quint  <[email protected]>
 
         [Modern Media Controls] Captions do not default to Auto when language is changed

Modified: trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp (213987 => 213988)


--- trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp	2017-03-15 17:40:59 UTC (rev 213987)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp	2017-03-15 17:59:08 UTC (rev 213988)
@@ -306,6 +306,8 @@
 #if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
     double patternPartitioningStart = monotonicallyIncreasingTime();
 #endif
+    
+    client.writeSource(ruleJSON);
 
     Vector<SerializedActionByte> actions;
     Vector<unsigned> actionLocations = serializeActions(parsedRuleList, actions);

Modified: trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.h (213987 => 213988)


--- trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.h	2017-03-15 17:40:59 UTC (rev 213987)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.h	2017-03-15 17:59:08 UTC (rev 213988)
@@ -40,6 +40,7 @@
     virtual ~ContentExtensionCompilationClient() { }
     
     // Functions should be called in this order. All except writeActions and finalize can be called multiple times, though.
+    virtual void writeSource(const String&) = 0;
     virtual void writeActions(Vector<SerializedActionByte>&&, bool conditionsApplyOnlyToDomain) = 0;
     virtual void writeFiltersWithoutConditionsBytecode(Vector<DFABytecode>&&) = 0;
     virtual void writeFiltersWithConditionsBytecode(Vector<DFABytecode>&&) = 0;

Modified: trunk/Source/WebKit2/ChangeLog (213987 => 213988)


--- trunk/Source/WebKit2/ChangeLog	2017-03-15 17:40:59 UTC (rev 213987)
+++ trunk/Source/WebKit2/ChangeLog	2017-03-15 17:59:08 UTC (rev 213988)
@@ -1,3 +1,33 @@
+2017-03-15  Alex Christensen  <[email protected]>
+
+        Compiled content extensions should include the JSON source
+        https://bugs.webkit.org/show_bug.cgi?id=169643
+
+        Reviewed by Geoffrey Garen.
+
+        * UIProcess/API/APIContentExtensionStore.cpp:
+        (API::ContentExtensionStore::ContentExtensionStore):
+        (API::ContentExtensionMetaData::fileSize):
+        (API::encodeContentExtensionMetaData):
+        (API::decodeContentExtensionMetaData):
+        (API::compiledToFile):
+        (API::createExtension):
+        (API::ContentExtensionStore::getContentExtensionSource):
+        * UIProcess/API/APIContentExtensionStore.h:
+        * UIProcess/API/Cocoa/WKContentExtensionStore.mm:
+        (toWKErrorCode):
+        (-[WKContentExtensionStore lookupContentExtensionForIdentifier:completionHandler:]):
+        (-[WKContentExtensionStore removeContentExtensionForIdentifier:completionHandler:]):
+        (-[WKContentExtensionStore _getContentExtensionSourceForIdentifier:completionHandler:]):
+        * UIProcess/API/Cocoa/WKContentExtensionStorePrivate.h:
+        * UIProcess/API/Cocoa/WKError.h:
+        * UIProcess/API/Cocoa/_WKUserContentExtensionStore.h:
+        * UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm:
+        (toUserContentExtensionStoreError):
+        (-[_WKUserContentExtensionStore compileContentExtensionForIdentifier:encodedContentExtension:completionHandler:]):
+        (-[_WKUserContentExtensionStore lookupContentExtensionForIdentifier:completionHandler:]):
+        (-[_WKUserContentExtensionStore removeContentExtensionForIdentifier:completionHandler:]):
+
 2017-03-15  Dean Jackson  <[email protected]>
 
         Sort Xcode project files

Modified: trunk/Source/WebKit2/UIProcess/API/APIContentExtensionStore.cpp (213987 => 213988)


--- trunk/Source/WebKit2/UIProcess/API/APIContentExtensionStore.cpp	2017-03-15 17:40:59 UTC (rev 213987)
+++ trunk/Source/WebKit2/UIProcess/API/APIContentExtensionStore.cpp	2017-03-15 17:59:08 UTC (rev 213988)
@@ -68,6 +68,7 @@
     , m_readQueue(WorkQueue::create("ContentExtensionStore Read Queue"))
     , m_removeQueue(WorkQueue::create("ContentExtensionStore Remove Queue"))
 {
+    WebCore::makeAllDirectories(storePath);
 }
 
 ContentExtensionStore::~ContentExtensionStore()
@@ -81,11 +82,12 @@
 
 // The size and offset of the densely packed bytes in the file, not sizeof and offsetof, which would
 // represent the size and offset of the structure in memory, possibly with compiler-added padding.
-const size_t ContentExtensionFileHeaderSize = 2 * sizeof(uint32_t) + 4 * sizeof(uint64_t);
-const size_t ConditionsApplyOnlyToDomainOffset = sizeof(uint32_t) + 4 * sizeof(uint64_t);
+const size_t ContentExtensionFileHeaderSize = 2 * sizeof(uint32_t) + 5 * sizeof(uint64_t);
+const size_t ConditionsApplyOnlyToDomainOffset = sizeof(uint32_t) + 5 * sizeof(uint64_t);
 
 struct ContentExtensionMetaData {
     uint32_t version { ContentExtensionStore::CurrentContentExtensionFileVersion };
+    uint64_t sourceSize { 0 };
     uint64_t actionsSize { 0 };
     uint64_t filtersWithoutConditionsBytecodeSize { 0 };
     uint64_t filtersWithConditionsBytecodeSize { 0 };
@@ -95,6 +97,7 @@
     size_t fileSize() const
     {
         return ContentExtensionFileHeaderSize
+            + sourceSize
             + actionsSize
             + filtersWithoutConditionsBytecodeSize
             + filtersWithConditionsBytecodeSize
@@ -107,6 +110,7 @@
     WTF::Persistence::Encoder encoder;
 
     encoder << metaData.version;
+    encoder << metaData.sourceSize;
     encoder << metaData.actionsSize;
     encoder << metaData.filtersWithoutConditionsBytecodeSize;
     encoder << metaData.filtersWithConditionsBytecodeSize;
@@ -129,6 +133,8 @@
         WTF::Persistence::Decoder decoder(data, size);
         if (!decoder.decode(metaData.version))
             return false;
+        if (!decoder.decode(metaData.sourceSize))
+            return false;
         if (!decoder.decode(metaData.actionsSize))
             return false;
         if (!decoder.decode(metaData.filtersWithoutConditionsBytecodeSize))
@@ -181,6 +187,7 @@
             : m_fileHandle(fileHandle)
             , m_metaData(metaData)
         {
+            ASSERT(!metaData.sourceSize);
             ASSERT(!metaData.actionsSize);
             ASSERT(!metaData.filtersWithoutConditionsBytecodeSize);
             ASSERT(!metaData.filtersWithConditionsBytecodeSize);
@@ -188,6 +195,25 @@
             ASSERT(!metaData.conditionsApplyOnlyToDomain);
         }
         
+        void writeSource(const String& sourceJSON) final {
+            ASSERT(!m_filtersWithoutConditionsBytecodeWritten);
+            ASSERT(!m_filtersWithConditionBytecodeWritten);
+            ASSERT(!m_conditionFiltersBytecodeWritten);
+            ASSERT(!m_actionsWritten);
+            ASSERT(!m_sourceWritten);
+            writeToFile(sourceJSON.is8Bit());
+            m_sourceWritten += sizeof(bool);
+            if (sourceJSON.is8Bit()) {
+                size_t serializedLength = sourceJSON.length() * sizeof(LChar);
+                writeToFile(Data(sourceJSON.characters8(), serializedLength));
+                m_sourceWritten += serializedLength;
+            } else {
+                size_t serializedLength = sourceJSON.length() * sizeof(UChar);
+                writeToFile(Data(reinterpret_cast<const uint8_t*>(sourceJSON.characters16()), serializedLength));
+                m_sourceWritten += serializedLength;
+            }
+        }
+        
         void writeFiltersWithoutConditionsBytecode(Vector<DFABytecode>&& bytecode) final
         {
             ASSERT(!m_filtersWithConditionBytecodeWritten);
@@ -222,6 +248,7 @@
         
         void finalize() final
         {
+            m_metaData.sourceSize = m_sourceWritten;
             m_metaData.actionsSize = m_actionsWritten;
             m_metaData.filtersWithoutConditionsBytecodeSize = m_filtersWithoutConditionsBytecodeWritten;
             m_metaData.filtersWithConditionsBytecodeSize = m_filtersWithConditionBytecodeWritten;
@@ -239,6 +266,10 @@
         bool hadErrorWhileWritingToFile() { return m_fileError; }
 
     private:
+        void writeToFile(bool value)
+        {
+            writeToFile(Data(reinterpret_cast<const uint8_t*>(&value), sizeof(value)));
+        }
         void writeToFile(const Data& data)
         {
             if (!m_fileError && !writeDataToFile(data, m_fileHandle)) {
@@ -253,6 +284,7 @@
         size_t m_filtersWithConditionBytecodeWritten { 0 };
         size_t m_conditionFiltersBytecodeWritten { 0 };
         size_t m_actionsWritten { 0 };
+        size_t m_sourceWritten { 0 };
         bool m_conditionsApplyOnlyToDomain { false };
         bool m_fileError { false };
     };
@@ -294,20 +326,21 @@
 static RefPtr<API::ContentExtension> createExtension(const String& identifier, const ContentExtensionMetaData& metaData, const Data& fileData)
 {
     auto sharedMemory = WebKit::SharedMemory::create(const_cast<uint8_t*>(fileData.data()), fileData.size(), WebKit::SharedMemory::Protection::ReadOnly);
+    const size_t headerAndSourceSize = ContentExtensionFileHeaderSize + metaData.sourceSize;
     auto compiledContentExtensionData = WebKit::WebCompiledContentExtensionData(
         WTFMove(sharedMemory),
         fileData,
         ConditionsApplyOnlyToDomainOffset,
-        ContentExtensionFileHeaderSize,
+        headerAndSourceSize,
         metaData.actionsSize,
-        ContentExtensionFileHeaderSize
+        headerAndSourceSize
             + metaData.actionsSize,
         metaData.filtersWithoutConditionsBytecodeSize,
-        ContentExtensionFileHeaderSize
+        headerAndSourceSize
             + metaData.actionsSize
             + metaData.filtersWithoutConditionsBytecodeSize,
         metaData.filtersWithConditionsBytecodeSize,
-        ContentExtensionFileHeaderSize
+        headerAndSourceSize
             + metaData.actionsSize
             + metaData.filtersWithoutConditionsBytecodeSize
             + metaData.filtersWithConditionsBytecodeSize,
@@ -401,7 +434,48 @@
     ASSERT_UNUSED(bytesWritten, bytesWritten == sizeof(invalidHeader));
     WebCore::closeFile(file);
 }
-    
+
+void ContentExtensionStore::getContentExtensionSource(const WTF::String& identifier, Function<void(WTF::String)> completionHandler)
+{
+    m_readQueue->dispatch([protectedThis = makeRef(*this), identifier = identifier.isolatedCopy(), storePath = m_storePath.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
+        auto path = constructedPath(storePath, identifier);
+        
+        auto complete = [protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler)](String source) mutable {
+            RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler), source = source.isolatedCopy()] {
+                completionHandler(source);
+            });
+        };
+        
+        ContentExtensionMetaData metaData;
+        Data fileData;
+        if (!openAndMapContentExtension(path, metaData, fileData)) {
+            complete({ });
+            return;
+        }
+        
+        switch (metaData.version) {
+        case 9:
+            if (!metaData.sourceSize) {
+                complete({ });
+                return;
+            }
+            bool is8Bit = fileData.data()[ContentExtensionFileHeaderSize];
+            size_t start = ContentExtensionFileHeaderSize + sizeof(bool);
+            size_t length = metaData.sourceSize - sizeof(bool);
+            if (is8Bit)
+                complete(String(fileData.data() + start, length));
+            else {
+                ASSERT(!(length % sizeof(UChar)));
+                complete(String(reinterpret_cast<const UChar*>(fileData.data() + start), length / sizeof(UChar)));
+            }
+            return;
+        }
+
+        // Older versions cannot recover the original JSON source from disk.
+        complete({ });
+    });
+}
+
 const std::error_category& contentExtensionStoreErrorCategory()
 {
     class ContentExtensionStoreErrorCategory : public std::error_category {

Modified: trunk/Source/WebKit2/UIProcess/API/APIContentExtensionStore.h (213987 => 213988)


--- trunk/Source/WebKit2/UIProcess/API/APIContentExtensionStore.h	2017-03-15 17:40:59 UTC (rev 213987)
+++ trunk/Source/WebKit2/UIProcess/API/APIContentExtensionStore.h	2017-03-15 17:59:08 UTC (rev 213988)
@@ -42,7 +42,7 @@
 class ContentExtensionStore final : public ObjectImpl<Object::Type::ContentExtensionStore> {
 public:
     enum class Error {
-        LookupFailed = 6, // Mirrors value of WKErrorContentExtensionStoreLookupFailed
+        LookupFailed = 1,
         VersionMismatch,
         CompileFailed,
         RemoveFailed
@@ -50,7 +50,9 @@
     
     // This should be incremented every time a functional change is made to the bytecode, file format, etc.
     // to prevent crashing while loading old data.
-    const static uint32_t CurrentContentExtensionFileVersion = 8;
+    // Also update ContentExtensionStore::getContentExtensionSource to be able to find the original JSON
+    // source from old versions.
+    const static uint32_t CurrentContentExtensionFileVersion = 9;
 
     static ContentExtensionStore& defaultStore();
     static Ref<ContentExtensionStore> storeWithPath(const WTF::String& storePath);
@@ -66,6 +68,7 @@
     // For testing only.
     void synchronousRemoveAllContentExtensions();
     void invalidateContentExtensionVersion(const WTF::String& identifier);
+    void getContentExtensionSource(const WTF::String& identifier, Function<void(WTF::String)>);
 
 private:
     WTF::String defaultStorePath();

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKContentExtensionStore.mm (213987 => 213988)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKContentExtensionStore.mm	2017-03-15 17:40:59 UTC (rev 213987)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKContentExtensionStore.mm	2017-03-15 17:59:08 UTC (rev 213988)
@@ -29,8 +29,26 @@
 
 #if WK_API_ENABLED
 
+#import "APIContentExtensionStore.h"
 #import "WKErrorInternal.h"
 
+static WKErrorCode toWKErrorCode(const std::error_code& error)
+{
+    ASSERT(error.category() == API::contentExtensionStoreErrorCategory());
+    switch (static_cast<API::ContentExtensionStore::Error>(error.value())) {
+    case API::ContentExtensionStore::Error::LookupFailed:
+        return WKErrorContentExtensionStoreLookupFailed;
+    case API::ContentExtensionStore::Error::VersionMismatch:
+        return WKErrorContentExtensionStoreVersionMismatch;
+    case API::ContentExtensionStore::Error::CompileFailed:
+        return WKErrorContentExtensionStoreCompileFailed;
+    case API::ContentExtensionStore::Error::RemoveFailed:
+        return WKErrorContentExtensionStoreRemoveFailed;
+    }
+    ASSERT_NOT_REACHED();
+    return WKErrorUnknown;
+}
+
 @implementation WKContentExtensionStore
 
 - (void)dealloc
@@ -92,8 +110,9 @@
             auto rawHandler = (void (^)(WKContentExtension *, NSError *))handler.get();
 
             auto userInfo = @{NSHelpAnchorErrorKey: [NSString stringWithFormat:@"Extension lookup failed: %s", error.message().c_str()]};
-            ASSERT(error.value() == WKErrorContentExtensionStoreLookupFailed || error.value() == WKErrorContentExtensionStoreVersionMismatch);
-            rawHandler(nil, [NSError errorWithDomain:WKErrorDomain code:error.value() userInfo:userInfo]);
+            auto wkError = toWKErrorCode(error);
+            ASSERT(wkError == WKErrorContentExtensionStoreLookupFailed || wkError == WKErrorContentExtensionStoreVersionMismatch);
+            rawHandler(nil, [NSError errorWithDomain:WKErrorDomain code:wkError userInfo:userInfo]);
             return;
         }
 
@@ -111,7 +130,7 @@
             auto rawHandler = (void (^)(NSError *))handler.get();
 
             auto userInfo = @{NSHelpAnchorErrorKey: [NSString stringWithFormat:@"Extension removal failed: %s", error.message().c_str()]};
-            ASSERT(error.value() == WKErrorContentExtensionStoreRemoveFailed);
+            ASSERT(toWKErrorCode(error) == WKErrorContentExtensionStoreRemoveFailed);
             rawHandler([NSError errorWithDomain:WKErrorDomain code:WKErrorContentExtensionStoreRemoveFailed userInfo:userInfo]);
             return;
         }
@@ -144,6 +163,18 @@
     _contentExtensionStore->invalidateContentExtensionVersion(identifier);
 }
 
+- (void)_getContentExtensionSourceForIdentifier:(NSString *)identifier completionHandler:(void (^)(NSString*))completionHandler
+{
+    auto handler = adoptNS([completionHandler copy]);
+    _contentExtensionStore->getContentExtensionSource(identifier, [handler](String source) {
+        auto rawHandler = (void (^)(NSString *))handler.get();
+        if (source.isNull())
+            rawHandler(nil);
+        else
+            rawHandler(source);
+    });
+}
+
 // NS_RELEASES_ARGUMENT to keep peak memory usage low.
 
 - (void)_compileContentExtensionForIdentifier:(NSString *)identifier encodedContentExtension:(NSString *)encodedContentExtension completionHandler:(void (^)(WKContentExtension *, NSError *))completionHandler

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKContentExtensionStorePrivate.h (213987 => 213988)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKContentExtensionStorePrivate.h	2017-03-15 17:40:59 UTC (rev 213987)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKContentExtensionStorePrivate.h	2017-03-15 17:59:08 UTC (rev 213988)
@@ -32,6 +32,7 @@
 // For testing only.
 - (void)_removeAllContentExtensions;
 - (void)_invalidateContentExtensionVersionForIdentifier:(NSString *)identifier;
+- (void)_getContentExtensionSourceForIdentifier:(NSString *)identifier completionHandler:(void (^)(NSString*))completionHandler;
 
 // NS_RELEASES_ARGUMENT to keep peak memory usage low.
 - (void)_compileContentExtensionForIdentifier:(NSString *)identifier encodedContentExtension:(NSString *) NS_RELEASES_ARGUMENT encodedContentExtension completionHandler:(void (^)(WKContentExtension *, NSError *))completionHandler;

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKError.h (213987 => 213988)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKError.h	2017-03-15 17:40:59 UTC (rev 213987)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKError.h	2017-03-15 17:59:08 UTC (rev 213988)
@@ -42,7 +42,7 @@
  @constant WKErrorJavaScriptExceptionOccurred          Indicates that a _javascript_ exception occurred.
  @constant WKErrorJavaScriptResultTypeIsUnsupported    Indicates that the result of _javascript_ execution could not be returned.
  @constant WKErrorContentExtensionStoreLookupFailed    Indicates that looking up a WKUserContentExtension failed.
- @constant WKErrorContentExtensionStoreVersionMismatch Indicates that looking up a WKUserContentExtension found an extension with an incompatible binary version.
+ @constant WKErrorContentExtensionStoreVersionMismatch Indicates that the WKUserContentExtension version did not match the latest.
  @constant WKErrorContentExtensionStoreCompileFailed   Indicates that compiling a WKUserContentExtension failed.
  @constant WKErrorContentExtensionStoreRemoveFailed    Indicates that removing a WKUserContentExtension failed.
  */

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.h (213987 => 213988)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.h	2017-03-15 17:40:59 UTC (rev 213987)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.h	2017-03-15 17:59:08 UTC (rev 213988)
@@ -44,7 +44,7 @@
 WK_EXTERN NSString * const _WKUserContentExtensionsDomain WK_API_AVAILABLE(macosx(10.12), ios(10.0));
 
 typedef NS_ENUM(NSInteger, _WKUserContentExtensionStoreErrorCode) {
-    _WKUserContentExtensionStoreErrorLookupFailed = 6, // Mirrors value of WKErrorContentExtensionStoreLookupFailed
+    _WKUserContentExtensionStoreErrorLookupFailed,
     _WKUserContentExtensionStoreErrorVersionMismatch,
     _WKUserContentExtensionStoreErrorCompileFailed,
     _WKUserContentExtensionStoreErrorRemoveFailed,

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm (213987 => 213988)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm	2017-03-15 17:40:59 UTC (rev 213987)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm	2017-03-15 17:59:08 UTC (rev 213988)
@@ -38,6 +38,26 @@
 
 NSString * const _WKUserContentExtensionsDomain = @"WKErrorDomain";
 
+static NSError *toUserContentExtensionStoreError(const NSError *error)
+{
+    if (!error)
+        return nil;
+
+    ASSERT(error.domain == WKErrorDomain);
+    switch (error.code) {
+    case WKErrorContentExtensionStoreLookupFailed:
+        return [NSError errorWithDomain:_WKUserContentExtensionsDomain code:_WKUserContentExtensionStoreErrorLookupFailed userInfo:error.userInfo];
+    case WKErrorContentExtensionStoreVersionMismatch:
+        return [NSError errorWithDomain:_WKUserContentExtensionsDomain code:_WKUserContentExtensionStoreErrorVersionMismatch userInfo:error.userInfo];
+    case WKErrorContentExtensionStoreCompileFailed:
+        return [NSError errorWithDomain:_WKUserContentExtensionsDomain code:_WKUserContentExtensionStoreErrorCompileFailed userInfo:error.userInfo];
+    case WKErrorContentExtensionStoreRemoveFailed:
+        return [NSError errorWithDomain:_WKUserContentExtensionsDomain code:_WKUserContentExtensionStoreErrorRemoveFailed userInfo:error.userInfo];
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+}
+
 @implementation _WKUserContentExtensionStore
 
 + (instancetype)defaultStore
@@ -54,7 +74,7 @@
 {
     [_contentExtensionStore _compileContentExtensionForIdentifier:identifier encodedContentExtension:encodedContentExtension completionHandler:^(WKContentExtension *contentExtension, NSError *error) {
         _WKUserContentFilter *contentFilter = contentExtension ? [[[_WKUserContentFilter alloc] _initWithWKContentExtension:contentExtension] autorelease] : nil;
-        completionHandler(contentFilter, error);
+        completionHandler(contentFilter, toUserContentExtensionStoreError(error));
     }];
 }
 
@@ -62,13 +82,15 @@
 {
     [_contentExtensionStore lookupContentExtensionForIdentifier:identifier completionHandler:^(WKContentExtension *contentExtension, NSError *error) {
         _WKUserContentFilter *contentFilter = contentExtension ? [[[_WKUserContentFilter alloc] _initWithWKContentExtension:contentExtension] autorelease] : nil;
-        completionHandler(contentFilter, error);
+        completionHandler(contentFilter, toUserContentExtensionStoreError(error));
     }];
 }
 
 - (void)removeContentExtensionForIdentifier:(NSString *)identifier completionHandler:(void (^)(NSError *))completionHandler
 {
-    [_contentExtensionStore removeContentExtensionForIdentifier:identifier completionHandler:completionHandler];
+    [_contentExtensionStore removeContentExtensionForIdentifier:identifier completionHandler:^(NSError *error) {
+        completionHandler(toUserContentExtensionStoreError(error));
+    }];
 }
 
 #pragma mark WKObject protocol implementation

Modified: trunk/Tools/ChangeLog (213987 => 213988)


--- trunk/Tools/ChangeLog	2017-03-15 17:40:59 UTC (rev 213987)
+++ trunk/Tools/ChangeLog	2017-03-15 17:59:08 UTC (rev 213988)
@@ -1,3 +1,14 @@
+2017-03-15  Alex Christensen  <[email protected]>
+
+        Compiled content extensions should include the JSON source
+        https://bugs.webkit.org/show_bug.cgi?id=169643
+
+        Reviewed by Geoffrey Garen.
+
+        * TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:
+        * TestWebKitAPI/Tests/WebKit2Cocoa/WKUserContentExtensionStore.mm:
+        (TEST_F):
+
 2017-03-15  Kocsen Chung  <[email protected]>
 
         Use git's -C flag when possible in VCSUtils.pm

Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp (213987 => 213988)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp	2017-03-15 17:40:59 UTC (rev 213987)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp	2017-03-15 17:59:08 UTC (rev 213988)
@@ -100,6 +100,8 @@
         EXPECT_EQ(data.topURLFilters.size(), 0ull);
     }
 
+    void writeSource(const String&) final { }
+
     void writeActions(Vector<ContentExtensions::SerializedActionByte>&& actions, bool conditionsApplyOnlyToDomain) final
     {
         EXPECT_FALSE(finalized);

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WKUserContentExtensionStore.mm (213987 => 213988)


--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WKUserContentExtensionStore.mm	2017-03-15 17:40:59 UTC (rev 213987)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WKUserContentExtensionStore.mm	2017-03-15 17:59:08 UTC (rev 213988)
@@ -146,6 +146,13 @@
         doneLookingUp = true;
     }];
     TestWebKitAPI::Util::run(&doneLookingUp);
+
+    __block bool doneGettingSource = false;
+    [[WKContentExtensionStore defaultStore] _getContentExtensionSourceForIdentifier:@"TestExtension" completionHandler:^(NSString* source) {
+        EXPECT_NULL(source);
+        doneGettingSource = true;
+    }];
+    TestWebKitAPI::Util::run(&doneGettingSource);
 }
 
 TEST_F(WKContentExtensionStoreTest, Removal)
@@ -183,4 +190,69 @@
     TestWebKitAPI::Util::run(&doneRemoving);
 }
 
+TEST_F(WKContentExtensionStoreTest, NonDefaultStore)
+{
+    NSURL *tempDir = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"ContentExtensionTest"] isDirectory:YES];
+    WKContentExtensionStore *store = [WKContentExtensionStore storeWithURL:tempDir];
+    NSString *identifier = @"TestExtension";
+    NSString *fileName = @"ContentExtension-TestExtension";
+
+    __block bool doneCompiling = false;
+    [store compileContentExtensionForIdentifier:identifier encodedContentExtension:basicFilter completionHandler:^(WKContentExtension *filter, NSError *error) {
+        EXPECT_NOT_NULL(filter);
+        EXPECT_NULL(error);
+        doneCompiling = true;
+    }];
+    TestWebKitAPI::Util::run(&doneCompiling);
+
+    NSData *data = "" dataWithContentsOfURL:[tempDir URLByAppendingPathComponent:fileName]];
+    EXPECT_NOT_NULL(data);
+    EXPECT_EQ(data.length, 228u);
+    
+    __block bool doneCheckingSource = false;
+    [store _getContentExtensionSourceForIdentifier:identifier completionHandler:^(NSString *source) {
+        EXPECT_NOT_NULL(source);
+        EXPECT_STREQ(basicFilter.UTF8String, source.UTF8String);
+        doneCheckingSource = true;
+    }];
+    TestWebKitAPI::Util::run(&doneCheckingSource);
+    
+    __block bool doneRemoving = false;
+    [store removeContentExtensionForIdentifier:identifier completionHandler:^(NSError *error) {
+        EXPECT_NULL(error);
+        doneRemoving = true;
+    }];
+    TestWebKitAPI::Util::run(&doneRemoving);
+
+    NSData *dataAfterRemoving = [NSData dataWithContentsOfURL:[tempDir URLByAppendingPathComponent:fileName]];
+    EXPECT_NULL(dataAfterRemoving);
+}
+
+TEST_F(WKContentExtensionStoreTest, NonASCIISource)
+{
+    static NSString *nonASCIIFilter = @"[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*webkit.org\"}, \"unused\":\"💩\"}]";
+    NSURL *tempDir = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"ContentExtensionTest"] isDirectory:YES];
+    WKContentExtensionStore *store = [WKContentExtensionStore storeWithURL:tempDir];
+    NSString *identifier = @"TestExtension";
+    NSString *fileName = @"ContentExtension-TestExtension";
+    
+    __block bool done = false;
+    [store compileContentExtensionForIdentifier:identifier encodedContentExtension:nonASCIIFilter completionHandler:^(WKContentExtension *filter, NSError *error) {
+        EXPECT_NOT_NULL(filter);
+        EXPECT_NULL(error);
+
+        [store _getContentExtensionSourceForIdentifier:identifier completionHandler:^(NSString *source) {
+            EXPECT_NOT_NULL(source);
+            EXPECT_STREQ(nonASCIIFilter.UTF8String, source.UTF8String);
+
+            [store _removeAllContentExtensions];
+            NSData *dataAfterRemoving = [NSData dataWithContentsOfURL:[tempDir URLByAppendingPathComponent:fileName]];
+            EXPECT_NULL(dataAfterRemoving);
+
+            done = true;
+        }];
+    }];
+    TestWebKitAPI::Util::run(&done);
+}
+
 #endif
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to