⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 242735 in webkit


Ignore:
Timestamp:
Mar 11, 2019, 1:21:39 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

Add a WKContentRuleList variant that uses copied memory instead of mmap'd shared memory for class A containerized apps
https://bugs.webkit.org/show_bug.cgi?id=195511
<rdar://problem/44873269>

Patch by Alex Christensen <achristensen@webkit.org> on 2019-03-11
Reviewed by Darin Adler.

Source/WebKit:

  • NetworkProcess/NetworkContentRuleListManager.cpp:

(WebKit::NetworkContentRuleListManager::addContentRuleLists):

  • NetworkProcess/NetworkContentRuleListManager.h:
  • NetworkProcess/cache/NetworkCacheFileSystem.cpp:

(WebKit::NetworkCache::pathRegisteredAsUnsafeToMemoryMapForTesting):
(WebKit::NetworkCache::registerPathAsUnsafeToMemoryMapForTesting):
(WebKit::NetworkCache::isSafeToUseMemoryMapForPath):

  • NetworkProcess/cache/NetworkCacheFileSystem.h:
  • Shared/WebCompiledContentRuleList.cpp:

(WebKit::WebCompiledContentRuleList::usesCopiedMemory const):
(WebKit::WebCompiledContentRuleList::conditionsApplyOnlyToDomain const):
(WebKit::WebCompiledContentRuleList::filtersWithoutConditionsBytecode const):
(WebKit::WebCompiledContentRuleList::filtersWithConditionsBytecode const):
(WebKit::WebCompiledContentRuleList::topURLFiltersBytecode const):
(WebKit::WebCompiledContentRuleList::actions const):

  • Shared/WebCompiledContentRuleList.h:
  • Shared/WebCompiledContentRuleListData.cpp:

(WebKit::WebCompiledContentRuleListData::size const):
(WebKit::WebCompiledContentRuleListData::dataPointer const):
(WebKit::WebCompiledContentRuleListData::encode const):
(WebKit::WebCompiledContentRuleListData::decode):

  • Shared/WebCompiledContentRuleListData.h:

(WebKit::WebCompiledContentRuleListData::WebCompiledContentRuleListData):

  • UIProcess/API/APIContentRuleList.cpp:

(API::ContentRuleList::usesCopiedMemory const):

  • UIProcess/API/APIContentRuleList.h:
  • UIProcess/API/APIContentRuleListStore.cpp:

(API::getData):
(API::decodeContentRuleListMetaData):
(API::ContentRuleListStore::readContentsOfFile):
(API::MappedOrCopiedData::dataPointer const):
(API::openAndMapOrCopyContentRuleList):
(API::compiledToFile):
(API::createExtension):
(API::ContentRuleListStore::lookupContentRuleList):
(API::ContentRuleListStore::compileContentRuleList):
(API::ContentRuleListStore::getContentRuleListSource):
(API::openAndMapContentRuleList): Deleted.

  • UIProcess/API/APIContentRuleListStore.h:
  • UIProcess/API/Cocoa/APIContentRuleListStoreCocoa.mm:

(API::ContentRuleListStore::readContentsOfFile):

  • UIProcess/API/Cocoa/WKContentRuleListStore.mm:

(+[WKContentRuleListStore _registerPathAsUnsafeToMemoryMapForTesting:]):

  • UIProcess/API/Cocoa/WKContentRuleListStorePrivate.h:
  • UIProcess/API/Cocoa/_WKUserContentFilter.mm:

(-[_WKUserContentFilter usesCopiedMemory]):

  • UIProcess/API/Cocoa/_WKUserContentFilterPrivate.h:
  • WebProcess/UserContent/WebUserContentController.cpp:

(WebKit::WebUserContentController::addContentRuleLists):

  • WebProcess/UserContent/WebUserContentController.h:
  • WebProcess/WebPage/WebPage.cpp:

(WebKit::m_hostFileDescriptor):

Tools:

  • TestWebKitAPI/Tests/WebKitCocoa/WKContentExtensionStore.mm:

(-[TestSchemeHandlerSubresourceShouldBeBlocked webView:startURLSchemeTask:]):
(-[TestSchemeHandlerSubresourceShouldBeBlocked webView:stopURLSchemeTask:]):
(TEST_F):

Location:
trunk
Files:
23 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r242728 r242735  
     12019-03-11  Alex Christensen  <achristensen@webkit.org>
     2
     3        Add a WKContentRuleList variant that uses copied memory instead of mmap'd shared memory for class A containerized apps
     4        https://bugs.webkit.org/show_bug.cgi?id=195511
     5        <rdar://problem/44873269>
     6
     7        Reviewed by Darin Adler.
     8
     9        * NetworkProcess/NetworkContentRuleListManager.cpp:
     10        (WebKit::NetworkContentRuleListManager::addContentRuleLists):
     11        * NetworkProcess/NetworkContentRuleListManager.h:
     12        * NetworkProcess/cache/NetworkCacheFileSystem.cpp:
     13        (WebKit::NetworkCache::pathRegisteredAsUnsafeToMemoryMapForTesting):
     14        (WebKit::NetworkCache::registerPathAsUnsafeToMemoryMapForTesting):
     15        (WebKit::NetworkCache::isSafeToUseMemoryMapForPath):
     16        * NetworkProcess/cache/NetworkCacheFileSystem.h:
     17        * Shared/WebCompiledContentRuleList.cpp:
     18        (WebKit::WebCompiledContentRuleList::usesCopiedMemory const):
     19        (WebKit::WebCompiledContentRuleList::conditionsApplyOnlyToDomain const):
     20        (WebKit::WebCompiledContentRuleList::filtersWithoutConditionsBytecode const):
     21        (WebKit::WebCompiledContentRuleList::filtersWithConditionsBytecode const):
     22        (WebKit::WebCompiledContentRuleList::topURLFiltersBytecode const):
     23        (WebKit::WebCompiledContentRuleList::actions const):
     24        * Shared/WebCompiledContentRuleList.h:
     25        * Shared/WebCompiledContentRuleListData.cpp:
     26        (WebKit::WebCompiledContentRuleListData::size const):
     27        (WebKit::WebCompiledContentRuleListData::dataPointer const):
     28        (WebKit::WebCompiledContentRuleListData::encode const):
     29        (WebKit::WebCompiledContentRuleListData::decode):
     30        * Shared/WebCompiledContentRuleListData.h:
     31        (WebKit::WebCompiledContentRuleListData::WebCompiledContentRuleListData):
     32        * UIProcess/API/APIContentRuleList.cpp:
     33        (API::ContentRuleList::usesCopiedMemory const):
     34        * UIProcess/API/APIContentRuleList.h:
     35        * UIProcess/API/APIContentRuleListStore.cpp:
     36        (API::getData):
     37        (API::decodeContentRuleListMetaData):
     38        (API::ContentRuleListStore::readContentsOfFile):
     39        (API::MappedOrCopiedData::dataPointer const):
     40        (API::openAndMapOrCopyContentRuleList):
     41        (API::compiledToFile):
     42        (API::createExtension):
     43        (API::ContentRuleListStore::lookupContentRuleList):
     44        (API::ContentRuleListStore::compileContentRuleList):
     45        (API::ContentRuleListStore::getContentRuleListSource):
     46        (API::openAndMapContentRuleList): Deleted.
     47        * UIProcess/API/APIContentRuleListStore.h:
     48        * UIProcess/API/Cocoa/APIContentRuleListStoreCocoa.mm:
     49        (API::ContentRuleListStore::readContentsOfFile):
     50        * UIProcess/API/Cocoa/WKContentRuleListStore.mm:
     51        (+[WKContentRuleListStore _registerPathAsUnsafeToMemoryMapForTesting:]):
     52        * UIProcess/API/Cocoa/WKContentRuleListStorePrivate.h:
     53        * UIProcess/API/Cocoa/_WKUserContentFilter.mm:
     54        (-[_WKUserContentFilter usesCopiedMemory]):
     55        * UIProcess/API/Cocoa/_WKUserContentFilterPrivate.h:
     56        * WebProcess/UserContent/WebUserContentController.cpp:
     57        (WebKit::WebUserContentController::addContentRuleLists):
     58        * WebProcess/UserContent/WebUserContentController.h:
     59        * WebProcess/WebPage/WebPage.cpp:
     60        (WebKit::m_hostFileDescriptor):
     61
    1622019-03-11  Chris Dumez  <cdumez@apple.com>
    263
  • trunk/Source/WebKit/NetworkProcess/NetworkContentRuleListManager.cpp

    r242710 r242735  
    6767}
    6868
    69 void NetworkContentRuleListManager::addContentRuleLists(UserContentControllerIdentifier identifier, const Vector<std::pair<String, WebCompiledContentRuleListData>>& contentRuleLists)
     69void NetworkContentRuleListManager::addContentRuleLists(UserContentControllerIdentifier identifier, Vector<std::pair<String, WebCompiledContentRuleListData>>&& contentRuleLists)
    7070{
    7171    auto& backend = *m_contentExtensionBackends.ensure(identifier, [] {
     
    7373    }).iterator->value;
    7474
    75     for (const auto& contentRuleList : contentRuleLists) {
    76         WebCompiledContentRuleListData contentRuleListData = contentRuleList.second;
    77         auto compiledContentRuleList = WebCompiledContentRuleList::create(WTFMove(contentRuleListData));
     75    for (auto&& contentRuleList : contentRuleLists) {
     76        auto compiledContentRuleList = WebCompiledContentRuleList::create(WTFMove(contentRuleList.second));
    7877        backend.addContentExtension(contentRuleList.first, WTFMove(compiledContentRuleList), ContentExtensions::ContentExtension::ShouldCompileCSS::No);
    7978    }
  • trunk/Source/WebKit/NetworkProcess/NetworkContentRuleListManager.h

    r242710 r242735  
    5252
    5353private:
    54     void addContentRuleLists(UserContentControllerIdentifier, const Vector<std::pair<String, WebCompiledContentRuleListData>>&);
     54    void addContentRuleLists(UserContentControllerIdentifier, Vector<std::pair<String, WebCompiledContentRuleListData>>&&);
    5555    void removeContentRuleList(UserContentControllerIdentifier, const String& name);
    5656    void removeAllContentRuleLists(UserContentControllerIdentifier);
  • trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheFileSystem.cpp

    r242710 r242735  
    146146}
    147147
     148static String& pathRegisteredAsUnsafeToMemoryMapForTesting()
     149{
     150    static NeverDestroyed<String> path;
     151    return path.get();
     152}
     153
     154void registerPathAsUnsafeToMemoryMapForTesting(const String& path)
     155{
     156    pathRegisteredAsUnsafeToMemoryMapForTesting() = path;
     157}
     158
     159   
    148160bool isSafeToUseMemoryMapForPath(const String& path)
    149161{
     162    if (path == pathRegisteredAsUnsafeToMemoryMapForTesting())
     163        return false;
     164
    150165#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR)
    151166    struct {
  • trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheFileSystem.h

    r242710 r242735  
    4444
    4545bool isSafeToUseMemoryMapForPath(const String& path);
     46void registerPathAsUnsafeToMemoryMapForTesting(const String&);
    4647
    4748}
  • trunk/Source/WebKit/Shared/WebCompiledContentRuleList.cpp

    r242710 r242735  
    4545}
    4646
     47bool WebCompiledContentRuleList::usesCopiedMemory() const
     48{
     49    return WTF::holds_alternative<RefPtr<WebCore::SharedBuffer>>(m_data.data);
     50}
     51
    4752bool WebCompiledContentRuleList::conditionsApplyOnlyToDomain() const
    4853{
    49     return *reinterpret_cast<uint32_t*>(reinterpret_cast<uint8_t*>(m_data.data->data()) + m_data.conditionsApplyOnlyToDomainOffset);
     54    return *reinterpret_cast<const uint32_t*>(reinterpret_cast<const uint8_t*>(m_data.dataPointer()) + m_data.conditionsApplyOnlyToDomainOffset);
    5055}
    5156
    5257const WebCore::ContentExtensions::DFABytecode* WebCompiledContentRuleList::filtersWithoutConditionsBytecode() const
    5358{
    54     return static_cast<const WebCore::ContentExtensions::DFABytecode*>(m_data.data->data()) + m_data.filtersWithoutConditionsBytecodeOffset;
     59    return static_cast<const WebCore::ContentExtensions::DFABytecode*>(m_data.dataPointer()) + m_data.filtersWithoutConditionsBytecodeOffset;
    5560}
    5661
     
    6267const WebCore::ContentExtensions::DFABytecode* WebCompiledContentRuleList::filtersWithConditionsBytecode() const
    6368{
    64     return static_cast<const WebCore::ContentExtensions::DFABytecode*>(m_data.data->data()) + m_data.filtersWithConditionsBytecodeOffset;
     69    return static_cast<const WebCore::ContentExtensions::DFABytecode*>(m_data.dataPointer()) + m_data.filtersWithConditionsBytecodeOffset;
    6570}
    6671
     
    7277const WebCore::ContentExtensions::DFABytecode* WebCompiledContentRuleList::topURLFiltersBytecode() const
    7378{
    74     return static_cast<const WebCore::ContentExtensions::DFABytecode*>(m_data.data->data()) + m_data.topURLFiltersBytecodeOffset;
     79    return static_cast<const WebCore::ContentExtensions::DFABytecode*>(m_data.dataPointer()) + m_data.topURLFiltersBytecodeOffset;
    7580}
    7681
     
    8287const WebCore::ContentExtensions::SerializedActionByte* WebCompiledContentRuleList::actions() const
    8388{
    84     return static_cast<const WebCore::ContentExtensions::SerializedActionByte*>(m_data.data->data()) + m_data.actionsOffset;
     89    return static_cast<const WebCore::ContentExtensions::SerializedActionByte*>(m_data.dataPointer()) + m_data.actionsOffset;
    8590}
    8691
  • trunk/Source/WebKit/Shared/WebCompiledContentRuleList.h

    r242710 r242735  
    3939    virtual ~WebCompiledContentRuleList();
    4040
    41     WebCompiledContentRuleListData data() const { return m_data; }
     41    const WebCompiledContentRuleListData& data() const { return m_data; }
    4242
     43    bool usesCopiedMemory() const;
     44   
    4345private:
    4446    WebCompiledContentRuleList(WebCompiledContentRuleListData&&);
  • trunk/Source/WebKit/Shared/WebCompiledContentRuleListData.cpp

    r242710 r242735  
    3030
    3131#include "ArgumentCoders.h"
     32#include "SharedBufferDataReference.h"
    3233
    3334namespace WebKit {
    3435
     36size_t WebCompiledContentRuleListData::size() const
     37{
     38    return WTF::switchOn(data, [] (const auto& sharedMemoryOrBuffer) {
     39        return sharedMemoryOrBuffer->size();
     40    });
     41}
     42
     43const void* WebCompiledContentRuleListData::dataPointer() const
     44{
     45    return WTF::switchOn(data, [] (const auto& sharedMemoryOrBuffer) -> const void* {
     46        return sharedMemoryOrBuffer->data();
     47    });
     48}
     49
    3550void WebCompiledContentRuleListData::encode(IPC::Encoder& encoder) const
    3651{
    37     SharedMemory::Handle handle;
    38     data->createHandle(handle, SharedMemory::Protection::ReadOnly);
    39     encoder << handle;
     52    if (auto sharedMemory = WTF::get_if<RefPtr<SharedMemory>>(data)) {
     53        encoder << true;
     54        SharedMemory::Handle handle;
     55        sharedMemory->get()->createHandle(handle, SharedMemory::Protection::ReadOnly);
     56        encoder << handle;
     57    } else {
     58        encoder << false;
     59        encoder << IPC::SharedBufferDataReference { *WTF::get<RefPtr<WebCore::SharedBuffer>>(data) };
     60    }
     61
     62    // fileData needs to be kept in the UIProcess, but it does not need to be serialized.
     63    // FIXME: Move it to API::ContentRuleList
    4064
    4165    encoder << conditionsApplyOnlyToDomainOffset;
     
    5377{
    5478    WebCompiledContentRuleListData compiledContentRuleListData;
    55     SharedMemory::Handle handle;
    56     if (!decoder.decode(handle))
     79
     80    Optional<bool> hasSharedMemory;
     81    decoder >> hasSharedMemory;
     82    if (!hasSharedMemory)
    5783        return WTF::nullopt;
    58     compiledContentRuleListData.data = SharedMemory::map(handle, SharedMemory::Protection::ReadOnly);
     84    if (*hasSharedMemory) {
     85        SharedMemory::Handle handle;
     86        if (!decoder.decode(handle))
     87            return WTF::nullopt;
     88        compiledContentRuleListData.data = { SharedMemory::map(handle, SharedMemory::Protection::ReadOnly) };
     89    } else {
     90        IPC::DataReference dataReference;
     91        if (!decoder.decode(dataReference))
     92            return WTF::nullopt;
     93        compiledContentRuleListData.data = { RefPtr<WebCore::SharedBuffer>(WebCore::SharedBuffer::create(dataReference.data(), dataReference.size())) };
     94    }
    5995
    6096    if (!decoder.decode(compiledContentRuleListData.conditionsApplyOnlyToDomainOffset))
  • trunk/Source/WebKit/Shared/WebCompiledContentRuleListData.h

    r242710 r242735  
    3030#include "NetworkCacheData.h"
    3131#include "SharedMemory.h"
     32#include <WebCore/SharedBuffer.h>
    3233#include <wtf/RefPtr.h>
     34#include <wtf/Variant.h>
    3335
    3436namespace IPC {
     
    4345    WebCompiledContentRuleListData() = default;
    4446
    45     WebCompiledContentRuleListData(RefPtr<SharedMemory>&& data, NetworkCache::Data fileData, unsigned conditionsApplyOnlyToDomainOffset, unsigned actionsOffset, unsigned actionsSize, unsigned filtersWithoutConditionsBytecodeOffset, unsigned filtersWithoutConditionsBytecodeSize, unsigned filtersWithConditionsBytecodeOffset, unsigned filtersWithConditionsBytecodeSize, unsigned topURLFiltersBytecodeOffset, unsigned topURLFiltersBytecodeSize)
     47    WebCompiledContentRuleListData(Variant<RefPtr<SharedMemory>, RefPtr<WebCore::SharedBuffer>>&& data, NetworkCache::Data fileData, unsigned conditionsApplyOnlyToDomainOffset, unsigned actionsOffset, unsigned actionsSize, unsigned filtersWithoutConditionsBytecodeOffset, unsigned filtersWithoutConditionsBytecodeSize, unsigned filtersWithConditionsBytecodeOffset, unsigned filtersWithConditionsBytecodeSize, unsigned topURLFiltersBytecodeOffset, unsigned topURLFiltersBytecodeSize)
    4648        : data(WTFMove(data))
    4749        , fileData(fileData)
     
    6163    static Optional<WebCompiledContentRuleListData> decode(IPC::Decoder&);
    6264
    63     RefPtr<SharedMemory> data;
     65    size_t size() const;
     66    const void* dataPointer() const;
     67   
     68    Variant<RefPtr<SharedMemory>, RefPtr<WebCore::SharedBuffer>> data;
    6469    NetworkCache::Data fileData;
    6570    unsigned conditionsApplyOnlyToDomainOffset { 0 };
  • trunk/Source/WebKit/UIProcess/API/APIContentRuleList.cpp

    r242710 r242735  
    4343}
    4444
     45bool ContentRuleList::usesCopiedMemory() const
     46{
     47    return m_compiledRuleList->usesCopiedMemory();
     48}
     49
    4550} // namespace API
    4651
  • trunk/Source/WebKit/UIProcess/API/APIContentRuleList.h

    r242710 r242735  
    4949    const WebKit::WebCompiledContentRuleList& compiledRuleList() const { return m_compiledRuleList.get(); }
    5050
     51    bool usesCopiedMemory() const;
     52
    5153private:
    5254    WTF::String m_name;
  • trunk/Source/WebKit/UIProcess/API/APIContentRuleListStore.cpp

    r242710 r242735  
    3838#include <WebCore/ContentExtensionParser.h>
    3939#include <WebCore/QualifiedName.h>
     40#include <WebCore/SharedBuffer.h>
    4041#include <string>
    4142#include <wtf/CompletionHandler.h>
     
    157158}
    158159
    159 static bool decodeContentRuleListMetaData(ContentRuleListMetaData& metaData, const WebKit::NetworkCache::Data& fileData)
     160template<typename T> void getData(const T&, const Function<bool(const uint8_t*, size_t)>&);
     161template<> void getData(const WebKit::NetworkCache::Data& data, const Function<bool(const uint8_t*, size_t)>& function)
     162{
     163    data.apply(function);
     164}
     165template<> void getData(const WebCore::SharedBuffer& data, const Function<bool(const uint8_t*, size_t)>& function)
     166{
     167    function(reinterpret_cast<const uint8_t*>(data.data()), data.size());
     168}
     169
     170template<typename T>
     171static Optional<ContentRuleListMetaData> decodeContentRuleListMetaData(const T& fileData)
    160172{
    161173    bool success = false;
    162     fileData.apply([&metaData, &success, &fileData](const uint8_t* data, size_t size) {
     174    ContentRuleListMetaData metaData;
     175    getData(fileData, [&metaData, &success, &fileData](const uint8_t* data, size_t size) {
    163176        // The file data should be mapped into one continuous memory segment so the size
    164177        // passed to the applier should always equal the data size.
     
    184197        return false;
    185198    });
    186     return success;
    187 }
    188 
    189 static bool openAndMapContentRuleList(const WTF::String& path, ContentRuleListMetaData& metaData, WebKit::NetworkCache::Data& fileData)
    190 {
    191     fileData = mapFile(fileSystemRepresentation(path).data());
     199    if (!success)
     200        return WTF::nullopt;
     201    return WTFMove(metaData);
     202}
     203
     204#if !PLATFORM(COCOA)
     205RefPtr<WebCore::SharedBuffer> ContentRuleListStore::readContentsOfFile(const WTF::String& filePath)
     206{
     207    ASSERT_NOT_REACHED();
     208    return nullptr;
     209}
     210#endif
     211
     212struct MappedOrCopiedData {
     213    ContentRuleListMetaData metaData;
     214    Variant<WebKit::NetworkCache::Data, RefPtr<WebCore::SharedBuffer>> data;
     215   
     216    const uint8_t* dataPointer() const
     217    {
     218        return WTF::switchOn(data, [] (const WebKit::NetworkCache::Data& data) {
     219            return data.data();
     220        }, [] (const RefPtr<WebCore::SharedBuffer>& sharedBuffer) {
     221            return reinterpret_cast<const uint8_t*>(sharedBuffer->data());
     222        });
     223    }
     224};
     225
     226static Optional<MappedOrCopiedData> openAndMapOrCopyContentRuleList(const WTF::String& path)
     227{
     228    if (!WebKit::NetworkCache::isSafeToUseMemoryMapForPath(path)) {
     229        RefPtr<WebCore::SharedBuffer> buffer = ContentRuleListStore::readContentsOfFile(path);
     230        if (!buffer)
     231            return WTF::nullopt;
     232        auto metaData = decodeContentRuleListMetaData(*buffer);
     233        if (!metaData)
     234            return WTF::nullopt;
     235        return {{ WTFMove(*metaData), { buffer.releaseNonNull() }}};
     236    }
     237
     238    WebKit::NetworkCache::Data fileData = mapFile(fileSystemRepresentation(path).data());
    192239    if (fileData.isNull())
    193         return false;
    194 
    195     if (!decodeContentRuleListMetaData(metaData, fileData))
    196         return false;
    197 
    198     return true;
     240        return WTF::nullopt;
     241    auto metaData = decodeContentRuleListMetaData(fileData);
     242    if (!metaData)
     243        return WTF::nullopt;
     244    return {{ WTFMove(*metaData), { WTFMove(fileData) }}};
    199245}
    200246
     
    213259}
    214260
    215 static std::error_code compiledToFile(WTF::String&& json, Vector<WebCore::ContentExtensions::ContentExtensionRule>&& parsedRules, const WTF::String& finalFilePath, ContentRuleListMetaData& metaData, WebKit::NetworkCache::Data& mappedData)
     261static Expected<MappedOrCopiedData, std::error_code> compiledToFile(WTF::String&& json, Vector<WebCore::ContentExtensions::ContentExtensionRule>&& parsedRules, const WTF::String& finalFilePath)
    216262{
    217263    using namespace WebCore::ContentExtensions;
     
    330376    if (temporaryFileHandle == invalidPlatformFileHandle) {
    331377        WTFLogAlways("Content Rule List compiling failed: Opening temporary file failed.");
    332         return ContentRuleListStore::Error::CompileFailed;
     378        return makeUnexpected(ContentRuleListStore::Error::CompileFailed);
    333379    }
    334380   
     
    339385        WTFLogAlways("Content Rule List compiling failed: Writing header to file failed.");
    340386        closeFile(temporaryFileHandle);
    341         return ContentRuleListStore::Error::CompileFailed;
    342     }
    343 
     387        return makeUnexpected(ContentRuleListStore::Error::CompileFailed);
     388    }
     389
     390    ContentRuleListMetaData metaData;
    344391    CompilationClient compilationClient(temporaryFileHandle, metaData);
    345392   
     
    347394        WTFLogAlways("Content Rule List compiling failed: Compiling failed.");
    348395        closeFile(temporaryFileHandle);
    349         return compilerError;
     396        return makeUnexpected(compilerError);
    350397    }
    351398    if (compilationClient.hadErrorWhileWritingToFile()) {
    352399        WTFLogAlways("Content Rule List compiling failed: Writing to file failed.");
    353400        closeFile(temporaryFileHandle);
    354         return ContentRuleListStore::Error::CompileFailed;
    355     }
    356 
    357     mappedData = adoptAndMapFile(temporaryFileHandle, 0, metaData.fileSize());
     401        return makeUnexpected(ContentRuleListStore::Error::CompileFailed);
     402    }
     403
     404    auto mappedData = adoptAndMapFile(temporaryFileHandle, 0, metaData.fileSize());
    358405    if (mappedData.isNull()) {
    359406        WTFLogAlways("Content Rule List compiling failed: Mapping file failed.");
    360         return ContentRuleListStore::Error::CompileFailed;
     407        return makeUnexpected(ContentRuleListStore::Error::CompileFailed);
    361408    }
    362409
    363410    if (!moveFile(temporaryFilePath, finalFilePath)) {
    364411        WTFLogAlways("Content Rule List compiling failed: Moving file failed.");
    365         return ContentRuleListStore::Error::CompileFailed;
    366     }
    367 
    368     return { };
    369 }
    370 
    371 static Ref<API::ContentRuleList> createExtension(const WTF::String& identifier, const ContentRuleListMetaData& metaData, const WebKit::NetworkCache::Data& fileData)
    372 {
    373     // Content extensions are always compiled to files, and at this point the file
    374     // has been already mapped, therefore tryCreateSharedMemory() cannot fail.
    375     auto sharedMemory = fileData.tryCreateSharedMemory();
    376     ASSERT(sharedMemory);
    377 
    378     const size_t headerAndSourceSize = ContentRuleListFileHeaderSize + metaData.sourceSize;
     412        return makeUnexpected(ContentRuleListStore::Error::CompileFailed);
     413    }
     414
     415    if (!isSafeToUseMemoryMapForPath(finalFilePath)) {
     416        auto contents = ContentRuleListStore::readContentsOfFile(finalFilePath);
     417        if (!contents)
     418            return makeUnexpected(ContentRuleListStore::Error::CompileFailed);
     419        return {{ WTFMove(metaData), WTFMove(contents) }};
     420    }
     421   
     422    return {{ WTFMove(metaData), WTFMove(mappedData) }};
     423}
     424
     425static Ref<API::ContentRuleList> createExtension(const WTF::String& identifier, MappedOrCopiedData&& data)
     426{
     427    RefPtr<WebKit::SharedMemory> sharedMemory;
     428    if (auto mappedFileData = WTF::get_if<WebKit::NetworkCache::Data>(data.data)) {
     429        sharedMemory = mappedFileData->tryCreateSharedMemory();
     430
     431        // Content extensions are always compiled to files, and at this point the file
     432        // has been already mapped, therefore tryCreateSharedMemory() cannot fail.
     433        ASSERT(sharedMemory);
     434    }
     435    auto mappedOrCopiedFileData = sharedMemory ?
     436        Variant<RefPtr<WebKit::SharedMemory>, RefPtr<WebCore::SharedBuffer>> { sharedMemory }
     437        : Variant<RefPtr<WebKit::SharedMemory>, RefPtr<WebCore::SharedBuffer>> { WTFMove(WTF::get<RefPtr<WebCore::SharedBuffer>>(data.data)) };
     438
     439    const size_t headerAndSourceSize = ContentRuleListFileHeaderSize + data.metaData.sourceSize;
    379440    auto compiledContentRuleListData = WebKit::WebCompiledContentRuleListData(
    380         WTFMove(sharedMemory),
    381         fileData,
     441        WTFMove(mappedOrCopiedFileData),
     442        WTF::holds_alternative<WebKit::NetworkCache::Data>(data.data) ? WTF::get<WebKit::NetworkCache::Data>(data.data) : WebKit::NetworkCache::Data { },
    382443        ConditionsApplyOnlyToDomainOffset,
    383444        headerAndSourceSize,
    384         metaData.actionsSize,
     445        data.metaData.actionsSize,
    385446        headerAndSourceSize
    386             + metaData.actionsSize,
    387         metaData.filtersWithoutConditionsBytecodeSize,
     447            + data.metaData.actionsSize,
     448        data.metaData.filtersWithoutConditionsBytecodeSize,
    388449        headerAndSourceSize
    389             + metaData.actionsSize
    390             + metaData.filtersWithoutConditionsBytecodeSize,
    391         metaData.filtersWithConditionsBytecodeSize,
     450            + data.metaData.actionsSize
     451            + data.metaData.filtersWithoutConditionsBytecodeSize,
     452        data.metaData.filtersWithConditionsBytecodeSize,
    392453        headerAndSourceSize
    393             + metaData.actionsSize
    394             + metaData.filtersWithoutConditionsBytecodeSize
    395             + metaData.filtersWithConditionsBytecodeSize,
    396         metaData.conditionedFiltersBytecodeSize
     454            + data.metaData.actionsSize
     455            + data.metaData.filtersWithoutConditionsBytecodeSize
     456            + data.metaData.filtersWithConditionsBytecodeSize,
     457        data.metaData.conditionedFiltersBytecodeSize
    397458    );
    398459    auto compiledContentRuleList = WebKit::WebCompiledContentRuleList::create(WTFMove(compiledContentRuleListData));
     
    405466        auto path = constructedPath(storePath, identifier, legacyFilename);
    406467       
    407         ContentRuleListMetaData metaData;
    408         WebKit::NetworkCache::Data fileData;
    409         if (!openAndMapContentRuleList(path, metaData, fileData)) {
     468        auto contentRuleList = openAndMapOrCopyContentRuleList(path);
     469        if (!contentRuleList) {
    410470            RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler)] () mutable {
    411471                completionHandler(nullptr, Error::LookupFailed);
     
    414474        }
    415475       
    416         if (metaData.version != ContentRuleListStore::CurrentContentRuleListFileVersion) {
     476        if (contentRuleList->metaData.version != ContentRuleListStore::CurrentContentRuleListFileVersion) {
    417477            RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler)] () mutable {
    418478                completionHandler(nullptr, Error::VersionMismatch);
     
    421481        }
    422482       
    423         RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), identifier = identifier.isolatedCopy(), fileData = WTFMove(fileData), metaData = WTFMove(metaData), completionHandler = WTFMove(completionHandler)] () mutable {
    424             completionHandler(createExtension(identifier, metaData, fileData), { });
     483        RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), identifier = identifier.isolatedCopy(), contentRuleList = WTFMove(*contentRuleList), completionHandler = WTFMove(completionHandler)] () mutable {
     484            completionHandler(createExtension(identifier, WTFMove(contentRuleList)), { });
    425485        });
    426486    });
     
    456516        auto path = constructedPath(storePath, identifier, legacyFilename);
    457517
    458         ContentRuleListMetaData metaData;
    459         WebKit::NetworkCache::Data fileData;
    460         auto error = compiledToFile(WTFMove(json), WTFMove(parsedRules), path, metaData, fileData);
    461         if (error) {
    462             RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), error = WTFMove(error), completionHandler = WTFMove(completionHandler)] () mutable {
     518        auto result = compiledToFile(WTFMove(json), WTFMove(parsedRules), path);
     519        if (!result.has_value()) {
     520            RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), error = WTFMove(result.error()), completionHandler = WTFMove(completionHandler)] () mutable {
    463521                completionHandler(nullptr, error);
    464522            });
     
    466524        }
    467525
    468         RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), identifier = WTFMove(identifier), fileData = WTFMove(fileData), metaData = WTFMove(metaData), completionHandler = WTFMove(completionHandler)] () mutable {
    469             RefPtr<API::ContentRuleList> contentRuleList = createExtension(identifier, metaData, fileData);
    470             completionHandler(contentRuleList, { });
     526        RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), identifier = WTFMove(identifier), data = WTFMove(result.value()), completionHandler = WTFMove(completionHandler)] () mutable {
     527            auto contentRuleList = createExtension(identifier, WTFMove(data));
     528            completionHandler(contentRuleList.ptr(), { });
    471529        });
    472530    });
     
    518576            });
    519577        };
    520        
    521         ContentRuleListMetaData metaData;
    522         WebKit::NetworkCache::Data fileData;
    523         if (!openAndMapContentRuleList(path, metaData, fileData)) {
     578
     579        auto contentRuleList = openAndMapOrCopyContentRuleList(path);
     580        if (!contentRuleList) {
    524581            complete({ });
    525582            return;
    526583        }
    527584       
    528         switch (metaData.version) {
     585        switch (contentRuleList->metaData.version) {
    529586        case 9:
    530587        case 10:
    531             if (!metaData.sourceSize) {
     588            if (!contentRuleList->metaData.sourceSize) {
    532589                complete({ });
    533590                return;
    534591            }
    535             bool is8Bit = fileData.data()[ContentRuleListFileHeaderSize];
     592            bool is8Bit = contentRuleList->dataPointer()[ContentRuleListFileHeaderSize];
    536593            size_t start = ContentRuleListFileHeaderSize + sizeof(bool);
    537             size_t length = metaData.sourceSize - sizeof(bool);
     594            size_t length = contentRuleList->metaData.sourceSize - sizeof(bool);
    538595            if (is8Bit)
    539                 complete(WTF::String(fileData.data() + start, length));
     596                complete(WTF::String(contentRuleList->dataPointer() + start, length));
    540597            else {
    541598                ASSERT(!(length % sizeof(UChar)));
    542                 complete(WTF::String(reinterpret_cast<const UChar*>(fileData.data() + start), length / sizeof(UChar)));
     599                complete(WTF::String(reinterpret_cast<const UChar*>(contentRuleList->dataPointer() + start), length / sizeof(UChar)));
    543600            }
    544601            return;
  • trunk/Source/WebKit/UIProcess/API/APIContentRuleListStore.h

    r242710 r242735  
    3131#include <system_error>
    3232#include <wtf/text/WTFString.h>
     33
     34namespace WebCore {
     35class SharedBuffer;
     36}
    3337
    3438namespace WTF {
     
    7377    void getContentRuleListSource(const WTF::String& identifier, CompletionHandler<void(WTF::String)>);
    7478
     79    static RefPtr<WebCore::SharedBuffer> readContentsOfFile(const WTF::String& path);
     80
    7581private:
    7682    WTF::String defaultStorePath(bool legacyFilename);
  • trunk/Source/WebKit/UIProcess/API/Cocoa/APIContentRuleListStoreCocoa.mm

    r242710 r242735  
    3030
    3131#include "SandboxUtilities.h"
     32#include <WebCore/SharedBuffer.h>
    3233
    3334namespace API {
     
    6465}
    6566
     67RefPtr<WebCore::SharedBuffer> ContentRuleListStore::readContentsOfFile(const String& filePath)
     68{
     69    ASSERT(!isMainThread());
     70    NSData *data = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:filePath isDirectory:NO]];
     71    if (!data)
     72        return nullptr;
     73    return WebCore::SharedBuffer::create(data);
     74}
     75
    6676} // namespace API
    6777
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKContentRuleListStore.mm

    r242710 r242735  
    2929
    3030#import "APIContentRuleListStore.h"
     31#import "NetworkCacheFilesystem.h"
    3132#import "WKErrorInternal.h"
    3233#import <wtf/BlockPtr.h>
     
    126127// For testing only.
    127128
     129+ (void)_registerPathAsUnsafeToMemoryMapForTesting:(NSString *)filename
     130{
     131    WebKit::NetworkCache::registerPathAsUnsafeToMemoryMapForTesting(filename);
     132}
     133
    128134- (void)_removeAllContentRuleLists
    129135{
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKContentRuleListStorePrivate.h

    r242710 r242735  
    3232- (void)_invalidateContentRuleListVersionForIdentifier:(NSString *)identifier;
    3333- (void)_getContentRuleListSourceForIdentifier:(NSString *)identifier completionHandler:(void (^)(NSString*))completionHandler;
     34+ (void)_registerPathAsUnsafeToMemoryMapForTesting:(NSString *)filename;
    3435
    3536// NS_RELEASES_ARGUMENT to keep peak memory usage low.
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKUserContentFilter.mm

    r242710 r242735  
    5757}
    5858
     59- (BOOL)usesCopiedMemory
     60{
     61    return _contentRuleList->_contentRuleList->usesCopiedMemory();
     62}
     63
    5964@end
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKUserContentFilterPrivate.h

    r242710 r242735  
    3131
    3232- (id)_initWithWKContentRuleList:(WKContentRuleList*)contentRuleList WK_API_AVAILABLE(macosx(10.13), ios(11.0));
     33@property (nonatomic, readonly) BOOL usesCopiedMemory;
    3334
    3435@end
  • trunk/Source/WebKit/WebProcess/UserContent/WebUserContentController.cpp

    r242710 r242735  
    349349
    350350#if ENABLE(CONTENT_EXTENSIONS)
    351 void WebUserContentController::addContentRuleLists(const Vector<std::pair<String, WebCompiledContentRuleListData>>& contentRuleLists)
    352 {
    353     for (const auto& contentRuleList : contentRuleLists) {
    354         WebCompiledContentRuleListData contentRuleListData = contentRuleList.second;
    355         auto compiledContentRuleList = WebCompiledContentRuleList::create(WTFMove(contentRuleListData));
     351void WebUserContentController::addContentRuleLists(Vector<std::pair<String, WebCompiledContentRuleListData>>&& contentRuleLists)
     352{
     353    for (auto&& contentRuleList : contentRuleLists) {
     354        auto compiledContentRuleList = WebCompiledContentRuleList::create(WTFMove(contentRuleList.second));
    356355
    357356        m_contentExtensionBackend.addContentExtension(contentRuleList.first, WTFMove(compiledContentRuleList));
  • trunk/Source/WebKit/WebProcess/UserContent/WebUserContentController.h

    r242710 r242735  
    7070    void addUserScriptMessageHandlers(const Vector<WebScriptMessageHandlerData>&);
    7171#if ENABLE(CONTENT_EXTENSIONS)
    72     void addContentRuleLists(const Vector<std::pair<String, WebCompiledContentRuleListData>>&);
     72    void addContentRuleLists(Vector<std::pair<String, WebCompiledContentRuleListData>>&&);
    7373#endif
    7474
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp

    r242714 r242735  
    638638    m_userContentController->addUserScriptMessageHandlers(parameters.messageHandlers);
    639639#if ENABLE(CONTENT_EXTENSIONS)
    640     m_userContentController->addContentRuleLists(parameters.contentRuleLists);
     640    m_userContentController->addContentRuleLists(WTFMove(parameters.contentRuleLists));
    641641#endif
    642642
  • trunk/Tools/ChangeLog

    r242733 r242735  
     12019-03-11  Alex Christensen  <achristensen@webkit.org>
     2
     3        Add a WKContentRuleList variant that uses copied memory instead of mmap'd shared memory for class A containerized apps
     4        https://bugs.webkit.org/show_bug.cgi?id=195511
     5        <rdar://problem/44873269>
     6
     7        Reviewed by Darin Adler.
     8
     9        * TestWebKitAPI/Tests/WebKitCocoa/WKContentExtensionStore.mm:
     10        (-[TestSchemeHandlerSubresourceShouldBeBlocked webView:startURLSchemeTask:]):
     11        (-[TestSchemeHandlerSubresourceShouldBeBlocked webView:stopURLSchemeTask:]):
     12        (TEST_F):
     13
    1142019-03-11  Chris Dumez  <cdumez@apple.com>
    215
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentExtensionStore.mm

    r242710 r242735  
    2929#import "PlatformUtilities.h"
    3030#import "Test.h"
     31#import "TestWKWebView.h"
    3132#import <WebKit/WKContentRuleList.h>
    3233#import <WebKit/WKContentRuleListStorePrivate.h>
     34#import <WebKit/_WKUserContentFilterPrivate.h>
    3335#import <wtf/RetainPtr.h>
     36#import <wtf/text/StringBuilder.h>
     37#import <wtf/text/StringConcatenate.h>
     38#import <wtf/text/StringConcatenateNumbers.h>
    3439
    3540class WKContentRuleListStoreTest : public testing::Test {
     
    378383    TestWebKitAPI::Util::run(&receivedAlert);
    379384}
     385
     386@interface TestSchemeHandlerSubresourceShouldBeBlocked : NSObject <WKURLSchemeHandler>
     387@end
     388@implementation TestSchemeHandlerSubresourceShouldBeBlocked
     389- (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
     390{
     391    EXPECT_TRUE([task.request.URL.path isEqualToString:@"/shouldload"]);
     392    [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil] autorelease]];
     393    [task didFinish];
     394}
     395- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)task
     396{
     397    EXPECT_TRUE(false);
     398}
     399@end
     400
     401TEST_F(WKContentRuleListStoreTest, UnsafeMMap)
     402{
     403    RetainPtr<NSString> tempDir = [NSTemporaryDirectory() stringByAppendingPathComponent:@"UnsafeMMapTest"];
     404    RetainPtr<WKContentRuleListStore> store = [WKContentRuleListStore storeWithURL:[NSURL fileURLWithPath:tempDir.get() isDirectory:YES]];
     405    static NSString *identifier = @"TestRuleList";
     406    static NSString *fileName = @"ContentRuleList-TestRuleList";
     407    static NSString *ruleListSourceString = @"[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"blockedsubresource\"}}]";
     408    RetainPtr<NSString> filePath = [tempDir stringByAppendingPathComponent:fileName];
     409
     410    auto runTest = [&] (bool shouldUseCopiedMemory) {
     411        EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:filePath.get()]);
     412       
     413        __block bool doneCompiling = false;
     414        __block RetainPtr<WKContentRuleList> ruleList;
     415        [store compileContentRuleListForIdentifier:identifier encodedContentRuleList:ruleListSourceString completionHandler:^(WKContentRuleList *filter, NSError *error) {
     416            EXPECT_NOT_NULL(filter);
     417            EXPECT_NULL(error);
     418            doneCompiling = true;
     419            ruleList = filter;
     420            EXPECT_TRUE([[[[_WKUserContentFilter alloc] _initWithWKContentRuleList:filter] autorelease] usesCopiedMemory] == shouldUseCopiedMemory);
     421        }];
     422        TestWebKitAPI::Util::run(&doneCompiling);
     423       
     424        EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:filePath.get()]);
     425
     426        auto handler = adoptNS([TestSchemeHandlerSubresourceShouldBeBlocked new]);
     427        auto configuration = adoptNS([WKWebViewConfiguration new]);
     428        [configuration setURLSchemeHandler:handler.get() forURLScheme:@"testmmap"];
     429        [[configuration userContentController] addContentRuleList:ruleList.get()];
     430        auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     431        [webView synchronouslyLoadHTMLString:@"<html>main resource content</html>" baseURL:[NSURL URLWithString:@"testmmap://webkit.org/mainresource"]];
     432
     433        auto loadingShouldSucceed = [&] (NSString *resourcePath, NSString *shouldSucceed) {
     434            __block bool doneEvaluating = false;
     435            [webView evaluateJavaScript:[NSString stringWithFormat:@"var caught = false; var xhr = new XMLHttpRequest(); xhr.open('GET', '%@', false); try{ xhr.send() } catch(e) { caught = true; }; caught != %@ ? 'success' : 'failure'", resourcePath, shouldSucceed] completionHandler:^(id result, NSError *error) {
     436                EXPECT_NULL(error);
     437                EXPECT_TRUE([@"success" isEqualToString:result]);
     438                doneEvaluating = true;
     439            }];
     440            TestWebKitAPI::Util::run(&doneEvaluating);
     441        };
     442        loadingShouldSucceed(@"/shouldload", @"true");
     443        loadingShouldSucceed(@"/blockedsubresource", @"false");
     444
     445        [[configuration userContentController] removeContentRuleList:ruleList.get()];
     446       
     447        __block bool doneLookingUp = false;
     448        [store lookUpContentRuleListForIdentifier:identifier completionHandler:^(WKContentRuleList *filter, NSError *error) {
     449            EXPECT_NOT_NULL(filter);
     450            EXPECT_NULL(error);
     451           
     452            doneLookingUp = true;
     453           
     454            EXPECT_TRUE([[[[_WKUserContentFilter alloc] _initWithWKContentRuleList:filter] autorelease] usesCopiedMemory] == shouldUseCopiedMemory);
     455            ruleList = filter;
     456        }];
     457        TestWebKitAPI::Util::run(&doneLookingUp);
     458
     459        [[configuration userContentController] addContentRuleList:ruleList.get()];
     460        loadingShouldSucceed(@"/shouldload", @"true");
     461        loadingShouldSucceed(@"/blockedsubresource", @"false");
     462
     463        __block bool doneCheckingSource = false;
     464        [store _getContentRuleListSourceForIdentifier:identifier completionHandler:^(NSString *source) {
     465            EXPECT_TRUE([source isEqualToString:ruleListSourceString]);
     466            doneCheckingSource = true;
     467        }];
     468        TestWebKitAPI::Util::run(&doneCheckingSource);
     469       
     470        __block bool doneRemoving = false;
     471        [store removeContentRuleListForIdentifier:identifier completionHandler:^(NSError *error) {
     472            EXPECT_NULL(error);
     473            doneRemoving = true;
     474        }];
     475        TestWebKitAPI::Util::run(&doneRemoving);
     476
     477        EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:filePath.get()]);
     478    };
     479   
     480    runTest(false);
     481    [WKContentRuleListStore _registerPathAsUnsafeToMemoryMapForTesting:filePath.get()];
     482    runTest(true);
     483}
Note: See TracChangeset for help on using the changeset viewer.